// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Level/Types.h" #include "Engine/Core/Collections/Array.h" /// /// Scene gameplay updating helper subsystem that boosts the level ticking by providing efficient objects cache. /// class SceneTicking { friend Scene; public: /// /// Tick function type. /// class Tick { public: /// /// Signature of the function to call /// typedef void (*Signature)(); typedef void (*SignatureObj)(void*); template static void MethodCaller(void* callee) { (static_cast(callee)->*Method)(); } public: void* Callee; SignatureObj FunctionObj; public: template void Bind(T* callee) { Callee = callee; FunctionObj = &MethodCaller; } /// /// Calls the binded function. /// /// Function result void Call() const { (*FunctionObj)(Callee); } }; class TickData { public: Array Scripts; #if USE_EDITOR Array ScriptsExecuteInEditor; #endif Array Ticks; TickData(int32 capacity) : Scripts(capacity) , Ticks(capacity) { } virtual void TickScripts(const Array& scripts) = 0; void Tick() { TickScripts(Scripts); for (int32 i = 0; i < Ticks.Count(); i++) { Ticks[i].Call(); } } #if USE_EDITOR void TickEditorScripts() { TickScripts(ScriptsExecuteInEditor); } #endif void AddScript(Script* script); void RemoveScript(Script* script); template void AddTick(T* callee) { SceneTicking::Tick tick; tick.Bind(callee); Ticks.Add(tick); } void RemoveTick(void* callee) { for (int32 i = 0; i < Ticks.Count(); i++) { if (Ticks[i].Callee == callee) { Ticks.RemoveAt(i); break; } } } void Clear() { Scripts.Clear(); Ticks.Clear(); #if USE_EDITOR ScriptsExecuteInEditor.Clear(); #endif } }; class FixedUpdateTickData : public TickData { public: FixedUpdateTickData() : TickData(512) { } void TickScripts(const Array& scripts) override; }; class UpdateTickData : public TickData { public: UpdateTickData() : TickData(1024) { } void TickScripts(const Array& scripts) override; }; class LateUpdateTickData : public TickData { public: LateUpdateTickData() : TickData(64) { } void TickScripts(const Array& scripts) override; }; private: Scene* Scene; explicit SceneTicking(::Scene* scene); public: /// /// Adds the script to scene ticking system. /// /// The object. void AddScript(Script* obj); /// /// Removes the script from scene ticking system. /// /// The object. void RemoveScript(Script* obj); /// /// Clears this instance data. /// void Clear(); public: /// /// The fixed update tick function. /// FixedUpdateTickData FixedUpdate; /// /// The update tick function. /// UpdateTickData Update; /// /// The late update tick function. /// LateUpdateTickData LateUpdate; };