mirror of
https://github.com/antopilo/Nuake.git
synced 2026-01-03 14:09:46 +03:00
Completed work on exposing subsystems to scene events
This commit is contained in:
@@ -42,7 +42,7 @@ namespace Nuake
|
||||
{
|
||||
Window::Get()->OnWindowSetScene().AddStatic(&Engine::OnWindowSetScene);
|
||||
|
||||
ScriptingEngineNet::Get().AddListener<ScriptingEngineNet::GameAssemblyLoadedDelegate>(&Engine::OnScriptingEngineGameAssemblyLoaded);
|
||||
ScriptingEngineNet::Get().OnGameAssemblyLoaded().AddStatic(&Engine::OnScriptingEngineGameAssemblyLoaded);
|
||||
|
||||
AudioManager::Get().Initialize();
|
||||
PhysicsManager::Get().Init();
|
||||
|
||||
@@ -60,6 +60,8 @@ namespace Nuake
|
||||
protected:
|
||||
static void OnWindowSetScene(Ref<Scene> oldScene, Ref<Scene> newScene);
|
||||
static void InitializeCoreSubsystems();
|
||||
|
||||
static void OnScriptingEngineUninitialize();
|
||||
static void OnScriptingEngineGameAssemblyLoaded();
|
||||
|
||||
static void OnScenePreInitialize(Ref<Scene> scene);
|
||||
|
||||
@@ -2,21 +2,32 @@
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#define DECLARE_MULTICAST_DELEGATE(multicastDelegateName, ...) typedef MulticastDelegate<__VA_ARGS__> multicastDelegateName;
|
||||
#define DECLARE_MULTICAST_DELEGATE(multicastDelegateName, ...) typedef MulticastDelegate<__VA_ARGS__> multicastDelegateName;
|
||||
|
||||
struct DelegateHandle
|
||||
{
|
||||
size_t id = InvalidHandle;
|
||||
|
||||
static inline size_t InvalidHandle = static_cast<size_t>(-1);
|
||||
|
||||
bool IsValid() const { return id != InvalidHandle; }
|
||||
void Reset() { id = InvalidHandle; }
|
||||
|
||||
// Comparison operators for convenience
|
||||
bool operator==(const DelegateHandle& other) const { return id == other.id; }
|
||||
bool operator!=(const DelegateHandle& other) const { return id != other.id; }
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
class MulticastDelegate
|
||||
{
|
||||
public:
|
||||
using DelegateID = size_t;
|
||||
|
||||
// Add a callable with bound variables (supports no arguments as well)
|
||||
template<typename Callable, typename... BoundArgs>
|
||||
DelegateID AddStatic(Callable&& func, BoundArgs&&... boundArgs)
|
||||
DelegateHandle AddStatic(Callable&& func, BoundArgs&&... boundArgs)
|
||||
{
|
||||
DelegateID id = nextID++;
|
||||
size_t id = GetNextID();
|
||||
auto boundFunction = [=](Args... args) {
|
||||
if constexpr (sizeof...(Args) > 0)
|
||||
{
|
||||
@@ -27,14 +38,14 @@ public:
|
||||
func(boundArgs...);
|
||||
}
|
||||
};
|
||||
delegates.push_back({id, boundFunction});
|
||||
return id;
|
||||
SetDelegate(id, boundFunction);
|
||||
return DelegateHandle{ id };
|
||||
}
|
||||
|
||||
template<typename Callable, typename Obj, typename... BoundArgs>
|
||||
DelegateID AddObject(Callable&& func, Obj* object, BoundArgs&&... boundArgs)
|
||||
template<typename Obj, typename Callable, typename... BoundArgs>
|
||||
DelegateHandle AddRaw(Obj* object, Callable&& func, BoundArgs&&... boundArgs)
|
||||
{
|
||||
DelegateID id = nextID++;
|
||||
size_t id = GetNextID();
|
||||
auto boundFunction = [=](Args... args) {
|
||||
if constexpr (sizeof...(Args) > 0)
|
||||
{
|
||||
@@ -45,42 +56,79 @@ public:
|
||||
(object->*func)(boundArgs...);
|
||||
}
|
||||
};
|
||||
delegates.push_back({id, boundFunction});
|
||||
return id;
|
||||
SetDelegate(id, boundFunction);
|
||||
return DelegateHandle{ id };
|
||||
}
|
||||
|
||||
// Remove a callable using the token returned by Add()
|
||||
void Remove(DelegateID id)
|
||||
void Remove(DelegateHandle& handle)
|
||||
{
|
||||
auto it = std::remove_if(delegates.begin(), delegates.end(), [id](const auto& pair)
|
||||
{
|
||||
return pair.first == id;
|
||||
});
|
||||
ASSERT(handle.IsValid());
|
||||
|
||||
if (it != delegates.end())
|
||||
if (handle.IsValid() && handle.id < delegates.size())
|
||||
{
|
||||
delegates.erase(it, delegates.end());
|
||||
delegates[handle.id].active = false;
|
||||
|
||||
// Mark this slot as reusable
|
||||
freeIDs.push_back(handle.id);
|
||||
}
|
||||
|
||||
// Invalidate the handle
|
||||
handle.Reset();
|
||||
}
|
||||
|
||||
// Clear all delegates
|
||||
void Clear()
|
||||
{
|
||||
delegates.clear();
|
||||
freeIDs.clear();
|
||||
nextID = 0;
|
||||
}
|
||||
|
||||
// Invoke all callables
|
||||
void Broadcast(Args... args)
|
||||
{
|
||||
for (auto& [id, delegate] : delegates)
|
||||
for (auto& delegate : delegates)
|
||||
{
|
||||
delegate(std::forward<Args>(args)...);
|
||||
if (delegate.active)
|
||||
{
|
||||
delegate.function(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using DelegatePair = std::pair<DelegateID, std::function<void(Args...)>>;
|
||||
|
||||
std::vector<DelegatePair> delegates; // Vector of (ID, callable) pairs
|
||||
DelegateID nextID = 0; // Unique ID generator
|
||||
struct Delegate
|
||||
{
|
||||
bool active = false;
|
||||
std::function<void(Args...)> function;
|
||||
};
|
||||
|
||||
// A vector of delegates with active state
|
||||
std::vector<Delegate> delegates;
|
||||
// List of reusable slots
|
||||
std::vector<size_t> freeIDs;
|
||||
size_t nextID = 0;
|
||||
|
||||
// Get the next available ID, either by reusing a free slot or by creating a new one
|
||||
size_t GetNextID()
|
||||
{
|
||||
if (!freeIDs.empty())
|
||||
{
|
||||
size_t id = freeIDs.back();
|
||||
freeIDs.pop_back();
|
||||
return id;
|
||||
}
|
||||
|
||||
return nextID++;
|
||||
}
|
||||
|
||||
// Set the delegate in the vector, makes the array larger if necessary
|
||||
void SetDelegate(size_t id, const std::function<void(Args...)>& func)
|
||||
{
|
||||
if (id >= delegates.size())
|
||||
delegates.resize(id + 1);
|
||||
|
||||
delegates[id] = { true, func };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -203,6 +203,8 @@ namespace Nuake
|
||||
managedObject.Destroy();
|
||||
}
|
||||
|
||||
onUninitializeDelegate.Broadcast();
|
||||
|
||||
Coral::GC::Collect();
|
||||
Coral::GC::WaitForPendingFinalizers();
|
||||
|
||||
@@ -331,15 +333,6 @@ namespace Nuake
|
||||
return widgetUUIDToManagedObjects[std::make_pair(canvasUUID, uuid)];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ScriptingEngineNet::AddListener(const T& delegate) {}
|
||||
|
||||
template <>
|
||||
void ScriptingEngineNet::AddListener<ScriptingEngineNet::GameAssemblyLoadedDelegate>(const GameAssemblyLoadedDelegate& delegate)
|
||||
{
|
||||
listenersGameAssemblyLoaded.push_back(delegate);
|
||||
}
|
||||
|
||||
std::vector<CompilationError> ScriptingEngineNet::BuildProjectAssembly(Ref<Project> project)
|
||||
{
|
||||
const std::string sanitizedProjectName = String::Sanitize(project->Name);
|
||||
@@ -541,10 +534,7 @@ namespace Nuake
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& delegate : listenersGameAssemblyLoaded)
|
||||
{
|
||||
delegate();
|
||||
}
|
||||
onGameAssemblyLoadedDelegate.Broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ namespace Nuake
|
||||
{
|
||||
class Project;
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE(OnGameAssemblyLoadedDelegate)
|
||||
DECLARE_MULTICAST_DELEGATE(OnUninitializeDelegate)
|
||||
|
||||
enum class ExposedVarTypes
|
||||
{
|
||||
Bool,
|
||||
@@ -115,8 +118,8 @@ namespace Nuake
|
||||
std::unordered_map<std::string, NetGameScriptObject> GetPointEntities() const { return pointEntityTypes; }
|
||||
std::unordered_map<std::string, UIWidgetObject> GetUIWidgets() const { return uiWidgets; }
|
||||
|
||||
template<class T> void AddListener(const T& delegate);
|
||||
template<> void AddListener(const GameAssemblyLoadedDelegate& delegate);
|
||||
OnGameAssemblyLoadedDelegate& OnUninitialize() { return onUninitializeDelegate; }
|
||||
OnUninitializeDelegate& OnGameAssemblyLoaded() { return onGameAssemblyLoadedDelegate; }
|
||||
|
||||
private:
|
||||
const std::string m_Scope = "Nuake.Net";
|
||||
@@ -149,7 +152,8 @@ namespace Nuake
|
||||
std::unordered_map<uint32_t, Coral::ManagedObject> entityToManagedObjects;
|
||||
std::map<std::pair<UUID, UUID>, Coral::ManagedObject> widgetUUIDToManagedObjects;
|
||||
|
||||
std::vector<GameAssemblyLoadedDelegate> listenersGameAssemblyLoaded;
|
||||
OnGameAssemblyLoadedDelegate onGameAssemblyLoadedDelegate;
|
||||
OnUninitializeDelegate onUninitializeDelegate;
|
||||
|
||||
ScriptingEngineNet();
|
||||
~ScriptingEngineNet();
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
#include "EngineSubsystem.h"
|
||||
|
||||
void Nuake::EngineSubsystem::SetCanTick(bool canTick)
|
||||
#include "src/Scripting/ScriptingEngineNet.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
canEverTick = canTick;
|
||||
void EngineSubsystem::SetCanTick(bool canTick)
|
||||
{
|
||||
canEverTick = canTick;
|
||||
}
|
||||
|
||||
bool EngineSubsystem::CanEverTick() const
|
||||
{
|
||||
return canEverTick;
|
||||
}
|
||||
}
|
||||
|
||||
bool Nuake::EngineSubsystem::CanEverTick() const
|
||||
{
|
||||
return canEverTick;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ namespace Nuake
|
||||
virtual void OnScenePostInitialize(Ref<Scene> scene) {}
|
||||
virtual void OnScenePreDestroy(Ref<Scene> scene) {}
|
||||
|
||||
private:
|
||||
protected:
|
||||
void OnScriptEngineUninitialize();
|
||||
|
||||
bool canEverTick = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "EngineSubsystemScriptable.h"
|
||||
|
||||
#include "Coral/Type.hpp"
|
||||
#include "src/Scripting/ScriptingEngineNet.h"
|
||||
|
||||
#include <Coral/Type.hpp>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
@@ -11,6 +13,16 @@ EngineSubsystemScriptable::EngineSubsystemScriptable(const Coral::ManagedObject&
|
||||
|
||||
}
|
||||
|
||||
EngineSubsystemScriptable::~EngineSubsystemScriptable()
|
||||
{
|
||||
if (!cSharpObjectInstance.IsValid())
|
||||
return;
|
||||
|
||||
ScriptingEngineNet::Get().OnUninitialize().Remove(scriptEngineUninitializeDelegateHandle);
|
||||
|
||||
cSharpObjectInstance.Destroy();
|
||||
}
|
||||
|
||||
Coral::ManagedObject& EngineSubsystemScriptable::GetManagedObjectInstance()
|
||||
{
|
||||
return cSharpObjectInstance;
|
||||
@@ -18,6 +30,8 @@ Coral::ManagedObject& EngineSubsystemScriptable::GetManagedObjectInstance()
|
||||
|
||||
void EngineSubsystemScriptable::Initialize()
|
||||
{
|
||||
scriptEngineUninitializeDelegateHandle = ScriptingEngineNet::Get().OnUninitialize().AddRaw(this, &EngineSubsystemScriptable::OnScriptEngineUninitialize);
|
||||
|
||||
if (!cSharpObjectInstance.IsValid())
|
||||
return;
|
||||
|
||||
@@ -52,12 +66,18 @@ void EngineSubsystemScriptable::OnScenePreDestroy(Ref<Scene> scene)
|
||||
{
|
||||
if (!cSharpObjectInstance.IsValid())
|
||||
return;
|
||||
|
||||
if (cSharpObjectInstance.GetType().GetTypeId() == -1)
|
||||
return;
|
||||
|
||||
cSharpObjectInstance.InvokeMethod("InternalOnScenePreDestroy");
|
||||
}
|
||||
|
||||
void EngineSubsystemScriptable::OnScriptEngineUninitialize()
|
||||
{
|
||||
if (!cSharpObjectInstance.IsValid())
|
||||
return;
|
||||
|
||||
cSharpObjectInstance.Destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "EngineSubsystem.h"
|
||||
#include "src/Core/MulticastDelegate.h"
|
||||
|
||||
#include <Coral/ManagedObject.hpp>
|
||||
|
||||
@@ -13,6 +14,7 @@ namespace Nuake
|
||||
{
|
||||
public:
|
||||
EngineSubsystemScriptable(const Coral::ManagedObject& object);
|
||||
virtual ~EngineSubsystemScriptable();
|
||||
|
||||
Coral::ManagedObject& GetManagedObjectInstance();
|
||||
|
||||
@@ -23,7 +25,11 @@ namespace Nuake
|
||||
virtual void OnScenePostInitialize(Ref<Scene> scene) override;
|
||||
virtual void OnScenePreDestroy(Ref<Scene> scene) override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
void OnScriptEngineUninitialize();
|
||||
|
||||
DelegateHandle scriptEngineUninitializeDelegateHandle;
|
||||
|
||||
Coral::ManagedObject cSharpObjectInstance;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user