aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/manager/ReplayManager.h
blob: d3af879f9a38a878c1fa13cd9abdfb29e20191d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#pragma once

#include <unordered_map>

#include "Manager.h"
#include "ComponentManager.h"
#include "util/OptionalRef.h"

namespace crepe {

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
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, //!< 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;
	//! 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;
};

} // namespace crepe