Merge branch 'develop' of https://github.com/antopilo/Nuake into develop
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "src/Threading/JobSystem.h"
|
||||
#include "src/Core/RegisterCoreTypes.h"
|
||||
#include "src/Modules/Modules.h"
|
||||
#include "src/Subsystems/EngineSubsystemScriptable.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <imgui/imgui_impl_glfw.h>
|
||||
@@ -39,6 +40,8 @@ namespace Nuake
|
||||
|
||||
void Engine::Init()
|
||||
{
|
||||
ScriptingEngineNet::Get().AddListener<ScriptingEngineNet::GameAssemblyLoadedDelegate>(&Engine::OnScriptingEngineGameAssemblyLoaded);
|
||||
|
||||
AudioManager::Get().Initialize();
|
||||
PhysicsManager::Get().Init();
|
||||
NavManager::Get().Initialize();
|
||||
@@ -53,6 +56,8 @@ namespace Nuake
|
||||
RegisterCoreTypes::RegisterCoreComponents();
|
||||
|
||||
Modules::StartupModules();
|
||||
|
||||
InitializeCoreSubsystems();
|
||||
}
|
||||
|
||||
void Engine::Tick()
|
||||
@@ -91,11 +96,27 @@ namespace Nuake
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
float scaledTimeStep = timeStep * timeScale;
|
||||
|
||||
// Tick all subsystems
|
||||
if (Engine::IsPlayMode())
|
||||
{
|
||||
for (auto subsystem : subsystems)
|
||||
{
|
||||
if (subsystem == nullptr)
|
||||
continue;
|
||||
|
||||
if (subsystem->CanEverTick())
|
||||
{
|
||||
subsystem->Tick(scaledTimeStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dont update if no scene is loaded.
|
||||
if (currentWindow->GetScene())
|
||||
{
|
||||
float scaledTimeStep = timeStep * timeScale;
|
||||
currentWindow->Update(scaledTimeStep);
|
||||
|
||||
// Play mode update all the entities, Editor does not.
|
||||
@@ -124,11 +145,13 @@ namespace Nuake
|
||||
lastFrameTime = (float)glfwGetTime(); // Reset timestep timer.
|
||||
|
||||
// Dont trigger init if already in player mode.
|
||||
if (GetGameState() == GameState::Playing)
|
||||
if (GetGameState() == GameState::Playing || GetGameState() == GameState::Loading)
|
||||
{
|
||||
Logger::Log("Cannot enter play mode if is already in play mode.", "engine", WARNING);
|
||||
Logger::Log("Cannot enter play mode if is already in play mode or is loading.", "engine", WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
SetGameState(GameState::Loading);
|
||||
|
||||
PhysicsManager::Get().ReInit();
|
||||
|
||||
@@ -216,6 +239,63 @@ namespace Nuake
|
||||
return currentProject;
|
||||
}
|
||||
|
||||
Ref<EngineSubsystemScriptable> Engine::GetScriptedSubsystem(const std::string& subsystemName)
|
||||
{
|
||||
if (scriptedSubsystemMap.contains(subsystemName))
|
||||
{
|
||||
return scriptedSubsystemMap[subsystemName];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Ref<EngineSubsystemScriptable> Engine::GetScriptedSubsystem(const int subsystemId)
|
||||
{
|
||||
if (subsystemId >= subsystems.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return std::reinterpret_pointer_cast<EngineSubsystemScriptable>(subsystems[subsystemId]);
|
||||
}
|
||||
|
||||
void Engine::InitializeCoreSubsystems()
|
||||
{
|
||||
}
|
||||
|
||||
void Engine::OnScriptingEngineGameAssemblyLoaded()
|
||||
{
|
||||
if (!Engine::IsPlayMode() && Engine::GetGameState() != GameState::Loading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
subsystems.clear();
|
||||
scriptedSubsystemMap.clear();
|
||||
|
||||
const Coral::ManagedAssembly& gameAssembly = ScriptingEngineNet::Get().GetGameAssembly();
|
||||
|
||||
const 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();
|
||||
scriptedSubsystem.SetPropertyValue("EngineSubsystemID", subsystems.size());
|
||||
Ref<EngineSubsystemScriptable> subsystemScript = CreateRef<EngineSubsystemScriptable>(scriptedSubsystem);
|
||||
subsystems.push_back(subsystemScript);
|
||||
|
||||
scriptedSubsystemMap[typeName] = subsystemScript;
|
||||
|
||||
subsystemScript->Initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Engine::LoadProject(Ref<Project> project)
|
||||
{
|
||||
currentProject = project;
|
||||
@@ -236,4 +316,4 @@ namespace Nuake
|
||||
{
|
||||
return currentWindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Logger.h"
|
||||
#include "src/Window.h"
|
||||
@@ -8,9 +9,12 @@ namespace Nuake
|
||||
{
|
||||
class Project;
|
||||
class Scene;
|
||||
class EngineSubsystem;
|
||||
class EngineSubsystemScriptable;
|
||||
|
||||
enum GameState
|
||||
{
|
||||
Loading,
|
||||
Playing,
|
||||
Paused,
|
||||
Stopped
|
||||
@@ -50,12 +54,22 @@ namespace Nuake
|
||||
static bool LoadProject(Ref<Project> project);
|
||||
static Ref<Project> GetProject();
|
||||
|
||||
static Ref<EngineSubsystemScriptable> GetScriptedSubsystem(const std::string& subsystemName);
|
||||
static Ref<EngineSubsystemScriptable> GetScriptedSubsystem(const int subsystemId);
|
||||
|
||||
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::unordered_map<std::string, Ref<EngineSubsystemScriptable>> scriptedSubsystemMap;
|
||||
|
||||
static GameState gameState;
|
||||
|
||||
static float lastFrameTime;
|
||||
|
||||
@@ -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 "..\..\Subsystems\EngineSubsystemScriptable.h"
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
@@ -112,10 +117,22 @@ namespace Nuake {
|
||||
Engine::QueueSceneSwitch(std::string(path));
|
||||
}
|
||||
|
||||
Coral::ManagedObject GetEngineSubsystemByName(Coral::String subsystemName)
|
||||
{
|
||||
const Ref<EngineSubsystemScriptable> 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);
|
||||
|
||||
37
Nuake/src/Scripting/NetModules/EngineSubsystemNetAPI.cpp
Normal file
37
Nuake/src/Scripting/NetModules/EngineSubsystemNetAPI.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "EngineSubsystemNetAPI.h"
|
||||
|
||||
#include "Engine.h"
|
||||
#include "src/Subsystems/EngineSubsystemScriptable.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
void SetCanTick(int subsystemId, bool tick)
|
||||
{
|
||||
auto subsystem = Engine::GetScriptedSubsystem(subsystemId);
|
||||
if (subsystem == nullptr)
|
||||
{
|
||||
Logger::Log("Subsystem isn't a valid scripted subsystem", "EngineSubsystemNetAPI", WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
subsystem->SetCanTick(tick);
|
||||
}
|
||||
|
||||
bool GetCanTick(int subsystemId)
|
||||
{
|
||||
auto subsystem = Engine::GetScriptedSubsystem(subsystemId);
|
||||
if (subsystem == nullptr)
|
||||
{
|
||||
Logger::Log("Subsystem isn't a valid scripted subsystem", "EngineSubsystemNetAPI", WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
return subsystem->CanEverTick();
|
||||
}
|
||||
|
||||
void EngineSubsystemNetAPI::RegisterMethods()
|
||||
{
|
||||
RegisterMethod("EngineSubsystem.SetCanTickIcall", &SetCanTick);
|
||||
RegisterMethod("EngineSubsystem.GetCanTickIcall", &GetCanTick);
|
||||
}
|
||||
}
|
||||
14
Nuake/src/Scripting/NetModules/EngineSubsystemNetAPI.h
Normal file
14
Nuake/src/Scripting/NetModules/EngineSubsystemNetAPI.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "NetAPIModule.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class EngineSubsystemNetAPI : public Nuake::NetAPIModule
|
||||
{
|
||||
public:
|
||||
virtual const std::string GetModuleName() const override { return "EngineSubsystem"; }
|
||||
virtual void RegisterMethods() override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "src/Scene/Components/NetScriptComponent.h"
|
||||
|
||||
#include "NetModules/EngineNetAPI.h"
|
||||
#include "NetModules/EngineSubsystemNetAPI.h"
|
||||
#include "NetModules/InputNetAPI.h"
|
||||
#include "NetModules/SceneNetAPI.h"
|
||||
#include "NetModules/UINetAPI.h"
|
||||
@@ -53,6 +54,7 @@ namespace Nuake
|
||||
modules =
|
||||
{
|
||||
CreateRef<EngineNetAPI>(),
|
||||
CreateRef<EngineSubsystemNetAPI>(),
|
||||
CreateRef<InputNetAPI>(),
|
||||
CreateRef<SceneNetAPI>(),
|
||||
CreateRef<UINetAPI>()
|
||||
@@ -329,6 +331,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);
|
||||
@@ -529,6 +540,11 @@ namespace Nuake
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& delegate : listenersGameAssemblyLoaded)
|
||||
{
|
||||
delegate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,9 @@ namespace Nuake
|
||||
|
||||
class ScriptingEngineNet
|
||||
{
|
||||
public:
|
||||
using GameAssemblyLoadedDelegate = std::function<void()>;
|
||||
|
||||
public:
|
||||
static ScriptingEngineNet& Get();
|
||||
|
||||
@@ -84,6 +87,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);
|
||||
|
||||
@@ -111,6 +115,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";
|
||||
@@ -141,6 +148,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();
|
||||
@@ -149,4 +158,4 @@ namespace Nuake
|
||||
std::string GenerateGUID();
|
||||
std::vector<CompilationError> ExtractErrors(const std::string& input);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
11
Nuake/src/Subsystems/EngineSubsystem.cpp
Normal file
11
Nuake/src/Subsystems/EngineSubsystem.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "EngineSubsystem.h"
|
||||
|
||||
void Nuake::EngineSubsystem::SetCanTick(bool canTick)
|
||||
{
|
||||
canEverTick = canTick;
|
||||
}
|
||||
|
||||
bool Nuake::EngineSubsystem::CanEverTick() const
|
||||
{
|
||||
return canEverTick;
|
||||
}
|
||||
21
Nuake/src/Subsystems/EngineSubsystem.h
Normal file
21
Nuake/src/Subsystems/EngineSubsystem.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#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:
|
||||
void SetCanTick(bool canTick);
|
||||
bool CanEverTick() const;
|
||||
|
||||
virtual void Initialize() {}
|
||||
virtual void Tick(float deltaTime) {}
|
||||
|
||||
private:
|
||||
bool canEverTick = false;
|
||||
};
|
||||
}
|
||||
35
Nuake/src/Subsystems/EngineSubsystemScriptable.cpp
Normal file
35
Nuake/src/Subsystems/EngineSubsystemScriptable.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "EngineSubsystemScriptable.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
|
||||
EngineSubsystemScriptable::EngineSubsystemScriptable(const Coral::ManagedObject& object)
|
||||
: cSharpObjectInstance(object)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Coral::ManagedObject& EngineSubsystemScriptable::GetManagedObjectInstance()
|
||||
{
|
||||
return cSharpObjectInstance;
|
||||
}
|
||||
|
||||
void EngineSubsystemScriptable::Initialize()
|
||||
{
|
||||
if (!cSharpObjectInstance.IsValid())
|
||||
return;
|
||||
|
||||
cSharpObjectInstance.InvokeMethod("Initialize");
|
||||
}
|
||||
|
||||
void EngineSubsystemScriptable::Tick(float deltaTime)
|
||||
{
|
||||
if (!cSharpObjectInstance.IsValid())
|
||||
return;
|
||||
|
||||
cSharpObjectInstance.InvokeMethod("OnTick", deltaTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
25
Nuake/src/Subsystems/EngineSubsystemScriptable.h
Normal file
25
Nuake/src/Subsystems/EngineSubsystemScriptable.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "EngineSubsystem.h"
|
||||
|
||||
#include <Coral/ManagedObject.hpp>
|
||||
|
||||
/**
|
||||
* Essentially just a wrapper for C# subsystems
|
||||
*/
|
||||
namespace Nuake
|
||||
{
|
||||
class EngineSubsystemScriptable : public EngineSubsystem
|
||||
{
|
||||
public:
|
||||
EngineSubsystemScriptable(const Coral::ManagedObject& object);
|
||||
|
||||
Coral::ManagedObject& GetManagedObjectInstance();
|
||||
|
||||
virtual void Initialize() override;
|
||||
virtual void Tick(float deltaTime) override;
|
||||
|
||||
private:
|
||||
Coral::ManagedObject cSharpObjectInstance;
|
||||
};
|
||||
}
|
||||
1
Nuake/src/Subsystems/SceneSubsystem.cpp
Normal file
1
Nuake/src/Subsystems/SceneSubsystem.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "SceneSubsystem.h"
|
||||
9
Nuake/src/Subsystems/SceneSubsystem.h
Normal file
9
Nuake/src/Subsystems/SceneSubsystem.h
Normal 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:
|
||||
|
||||
};
|
||||
25
NuakeNet/src/EngineSubsystem.cs
Normal file
25
NuakeNet/src/EngineSubsystem.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace Nuake.Net
|
||||
{
|
||||
public class EngineSubsystem
|
||||
{
|
||||
internal static unsafe delegate*<int, bool, void> SetCanTickIcall;
|
||||
internal static unsafe delegate*<int, bool> GetCanTickIcall;
|
||||
|
||||
public int EngineSubsystemID { get; protected set; }
|
||||
|
||||
public bool CanTick
|
||||
{
|
||||
set
|
||||
{
|
||||
unsafe { SetCanTickIcall(EngineSubsystemID, value); }
|
||||
}
|
||||
get
|
||||
{
|
||||
unsafe { return GetCanTickIcall(EngineSubsystemID); }
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Initialize() {}
|
||||
public virtual void OnTick(float deltaTime) {}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
|
||||
Reference in New Issue
Block a user