From 770496ee9d0e45480c0e0f8951adb8eee247bfe1 Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Tue, 10 Dec 2024 19:50:26 +0100
Subject: big WIP

---
 src/crepe/manager/ReplayManager.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 src/crepe/manager/ReplayManager.cpp

(limited to 'src/crepe/manager/ReplayManager.cpp')

diff --git a/src/crepe/manager/ReplayManager.cpp b/src/crepe/manager/ReplayManager.cpp
new file mode 100644
index 0000000..3643a8e
--- /dev/null
+++ b/src/crepe/manager/ReplayManager.cpp
@@ -0,0 +1,8 @@
+#include "ReplayManager.h"
+#include "manager/Manager.h"
+
+using namespace crepe;
+
+ReplayManager::ReplayManager(Mediator & mediator) : Manager(mediator) {
+}
+
-- 
cgit v1.2.3


From a2b67f879e2073c5b094c9a480bf637c98703001 Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Wed, 11 Dec 2024 18:42:38 +0100
Subject: example working again

---
 src/crepe/api/LoopManager.h         |  5 ++++-
 src/crepe/manager/Mediator.h        |  2 ++
 src/crepe/manager/ReplayManager.cpp | 17 +++++++++++++++++
 src/example/replay.cpp              | 22 +++++++++++++---------
 4 files changed, 36 insertions(+), 10 deletions(-)

(limited to 'src/crepe/manager/ReplayManager.cpp')

diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h
index 28aa423..f34a5a0 100644
--- a/src/crepe/api/LoopManager.h
+++ b/src/crepe/api/LoopManager.h
@@ -2,13 +2,14 @@
 
 #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"
-#include "manager/ResourceManager.h"
 
 namespace crepe {
 
@@ -76,6 +77,8 @@ private:
 	SDLContext sdl_context{mediator};
 	//! LoopTimer instance
 	LoopTimer loop_timer{mediator};
+	//! ReplayManager instance
+	ReplayManager replay_manager{mediator};
 
 private:
 	/**
diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h
index 628154a..eef4432 100644
--- a/src/crepe/manager/Mediator.h
+++ b/src/crepe/manager/Mediator.h
@@ -13,6 +13,7 @@ class SaveManager;
 class ResourceManager;
 class SDLContext;
 class LoopTimer;
+class ReplayManager;
 
 /**
  * Struct to pass references to classes that would otherwise need to be singletons down to
@@ -34,6 +35,7 @@ struct Mediator {
 	OptionalRef<EventManager> event_manager = EventManager::get_instance();
 	OptionalRef<ResourceManager> resource_manager;
 	OptionalRef<LoopTimer> timer;
+	OptionalRef<ReplayManager> replay_manager;
 };
 
 } // namespace crepe
diff --git a/src/crepe/manager/ReplayManager.cpp b/src/crepe/manager/ReplayManager.cpp
index 3643a8e..40d34a4 100644
--- a/src/crepe/manager/ReplayManager.cpp
+++ b/src/crepe/manager/ReplayManager.cpp
@@ -4,5 +4,22 @@
 using namespace crepe;
 
 ReplayManager::ReplayManager(Mediator & mediator) : Manager(mediator) {
+	mediator.replay_manager = *this;
+}
+
+void ReplayManager::record_start() {
+
+}
+
+recording_t ReplayManager::record_end() {
+	return 0;
+}
+
+void ReplayManager::play(recording_t handle) {
+
+}
+
+void ReplayManager::release(recording_t handle) {
+
 }
 
diff --git a/src/example/replay.cpp b/src/example/replay.cpp
index 0c4f9b3..67acbd8 100644
--- a/src/example/replay.cpp
+++ b/src/example/replay.cpp
@@ -33,26 +33,30 @@ class AnimationScript : public Script {
 
 class Timeline : public Script {
 	unsigned i = 0;
-	OptionalRef<ReplayManager> mgr;
+	ReplayManager & mgr;
 	recording_t recording;
+
+public:
+	Timeline(ReplayManager & mgr)
+		: mgr(mgr) {}
+
 	void update() {
-		ReplayManager & mgr = this->mgr;
 		switch (i++) {
 			default: break;
 			case 10:
-							 // mgr.record_start();
+							 mgr.record_start();
 							 Log::logf("start");
 							 break;
 			case 60:
-							 // this->recording = mgr.record_end();
+							 this->recording = mgr.record_end();
 							 Log::logf("stop");
 							 break;
 			case 70:
-							 // mgr.play(this->recording);
+							 mgr.play(this->recording);
 							 Log::logf("play");
 							 break;
 			case 71:
-							 // mgr.release(this->recording);
+							 mgr.release(this->recording);
 							 Log::logf("end");
 							 break;
 			case 72:
@@ -68,8 +72,8 @@ public:
 	using Scene::Scene;
 
 	void load_scene() {
-		Mediator & m = this->mediator;
-		ComponentManager & mgr = m.component_manager;
+		Mediator & mediator = this->mediator;
+		ComponentManager & mgr = mediator.component_manager;
 
 		GameObject cam = mgr.new_object("cam");
 		cam.add_component<Camera>(ivec2{640,480},vec2{3,3}, Camera::Data{
@@ -86,7 +90,7 @@ public:
 		square.add_component<BehaviorScript>().set_script<AnimationScript>();
 
 		GameObject scapegoat = mgr.new_object("");
-		scapegoat.add_component<BehaviorScript>().set_script<Timeline>();
+		scapegoat.add_component<BehaviorScript>().set_script<Timeline>(mediator.replay_manager);
 	}
 
 	string get_name() const { return "scene1"; }
-- 
cgit v1.2.3


From 313da47b72aafa0b40ac2cd2b586d525ed17fbd4 Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Wed, 11 Dec 2024 18:51:58 +0100
Subject: more WIP

---
 src/crepe/manager/ReplayManager.cpp | 17 ++++++++++++++---
 src/example/replay.cpp              |  8 +++-----
 2 files changed, 17 insertions(+), 8 deletions(-)

(limited to 'src/crepe/manager/ReplayManager.cpp')

diff --git a/src/crepe/manager/ReplayManager.cpp b/src/crepe/manager/ReplayManager.cpp
index 40d34a4..82c2275 100644
--- a/src/crepe/manager/ReplayManager.cpp
+++ b/src/crepe/manager/ReplayManager.cpp
@@ -1,25 +1,36 @@
+#include "../util/Log.h"
+
 #include "ReplayManager.h"
-#include "manager/Manager.h"
+#include "Manager.h"
 
 using namespace crepe;
+using namespace std;
 
 ReplayManager::ReplayManager(Mediator & mediator) : Manager(mediator) {
 	mediator.replay_manager = *this;
 }
 
 void ReplayManager::record_start() {
-
+	if (this->recording) this->release(this->current_recording);
+	this->current_recording++;
+	this->recording = true;
 }
 
 recording_t ReplayManager::record_end() {
-	return 0;
+	this->recording = false;
+	return this->current_recording;
 }
 
 void ReplayManager::play(recording_t handle) {
+	if (!this->memory.contains(handle))
+		throw out_of_range(format("ReplayManager: no recording for handle {}", handle));
+	Recording & recording = *this->memory.at(handle);
 
+	dbg_log("TODO: magic");
 }
 
 void ReplayManager::release(recording_t handle) {
+	dbg_log("release");
 
 }
 
diff --git a/src/example/replay.cpp b/src/example/replay.cpp
index 67acbd8..2f9c63e 100644
--- a/src/example/replay.cpp
+++ b/src/example/replay.cpp
@@ -2,6 +2,7 @@
 #include <crepe/api/BoxCollider.h>
 #include <crepe/api/Camera.h>
 #include <crepe/api/Color.h>
+#include <crepe/api/Config.h>
 #include <crepe/api/Event.h>
 #include <crepe/api/GameObject.h>
 #include <crepe/api/LoopManager.h>
@@ -45,22 +46,17 @@ public:
 			default: break;
 			case 10:
 							 mgr.record_start();
-							 Log::logf("start");
 							 break;
 			case 60:
 							 this->recording = mgr.record_end();
-							 Log::logf("stop");
 							 break;
 			case 70:
 							 mgr.play(this->recording);
-							 Log::logf("play");
 							 break;
 			case 71:
 							 mgr.release(this->recording);
-							 Log::logf("end");
 							 break;
 			case 72:
-							 Log::logf("exit");
 							 throw;
 							 break;
 		};
@@ -97,6 +93,8 @@ public:
 };
 
 int main(int argc, char * argv[]) {
+	Config & cfg = Config::get_instance();
+	cfg.log.level = Log::Level::DEBUG;
 	LoopManager gameloop;
 
 	gameloop.add_scene<TestScene>();
-- 
cgit v1.2.3


From 359ad8db97305856f4cfdade1cd1dada78a7a635 Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Wed, 11 Dec 2024 21:04:30 +0100
Subject: more replay system WIP

---
 src/crepe/Component.cpp                |  9 +++++
 src/crepe/Component.h                  | 13 ++++---
 src/crepe/api/GameObject.cpp           | 10 ++---
 src/crepe/api/GameObject.h             | 13 +++++--
 src/crepe/api/LoopManager.cpp          |  2 +
 src/crepe/api/Transform.cpp            | 10 +++++
 src/crepe/api/Transform.h              |  7 ++++
 src/crepe/manager/ComponentManager.cpp | 26 +++++++++++++
 src/crepe/manager/ComponentManager.h   |  9 ++++-
 src/crepe/manager/Mediator.h           |  2 +
 src/crepe/manager/ReplayManager.cpp    | 25 ++++++------
 src/crepe/manager/ReplayManager.h      | 24 ++++++++----
 src/crepe/system/ReplaySystem.cpp      | 70 ++++++++++++++++++++++++++++++++++
 src/crepe/system/ReplaySystem.h        | 11 ++++++
 src/test/ECSTest.cpp                   | 14 +++++++
 15 files changed, 209 insertions(+), 36 deletions(-)

(limited to 'src/crepe/manager/ReplayManager.cpp')

diff --git a/src/crepe/Component.cpp b/src/crepe/Component.cpp
index 141e1a8..8086492 100644
--- a/src/crepe/Component.cpp
+++ b/src/crepe/Component.cpp
@@ -1,6 +1,7 @@
 #include "Component.h"
 
 using namespace crepe;
+using namespace std;
 
 Component::Component(game_object_id_t id) : game_object_id(id) {}
 
@@ -8,3 +9,11 @@ Component & Component::operator=(const Component &) {
 	return *this;
 }
 
+unique_ptr<Component> Component::save() const {
+	return unique_ptr<Component>(new Component(*this));
+}
+
+void Component::restore(const Component & snapshot) {
+	*this = snapshot;
+}
+
diff --git a/src/crepe/Component.h b/src/crepe/Component.h
index 47c5c34..fc0268c 100644
--- a/src/crepe/Component.h
+++ b/src/crepe/Component.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <memory>
+
 #include "types.h"
 
 namespace crepe {
@@ -32,15 +34,16 @@ protected:
 	//! Only ComponentManager can create components
 	friend class ComponentManager;
 
-	// create snapshot
-	Component(const Component &) = default;
-	// restore snapshot
-	virtual Component & operator=(const Component &);
-
 	// components are never moved
 	Component(Component &&) = delete;
 	virtual Component & operator=(Component &&) = delete;
 
+protected:
+	virtual std::unique_ptr<Component> save() const;
+	Component(const Component &) = default;
+	virtual void restore(const Component & snapshot);
+	virtual Component & operator=(const Component &);
+
 public:
 	virtual ~Component() = default;
 
diff --git a/src/crepe/api/GameObject.cpp b/src/crepe/api/GameObject.cpp
index ea9c425..68b074e 100644
--- a/src/crepe/api/GameObject.cpp
+++ b/src/crepe/api/GameObject.cpp
@@ -11,13 +11,9 @@ GameObject::GameObject(Mediator & mediator, game_object_id_t id,
 					   const std::string & name, const std::string & tag,
 					   const vec2 & position, double rotation, double scale)
 	: id(id),
-	  mediator(mediator) {
-
-	// Add Transform and Metadata components
-	ComponentManager & mgr = this->mediator.component_manager;
-	mgr.add_component<Transform>(this->id, position, rotation, scale);
-	mgr.add_component<Metadata>(this->id, name, tag);
-}
+	  mediator(mediator),
+		transform(mediator.component_manager->add_component<Transform>(this->id, position, rotation, scale)),
+		metadata(mediator.component_manager->add_component<Metadata>(this->id, name, tag)) { }
 
 void GameObject::set_parent(const GameObject & parent) {
 	ComponentManager & mgr = this->mediator.component_manager;
diff --git a/src/crepe/api/GameObject.h b/src/crepe/api/GameObject.h
index a311c21..6203f81 100644
--- a/src/crepe/api/GameObject.h
+++ b/src/crepe/api/GameObject.h
@@ -7,6 +7,8 @@
 namespace crepe {
 
 class Mediator;
+class Transform;
+class Metadata;
 
 /**
  * \brief Represents a GameObject
@@ -34,6 +36,13 @@ private:
 	//! ComponentManager instances GameObject
 	friend class ComponentManager;
 
+public:
+	//! The id of the GameObject
+	const game_object_id_t id;
+
+	Transform & transform;
+	Metadata & metadata;
+
 public:
 	/**
 	 * \brief Set the parent of this GameObject
@@ -68,10 +77,6 @@ public:
 	 */
 	void set_persistent(bool persistent = true);
 
-public:
-	//! The id of the GameObject
-	const game_object_id_t id;
-
 protected:
 	Mediator & mediator;
 };
diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp
index 3511bca..2855455 100644
--- a/src/crepe/api/LoopManager.cpp
+++ b/src/crepe/api/LoopManager.cpp
@@ -25,6 +25,8 @@ LoopManager::LoopManager() {
 	this->load_system<InputSystem>();
 	this->load_system<EventSystem>();
 	this->load_system<AudioSystem>();
+
+	this->mediator.loop_manager = *this;
 }
 
 void LoopManager::start() {
diff --git a/src/crepe/api/Transform.cpp b/src/crepe/api/Transform.cpp
index a85b792..5fc886b 100644
--- a/src/crepe/api/Transform.cpp
+++ b/src/crepe/api/Transform.cpp
@@ -3,6 +3,7 @@
 #include "Transform.h"
 
 using namespace crepe;
+using namespace std;
 
 Transform::Transform(game_object_id_t id, const vec2 & point, double rotation, double scale)
 	: Component(id),
@@ -11,3 +12,12 @@ Transform::Transform(game_object_id_t id, const vec2 & point, double rotation, d
 	  scale(scale) {
 	dbg_trace();
 }
+
+unique_ptr<Component> Transform::save() const {
+	return unique_ptr<Component>{new Transform(*this)};
+}
+
+void Transform::restore(const Component & snapshot) {
+	*this = static_cast<const Transform &>(snapshot);
+}
+
diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h
index 7ee6d65..bbd23e0 100644
--- a/src/crepe/api/Transform.h
+++ b/src/crepe/api/Transform.h
@@ -35,6 +35,13 @@ protected:
 	virtual int get_instances_max() const { return 1; }
 	//! ComponentManager instantiates all components
 	friend class ComponentManager;
+
+protected:
+	virtual std::unique_ptr<Component> save() const;
+	Transform(const Transform &) = default;
+	virtual void restore(const Component & snapshot);
+	virtual Transform & operator=(const Transform &) = default;
+
 };
 
 } // namespace crepe
diff --git a/src/crepe/manager/ComponentManager.cpp b/src/crepe/manager/ComponentManager.cpp
index 24ba0d7..5f5c050 100644
--- a/src/crepe/manager/ComponentManager.cpp
+++ b/src/crepe/manager/ComponentManager.cpp
@@ -72,3 +72,29 @@ set<game_object_id_t> ComponentManager::get_objects_by_tag(const string & tag) c
 	return this->get_objects_by_predicate<Metadata>(
 		[tag](const Metadata & data) { return data.tag == tag; });
 }
+
+ComponentManager::Snapshot ComponentManager::save() {
+	Snapshot snapshot{};
+	for (const auto & [type, by_id_index] : this->components) {
+		for (game_object_id_t id = 0; id < by_id_index.size(); id++) {
+			const auto & components = by_id_index[id];
+			for (size_t index = 0; index < components.size(); index++) {
+				const Component & component = *components[index];
+				snapshot.components.push_back(SnapshotComponent{
+					.type = type,
+					.id = id,
+					.index = index,
+					.component = component.save(),
+				});
+			}
+		}
+	}
+	return snapshot;
+}
+
+void ComponentManager::restore(const Snapshot & snapshot) {
+	for (const SnapshotComponent & info : snapshot.components) {
+		this->components[info.type][info.id][info.index]->restore(*info.component);
+	}
+}
+
diff --git a/src/crepe/manager/ComponentManager.h b/src/crepe/manager/ComponentManager.h
index dd7c154..457a196 100644
--- a/src/crepe/manager/ComponentManager.h
+++ b/src/crepe/manager/ComponentManager.h
@@ -143,10 +143,15 @@ public:
 	RefVector<T> get_components_by_tag(const std::string & tag) const;
 
 	struct SnapshotComponent {
-		Component component;
+		std::type_index type;
+		game_object_id_t id;
+		size_t index;
+		std::unique_ptr<Component> component;
 	};
 	struct Snapshot {
-		
+		// TODO: some kind of hash code that ensures components exist in all the same places as
+		// this snapshot
+		std::vector<SnapshotComponent> components;
 	};
 	Snapshot save();
 	void restore(const Snapshot &);
diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h
index eef4432..f5864e7 100644
--- a/src/crepe/manager/Mediator.h
+++ b/src/crepe/manager/Mediator.h
@@ -14,6 +14,7 @@ class ResourceManager;
 class SDLContext;
 class LoopTimer;
 class ReplayManager;
+class LoopManager;
 
 /**
  * Struct to pass references to classes that would otherwise need to be singletons down to
@@ -36,6 +37,7 @@ struct Mediator {
 	OptionalRef<ResourceManager> resource_manager;
 	OptionalRef<LoopTimer> timer;
 	OptionalRef<ReplayManager> replay_manager;
+	OptionalRef<LoopManager> loop_manager;
 };
 
 } // namespace crepe
diff --git a/src/crepe/manager/ReplayManager.cpp b/src/crepe/manager/ReplayManager.cpp
index 82c2275..81ff114 100644
--- a/src/crepe/manager/ReplayManager.cpp
+++ b/src/crepe/manager/ReplayManager.cpp
@@ -1,4 +1,4 @@
-#include "../util/Log.h"
+#include <format>
 
 #include "ReplayManager.h"
 #include "Manager.h"
@@ -11,26 +11,29 @@ ReplayManager::ReplayManager(Mediator & mediator) : Manager(mediator) {
 }
 
 void ReplayManager::record_start() {
-	if (this->recording) this->release(this->current_recording);
-	this->current_recording++;
-	this->recording = true;
+	if (this->state == RECORDING) this->release(this->id);
+	this->id++;
+	this->memory[this->id] = make_unique<Recording>();
+	this->recording = *this->memory.at(this->id);
+	this->state = RECORDING;
 }
 
 recording_t ReplayManager::record_end() {
-	this->recording = false;
-	return this->current_recording;
+	this->state = IDLE;
+	return this->id;
 }
 
 void ReplayManager::play(recording_t handle) {
 	if (!this->memory.contains(handle))
 		throw out_of_range(format("ReplayManager: no recording for handle {}", handle));
-	Recording & recording = *this->memory.at(handle);
-
-	dbg_log("TODO: magic");
+	this->recording = *this->memory.at(handle);
+	this->recording->frame = 0;
+	this->state = PLAYING;
 }
 
 void ReplayManager::release(recording_t handle) {
-	dbg_log("release");
-
+	if (!this->memory.contains(handle))
+		return;
+	this->memory.erase(handle);
 }
 
diff --git a/src/crepe/manager/ReplayManager.h b/src/crepe/manager/ReplayManager.h
index c50196c..672d093 100644
--- a/src/crepe/manager/ReplayManager.h
+++ b/src/crepe/manager/ReplayManager.h
@@ -1,13 +1,14 @@
 #pragma once
 
+#include <unordered_map>
+
 #include "Manager.h"
 #include "ComponentManager.h"
-#include <unordered_map>
+#include "util/OptionalRef.h"
 
 namespace crepe {
 
 class ReplaySystem;
-class Memento;
 
 typedef size_t recording_t;
 
@@ -20,11 +21,20 @@ protected:
 	void record_frame();
 
 private:
-	typedef std::vector<ComponentManager::Snapshot> Recording;
-
-	bool recording = false;
-	recording_t current_recording = -1;
-
+	struct Recording {
+		size_t frame = 0;
+		std::vector<ComponentManager::Snapshot> frames;
+	};
+
+	enum State {
+		IDLE,
+		RECORDING,
+		PLAYING,
+	};
+
+	State state = IDLE;
+	OptionalRef<Recording> recording;
+	recording_t id = -1;
 
 	std::unordered_map<recording_t, std::unique_ptr<Recording>> memory;
 public:
diff --git a/src/crepe/system/ReplaySystem.cpp b/src/crepe/system/ReplaySystem.cpp
index 3aabb58..85595a2 100644
--- a/src/crepe/system/ReplaySystem.cpp
+++ b/src/crepe/system/ReplaySystem.cpp
@@ -1,7 +1,77 @@
+#include "system/ScriptSystem.h"
+
+#include "../manager/ReplayManager.h"
+
 #include "ReplaySystem.h"
 
+#include "../api/LoopManager.h"
+
 using namespace crepe;
+using namespace std;
 
 void ReplaySystem::fixed_update() {
+	ReplayManager & replay = this->mediator.replay_manager;
+
+	switch (replay.state) {
+		case ReplayManager::IDLE: break;
+		case ReplayManager::RECORDING: {
+			this->update_recording();
+			break;
+		}
+		case ReplayManager::PLAYING: {
+			this->update_playing();
+			break;
+		}
+	}
+
+	this->last_state = replay.state;
+}
+
+void ReplaySystem::update_recording() {
+	ReplayManager & replay = this->mediator.replay_manager;
+	ComponentManager & components = this->mediator.component_manager;
+
+	ReplayManager::Recording & recording = replay.recording;
+	recording.frames.push_back(components.save());
+	recording.frame++;
+}
+
+void ReplaySystem::update_playing() {
+	ReplayManager & replay = this->mediator.replay_manager;
+
+	if (this->last_state != ReplayManager::PLAYING) {
+		this->playback_begin();
+	}
+
+	ReplayManager::Recording & recording = replay.recording;
+
+	if (recording.frames.size() == recording.frame) {
+		this->playback_end();
+		return;
+	}
+
+	ComponentManager & components = this->mediator.component_manager;
+	ComponentManager::Snapshot & frame = recording.frames.at(recording.frame);
+
+	components.restore(frame);
+	recording.frame++;
+}
+
+void ReplaySystem::playback_begin() {
+	LoopManager & loop_manager = this->mediator.loop_manager;
+	// TODO: store system active state
+	// TODO: disable most systems
+	// TODO: store components snapshot
+}
+
+void ReplaySystem::playback_end() {
+	ReplayManager & replay = this->mediator.replay_manager;
+
+	replay.state = ReplayManager::IDLE;
+
+	LoopManager & loop_manager = this->mediator.loop_manager;
+
+	// TODO: restore system active state snapshot
+	// TODO: restore components snapshot
 }
 
diff --git a/src/crepe/system/ReplaySystem.h b/src/crepe/system/ReplaySystem.h
index 15ef3fc..fb40176 100644
--- a/src/crepe/system/ReplaySystem.h
+++ b/src/crepe/system/ReplaySystem.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "../manager/ReplayManager.h"
+
 #include "System.h"
 
 namespace crepe {
@@ -9,6 +11,15 @@ public:
 	using System::System;
 
 	void fixed_update() override;
+
+private:
+	ReplayManager::State last_state = ReplayManager::IDLE;
+	void update_recording();
+	void update_playing();
+
+	std::unordered_map<std::type_index, bool> system_active_snapshot;
+	void playback_begin();
+	void playback_end();
 };
 
 }
diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp
index af2b7b0..8f86a91 100644
--- a/src/test/ECSTest.cpp
+++ b/src/test/ECSTest.cpp
@@ -466,3 +466,17 @@ TEST_F(ECSTest, ComponentsByTag) {
 		EXPECT_EQ(objects.size(), 3);
 	}
 }
+
+TEST_F(ECSTest, Snapshot) {
+	GameObject foo = mgr.new_object("foo");
+
+	foo.transform.position = {1, 1};
+
+	ComponentManager::Snapshot snapshot = mgr.save();
+
+	foo.transform.position = {0, 0};
+
+	mgr.restore(snapshot);
+
+	EXPECT_EQ(foo.transform.position, (vec2{1, 1}));
+}
-- 
cgit v1.2.3


From f34daa492c30a0d28b747817a9f2d6fb0186cf80 Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Thu, 12 Dec 2024 18:46:34 +0100
Subject: clean up ReplayManager API

---
 src/crepe/api/Script.hpp            |  3 +++
 src/crepe/manager/ReplayManager.cpp | 28 +++++++++++++++++++++
 src/crepe/manager/ReplayManager.h   | 33 +++++++++++++------------
 src/crepe/system/ReplaySystem.cpp   | 49 ++++++-------------------------------
 4 files changed, 56 insertions(+), 57 deletions(-)

(limited to 'src/crepe/manager/ReplayManager.cpp')

diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp
index 225a51c..547fb8b 100644
--- a/src/crepe/api/Script.hpp
+++ b/src/crepe/api/Script.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "../manager/ComponentManager.h"
+#include "../manager/ReplayManager.h"
 
 #include "BehaviorScript.h"
 #include "Script.h"
@@ -36,6 +37,8 @@ void Script::subscribe_internal(const EventHandler<EventType> & callback,
 		[this, callback](const EventType & data) -> bool {
 			bool & active = this->active;
 			if (!active) return false;
+			ReplayManager & replay = this->mediator->replay_manager;
+			if (replay.get_state() == ReplayManager::PLAYING) return false;
 			return callback(data);
 		},
 		channel);
diff --git a/src/crepe/manager/ReplayManager.cpp b/src/crepe/manager/ReplayManager.cpp
index 81ff114..ab8a5a0 100644
--- a/src/crepe/manager/ReplayManager.cpp
+++ b/src/crepe/manager/ReplayManager.cpp
@@ -37,3 +37,31 @@ void ReplayManager::release(recording_t handle) {
 	this->memory.erase(handle);
 }
 
+void ReplayManager::frame_record() {
+	ComponentManager & components = this->mediator.component_manager;
+	Recording & recording = this->recording;
+
+	recording.frames.push_back(components.save());
+	recording.frame++;
+}
+
+bool ReplayManager::frame_step() {
+	ComponentManager & components = this->mediator.component_manager;
+	Recording & recording = this->recording;
+
+	ComponentManager::Snapshot & frame = recording.frames.at(recording.frame);
+
+	components.restore(frame);
+	recording.frame++;
+
+	if (recording.frame < recording.frames.size()) return false;
+	// end of recording
+	recording.frame = 0;
+	this->state = IDLE;
+	return true;
+}
+
+ReplayManager::State ReplayManager::get_state() const {
+	return this->state;
+}
+
diff --git a/src/crepe/manager/ReplayManager.h b/src/crepe/manager/ReplayManager.h
index 672d093..5794761 100644
--- a/src/crepe/manager/ReplayManager.h
+++ b/src/crepe/manager/ReplayManager.h
@@ -15,33 +15,34 @@ typedef size_t recording_t;
 class ReplayManager : public Manager {
 public:
 	ReplayManager(Mediator & mediator);
-	friend class ReplaySystem;
-
-protected:
-	void record_frame();
-
-private:
-	struct Recording {
-		size_t frame = 0;
-		std::vector<ComponentManager::Snapshot> frames;
-	};
 
+public:
+	void record_start();
+	recording_t record_end();
+	void play(recording_t handle);
+	void release(recording_t handle);
+	
+public:
 	enum State {
 		IDLE,
 		RECORDING,
 		PLAYING,
 	};
+	State get_state() const;
 
+public:
+	void frame_record();
+	bool frame_step();
+
+private:
+	struct Recording {
+		size_t frame = 0;
+		std::vector<ComponentManager::Snapshot> frames;
+	};
 	State state = IDLE;
 	OptionalRef<Recording> recording;
 	recording_t id = -1;
-
 	std::unordered_map<recording_t, std::unique_ptr<Recording>> memory;
-public:
-	void record_start();
-	recording_t record_end();
-	void play(recording_t handle);
-	void release(recording_t handle);
 };
 
 } // namespace crepe
diff --git a/src/crepe/system/ReplaySystem.cpp b/src/crepe/system/ReplaySystem.cpp
index a6b8fb1..39b5c14 100644
--- a/src/crepe/system/ReplaySystem.cpp
+++ b/src/crepe/system/ReplaySystem.cpp
@@ -1,4 +1,3 @@
-#include "../util/Log.h"
 #include "../manager/ReplayManager.h"
 #include "../manager/SystemManager.h"
 
@@ -10,52 +9,23 @@ using namespace std;
 
 void ReplaySystem::fixed_update() {
 	ReplayManager & replay = this->mediator.replay_manager;
+	ReplayManager::State state = replay.get_state();
+	ReplayManager::State last_state = this->last_state;
+	this->last_state = state;
 
-	switch (replay.state) {
+	switch (state) {
 		case ReplayManager::IDLE: break;
 		case ReplayManager::RECORDING: {
-			this->update_recording();
+			replay.frame_record();
 			break;
 		}
 		case ReplayManager::PLAYING: {
-			this->update_playing();
+			if (last_state != ReplayManager::PLAYING) this->playback_begin();
+			bool last = replay.frame_step();
+			if (last) this->playback_end();
 			break;
 		}
 	}
-
-	this->last_state = replay.state;
-}
-
-void ReplaySystem::update_recording() {
-	ReplayManager & replay = this->mediator.replay_manager;
-	ComponentManager & components = this->mediator.component_manager;
-
-	ReplayManager::Recording & recording = replay.recording;
-	recording.frames.push_back(components.save());
-	recording.frame++;
-}
-
-void ReplaySystem::update_playing() {
-	ReplayManager & replay = this->mediator.replay_manager;
-
-	if (this->last_state != ReplayManager::PLAYING) {
-		this->playback_begin();
-	}
-
-	ReplayManager::Recording & recording = replay.recording;
-
-	if (recording.frames.size() == recording.frame) {
-		dbg_log("Finished playback");
-		this->playback_end();
-		return;
-	}
-
-	ComponentManager & components = this->mediator.component_manager;
-	ComponentManager::Snapshot & frame = recording.frames.at(recording.frame);
-
-	dbg_logf("Playing recording frame {}", recording.frame);
-	components.restore(frame);
-	recording.frame++;
 }
 
 void ReplaySystem::playback_begin() {
@@ -78,8 +48,5 @@ void ReplaySystem::playback_end() {
 
 	components.restore(this->playback.components);
 	systems.restore(this->playback.systems);
-
-	ReplayManager & replay = this->mediator.replay_manager;
-	replay.state = ReplayManager::IDLE;
 }
 
-- 
cgit v1.2.3


From 23196be83778973d9688cc5d465e4e4a16476568 Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Thu, 12 Dec 2024 22:45:12 +0100
Subject: add documentation

---
 src/crepe/Component.h                | 17 ++++++++++++
 src/crepe/api/BehaviorScript.h       |  1 -
 src/crepe/api/Engine.cpp             |  7 ++---
 src/crepe/api/Engine.h               | 14 ++++++----
 src/crepe/api/GameObject.h           |  3 ++-
 src/crepe/api/ParticleEmitter.cpp    | 15 +++++++++++
 src/crepe/api/ParticleEmitter.h      |  6 +++++
 src/crepe/api/Script.hpp             | 11 ++++++--
 src/crepe/api/Transform.h            |  1 -
 src/crepe/manager/ComponentManager.h | 24 +++++++++++++++--
 src/crepe/manager/ReplayManager.cpp  |  7 +++++
 src/crepe/manager/ReplayManager.h    | 52 +++++++++++++++++++++++++++++++-----
 src/crepe/manager/SystemManager.h    | 24 +++++++++++++++++
 src/crepe/system/CMakeLists.txt      |  1 +
 src/crepe/system/EventSystem.h       |  7 +++++
 src/crepe/system/ReplaySystem.h      | 15 +++++++++++
 src/example/replay.cpp               |  4 +--
 17 files changed, 185 insertions(+), 24 deletions(-)

(limited to 'src/crepe/manager/ReplayManager.cpp')

diff --git a/src/crepe/Component.h b/src/crepe/Component.h
index fc0268c..52e06d5 100644
--- a/src/crepe/Component.h
+++ b/src/crepe/Component.h
@@ -39,10 +39,27 @@ protected:
 	virtual Component & operator=(Component &&) = delete;
 
 protected:
+	/**
+	 * \name ReplayManager (Memento) functions
+	 * \{
+	 */
+	/**
+	 * \brief Save a snapshot of this component's state
+	 * \note This function should only be implemented on components that should be saved/restored
+	 * by ReplayManager.
+	 * \returns Unique pointer to a deep copy of this component
+	 */
 	virtual std::unique_ptr<Component> save() const;
+	//! Copy constructor (used by \c save())
 	Component(const Component &) = default;
+	/**
+	 * \brief Restore this component from a snapshot
+	 * \param snapshot Data to fill this component with (as returned by \c save())
+	 */
 	virtual void restore(const Component & snapshot);
+	//! Copy assignment operator (used by \c restore())
 	virtual Component & operator=(const Component &);
+	//! \}
 
 public:
 	virtual ~Component() = default;
diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h
index 02d588a..3909b96 100644
--- a/src/crepe/api/BehaviorScript.h
+++ b/src/crepe/api/BehaviorScript.h
@@ -9,7 +9,6 @@
 namespace crepe {
 
 class ScriptSystem;
-class Mediator;
 class ComponentManager;
 class Script;
 
diff --git a/src/crepe/api/Engine.cpp b/src/crepe/api/Engine.cpp
index 7ae89b9..e8b7fd6 100644
--- a/src/crepe/api/Engine.cpp
+++ b/src/crepe/api/Engine.cpp
@@ -5,12 +5,12 @@
 using namespace crepe;
 using namespace std;
 
-void Engine::start() {
+int Engine::main() noexcept {
 	try {
 		this->setup();
 	} catch (const exception & e) {
 		Log::logf(Log::Level::ERROR, "Uncaught exception in setup: {}\n", e.what());
-		return;
+		return EXIT_FAILURE;
 	}
 
 	try {
@@ -19,10 +19,11 @@ void Engine::start() {
 		Log::logf(Log::Level::ERROR, "Uncaught exception in main loop: {}\n", e.what());
 		this->event_manager.trigger_event<ShutDownEvent>();
 	}
+
+	return EXIT_SUCCESS;
 }
 
 void Engine::setup() {
-	this->game_running = true;
 	this->loop_timer.start();
 	this->scene_manager.load_next_scene();
 
diff --git a/src/crepe/api/Engine.h b/src/crepe/api/Engine.h
index 5421d60..efe7853 100644
--- a/src/crepe/api/Engine.h
+++ b/src/crepe/api/Engine.h
@@ -20,13 +20,16 @@ namespace crepe {
  */
 class Engine {
 public:
-	void start();
-
 	/**
-	 * \brief Add a new concrete scene to the scene manager
+	 * \brief Engine entrypoint
+	 *
+	 * This function is called by the game programmer after registering all scenes
 	 *
-	 * \tparam T  Type of concrete scene
+	 * \returns process exit code
 	 */
+	int main() noexcept;
+
+	//! \copydoc SceneManager::add_scene
 	template <typename T>
 	void add_scene();
 
@@ -44,7 +47,8 @@ private:
 	 */
 	void loop();
 
-	bool game_running = false;
+	//! Game loop condition
+	bool game_running = true;
 
 private:
 	//! Global context
diff --git a/src/crepe/api/GameObject.h b/src/crepe/api/GameObject.h
index 6203f81..0dabed1 100644
--- a/src/crepe/api/GameObject.h
+++ b/src/crepe/api/GameObject.h
@@ -39,8 +39,9 @@ private:
 public:
 	//! The id of the GameObject
 	const game_object_id_t id;
-
+	//! This entity's transform
 	Transform & transform;
+	//! This entity's metadata
 	Metadata & metadata;
 
 public:
diff --git a/src/crepe/api/ParticleEmitter.cpp b/src/crepe/api/ParticleEmitter.cpp
index 90b77a0..fd69e26 100644
--- a/src/crepe/api/ParticleEmitter.cpp
+++ b/src/crepe/api/ParticleEmitter.cpp
@@ -1,6 +1,7 @@
 #include "ParticleEmitter.h"
 
 using namespace crepe;
+using namespace std;
 
 ParticleEmitter::ParticleEmitter(game_object_id_t game_object_id, const Data & data)
 	: Component(game_object_id),
@@ -9,3 +10,17 @@ ParticleEmitter::ParticleEmitter(game_object_id_t game_object_id, const Data & d
 		this->data.particles.emplace_back();
 	}
 }
+
+unique_ptr<Component> ParticleEmitter::save() const {
+	return unique_ptr<Component>{new ParticleEmitter(*this)};
+}
+
+void ParticleEmitter::restore(const Component & snapshot) {
+	*this = static_cast<const ParticleEmitter &>(snapshot);
+}
+
+ParticleEmitter & ParticleEmitter::operator=(const ParticleEmitter & other) {
+	data.particles = other.data.particles;
+	return *this;
+}
+
diff --git a/src/crepe/api/ParticleEmitter.h b/src/crepe/api/ParticleEmitter.h
index b83fd61..5f563de 100644
--- a/src/crepe/api/ParticleEmitter.h
+++ b/src/crepe/api/ParticleEmitter.h
@@ -80,6 +80,12 @@ public:
 public:
 	//! Configuration data for particle emission settings.
 	Data data;
+
+protected:
+	virtual std::unique_ptr<Component> save() const;
+	ParticleEmitter(const ParticleEmitter &) = default;
+	virtual void restore(const Component & snapshot);
+	virtual ParticleEmitter & operator=(const ParticleEmitter &);
 };
 
 } // namespace crepe
diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp
index 2553fd1..b42a6df 100644
--- a/src/crepe/api/Script.hpp
+++ b/src/crepe/api/Script.hpp
@@ -40,10 +40,17 @@ void Script::subscribe_internal(const EventHandler<EventType> & callback,
 	EventManager & mgr = this->mediator->event_manager;
 	subscription_t listener = mgr.subscribe<EventType>(
 		[this, callback](const EventType & data) -> bool {
+			// check if (parent) BehaviorScript component is active
 			bool & active = this->active;
 			if (!active) return false;
-			ReplayManager & replay = this->mediator->replay_manager;
-			if (replay.get_state() == ReplayManager::PLAYING) return false;
+
+			// check if replay manager is playing (if initialized)
+			try {
+				ReplayManager & replay = this->mediator->replay_manager;
+				if (replay.get_state() == ReplayManager::PLAYING) return false;
+			} catch (const std::runtime_error &) {}
+
+			// call user-provided callback
 			return callback(data);
 		},
 		channel);
diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h
index bbd23e0..a6f3486 100644
--- a/src/crepe/api/Transform.h
+++ b/src/crepe/api/Transform.h
@@ -41,7 +41,6 @@ protected:
 	Transform(const Transform &) = default;
 	virtual void restore(const Component & snapshot);
 	virtual Transform & operator=(const Transform &) = default;
-
 };
 
 } // namespace crepe
diff --git a/src/crepe/manager/ComponentManager.h b/src/crepe/manager/ComponentManager.h
index 457a196..c3a5b4a 100644
--- a/src/crepe/manager/ComponentManager.h
+++ b/src/crepe/manager/ComponentManager.h
@@ -142,19 +142,39 @@ public:
 	template <typename T>
 	RefVector<T> get_components_by_tag(const std::string & tag) const;
 
+	//! Snapshot of single component (including path in \c components)
 	struct SnapshotComponent {
+		//! \c components path
 		std::type_index type;
+		//! \c components path
 		game_object_id_t id;
+		//! \c components path
 		size_t index;
+		//! Actual component snapshot
 		std::unique_ptr<Component> component;
 	};
+	//! Snapshot of the entire component manager state
 	struct Snapshot {
+		//! All components
+		std::vector<SnapshotComponent> components;
 		// TODO: some kind of hash code that ensures components exist in all the same places as
 		// this snapshot
-		std::vector<SnapshotComponent> components;
 	};
+	/**
+	 * \name ReplayManager (Memento) functions
+	 * \{
+	 */
+	/**
+	 * \brief Save a snapshot of the component manager state
+	 * \returns Deep copy of the component manager's internal state
+	 */
 	Snapshot save();
-	void restore(const Snapshot &);
+	/**
+	 * \brief Restore component manager from a snapshot
+	 * \param snapshot Snapshot to restore from (as returned by \c save())
+	 */
+	void restore(const Snapshot & snapshot);
+	//! \}
 
 private:
 	/**
diff --git a/src/crepe/manager/ReplayManager.cpp b/src/crepe/manager/ReplayManager.cpp
index ab8a5a0..db6acb0 100644
--- a/src/crepe/manager/ReplayManager.cpp
+++ b/src/crepe/manager/ReplayManager.cpp
@@ -38,6 +38,9 @@ void ReplayManager::release(recording_t handle) {
 }
 
 void ReplayManager::frame_record() {
+	if (this->state != RECORDING)
+		throw runtime_error("ReplayManager: frame_step called while not playing");
+
 	ComponentManager & components = this->mediator.component_manager;
 	Recording & recording = this->recording;
 
@@ -46,6 +49,9 @@ void ReplayManager::frame_record() {
 }
 
 bool ReplayManager::frame_step() {
+	if (this->state != PLAYING)
+		throw runtime_error("ReplayManager: frame_step called while not playing");
+
 	ComponentManager & components = this->mediator.component_manager;
 	Recording & recording = this->recording;
 
@@ -58,6 +64,7 @@ bool ReplayManager::frame_step() {
 	// end of recording
 	recording.frame = 0;
 	this->state = IDLE;
+	this->recording.clear();
 	return true;
 }
 
diff --git a/src/crepe/manager/ReplayManager.h b/src/crepe/manager/ReplayManager.h
index 7be18f3..d3af879 100644
--- a/src/crepe/manager/ReplayManager.h
+++ b/src/crepe/manager/ReplayManager.h
@@ -8,13 +8,14 @@
 
 namespace crepe {
 
-class ReplaySystem;
-
 typedef size_t recording_t;
 
 /**
  * \brief Replay manager
  *
+ * The replay manager is responsible for creating, storing and restoring ComponentManager
+ * snapshots. Sequential snapshots can be recorded and replayed in combination with
+ * ReplaySystem.
  */
 class ReplayManager : public Manager {
 	// TODO: Delete recordings at end of scene
@@ -22,31 +23,70 @@ public:
 	ReplayManager(Mediator & mediator);
 
 public:
+	//! Start a new recording
 	void record_start();
+	/**
+	 * \brief End the latest recording started by \c record_start()
+	 * \returns Handle to recording
+	 */
 	recording_t record_end();
+	/**
+	 * \brief Play a recording
+	 * \param handle Handle to recording (as returned by \c record_end())
+	 */
 	void play(recording_t handle);
+	/**
+	 * \brief Delete a recording from memory
+	 * \param handle Handle to recording (as returned by \c record_end())
+	 */
 	void release(recording_t handle);
 	
 public:
+	//! Internal state
 	enum State {
-		IDLE,
-		RECORDING,
-		PLAYING,
+		IDLE, //!< Not doing anything
+		RECORDING, //!< Currently recording
+		PLAYING, //!< Currently playing back a recording
 	};
+	//! Get current internal state
 	State get_state() const;
 
 public:
+	/**
+	 * \brief Record a single frame to the current recording
+	 *
+	 * This function is called by ReplaySystem after the game programmer has called \c
+	 * record_start()
+	 */
 	void frame_record();
+	/**
+	 * \brief Play the next frame of the current recording
+	 *
+	 * \returns `true` if the recording is finished playing
+	 * \returns `false` if there are more frames
+	 *
+	 * This function also automatically resets the internal state from PLAYING to IDLE at the end
+	 * of a recording.
+	 */
 	bool frame_step();
 
 private:
+	/**
+	 * \brief Recording data
+	 */
 	struct Recording {
+		//! Current frame being shown
 		size_t frame = 0;
+		//! All frames in recording
 		std::vector<ComponentManager::Snapshot> frames;
 	};
+	//! Internal state
 	State state = IDLE;
-	OptionalRef<Recording> recording;
+	//! Current recording handle
 	recording_t id = -1;
+	//! Current recording data
+	OptionalRef<Recording> recording;
+	//! Recording storage
 	std::unordered_map<recording_t, std::unique_ptr<Recording>> memory;
 };
 
diff --git a/src/crepe/manager/SystemManager.h b/src/crepe/manager/SystemManager.h
index 6cf7f2b..a47961b 100644
--- a/src/crepe/manager/SystemManager.h
+++ b/src/crepe/manager/SystemManager.h
@@ -1,11 +1,21 @@
 #pragma once
 
+#include <typeindex>
+#include <unordered_map>
+#include <memory>
+
 #include "../system/System.h"
 
 #include "Manager.h"
 
 namespace crepe {
 
+/**
+ * \brief Collection of all systems
+ *
+ * This manager aggregates all systems and provides utility functions to retrieve references to
+ * and update systems.
+ */
 class SystemManager : public Manager {
 public:
 	SystemManager(Mediator &);
@@ -50,9 +60,23 @@ public:
 	T & get_system();
 
 public:
+	/**
+	 * \brief SystemManager snapshot
+	 *
+	 * The SystemManager snapshot only stores which systems are active
+	 */
 	typedef std::unordered_map<std::type_index, bool> Snapshot;
+	/**
+	 * \brief Save a snapshot of the systems' state
+	 * \returns Copy of each system's active property
+	 */
 	Snapshot save();
+	/**
+	 * \brief Restore system active state from a snapshot
+	 * \param snapshot Snapshot to restore from (as returned by \c save())
+	 */
 	void restore(const Snapshot & snapshot);
+	//! Disable all systems
 	void disable_all();
 };
 
diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt
index 3473876..52369d0 100644
--- a/src/crepe/system/CMakeLists.txt
+++ b/src/crepe/system/CMakeLists.txt
@@ -23,5 +23,6 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
 	AnimatorSystem.h
 	InputSystem.h
 	EventSystem.h
+	ReplaySystem.h
 	AISystem.h
 )
diff --git a/src/crepe/system/EventSystem.h b/src/crepe/system/EventSystem.h
index a179d00..ff3ca4e 100644
--- a/src/crepe/system/EventSystem.h
+++ b/src/crepe/system/EventSystem.h
@@ -4,10 +4,17 @@
 
 namespace crepe {
 
+/**
+ * \brief EventManager dispatch helper system
+ */
 class EventSystem : public System {
 public:
 	using System::System;
 
+	/**
+	 * \brief Dispatch queued events
+	 * \see EventManager::dispatch_events
+	 */
 	void fixed_update() override;
 };
 
diff --git a/src/crepe/system/ReplaySystem.h b/src/crepe/system/ReplaySystem.h
index 919c554..8ba60d5 100644
--- a/src/crepe/system/ReplaySystem.h
+++ b/src/crepe/system/ReplaySystem.h
@@ -7,6 +7,11 @@
 
 namespace crepe {
 
+/**
+ * \brief ReplayManager helper system
+ *
+ * This system records and replays recordings using ReplayManager.
+ */
 class ReplaySystem : public System {
 public:
 	using System::System;
@@ -14,15 +19,25 @@ public:
 	void fixed_update() override;
 
 private:
+	//! Last ReplayManager state
 	ReplayManager::State last_state = ReplayManager::IDLE;
 
+	/**
+	 * \brief Playback snapshot
+	 *
+	 * When starting playback, the component state is saved and most systems are disabled. This
+	 * struct stores the engine state before ReplayManager::play is called.
+	 */
 	struct Snapshot {
 		ComponentManager::Snapshot components;
 		SystemManager::Snapshot systems;
 	};
+	//! Before playback snapshot
 	Snapshot playback;
 
+	//! Snapshot state and disable systems during playback
 	void playback_begin();
+	//! Restore state from before \c playback_begin()
 	void playback_end();
 };
 
diff --git a/src/example/replay.cpp b/src/example/replay.cpp
index 7faf6cb..130c0d3 100644
--- a/src/example/replay.cpp
+++ b/src/example/replay.cpp
@@ -83,7 +83,5 @@ int main(int argc, char * argv[]) {
 	Engine engine;
 
 	engine.add_scene<TestScene>();
-	engine.start();
-
-	return 0;
+	return engine.main();
 }
-- 
cgit v1.2.3


From 1d1c256eea43a3d0685919ed2997e10990ef639f Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Thu, 12 Dec 2024 22:45:30 +0100
Subject: `make format`

---
 src/crepe/Component.cpp                |  5 +----
 src/crepe/api/Engine.cpp               |  7 ++++---
 src/crepe/api/Engine.h                 |  5 ++---
 src/crepe/api/GameObject.cpp           | 11 ++++++-----
 src/crepe/api/GameObject.h             |  5 ++---
 src/crepe/api/ParticleEmitter.cpp      |  1 -
 src/crepe/api/Script.cpp               |  1 -
 src/crepe/api/Script.h                 | 10 ++++++----
 src/crepe/api/Script.hpp               |  3 ++-
 src/crepe/api/Transform.cpp            |  1 -
 src/crepe/manager/ComponentManager.cpp |  1 -
 src/crepe/manager/ReplayManager.cpp    | 10 +++-------
 src/crepe/manager/ReplayManager.h      |  5 +++--
 src/crepe/manager/SystemManager.cpp    |  5 ++---
 src/crepe/manager/SystemManager.h      |  2 +-
 src/crepe/manager/SystemManager.hpp    |  7 ++++---
 src/crepe/system/EventSystem.cpp       |  3 +--
 src/crepe/system/EventSystem.h         |  3 +--
 src/crepe/system/ReplaySystem.cpp      |  6 +++---
 src/crepe/system/ReplaySystem.h        |  3 +--
 src/crepe/system/ScriptSystem.cpp      |  2 +-
 src/crepe/util/Log.cpp                 |  2 +-
 src/crepe/util/dbg.h                   |  1 -
 src/example/replay.cpp                 | 27 ++++++++++++---------------
 src/test/Profiling.cpp                 |  6 ++++--
 src/test/ReplayManagerTest.cpp         | 14 ++++++++------
 26 files changed, 68 insertions(+), 78 deletions(-)

(limited to 'src/crepe/manager/ReplayManager.cpp')

diff --git a/src/crepe/Component.cpp b/src/crepe/Component.cpp
index 1aed507..ae76e65 100644
--- a/src/crepe/Component.cpp
+++ b/src/crepe/Component.cpp
@@ -14,7 +14,4 @@ unique_ptr<Component> Component::save() const {
 	return unique_ptr<Component>(new Component(*this));
 }
 
-void Component::restore(const Component & snapshot) {
-	*this = snapshot;
-}
-
+void Component::restore(const Component & snapshot) { *this = snapshot; }
diff --git a/src/crepe/api/Engine.cpp b/src/crepe/api/Engine.cpp
index e8b7fd6..bbb4494 100644
--- a/src/crepe/api/Engine.cpp
+++ b/src/crepe/api/Engine.cpp
@@ -46,7 +46,8 @@ void Engine::loop() {
 			try {
 				systems.fixed_update();
 			} catch (const exception & e) {
-				Log::logf(Log::Level::WARNING, "Uncaught exception in fixed update function: {}\n", e.what());
+				Log::logf(Log::Level::WARNING,
+						  "Uncaught exception in fixed update function: {}\n", e.what());
 			}
 			timer.advance_fixed_elapsed_time();
 		}
@@ -54,9 +55,9 @@ void Engine::loop() {
 		try {
 			systems.frame_update();
 		} catch (const exception & e) {
-			Log::logf(Log::Level::WARNING, "Uncaught exception in frame update function: {}\n", e.what());
+			Log::logf(Log::Level::WARNING, "Uncaught exception in frame update function: {}\n",
+					  e.what());
 		}
 		timer.enforce_frame_rate();
 	}
 }
-
diff --git a/src/crepe/api/Engine.h b/src/crepe/api/Engine.h
index efe7853..3145723 100644
--- a/src/crepe/api/Engine.h
+++ b/src/crepe/api/Engine.h
@@ -2,14 +2,13 @@
 
 #include "../facade/SDLContext.h"
 #include "../manager/ComponentManager.h"
+#include "../manager/EventManager.h"
+#include "../manager/LoopTimerManager.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 "../manager/LoopTimerManager.h"
-#include "../manager/EventManager.h"
 
 namespace crepe {
 
diff --git a/src/crepe/api/GameObject.cpp b/src/crepe/api/GameObject.cpp
index 68b074e..9b94cad 100644
--- a/src/crepe/api/GameObject.cpp
+++ b/src/crepe/api/GameObject.cpp
@@ -7,13 +7,14 @@
 using namespace crepe;
 using namespace std;
 
-GameObject::GameObject(Mediator & mediator, game_object_id_t id,
-					   const std::string & name, const std::string & tag,
-					   const vec2 & position, double rotation, double scale)
+GameObject::GameObject(Mediator & mediator, game_object_id_t id, const std::string & name,
+					   const std::string & tag, const vec2 & position, double rotation,
+					   double scale)
 	: id(id),
 	  mediator(mediator),
-		transform(mediator.component_manager->add_component<Transform>(this->id, position, rotation, scale)),
-		metadata(mediator.component_manager->add_component<Metadata>(this->id, name, tag)) { }
+	  transform(mediator.component_manager->add_component<Transform>(this->id, position,
+																	 rotation, scale)),
+	  metadata(mediator.component_manager->add_component<Metadata>(this->id, name, tag)) {}
 
 void GameObject::set_parent(const GameObject & parent) {
 	ComponentManager & mgr = this->mediator.component_manager;
diff --git a/src/crepe/api/GameObject.h b/src/crepe/api/GameObject.h
index 0dabed1..572ce3a 100644
--- a/src/crepe/api/GameObject.h
+++ b/src/crepe/api/GameObject.h
@@ -30,9 +30,8 @@ private:
 	 * \param rotation The rotation of the GameObject
 	 * \param scale The scale of the GameObject
 	 */
-	GameObject(Mediator & mediator, game_object_id_t id,
-			   const std::string & name, const std::string & tag, const vec2 & position,
-			   double rotation, double scale);
+	GameObject(Mediator & mediator, game_object_id_t id, const std::string & name,
+			   const std::string & tag, const vec2 & position, double rotation, double scale);
 	//! ComponentManager instances GameObject
 	friend class ComponentManager;
 
diff --git a/src/crepe/api/ParticleEmitter.cpp b/src/crepe/api/ParticleEmitter.cpp
index fd69e26..a9c5cf6 100644
--- a/src/crepe/api/ParticleEmitter.cpp
+++ b/src/crepe/api/ParticleEmitter.cpp
@@ -23,4 +23,3 @@ ParticleEmitter & ParticleEmitter::operator=(const ParticleEmitter & other) {
 	data.particles = other.data.particles;
 	return *this;
 }
-
diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp
index 8b95cc9..34e7908 100644
--- a/src/crepe/api/Script.cpp
+++ b/src/crepe/api/Script.cpp
@@ -45,4 +45,3 @@ void Script::replay::release(recording_t recording) {
 	ReplayManager & mgr = this->mediator->replay_manager;
 	return mgr.release(recording);
 }
-
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index 18a029b..6536fa4 100644
--- a/src/crepe/api/Script.h
+++ b/src/crepe/api/Script.h
@@ -2,13 +2,13 @@
 
 #include <vector>
 
-#include "../manager/ReplayManager.h"
 #include "../manager/EventManager.h"
 #include "../manager/Mediator.h"
+#include "../manager/ReplayManager.h"
 #include "../system/CollisionSystem.h"
 #include "../types.h"
-#include "../util/OptionalRef.h"
 #include "../util/Log.h"
+#include "../util/OptionalRef.h"
 
 namespace crepe {
 
@@ -115,10 +115,12 @@ protected:
 	void subscribe(const EventHandler<EventType> & callback);
 	//! \copydoc EventManager::trigger_event
 	template <typename EventType>
-	void trigger_event(const EventType & event = {}, event_channel_t channel = EventManager::CHANNEL_ALL);
+	void trigger_event(const EventType & event = {},
+					   event_channel_t channel = EventManager::CHANNEL_ALL);
 	//! \copydoc EventManager::queue_event
 	template <typename EventType>
-	void queue_event(const EventType & event = {}, event_channel_t channel = EventManager::CHANNEL_ALL);
+	void queue_event(const EventType & event = {},
+					 event_channel_t channel = EventManager::CHANNEL_ALL);
 	//! \}
 
 	/**
diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp
index b42a6df..4462a41 100644
--- a/src/crepe/api/Script.hpp
+++ b/src/crepe/api/Script.hpp
@@ -48,7 +48,8 @@ void Script::subscribe_internal(const EventHandler<EventType> & callback,
 			try {
 				ReplayManager & replay = this->mediator->replay_manager;
 				if (replay.get_state() == ReplayManager::PLAYING) return false;
-			} catch (const std::runtime_error &) {}
+			} catch (const std::runtime_error &) {
+			}
 
 			// call user-provided callback
 			return callback(data);
diff --git a/src/crepe/api/Transform.cpp b/src/crepe/api/Transform.cpp
index 32b44e1..fcfce14 100644
--- a/src/crepe/api/Transform.cpp
+++ b/src/crepe/api/Transform.cpp
@@ -20,4 +20,3 @@ unique_ptr<Component> Transform::save() const {
 void Transform::restore(const Component & snapshot) {
 	*this = static_cast<const Transform &>(snapshot);
 }
-
diff --git a/src/crepe/manager/ComponentManager.cpp b/src/crepe/manager/ComponentManager.cpp
index bc104d3..745ddae 100644
--- a/src/crepe/manager/ComponentManager.cpp
+++ b/src/crepe/manager/ComponentManager.cpp
@@ -97,4 +97,3 @@ void ComponentManager::restore(const Snapshot & snapshot) {
 		this->components[info.type][info.id][info.index]->restore(*info.component);
 	}
 }
-
diff --git a/src/crepe/manager/ReplayManager.cpp b/src/crepe/manager/ReplayManager.cpp
index db6acb0..090a94e 100644
--- a/src/crepe/manager/ReplayManager.cpp
+++ b/src/crepe/manager/ReplayManager.cpp
@@ -1,7 +1,7 @@
 #include <format>
 
-#include "ReplayManager.h"
 #include "Manager.h"
+#include "ReplayManager.h"
 
 using namespace crepe;
 using namespace std;
@@ -32,8 +32,7 @@ void ReplayManager::play(recording_t handle) {
 }
 
 void ReplayManager::release(recording_t handle) {
-	if (!this->memory.contains(handle))
-		return;
+	if (!this->memory.contains(handle)) return;
 	this->memory.erase(handle);
 }
 
@@ -68,7 +67,4 @@ bool ReplayManager::frame_step() {
 	return true;
 }
 
-ReplayManager::State ReplayManager::get_state() const {
-	return this->state;
-}
-
+ReplayManager::State ReplayManager::get_state() const { return this->state; }
diff --git a/src/crepe/manager/ReplayManager.h b/src/crepe/manager/ReplayManager.h
index d3af879..ab15b27 100644
--- a/src/crepe/manager/ReplayManager.h
+++ b/src/crepe/manager/ReplayManager.h
@@ -2,8 +2,8 @@
 
 #include <unordered_map>
 
-#include "Manager.h"
 #include "ComponentManager.h"
+#include "Manager.h"
 #include "util/OptionalRef.h"
 
 namespace crepe {
@@ -19,6 +19,7 @@ typedef size_t recording_t;
  */
 class ReplayManager : public Manager {
 	// TODO: Delete recordings at end of scene
+
 public:
 	ReplayManager(Mediator & mediator);
 
@@ -40,7 +41,7 @@ public:
 	 * \param handle Handle to recording (as returned by \c record_end())
 	 */
 	void release(recording_t handle);
-	
+
 public:
 	//! Internal state
 	enum State {
diff --git a/src/crepe/manager/SystemManager.cpp b/src/crepe/manager/SystemManager.cpp
index f67e786..5ada30f 100644
--- a/src/crepe/manager/SystemManager.cpp
+++ b/src/crepe/manager/SystemManager.cpp
@@ -2,13 +2,13 @@
 #include "../system/AnimatorSystem.h"
 #include "../system/AudioSystem.h"
 #include "../system/CollisionSystem.h"
+#include "../system/EventSystem.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 "../system/ReplaySystem.h"
+#include "../system/ScriptSystem.h"
 
 #include "SystemManager.h"
 
@@ -64,4 +64,3 @@ void SystemManager::disable_all() {
 		system->active = false;
 	}
 }
-
diff --git a/src/crepe/manager/SystemManager.h b/src/crepe/manager/SystemManager.h
index a47961b..50acf77 100644
--- a/src/crepe/manager/SystemManager.h
+++ b/src/crepe/manager/SystemManager.h
@@ -1,8 +1,8 @@
 #pragma once
 
+#include <memory>
 #include <typeindex>
 #include <unordered_map>
-#include <memory>
 
 #include "../system/System.h"
 
diff --git a/src/crepe/manager/SystemManager.hpp b/src/crepe/manager/SystemManager.hpp
index 46ada5f..3d26e4c 100644
--- a/src/crepe/manager/SystemManager.hpp
+++ b/src/crepe/manager/SystemManager.hpp
@@ -1,8 +1,8 @@
 #pragma once
 
-#include <memory>
 #include <cassert>
 #include <format>
+#include <memory>
 
 #include "SystemManager.h"
 
@@ -11,7 +11,8 @@ 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");
+	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))
@@ -28,7 +29,7 @@ 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");
+				  "load_system must recieve a derivative class of System");
 
 	const type_info & type = typeid(T);
 	if (this->systems.contains(type))
diff --git a/src/crepe/system/EventSystem.cpp b/src/crepe/system/EventSystem.cpp
index 5475798..7e168ab 100644
--- a/src/crepe/system/EventSystem.cpp
+++ b/src/crepe/system/EventSystem.cpp
@@ -1,5 +1,5 @@
-#include "../manager/EventManager.h"
 #include "EventSystem.h"
+#include "../manager/EventManager.h"
 
 using namespace crepe;
 
@@ -7,4 +7,3 @@ void EventSystem::fixed_update() {
 	EventManager & ev = this->mediator.event_manager;
 	ev.dispatch_events();
 }
-
diff --git a/src/crepe/system/EventSystem.h b/src/crepe/system/EventSystem.h
index ff3ca4e..0ae48d2 100644
--- a/src/crepe/system/EventSystem.h
+++ b/src/crepe/system/EventSystem.h
@@ -18,5 +18,4 @@ public:
 	void fixed_update() override;
 };
 
-}
-
+} // namespace crepe
diff --git a/src/crepe/system/ReplaySystem.cpp b/src/crepe/system/ReplaySystem.cpp
index 2b2e4ab..efc3be4 100644
--- a/src/crepe/system/ReplaySystem.cpp
+++ b/src/crepe/system/ReplaySystem.cpp
@@ -1,9 +1,9 @@
 #include "../manager/ReplayManager.h"
 #include "../manager/SystemManager.h"
 
+#include "EventSystem.h"
 #include "RenderSystem.h"
 #include "ReplaySystem.h"
-#include "EventSystem.h"
 
 using namespace crepe;
 using namespace std;
@@ -15,7 +15,8 @@ void ReplaySystem::fixed_update() {
 	this->last_state = state;
 
 	switch (state) {
-		case ReplayManager::IDLE: break;
+		case ReplayManager::IDLE:
+			break;
 		case ReplayManager::RECORDING: {
 			replay.frame_record();
 			break;
@@ -51,4 +52,3 @@ void ReplaySystem::playback_end() {
 	components.restore(this->playback.components);
 	systems.restore(this->playback.systems);
 }
-
diff --git a/src/crepe/system/ReplaySystem.h b/src/crepe/system/ReplaySystem.h
index 8ba60d5..bbc8d76 100644
--- a/src/crepe/system/ReplaySystem.h
+++ b/src/crepe/system/ReplaySystem.h
@@ -41,5 +41,4 @@ private:
 	void playback_end();
 };
 
-}
-
+} // namespace crepe
diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp
index 11da618..0d10011 100644
--- a/src/crepe/system/ScriptSystem.cpp
+++ b/src/crepe/system/ScriptSystem.cpp
@@ -1,7 +1,7 @@
-#include "../util/dbg.h"
 #include "../api/BehaviorScript.h"
 #include "../api/Script.h"
 #include "../manager/ComponentManager.h"
+#include "../util/dbg.h"
 
 #include "ScriptSystem.h"
 
diff --git a/src/crepe/util/Log.cpp b/src/crepe/util/Log.cpp
index e11a8d9..ce25a1d 100644
--- a/src/crepe/util/Log.cpp
+++ b/src/crepe/util/Log.cpp
@@ -3,8 +3,8 @@
 
 #include "../api/Config.h"
 
-#include "LogColor.h"
 #include "Log.h"
+#include "LogColor.h"
 
 using namespace crepe;
 using namespace std;
diff --git a/src/crepe/util/dbg.h b/src/crepe/util/dbg.h
index 500e959..c7283ee 100644
--- a/src/crepe/util/dbg.h
+++ b/src/crepe/util/dbg.h
@@ -16,4 +16,3 @@
 #define dbg_log(str) _crepe_logf_here(crepe::Log::Level::DEBUG, ": {}", str)
 #define dbg_trace() _crepe_logf_here(crepe::Log::Level::TRACE, "", "")
 // NOLINTEND
-
diff --git a/src/example/replay.cpp b/src/example/replay.cpp
index 130c0d3..82fd478 100644
--- a/src/example/replay.cpp
+++ b/src/example/replay.cpp
@@ -1,6 +1,6 @@
+#include <crepe/api/Config.h>
 #include <crepe/api/Engine.h>
 #include <crepe/api/Script.h>
-#include <crepe/api/Config.h>
 
 using namespace crepe;
 using namespace std;
@@ -9,13 +9,11 @@ class AnimationScript : public Script {
 	Transform * transform;
 	float t = 0;
 
-	void init() {
-		transform = &get_component<Transform>();
-	}
+	void init() { transform = &get_component<Transform>(); }
 
 	void update() {
 		t += 0.05;
-		transform->position = { sin(t), cos(t) };
+		transform->position = {sin(t), cos(t)};
 	}
 };
 
@@ -25,7 +23,8 @@ class Timeline : public Script {
 
 	void update() {
 		switch (i++) {
-			default: break;
+			default:
+				break;
 			case 10:
 				logf("record start");
 				replay.record_start();
@@ -56,17 +55,15 @@ public:
 		ComponentManager & mgr = mediator.component_manager;
 
 		GameObject cam = mgr.new_object("cam");
-		cam.add_component<Camera>(ivec2{640,480},vec2{3,3}, Camera::Data{
-			.bg_color = Color::WHITE,
-		});
+		cam.add_component<Camera>(ivec2{640, 480}, vec2{3, 3},
+								  Camera::Data{
+									  .bg_color = Color::WHITE,
+								  });
 
 		GameObject square = mgr.new_object("square");
-		square.add_component<Sprite>(
-			Asset{"asset/texture/square.png"},
-			Sprite::Data{
-				.size = { 0.5, 0.5 },
-			}
-		);
+		square.add_component<Sprite>(Asset{"asset/texture/square.png"}, Sprite::Data{
+																			.size = {0.5, 0.5},
+																		});
 		square.add_component<BehaviorScript>().set_script<AnimationScript>();
 
 		GameObject scapegoat = mgr.new_object("");
diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp
index eccfd89..f5ae4b1 100644
--- a/src/test/Profiling.cpp
+++ b/src/test/Profiling.cpp
@@ -102,12 +102,14 @@ public:
 	// Run and profile all systems, return the total time in milliseconds
 	std::chrono::microseconds run_all_systems() {
 		std::chrono::microseconds total_microseconds = 0us;
-		total_microseconds += time_function("PhysicsSystem", [&]() { physics_sys.fixed_update(); });
+		total_microseconds
+			+= time_function("PhysicsSystem", [&]() { physics_sys.fixed_update(); });
 		total_microseconds
 			+= time_function("CollisionSystem", [&]() { collision_sys.fixed_update(); });
 		total_microseconds
 			+= time_function("ParticleSystem", [&]() { particle_sys.fixed_update(); });
-		total_microseconds += time_function("RenderSystem", [&]() { render_sys.frame_update(); });
+		total_microseconds
+			+= time_function("RenderSystem", [&]() { render_sys.frame_update(); });
 		return total_microseconds;
 	}
 
diff --git a/src/test/ReplayManagerTest.cpp b/src/test/ReplayManagerTest.cpp
index aa5a766..5ee4b40 100644
--- a/src/test/ReplayManagerTest.cpp
+++ b/src/test/ReplayManagerTest.cpp
@@ -1,10 +1,10 @@
 #include <gtest/gtest.h>
 
-#include <crepe/manager/ReplayManager.h>
-#include <crepe/system/ReplaySystem.h>
+#include <crepe/api/BehaviorScript.h>
 #include <crepe/api/Scene.h>
 #include <crepe/api/Script.h>
-#include <crepe/api/BehaviorScript.h>
+#include <crepe/manager/ReplayManager.h>
+#include <crepe/system/ReplaySystem.h>
 
 using namespace std;
 using namespace crepe;
@@ -12,14 +12,17 @@ using namespace testing;
 
 class ReplayManagerTest : public Test {
 	Mediator mediator;
+
 public:
 	ComponentManager component_manager{mediator};
 	ReplayManager replay_manager{mediator};
 	ReplaySystem replay_system{mediator};
 
 	GameObject entity = component_manager.new_object("foo");
-	Transform & entity_transform = component_manager.get_components_by_id<Transform>(entity.id).back();
-	Metadata & entity_metadata = component_manager.get_components_by_id<Metadata>(entity.id).back();
+	Transform & entity_transform
+		= component_manager.get_components_by_id<Transform>(entity.id).back();
+	Metadata & entity_metadata
+		= component_manager.get_components_by_id<Metadata>(entity.id).back();
 };
 
 TEST_F(ReplayManagerTest, Default) {
@@ -33,4 +36,3 @@ TEST_F(ReplayManagerTest, Default) {
 
 	// recording_t recording = replay_manager.record_end();
 }
-
-- 
cgit v1.2.3