GCC Code Coverage Report


Directory: ./
File: lib/ecs/include/ECS/ComponentManager.hpp
Date: 2025-09-29 13:19:55
Exec Total Coverage
Lines: 42 49 85.7%
Functions: 22 84 26.2%
Branches: 23 53 43.4%

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