Line | Branch | Exec | Source |
---|---|---|---|
1 | #pragma once | ||
2 | |||
3 | #include "Types.hpp" | ||
4 | #include "Component.hpp" | ||
5 | #include <unordered_map> | ||
6 | #include <memory> | ||
7 | #include <vector> | ||
8 | #include <typeinfo> | ||
9 | #include <algorithm> | ||
10 | |||
11 | namespace ECS { | ||
12 | class IComponentArray { | ||
13 | public: | ||
14 | 18 | virtual ~IComponentArray() = default; | |
15 | virtual void RemoveComponent(EntityID entity) = 0; | ||
16 | virtual void Clear() = 0; | ||
17 | }; | ||
18 | |||
19 | template<typename T> | ||
20 | class ComponentArray : public IComponentArray { | ||
21 | private: | ||
22 | std::unordered_map<EntityID, std::unique_ptr<T>> m_components; | ||
23 | |||
24 | public: | ||
25 | 20 | void AddComponent(EntityID entity, std::unique_ptr<T> component) { | |
26 | 20 | m_components[entity] = std::move(component); | |
27 | 20 | } | |
28 | |||
29 | 6 | T* GetComponent(EntityID entity) { | |
30 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
6 | auto it = m_components.find(entity); |
31 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | return (it != m_components.end()) ? it->second.get() : nullptr; |
32 | } | ||
33 | |||
34 | 4 | void RemoveComponent(EntityID entity) override { | |
35 | 4 | m_components.erase(entity); | |
36 | 4 | } | |
37 | |||
38 | 8 | bool HasComponent(EntityID entity) const { | |
39 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
8 | return m_components.find(entity) != m_components.end(); |
40 | } | ||
41 | |||
42 | ✗ | void Clear() override { | |
43 | ✗ | m_components.clear(); | |
44 | ✗ | } | |
45 | |||
46 | ✗ | auto begin() { return m_components.begin(); } | |
47 | ✗ | auto end() { return m_components.end(); } | |
48 | auto begin() const { return m_components.begin(); } | ||
49 | auto end() const { return m_components.end(); } | ||
50 | }; | ||
51 | |||
52 | class ComponentManager { | ||
53 | private: | ||
54 | std::unordered_map<ComponentTypeID, std::unique_ptr<IComponentArray>> m_componentArrays; | ||
55 | std::unordered_map<EntityID, std::vector<ComponentTypeID>> m_entityComponents; | ||
56 | |||
57 | template<typename T> | ||
58 | 28 | ComponentArray<T>* GetComponentArray() { | |
59 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
28 | ComponentTypeID typeID = Component<T>::GetStaticTypeID(); |
60 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
28 | auto it = m_componentArrays.find(typeID); |
61 | |||
62 |
2/2✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5 times.
|
28 | if (it == m_componentArrays.end()) { |
63 |
2/4✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
|
18 | m_componentArrays[typeID] = std::make_unique<ComponentArray<T>>(); |
64 | } | ||
65 | |||
66 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
56 | return static_cast<ComponentArray<T>*>(m_componentArrays[typeID].get()); |
67 | } | ||
68 | |||
69 | public: | ||
70 | 6 | ComponentManager() = default; | |
71 | 6 | ~ComponentManager() = default; | |
72 | |||
73 | template<typename T, typename... Args> | ||
74 | 20 | T* AddComponent(EntityID entity, Args&&... args) { | |
75 |
2/5✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
20 | auto component = std::make_unique<T>(std::forward<Args>(args)...); |
76 | 20 | T* componentPtr = component.get(); | |
77 | |||
78 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
|
20 | GetComponentArray<T>()->AddComponent(entity, std::move(component)); |
79 | |||
80 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | ComponentTypeID typeID = Component<T>::GetStaticTypeID(); |
81 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
20 | m_entityComponents[entity].push_back(typeID); |
82 | |||
83 | 20 | return componentPtr; | |
84 | 20 | } | |
85 | |||
86 | template<typename T> | ||
87 | 6 | T* GetComponent(EntityID entity) { | |
88 | 6 | return GetComponentArray<T>()->GetComponent(entity); | |
89 | } | ||
90 | |||
91 | template<typename T> | ||
92 | 1 | void RemoveComponent(EntityID entity) { | |
93 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | GetComponentArray<T>()->RemoveComponent(entity); |
94 | |||
95 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ComponentTypeID typeID = Component<T>::GetStaticTypeID(); |
96 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | auto& components = m_entityComponents[entity]; |
97 |
2/4✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
|
1 | components.erase(std::remove(components.begin(), components.end(), typeID), components.end()); |
98 | 1 | } | |
99 | |||
100 | template<typename T> | ||
101 | 5 | bool HasComponent(EntityID entity) const { | |
102 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
5 | ComponentTypeID typeID = Component<T>::GetStaticTypeID(); |
103 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
5 | auto it = m_componentArrays.find(typeID); |
104 |
0/2✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
5 | if (it == m_componentArrays.end()) { |
105 | 1 | return false; | |
106 | } | ||
107 |
0/2✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
4 | return static_cast<const ComponentArray<T>*>(it->second.get())->HasComponent(entity); |
108 | } | ||
109 | |||
110 | void RemoveAllComponents(EntityID entity); | ||
111 | void Clear(); | ||
112 | |||
113 | template<typename T> | ||
114 | ✗ | ComponentArray<T>* GetAllComponents() { | |
115 | ✗ | return GetComponentArray<T>(); | |
116 | } | ||
117 | }; | ||
118 | } | ||
119 |