From 000062b462a3af86db4dac4d8c9e5ef32feb2996 Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Wed, 11 Dec 2024 21:19:57 +0100
Subject: split up loopmanager into SystemManager and Engine

---
 src/crepe/api/CMakeLists.txt        |   5 +-
 src/crepe/api/Engine.cpp            |  37 ++++++++++++
 src/crepe/api/Engine.h              |  73 ++++++++++++++++++++++++
 src/crepe/api/Engine.hpp            |  12 ++++
 src/crepe/api/LoopManager.cpp       |  75 -------------------------
 src/crepe/api/LoopManager.h         | 109 ------------------------------------
 src/crepe/api/LoopManager.hpp       |  46 ---------------
 src/crepe/api/LoopTimer.h           |   2 +-
 src/crepe/manager/CMakeLists.txt    |   3 +
 src/crepe/manager/Mediator.h        |   4 +-
 src/crepe/manager/SystemManager.cpp |  45 +++++++++++++++
 src/crepe/manager/SystemManager.h   |  55 ++++++++++++++++++
 src/crepe/manager/SystemManager.hpp |  40 +++++++++++++
 src/crepe/system/ReplaySystem.cpp   |  11 ++--
 14 files changed, 277 insertions(+), 240 deletions(-)
 create mode 100644 src/crepe/api/Engine.cpp
 create mode 100644 src/crepe/api/Engine.h
 create mode 100644 src/crepe/api/Engine.hpp
 delete mode 100644 src/crepe/api/LoopManager.cpp
 delete mode 100644 src/crepe/api/LoopManager.h
 delete mode 100644 src/crepe/api/LoopManager.hpp
 create mode 100644 src/crepe/manager/SystemManager.cpp
 create mode 100644 src/crepe/manager/SystemManager.h
 create mode 100644 src/crepe/manager/SystemManager.hpp

(limited to 'src/crepe')

diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt
index 46deb67..6e062f9 100644
--- a/src/crepe/api/CMakeLists.txt
+++ b/src/crepe/api/CMakeLists.txt
@@ -15,7 +15,7 @@ target_sources(crepe PUBLIC
 	CircleCollider.cpp
 	IKeyListener.cpp
 	IMouseListener.cpp
-	LoopManager.cpp
+	Engine.cpp
 	LoopTimer.cpp
 	Asset.cpp
 	EventHandler.cpp
@@ -49,7 +49,8 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
 	Event.h
 	IKeyListener.h
 	IMouseListener.h
-	LoopManager.h
+	Engine.h
+	Engine.hpp
 	LoopTimer.h
 	Asset.h
 	Button.h
diff --git a/src/crepe/api/Engine.cpp b/src/crepe/api/Engine.cpp
new file mode 100644
index 0000000..8ed55fa
--- /dev/null
+++ b/src/crepe/api/Engine.cpp
@@ -0,0 +1,37 @@
+#include "Engine.h"
+
+using namespace crepe;
+using namespace std;
+
+void Engine::start() {
+	this->setup();
+	this->loop();
+}
+
+void Engine::setup() {
+	LoopTimer & timer = this->loop_timer;
+	this->game_running = true;
+	this->scene_manager.load_next_scene();
+	timer.start();
+	timer.set_fps(200);
+}
+
+void Engine::loop() {
+	LoopTimer & timer = this->loop_timer;
+	SystemManager & systems = this->system_manager;
+
+	timer.start();
+
+	while (game_running) {
+		timer.update();
+
+		while (timer.get_lag() >= timer.get_fixed_delta_time()) {
+			systems.fixed_update();
+			timer.advance_fixed_update();
+		}
+
+		systems.frame_update();
+		timer.enforce_frame_rate();
+	}
+}
+
diff --git a/src/crepe/api/Engine.h b/src/crepe/api/Engine.h
new file mode 100644
index 0000000..7601015
--- /dev/null
+++ b/src/crepe/api/Engine.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "../facade/SDLContext.h"
+#include "../manager/ComponentManager.h"
+#include "../manager/ReplayManager.h"
+#include "../manager/ResourceManager.h"
+#include "../manager/ResourceManager.h"
+#include "../manager/SaveManager.h"
+#include "../manager/SceneManager.h"
+#include "../manager/SystemManager.h"
+
+#include "LoopTimer.h"
+
+namespace crepe {
+
+/**
+ * \brief Main game entrypoint
+ *
+ * This class is responsible for managing the game loop, including initialization and updating.
+ */
+class Engine {
+public:
+	void start();
+
+	/**
+	 * \brief Add a new concrete scene to the scene manager
+	 *
+	 * \tparam T  Type of concrete scene
+	 */
+	template <typename T>
+	void add_scene();
+
+private:
+	/**
+	 * \brief Setup function for one-time initialization.
+	 *
+	 * This function initializes necessary components for the game.
+	 */
+	void setup();
+	/**
+	 * \brief Main game loop function.
+	 *
+	 * This function runs the main loop, handling game updates and rendering.
+	 */
+	void loop();
+
+	bool game_running = false;
+
+private:
+	//! Global context
+	Mediator mediator;
+
+	//! Component manager instance
+	ComponentManager component_manager{mediator};
+	//! Scene manager instance
+	SceneManager scene_manager{mediator};
+	//! Resource manager instance
+	ResourceManager resource_manager{mediator};
+	//! Save manager instance
+	SaveManager save_manager{mediator};
+	//! SDLContext instance
+	SDLContext sdl_context{mediator};
+	//! LoopTimer instance
+	LoopTimer loop_timer{mediator};
+	//! ReplayManager instance
+	ReplayManager replay_manager{mediator};
+	//! SystemManager
+	SystemManager system_manager{mediator};
+};
+
+} // namespace crepe
+
+#include "Engine.hpp"
diff --git a/src/crepe/api/Engine.hpp b/src/crepe/api/Engine.hpp
new file mode 100644
index 0000000..f2fdc0a
--- /dev/null
+++ b/src/crepe/api/Engine.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "Engine.h"
+
+namespace crepe {
+
+template <class T>
+void Engine::add_scene() {
+	this->scene_manager.add_scene<T>();
+}
+
+} // namespace crepe
diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp
deleted file mode 100644
index 2855455..0000000
--- a/src/crepe/api/LoopManager.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "../system/AISystem.h"
-#include "../system/AnimatorSystem.h"
-#include "../system/AudioSystem.h"
-#include "../system/CollisionSystem.h"
-#include "../system/InputSystem.h"
-#include "../system/ParticleSystem.h"
-#include "../system/PhysicsSystem.h"
-#include "../system/RenderSystem.h"
-#include "../system/ScriptSystem.h"
-#include "../system/EventSystem.h"
-
-#include "LoopManager.h"
-
-using namespace crepe;
-using namespace std;
-
-LoopManager::LoopManager() {
-	this->load_system<ScriptSystem>();
-	this->load_system<AISystem>();
-	this->load_system<PhysicsSystem>();
-	this->load_system<CollisionSystem>();
-	this->load_system<AnimatorSystem>();
-	this->load_system<ParticleSystem>();
-	this->load_system<RenderSystem>();
-	this->load_system<InputSystem>();
-	this->load_system<EventSystem>();
-	this->load_system<AudioSystem>();
-
-	this->mediator.loop_manager = *this;
-}
-
-void LoopManager::start() {
-	this->setup();
-	this->loop();
-}
-
-void LoopManager::fixed_update() {
-	for (auto & [type, system] : this->systems) {
-		if (!system->active) continue;
-		system->fixed_update();
-	}
-}
-
-void LoopManager::frame_update() {
-	for (auto & [type, system] : this->systems) {
-		if (!system->active) continue;
-		system->frame_update();
-	}
-}
-
-void LoopManager::setup() {
-	LoopTimer & timer = this->loop_timer;
-	this->game_running = true;
-	this->scene_manager.load_next_scene();
-	timer.start();
-	timer.set_fps(200);
-}
-
-void LoopManager::loop() {
-	LoopTimer & timer = this->loop_timer;
-	timer.start();
-
-	while (game_running) {
-		timer.update();
-
-		while (timer.get_lag() >= timer.get_fixed_delta_time()) {
-			this->fixed_update();
-			timer.advance_fixed_update();
-		}
-
-		this->frame_update();
-		timer.enforce_frame_rate();
-	}
-}
-
diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h
deleted file mode 100644
index f34a5a0..0000000
--- a/src/crepe/api/LoopManager.h
+++ /dev/null
@@ -1,109 +0,0 @@
-#pragma once
-
-#include "../facade/SDLContext.h"
-#include "../manager/ComponentManager.h"
-#include "../manager/ReplayManager.h"
-#include "../manager/ResourceManager.h"
-#include "../manager/ResourceManager.h"
-#include "../manager/SaveManager.h"
-#include "../manager/SceneManager.h"
-#include "../system/System.h"
-
-#include "LoopTimer.h"
-
-namespace crepe {
-
-/**
- * \brief Main game loop manager
- *
- * This class is responsible for managing the game loop, including initialization and updating.
- */
-class LoopManager {
-public:
-	void start();
-	LoopManager();
-
-	/**
-	 * \brief Add a new concrete scene to the scene manager
-	 *
-	 * \tparam T  Type of concrete scene
-	 */
-	template <typename T>
-	void add_scene();
-
-private:
-	/**
-	 * \brief Setup function for one-time initialization.
-	 *
-	 * This function initializes necessary components for the game.
-	 */
-	void setup();
-	/**
-	 * \brief Main game loop function.
-	 *
-	 * This function runs the main loop, handling game updates and rendering.
-	 */
-	void loop();
-
-	/**
-	 * \brief Per-frame update.
-	 *
-	 * Updates the game state based on the elapsed time since the last frame.
-	 */
-	void frame_update();
-
-	/**
-	 * \brief Fixed update executed at a fixed rate.
-	 *
-	 * This function updates physics and game logic based on LoopTimer's fixed_delta_time.
-	 */
-	void fixed_update();
-
-	bool game_running = false;
-
-private:
-	//! Global context
-	Mediator mediator;
-
-	//! Component manager instance
-	ComponentManager component_manager{mediator};
-	//! Scene manager instance
-	SceneManager scene_manager{mediator};
-	//! Resource manager instance
-	ResourceManager resource_manager{mediator};
-	//! Save manager instance
-	SaveManager save_manager{mediator};
-	//! SDLContext instance
-	SDLContext sdl_context{mediator};
-	//! LoopTimer instance
-	LoopTimer loop_timer{mediator};
-	//! ReplayManager instance
-	ReplayManager replay_manager{mediator};
-
-private:
-	/**
-	 * \brief Collection of System instances
-	 *
-	 * This map holds System instances indexed by the system's class typeid. It is filled in the
-	 * constructor of \c LoopManager using LoopManager::load_system.
-	 */
-	std::unordered_map<std::type_index, std::unique_ptr<System>> systems;
-	/**
-	 * \brief Initialize a system
-	 * \tparam T System type (must be derivative of \c System)
-	 */
-	template <class T>
-	void load_system();
-	/**
-	 * \brief Retrieve a reference to ECS system
-	 * \tparam T System type
-	 * \returns Reference to system instance
-	 * \throws std::runtime_error if the System is not initialized
-	 */
-	template <class T>
-	T & get_system();
-};
-
-} // namespace crepe
-
-#include "LoopManager.hpp"
diff --git a/src/crepe/api/LoopManager.hpp b/src/crepe/api/LoopManager.hpp
deleted file mode 100644
index 627b281..0000000
--- a/src/crepe/api/LoopManager.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-
-#include <memory>
-#include <cassert>
-#include <format>
-
-#include "../system/System.h"
-#include "LoopManager.h"
-
-namespace crepe {
-
-template <class T>
-void LoopManager::add_scene() {
-	this->scene_manager.add_scene<T>();
-}
-
-template <class T>
-T & LoopManager::get_system() {
-	using namespace std;
-	static_assert(is_base_of<System, T>::value, "get_system must recieve a derivative class of System");
-
-	const type_info & type = typeid(T);
-	if (!this->systems.contains(type))
-		throw runtime_error(format("LoopManager: {} is not initialized", type.name()));
-
-	System * system = this->systems.at(type).get();
-	T * concrete_system = dynamic_cast<T *>(system);
-	assert(concrete_system != nullptr);
-
-	return *concrete_system;
-}
-
-template <class T>
-void LoopManager::load_system() {
-	using namespace std;
-	static_assert(is_base_of<System, T>::value,
-			"load_system must recieve a derivative class of System");
-
-	const type_info & type = typeid(T);
-	if (this->systems.contains(type))
-		throw runtime_error(format("LoopManager: {} is already initialized", type.name()));
-	System * system = new T(this->mediator);
-	this->systems[type] = unique_ptr<System>(system);
-}
-
-} // namespace crepe
diff --git a/src/crepe/api/LoopTimer.h b/src/crepe/api/LoopTimer.h
index 0a73a4c..fb52a10 100644
--- a/src/crepe/api/LoopTimer.h
+++ b/src/crepe/api/LoopTimer.h
@@ -54,7 +54,7 @@ public:
 	void set_game_scale(double game_scale);
 
 private:
-	friend class LoopManager;
+	friend class Engine;
 
 	/**
 	 * \brief Start the loop timer.
diff --git a/src/crepe/manager/CMakeLists.txt b/src/crepe/manager/CMakeLists.txt
index 459bbfa..aa19f3e 100644
--- a/src/crepe/manager/CMakeLists.txt
+++ b/src/crepe/manager/CMakeLists.txt
@@ -6,6 +6,7 @@ target_sources(crepe PUBLIC
 	SceneManager.cpp
 	ResourceManager.cpp
 	ReplayManager.cpp
+	SystemManager.cpp
 )
 
 target_sources(crepe PUBLIC FILE_SET HEADERS FILES
@@ -21,5 +22,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
 	ResourceManager.h
 	ResourceManager.hpp
 	ReplayManager.h
+	SystemManager.h
+	SystemManager.hpp
 )
 
diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h
index f5864e7..95ca4b5 100644
--- a/src/crepe/manager/Mediator.h
+++ b/src/crepe/manager/Mediator.h
@@ -14,7 +14,7 @@ class ResourceManager;
 class SDLContext;
 class LoopTimer;
 class ReplayManager;
-class LoopManager;
+class SystemManager;
 
 /**
  * Struct to pass references to classes that would otherwise need to be singletons down to
@@ -37,7 +37,7 @@ struct Mediator {
 	OptionalRef<ResourceManager> resource_manager;
 	OptionalRef<LoopTimer> timer;
 	OptionalRef<ReplayManager> replay_manager;
-	OptionalRef<LoopManager> loop_manager;
+	OptionalRef<SystemManager> system_manager;
 };
 
 } // namespace crepe
diff --git a/src/crepe/manager/SystemManager.cpp b/src/crepe/manager/SystemManager.cpp
new file mode 100644
index 0000000..8fd80a7
--- /dev/null
+++ b/src/crepe/manager/SystemManager.cpp
@@ -0,0 +1,45 @@
+#include "../system/AISystem.h"
+#include "../system/AnimatorSystem.h"
+#include "../system/AudioSystem.h"
+#include "../system/CollisionSystem.h"
+#include "../system/InputSystem.h"
+#include "../system/ParticleSystem.h"
+#include "../system/PhysicsSystem.h"
+#include "../system/RenderSystem.h"
+#include "../system/ScriptSystem.h"
+#include "../system/EventSystem.h"
+
+#include "SystemManager.h"
+
+using namespace crepe;
+using namespace std;
+
+SystemManager::SystemManager(Mediator & mediator) : Manager(mediator) {
+	this->load_system<ScriptSystem>();
+	this->load_system<AISystem>();
+	this->load_system<PhysicsSystem>();
+	this->load_system<CollisionSystem>();
+	this->load_system<AnimatorSystem>();
+	this->load_system<ParticleSystem>();
+	this->load_system<RenderSystem>();
+	this->load_system<InputSystem>();
+	this->load_system<EventSystem>();
+	this->load_system<AudioSystem>();
+
+	this->mediator.system_manager = *this;
+}
+
+void SystemManager::fixed_update() {
+	for (auto & [type, system] : this->systems) {
+		if (!system->active) continue;
+		system->fixed_update();
+	}
+}
+
+void SystemManager::frame_update() {
+	for (auto & [type, system] : this->systems) {
+		if (!system->active) continue;
+		system->frame_update();
+	}
+}
+
diff --git a/src/crepe/manager/SystemManager.h b/src/crepe/manager/SystemManager.h
new file mode 100644
index 0000000..5726a5c
--- /dev/null
+++ b/src/crepe/manager/SystemManager.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include "../system/System.h"
+
+#include "Manager.h"
+
+namespace crepe {
+
+class SystemManager : public Manager {
+public:
+	SystemManager(Mediator &);
+
+	/**
+	 * \brief Per-frame update.
+	 *
+	 * Updates the game state based on the elapsed time since the last frame.
+	 */
+	void frame_update();
+
+	/**
+	 * \brief Fixed update executed at a fixed rate.
+	 *
+	 * This function updates physics and game logic based on LoopTimer's fixed_delta_time.
+	 */
+	void fixed_update();
+
+private:
+	/**
+	 * \brief Collection of System instances
+	 *
+	 * This map holds System instances indexed by the system's class typeid. It is filled in the
+	 * constructor of \c SystemManager using SystemManager::load_system.
+	 */
+	std::unordered_map<std::type_index, std::unique_ptr<System>> systems;
+	/**
+	 * \brief Initialize a system
+	 * \tparam T System type (must be derivative of \c System)
+	 */
+	template <class T>
+	void load_system();
+
+public:
+	/**
+	 * \brief Retrieve a reference to ECS system
+	 * \tparam T System type
+	 * \returns Reference to system instance
+	 * \throws std::runtime_error if the System is not initialized
+	 */
+	template <class T>
+	T & get_system();
+};
+
+} // namespace crepe
+
+#include "SystemManager.hpp"
diff --git a/src/crepe/manager/SystemManager.hpp b/src/crepe/manager/SystemManager.hpp
new file mode 100644
index 0000000..46ada5f
--- /dev/null
+++ b/src/crepe/manager/SystemManager.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <memory>
+#include <cassert>
+#include <format>
+
+#include "SystemManager.h"
+
+namespace crepe {
+
+template <class T>
+T & SystemManager::get_system() {
+	using namespace std;
+	static_assert(is_base_of<System, T>::value, "get_system must recieve a derivative class of System");
+
+	const type_info & type = typeid(T);
+	if (!this->systems.contains(type))
+		throw runtime_error(format("SystemManager: {} is not initialized", type.name()));
+
+	System * system = this->systems.at(type).get();
+	T * concrete_system = dynamic_cast<T *>(system);
+	assert(concrete_system != nullptr);
+
+	return *concrete_system;
+}
+
+template <class T>
+void SystemManager::load_system() {
+	using namespace std;
+	static_assert(is_base_of<System, T>::value,
+			"load_system must recieve a derivative class of System");
+
+	const type_info & type = typeid(T);
+	if (this->systems.contains(type))
+		throw runtime_error(format("SystemManager: {} is already initialized", type.name()));
+	System * system = new T(this->mediator);
+	this->systems[type] = unique_ptr<System>(system);
+}
+
+} // namespace crepe
diff --git a/src/crepe/system/ReplaySystem.cpp b/src/crepe/system/ReplaySystem.cpp
index 85595a2..5a90752 100644
--- a/src/crepe/system/ReplaySystem.cpp
+++ b/src/crepe/system/ReplaySystem.cpp
@@ -1,11 +1,10 @@
-#include "system/ScriptSystem.h"
+#include "ScriptSystem.h"
 
 #include "../manager/ReplayManager.h"
+#include "../manager/SystemManager.h"
 
 #include "ReplaySystem.h"
 
-#include "../api/LoopManager.h"
-
 using namespace crepe;
 using namespace std;
 
@@ -58,7 +57,8 @@ void ReplaySystem::update_playing() {
 }
 
 void ReplaySystem::playback_begin() {
-	LoopManager & loop_manager = this->mediator.loop_manager;
+	SystemManager & systems = this->mediator.system_manager;
+	systems.get_system<ScriptSystem>().active = false;
 	// TODO: store system active state
 	// TODO: disable most systems
 	// TODO: store components snapshot
@@ -69,7 +69,8 @@ void ReplaySystem::playback_end() {
 
 	replay.state = ReplayManager::IDLE;
 
-	LoopManager & loop_manager = this->mediator.loop_manager;
+	SystemManager & systems = this->mediator.system_manager;
+	systems.get_system<ScriptSystem>().active = true;
 
 	// TODO: restore system active state snapshot
 	// TODO: restore components snapshot
-- 
cgit v1.2.3