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