First pass scriptable subsystems that has the same lifetime of the engine

This commit is contained in:
WiggleWizard
2024-09-18 12:44:46 +01:00
parent 67d7865a20
commit 510b577f49
17 changed files with 219 additions and 6 deletions

View File

@@ -20,6 +20,8 @@
#include <imgui/imgui_impl_opengl3.h>
#include <Tracy.hpp>
#include "src/Subsystems/EngineSubsystemScript.h"
#include "src/Subsystems/TickableEngineSubsystem.h"
namespace Nuake
@@ -39,6 +41,8 @@ namespace Nuake
void Engine::Init()
{
ScriptingEngineNet::Get().AddListener<ScriptingEngineNet::GameAssemblyLoadedDelegate>(&Engine::OnScriptingEngineGameAssemblyLoaded);
AudioManager::Get().Initialize();
PhysicsManager::Get().Init();
NavManager::Get().Initialize();
@@ -53,6 +57,8 @@ namespace Nuake
RegisterCoreTypes::RegisterCoreComponents();
Modules::StartupModules();
InitializeCoreSubsystems();
}
void Engine::Tick()
@@ -92,6 +98,15 @@ namespace Nuake
}
}
// Tick all subsystems
for (auto subsystem : tickableSubsystems)
{
if (subsystem != nullptr)
{
subsystem->Tick();
}
}
// Dont update if no scene is loaded.
if (currentWindow->GetScene())
{
@@ -216,6 +231,46 @@ namespace Nuake
return currentProject;
}
Ref<EngineSubsystemScript> Engine::GetScriptedSubsystem(const std::string& subsystemName)
{
if (scriptedSubsystemMap.contains(subsystemName))
{
return scriptedSubsystemMap[subsystemName];
}
return nullptr;
}
void Engine::InitializeCoreSubsystems()
{
}
void Engine::OnScriptingEngineGameAssemblyLoaded()
{
subsystems.clear();
scriptedSubsystemMap.clear();
auto& gameAssembly = ScriptingEngineNet::Get().GetGameAssembly();
auto scriptTypeEngineSubsystem = gameAssembly.GetType("Nuake.Net.EngineSubsystem");
const auto& types = gameAssembly.GetTypes();
for (const auto& type : types)
{
// Initialize all subsystems
if (type->IsSubclassOf(scriptTypeEngineSubsystem))
{
const std::string typeName = std::string(type->GetFullName());
Logger::Log("Creating Scripted Subsystem " + typeName);
Coral::ManagedObject scriptedSubsystem = type->CreateInstance();
Ref<EngineSubsystemScript> subsystemScript = CreateRef<EngineSubsystemScript>(scriptedSubsystem);
subsystems.push_back(subsystemScript);
scriptedSubsystemMap[typeName] = subsystemScript;
}
}
}
bool Engine::LoadProject(Ref<Project> project)
{
currentProject = project;
@@ -236,4 +291,4 @@ namespace Nuake
{
return currentWindow;
}
}
}

View File

@@ -1,4 +1,5 @@
#pragma once
#include "src/Core/Core.h"
#include "src/Core/Logger.h"
#include "src/Window.h"
@@ -8,6 +9,9 @@ namespace Nuake
{
class Project;
class Scene;
class EngineSubsystem;
class TickableEngineSubsystem;
class EngineSubsystemScript;
enum GameState
{
@@ -50,12 +54,23 @@ namespace Nuake
static bool LoadProject(Ref<Project> project);
static Ref<Project> GetProject();
static Ref<EngineSubsystemScript> GetScriptedSubsystem(const std::string& subsystemName);
protected:
static void InitializeCoreSubsystems();
static void OnScriptingEngineGameAssemblyLoaded();
private:
static Ref<Window> currentWindow;
static Ref<Project> currentProject;
static Ref<Scene> currentScene;
static std::string queuedScene;
static inline std::vector<Ref<EngineSubsystem>> subsystems;
static inline std::vector<Ref<TickableEngineSubsystem>> tickableSubsystems;
static inline std::unordered_map<std::string, Ref<EngineSubsystemScript>> scriptedSubsystemMap;
static GameState gameState;
static float lastFrameTime;

View File

@@ -1,10 +1,15 @@
#include "EngineNetAPI.h"
#include <Coral/String.hpp>
#include <src/Core/Maths.h>
#include <Engine.h>
#include "src/Core/Maths.h"
#include "src/Rendering/SceneRenderer.h"
#include "Engine.h"
#include "src/Physics/PhysicsManager.h"
#include <Coral/String.hpp>
#include <Coral/ManagedObject.hpp>
#include <Coral/Array.hpp>
#include <src/Physics/PhysicsManager.h>
#include "Coral/Type.hpp"
#include "src/Subsystems/EngineSubsystemScript.h"
namespace Nuake {
@@ -112,10 +117,22 @@ namespace Nuake {
Engine::QueueSceneSwitch(std::string(path));
}
Coral::ManagedObject GetEngineSubsystemByName(Coral::String subsystemName)
{
const Ref<EngineSubsystemScript> scriptedSubsystem = Engine::GetScriptedSubsystem(subsystemName);
if (scriptedSubsystem == nullptr)
{
return {};
}
return scriptedSubsystem->GetManagedObjectInstance();
}
void EngineNetAPI::RegisterMethods()
{
RegisterMethod("Engine.LoadSceneIcall", &LoadScene);
RegisterMethod("Engine.LoggerLogIcall", (void*)(&Log));
RegisterMethod("Engine.GetSubsystemByNameIcall", &GetEngineSubsystemByName);
// Debug renderer
RegisterMethod("Debug.DrawLineIcall", &DrawLine);

View File

@@ -324,6 +324,15 @@ 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);
@@ -525,6 +534,11 @@ namespace Nuake
}
}
}
for (auto& delegate : listenersGameAssemblyLoaded)
{
delegate();
}
}
}

View File

@@ -73,6 +73,9 @@ namespace Nuake
class ScriptingEngineNet
{
public:
using GameAssemblyLoadedDelegate = std::function<void()>;
public:
static ScriptingEngineNet& Get();
@@ -83,6 +86,7 @@ namespace Nuake
Coral::HostInstance* GetHostInstance() { return hostInstance; }
Coral::AssemblyLoadContext& GetLoadContext() { return loadContext; }
Coral::ManagedAssembly GetNuakeAssembly() const { return nuakeAssembly; }
Coral::ManagedAssembly& GetGameAssembly() { return gameAssembly; }
Coral::ManagedAssembly ReloadEngineAPI(Coral::AssemblyLoadContext & context);
@@ -110,6 +114,9 @@ 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);
private:
const std::string m_Scope = "Nuake.Net";
const std::string m_EngineAssemblyName = "NuakeNet.dll";
@@ -140,6 +147,8 @@ namespace Nuake
std::unordered_map<uint32_t, Coral::ManagedObject> entityToManagedObjects;
std::map<std::pair<UUID, UUID>, Coral::ManagedObject> widgetUUIDToManagedObjects;
std::vector<GameAssemblyLoadedDelegate> listenersGameAssemblyLoaded;
ScriptingEngineNet();
~ScriptingEngineNet();
@@ -148,4 +157,4 @@ namespace Nuake
std::string GenerateGUID();
std::vector<CompilationError> ExtractErrors(const std::string& input);
};
}
}

View File

@@ -0,0 +1 @@
#include "EngineSubsystem.h"

View File

@@ -0,0 +1,14 @@
#pragma once
/**
* Specific type of subsystem that runs within the context of the engine, being created at the start of the
* engine's lifetime and destroyed just before the engine shuts down.
*/
namespace Nuake
{
class EngineSubsystem
{
public:
};
}

View File

@@ -0,0 +1,18 @@
#include "EngineSubsystemScript.h"
namespace Nuake
{
EngineSubsystemScript::EngineSubsystemScript(const Coral::ManagedObject& object)
: cSharpObjectInstance(object)
{
}
Coral::ManagedObject& EngineSubsystemScript::GetManagedObjectInstance()
{
return cSharpObjectInstance;
}
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include "EngineSubsystem.h"
#include "Coral/ManagedObject.hpp"
/**
* Essentially just a wrapper for C# subsystems
*/
namespace Nuake
{
class EngineSubsystemScript : public EngineSubsystem
{
public:
EngineSubsystemScript(const Coral::ManagedObject& object);
Coral::ManagedObject& GetManagedObjectInstance();
private:
Coral::ManagedObject cSharpObjectInstance;
};
}

View File

@@ -0,0 +1 @@
#include "SceneSubsystem.h"

View File

@@ -0,0 +1,9 @@
#pragma once
// Currently unused, but it's meant to be the base for all ECS "systems" at some point
// that can be extended with a script.
class SceneSubsystem
{
public:
};

View File

@@ -0,0 +1 @@
#include "TickableEngineSubsystem.h"

View File

@@ -0,0 +1,13 @@
#pragma once
#include "EngineSubsystem.h"
namespace Nuake
{
class TickableEngineSubsystem : public EngineSubsystem
{
public:
virtual void Tick() {}
};
}

View File

@@ -0,0 +1,6 @@
namespace Nuake.Net;
public class EngineSubsystem
{
}

View File

@@ -0,0 +1,6 @@
namespace Nuake.Net;
public class EngineTickableSubsystem
{
}

View File

@@ -5,6 +5,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -18,6 +19,8 @@ namespace Nuake.Net
{
internal static unsafe delegate*<NativeString, void> LoggerLogIcall;
internal static unsafe delegate*<NativeString, void> LoadSceneIcall;
internal static unsafe delegate*<NativeString, NativeInstance<EngineSubsystem>> GetSubsystemByNameIcall;
public Engine() { }
public static void LoadScene(string path)
@@ -33,6 +36,14 @@ namespace Nuake.Net
{
unsafe { LoggerLogIcall(input); }
}
public static T? GetSubsystem<T>() where T : EngineSubsystem
{
unsafe
{
return (T?)GetSubsystemByNameIcall(typeof(T).FullName);
}
}
}
public struct AABB

View File

@@ -127,6 +127,8 @@ project "Nuake"
"%{prj.name}/src/Threading/**.cpp",
"%{prj.name}/src/UI/**.h",
"%{prj.name}/src/UI/**.cpp",
"%{prj.name}/src/Subsystems/**.h",
"%{prj.name}/src/Subsystems/**.cpp",
"%{prj.name}/src/Vendors/**.h",
"%{prj.name}/src/Vendors/**.cpp",