aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/ComponentManager.hpp
blob: c872594bf584f30e125e44a0d997eb1ba6485cfb (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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#pragma once

#include <type_traits>

#include "ComponentManager.h"
#include "api/BehaviorScript.h"

namespace crepe {

template <class T, typename... Args>
void ComponentManager::add_component(uint32_t id, Args &&... args) {
	using namespace std;

	static_assert(is_base_of<Component, T>::value, "add_component must recieve a derivative class of Component");

	// Determine the type of T (this is used as the key of the unordered_map<>)
	type_index type = typeid(T);

	// Check if this component type is already in the unordered_map<>
	if (components.find(type) == components.end()) {
		//If not, create a new (empty) vector<> of vector<unique_ptr<Component>>
		components[type] = vector<vector<unique_ptr<Component>>>();
	}

	// Resize the vector<> if the id is greater than the current size
	if (id >= components[type].size()) {
		// Initialize new slots to nullptr (resize does automatically init to nullptr)
		components[type].resize(id + 1);
	}

	// Create a new component of type T (arguments directly forwarded). The
	// constructor must be called by ComponentManager.
	T * instance = new T(forward<Args>(args)...);
	// store its unique_ptr in the vector<>
	components[type][id].push_back(unique_ptr<T>(instance));
}

template <typename T>
void ComponentManager::delete_components_by_id(uint32_t id) {
	using namespace std;

	// Determine the type of T (this is used as the key of the unordered_map<>)
	type_index type = typeid(T);

	// Find the type (in the unordered_map<>)
	if (components.find(type) != components.end()) {
		// Get the correct vector<>
		vector<vector<unique_ptr<Component>>> & component_array
			= components[type];

		// Make sure that the id (that we are looking for) is within the boundaries of the vector<>
		if (id < component_array.size()) {
			// Clear the whole vector<> of this specific type and id
			component_array[id].clear();
		}
	}
}

template <typename T>
void ComponentManager::delete_components() {
	// Determine the type of T (this is used as the key of the unordered_map<>)
	std::type_index type = typeid(T);

	if (components.find(type) == components.end()) return;

	components[type].clear();
}

template <typename T>
std::vector<std::reference_wrapper<T>>
ComponentManager::get_components_by_id(uint32_t id) const {
	using namespace std;

	// Determine the type of T (this is used as the key of the unordered_map<>)
	type_index type = typeid(T);

	// Create an empty vector<>
	vector<reference_wrapper<T>> component_vector;

	if (components.find(type) == components.end()) return component_vector;

	// Get the correct vector<>
	const vector<vector<unique_ptr<Component>>> & component_array = components.at(type);

	// Make sure that the id (that we are looking for) is within the boundaries of the vector<>
	if (id >= component_array.size()) return component_vector;

	// Loop trough the whole vector<>
	for (const unique_ptr<Component> & component_ptr : component_array[id]) {
		// Cast the unique_ptr to a raw pointer
		T * casted_component = static_cast<T *>(component_ptr.get());

		if (casted_component == nullptr) continue;

		// Add the dereferenced raw pointer to the vector<>
		component_vector.push_back(*casted_component);
	}

	return component_vector;
}

template <typename T>
std::vector<std::reference_wrapper<T>>
ComponentManager::get_components_by_type() const {
	using namespace std;

	// Determine the type of T (this is used as the key of the unordered_map<>)
	type_index type = typeid(T);

	// Create an empty vector<>
	vector<reference_wrapper<T>> component_vector;
	// Set the id to 0 (the id will also be stored in the returned vector<>)
	// uint32_t id = 0;

	// Find the type (in the unordered_map<>)
	if (components.find(type) == components.end()) return component_vector;

	// Get the correct vector<>
	const vector<vector<unique_ptr<Component>>> & component_array = components.at(type);

	// Loop through the whole vector<>
	for (const vector<unique_ptr<Component>> & component : component_array) {
		// Loop trough the whole vector<>
		for (const unique_ptr<Component> & component_ptr : component) {
			// Cast the unique_ptr to a raw pointer
			T * casted_component = static_cast<T *>(component_ptr.get());

			// Ensure that the cast was successful
			if (casted_component == nullptr) continue;

			// Pair the dereferenced raw pointer and the id and add it to the vector<>
			component_vector.emplace_back(ref(*casted_component));
		}

		// Increase the id (the id will also be stored in the returned vector<>)
		//++id;
	}

	// Return the vector<>
	return component_vector;
}

} // namespace crepe