diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 184b9611..3577475d 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -1,5 +1,6 @@ #include "SBpch.h" #include "SBApplication.h" +#include "ECS_Base/UnitTesting/SHECSUnitTest.h" #ifdef SHEDITOR #include "Editor/SHEditor.h" @@ -23,11 +24,13 @@ namespace Sandbox { window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); - + #ifdef SHEDITOR #else #endif + + } void SBApplication::Update(void) diff --git a/SHADE_Engine/SHADE_Engine.vcxproj b/SHADE_Engine/SHADE_Engine.vcxproj index d84f3c05..2b2541bb 100644 --- a/SHADE_Engine/SHADE_Engine.vcxproj +++ b/SHADE_Engine/SHADE_Engine.vcxproj @@ -118,6 +118,9 @@ + + + @@ -204,6 +207,7 @@ + diff --git a/SHADE_Engine/SHADE_Engine.vcxproj.filters b/SHADE_Engine/SHADE_Engine.vcxproj.filters index 8fc412c5..4f80a4f8 100644 --- a/SHADE_Engine/SHADE_Engine.vcxproj.filters +++ b/SHADE_Engine/SHADE_Engine.vcxproj.filters @@ -388,6 +388,9 @@ + + + @@ -591,5 +594,6 @@ + \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.cpp b/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.cpp index acf7cba3..551233db 100644 --- a/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.cpp +++ b/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.cpp @@ -34,7 +34,7 @@ namespace SHADE } } - void SHSystemManager::RunRoutines(bool editorPause) noexcept + void SHSystemManager::RunRoutines(bool editorPause, double deltaTime) noexcept { for (auto& routine : systemRoutineContainer) { @@ -43,7 +43,7 @@ namespace SHADE if (routine.get()->IsRunInEditorPause) { std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); - routine.get()->Execute(0.0); + routine.get()->Execute(deltaTime); std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); routine.get()->stats.executionTime = std::chrono::duration(end - start).count(); } @@ -51,7 +51,7 @@ namespace SHADE else { std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); - routine.get()->Execute(0.0); + routine.get()->Execute(deltaTime); std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); routine.get()->stats.executionTime = std::chrono::duration(end - start).count(); } @@ -61,6 +61,8 @@ namespace SHADE void SHSystemManager::Exit() noexcept { + systemRoutineContainer.clear(); + for (SystemContainer::reverse_iterator it = systemContainer.rbegin(); it != systemContainer.rend(); ++it) { (*it).second->Exit(); diff --git a/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.h b/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.h index 616a8db3..f97d98a2 100644 --- a/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.h +++ b/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.h @@ -55,7 +55,7 @@ namespace SHADE * none ***************************************************************************/ template - static std::enable_if_t, void> CreateSystem() + static std::enable_if_t, SystemID> CreateSystem() { SystemTypeID typeID = SystemFamily::GetID(); @@ -64,10 +64,12 @@ namespace SHADE while (systemContainer.find(id) != systemContainer.end()) { ++version; - SystemID id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID; + id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID; } systemContainer.emplace(id, std::make_unique()); + systemContainer[id].get()->systemID = id; + return id; } @@ -103,7 +105,7 @@ namespace SHADE ***************************************************************************/ static void Init() noexcept; - static void RunRoutines(bool editorPause) noexcept; + static void RunRoutines(bool editorPause, double deltaTime) noexcept; template static void RegisterRoutine(SystemVersionID version = 0) noexcept @@ -112,6 +114,7 @@ namespace SHADE if (system == nullptr) return; systemRoutineContainer.emplace_back(std::make_unique()); + systemRoutineContainer.back().get()->system = system; } diff --git a/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.cpp b/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.cpp index 2c97bfb4..fa34a5cf 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.cpp +++ b/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.cpp @@ -1,10 +1,11 @@ +#include "SHpch.h" #include "SHFixedSystemRoutine.h" #include "../SHECSMacros.h" namespace SHADE { - void SHFixedSystemRoutine::Execute(double dt) + void SHFixedSystemRoutine::Execute(double dt) noexcept { accumulatedTime += dt; int counter = 0; diff --git a/SHADE_Engine/src/ECS_Base/System/SHRoutineStats.h b/SHADE_Engine/src/ECS_Base/System/SHRoutineStats.h index e294264a..513358ee 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHRoutineStats.h +++ b/SHADE_Engine/src/ECS_Base/System/SHRoutineStats.h @@ -15,13 +15,14 @@ namespace SHADE double executionTime; int numSteps{1}; - friend std::ostream& operator<<(std::ostream& os, const SHRoutineStats& stats); + //friend std::ostream& operator<<(std::ostream& os, const SHRoutineStats& stats); }; - std::ostream& operator<<(std::ostream& os, const SHRoutineStats& stats) - { - os << stats.name << ": Execution Time: " << stats.executionTime << " Number of steps: " << stats.numSteps << std::endl; - } + //std::ostream& operator<<(std::ostream& os, const SHRoutineStats& stats) + //{ + // os << stats.name << ": Execution Time: " << stats.executionTime << " Number of steps: " << stats.numSteps << std::endl; + // return os; + //} } \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystem.h b/SHADE_Engine/src/ECS_Base/System/SHSystem.h index a2964a91..19b16f72 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHSystem.h +++ b/SHADE_Engine/src/ECS_Base/System/SHSystem.h @@ -10,6 +10,8 @@ #pragma once +#include "../SHECSMacros.h" + namespace SHADE { @@ -17,12 +19,18 @@ namespace SHADE class SHSystem { + private: + SystemID systemID; + protected: /*!************************************************************************* * \brief * Protected default constructor for SHSytem class ***************************************************************************/ SHSystem()= default; + + + public: /*!************************************************************************* @@ -51,37 +59,14 @@ namespace SHADE ***************************************************************************/ virtual void Exit() = 0; + friend class SHSystemManager; + + inline SystemID GetSystemID(void) const noexcept { return systemID; } + inline SystemVersionID GetSystemVersion(void) const noexcept { return static_cast(systemID >> sizeof(SystemVersionID) * CHAR_BIT); } - protected: - }; - - - class SHTestSystem : public SHSystem - { - public: - - SHTestSystem() = default; - ~SHTestSystem() = default; - - int value{5}; - - void Init() - { - - } - - - - void Exit() - { - - } - }; - - } \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.cpp b/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.cpp index 83107c60..73157e8b 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.cpp +++ b/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.cpp @@ -1,5 +1,7 @@ +#include "SHpch.h" #include "SHSystemRoutine.h" + namespace SHADE { diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp new file mode 100644 index 00000000..c9d8477b --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp @@ -0,0 +1,181 @@ +#include "SHpch.h" +#include "SHECSUnitTest.h" +#include "../Managers/SHComponentManager.h" +#include "../Managers/SHEntityManager.h" +#include "../Managers/SHSystemManager.h" +#include "SHTestComponents.h" +#include "SHTestSystems.h" +#include "Tools/SHLogger.h" + + + +namespace SHADE +{ + void SHECSUnitTest::TestAll(void) noexcept + { + TestBasicEntityCreate(); + TestEntityCreateTemplate(); + TestEntityDestroy(); + TestSystemRoutine(); + } + + + void SHECSUnitTest::TestBasicEntityCreate(void) noexcept + { + + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + + SHLOG_INFO("Test for add and remove component") + + EntityID id1 = SHEntityManager::CreateEntity(); + EntityID id2 = SHEntityManager::CreateEntity(); + EntityID id3 = SHEntityManager::CreateEntity(); + + + SHComponentManager::AddComponent(id1); + } + + + void SHECSUnitTest::TestEntityCreateTemplate(void) noexcept + { + std::cout << "\nTest2" << std::endl; + //Test entity Creation. + + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + + + + for (size_t i = 0; i < 10000; ++i) + { + switch (i % 3) + { + case 0: + { + SHEntityManager::CreateEntity(); + }break; + case 1: + { + SHEntityManager::CreateEntity(); + }break; + + case 2: + { + SHEntityManager::CreateEntity(); + }break; + default: + break; + } + + + } + + + auto& denseA = SHComponentManager::GetDense(); + auto& denseB = SHComponentManager::GetDense(); + auto& denseC = SHComponentManager::GetDense(); + + std::cout << "Test Entity Creation" << std::endl; + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 10000) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 3334) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 3333) ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 10000 ? " Success" : " Failure") << std::endl; + + SHEntityManager::DestroyAllEntity(); + std::cout << std::endl << "Test Destroy All Entity" << std::endl; + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 0 ? " Success" : " Failure") << std::endl; + + + } + + + void SHECSUnitTest::TestEntityDestroy(void) noexcept + { + std::cout << "\nTest3" << std::endl; + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + + + + for (size_t i = 0; i < 10000; ++i) + { + switch (i % 3) + { + case 0: + { + SHEntityManager::CreateEntity(); + }break; + case 1: + { + SHEntityManager::CreateEntity(); + }break; + + case 2: + { + SHEntityManager::CreateEntity(); + }break; + default: + break; + } + + + } + + SHEntityManager::DestroyEntity(5000); + SHEntityManager::DestroyEntity(5001); + + + + + auto& denseA = SHComponentManager::GetDense(); + auto& denseB = SHComponentManager::GetDense(); + auto& denseC = SHComponentManager::GetDense(); + + + std::cout << "Test Entity Deletion" << std::endl; + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 9998) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 3333) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 3333) ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 9998 ? " Success" : " Failure") << std::endl; + + + std::cout << std::endl << "Test Entity Recreation" << std::endl; + EntityID id = SHEntityManager::CreateEntity(); + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 9998) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 3333) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 3334) ? " Success" : " Failure") << std::endl; + std::cout << "Entity ID: " << id << " EntityIndex: " << EntityHandleGenerator::GetIndex(id) << (EntityHandleGenerator::GetIndex(id) == 5001 ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 9999 ? " Success" : " Failure") << std::endl; + + + SHEntityManager::DestroyAllEntity(); + std::cout << std::endl << "Check Destroy All Entity" << std::endl; + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 0 ? " Success" : " Failure") << std::endl; + + } + + void SHECSUnitTest::TestSystemRoutine(void) noexcept + { + SHSystemManager::CreateSystem(); + SHSystemManager::CreateSystem(); + + + SHSystemManager::RegisterRoutine(1); + + SHSystemManager::RunRoutines(false, 1.0 / 120.0); + + SHSystemManager::Exit(); + } + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.h b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.h new file mode 100644 index 00000000..938ba865 --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.h @@ -0,0 +1,22 @@ +#pragma once + +namespace SHADE +{ + class SHECSUnitTest + { + public: + SHECSUnitTest() = delete; + ~SHECSUnitTest() = delete; + + static void TestBasicEntityCreate(void) noexcept; + static void TestEntityCreateTemplate(void) noexcept; + static void TestEntityDestroy(void) noexcept; + static void TestSystemRoutine(void) noexcept; + + static void TestAll(void) noexcept; + + + + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestComponents.h b/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestComponents.h new file mode 100644 index 00000000..e2e53d6b --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestComponents.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../Components/SHComponent.h" + +namespace SHADE +{ + + class SHComponent_A :public SHComponent + { + public: + int value{}; + + }; + + + class SHComponent_B :public SHComponent + { + public: + float x{}; + float y{}; + float z{}; + }; + + class SHComponent_C :public SHComponent + { + public: + std::string value{}; + }; + +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestSystems.h b/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestSystems.h new file mode 100644 index 00000000..7231b323 --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestSystems.h @@ -0,0 +1,40 @@ +#pragma once + + +#include +#include "../System/SHSystem.h" +#include "../System/SHSystemRoutine.h" + +namespace SHADE +{ + + class SHTestSystem : public SHSystem + { + public: + SHTestSystem() {}; + ~SHTestSystem() {}; + + + + std::string test{ "Test system" }; + + void Init() {}; + void Exit() {}; + + class SHTestRoutine : public SHSystemRoutine + { + public: + SHTestRoutine() + :SHSystemRoutine("Test System Routine", false) {} + + + virtual void Execute(double dt) noexcept + { + + std::cout << GetName() << " System Version: " << GetSystem()->GetSystemVersion() << std::endl; + } + }; + + + }; +} \ No newline at end of file