Files
Nuake/Nuake/src/Scene/Systems/ScriptingSystem.cpp
antopilo 0e750bda89 work
2024-09-21 14:02:20 -04:00

243 lines
7.0 KiB
C++

#include "ScriptingSystem.h"
#include "src/Scene/Components/NetScriptComponent.h"
#include "src/Scene/Scene.h"
#include "Engine.h"
#include "src/Scripting/ScriptingEngineNet.h"
#include "src/Physics/PhysicsManager.h"
#include <src/UI/Parsers/CanvasParser.h>
namespace Nuake
{
ScriptingSystem::ScriptingSystem(Scene* scene)
{
m_Scene = scene;
}
bool ScriptingSystem::Init()
{
Logger::Log("Initializing ScriptingSystem");
preInitDelegate.Broadcast();
auto& scriptingEngineNet = ScriptingEngineNet::Get();
scriptingEngineNet.Uninitialize();
scriptingEngineNet.Initialize();
scriptingEngineNet.LoadProjectAssembly(Engine::GetProject());
auto netEntities = m_Scene->m_Registry.view<NetScriptComponent>();
for (auto& e : netEntities)
{
NetScriptComponent& netScriptComponent = netEntities.get<NetScriptComponent>(e);
if (netScriptComponent.ScriptPath.empty())
continue;
auto entity = Entity{ e, m_Scene };
// Creates an instance of the entity script in C#
scriptingEngineNet.RegisterEntityScript(entity);
netScriptComponent.Initialized = true;
}
// Instantiate UI widgets
for (auto& uiWidget : CanvasParser::Get().GetAllCustomWidgetInstance())
{
scriptingEngineNet.RegisterCustomWidgetInstance(uiWidget.first.first, uiWidget.first.second, uiWidget.second);
}
// Call OnInit on entity script instances
for (auto& e : netEntities)
{
auto entity = Entity{ e, m_Scene };
if (entity.IsValid() && scriptingEngineNet.HasEntityScriptInstance(entity))
{
// We can now call on init on it.
auto scriptInstance = scriptingEngineNet.GetEntityScript(entity);
scriptInstance.InvokeMethod("OnInit");
}
}
// Call OnInit on UI widgets
for (auto& widget : CanvasParser::Get().GetAllCustomWidgetInstance())
{
const UUID& canvasInstanceUUID = widget.first.first;
const UUID& widgetInstanceUUID = widget.first.second;
if (scriptingEngineNet.HasCustomWidgetInstance(canvasInstanceUUID, widgetInstanceUUID))
{
auto widgetInstance = scriptingEngineNet.GetCustomWidgetInstance(canvasInstanceUUID, widgetInstanceUUID);
widgetInstance.InvokeMethod("OnInit");
}
}
postInitDelegate.Broadcast();
return true;
}
void ScriptingSystem::Update(Timestep ts)
{
if (!Engine::IsPlayMode())
return;
auto& scriptingEngineNet = ScriptingEngineNet::Get();
auto netEntities = m_Scene->m_Registry.view<NetScriptComponent>();
// Instance all the new entities
std::vector<Entity> entityJustInstanced;
for (auto& e : netEntities)
{
auto& netScriptComponent = netEntities.get<NetScriptComponent>(e);
if (!netScriptComponent.Initialized)
{
if (netScriptComponent.ScriptPath.empty())
continue;
auto entity = Entity{ e, m_Scene };
// Creates an instance of the entity script in C#
scriptingEngineNet.RegisterEntityScript(entity);
netScriptComponent.Initialized = true;
entityJustInstanced.push_back(entity);
}
}
// Call init on the newly created instance
for (auto& e : entityJustInstanced)
{
auto& netScriptComponent = e.GetComponent<NetScriptComponent>();
if (e.IsValid() && scriptingEngineNet.HasEntityScriptInstance(e))
{
// We can now call on init on it.
auto scriptInstance = scriptingEngineNet.GetEntityScript(e);
scriptInstance.InvokeMethod("OnInit");
}
}
// Then call update on all the other scripts
for (auto& e : netEntities)
{
NetScriptComponent& netScriptComponent = netEntities.get<NetScriptComponent>(e);
if (netScriptComponent.ScriptPath.empty())
continue;
auto entity = Entity{ e, m_Scene };
auto scriptInstance = scriptingEngineNet.GetEntityScript(entity);
scriptInstance.InvokeMethod("OnUpdate", ts.GetSeconds());
}
for (auto& widget : CanvasParser::Get().GetAllCustomWidgetInstance())
{
const UUID& canvasInstanceUUID = widget.first.first;
const UUID& widgetInstanceUUID = widget.first.second;
if (scriptingEngineNet.HasCustomWidgetInstance(canvasInstanceUUID, widgetInstanceUUID))
{
auto widgetInstance = scriptingEngineNet.GetCustomWidgetInstance(canvasInstanceUUID, widgetInstanceUUID);
widgetInstance.InvokeMethod("OnTick", ts.GetSeconds());
}
}
DispatchPhysicCallbacks();
}
void ScriptingSystem::FixedUpdate(Timestep ts)
{
if (!Engine::IsPlayMode())
return;
auto& scriptingEngineNet = ScriptingEngineNet::Get();
auto netEntities = m_Scene->m_Registry.view<NetScriptComponent>();
for (auto& e : netEntities)
{
NetScriptComponent& netScriptComponent = netEntities.get<NetScriptComponent>(e);
if (netScriptComponent.ScriptPath.empty())
continue;
auto entity = Entity{ e, m_Scene };
auto scriptInstance = scriptingEngineNet.GetEntityScript(entity);
scriptInstance.InvokeMethod("OnFixedUpdate", ts.GetSeconds());
}
}
void ScriptingSystem::Exit()
{
auto& scriptingEngineNet = ScriptingEngineNet::Get();
auto netEntities = m_Scene->m_Registry.view<NetScriptComponent>();
for (auto& e : netEntities)
{
NetScriptComponent& netScriptComponent = netEntities.get<NetScriptComponent>(e);
if (netScriptComponent.ScriptPath.empty())
continue;
auto entity = Entity{ e, m_Scene };
if (entity.IsValid() && scriptingEngineNet.HasEntityScriptInstance(entity))
{
Logger::Log(entity.GetComponent<NameComponent>().Name);
auto scriptInstance = scriptingEngineNet.GetEntityScript(entity);
scriptInstance.InvokeMethod("OnDestroy");
}
}
ScriptingEngineNet::Get().Uninitialize();
}
void ScriptingSystem::InitializeNewScripts()
{
auto& scriptingEngineNet = ScriptingEngineNet::Get();
auto netEntities = m_Scene->m_Registry.view<NetScriptComponent>();
// Instance all the new entities
std::vector<Entity> entityJustInstanced;
for (auto& e : netEntities)
{
auto& netScriptComponent = netEntities.get<NetScriptComponent>(e);
if (!netScriptComponent.Initialized)
{
if (netScriptComponent.ScriptPath.empty())
continue;
auto entity = Entity{ e, m_Scene };
// Creates an instance of the entity script in C#
scriptingEngineNet.RegisterEntityScript(entity);
netScriptComponent.Initialized = true;
entityJustInstanced.push_back(entity);
}
}
}
void ScriptingSystem::DispatchPhysicCallbacks()
{
auto& scriptingEngineNet = ScriptingEngineNet::Get();
auto& physicsManager = PhysicsManager::Get();
const auto collisions = physicsManager.GetCollisions();
for (const auto& col : collisions)
{
// Calling both collidee(?)
Entity entity1 = { (entt::entity)col.Entity1, m_Scene };
if (entity1.IsValid() && scriptingEngineNet.HasEntityScriptInstance(entity1))
{
auto scriptInstance = scriptingEngineNet.GetEntityScript(entity1);
scriptInstance.InvokeMethod("OnCollisionInternal", (int)col.Entity2);
}
Entity entity2 = { (entt::entity)col.Entity2, m_Scene };
if (entity2.IsValid() && scriptingEngineNet.HasEntityScriptInstance(entity2))
{
auto scriptInstance = scriptingEngineNet.GetEntityScript(entity2);
scriptInstance.InvokeMethod("OnCollisionInternal", (int)col.Entity1);
}
}
physicsManager.GetWorld()->ClearCollisionData();
}
}