NcEngine
All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
FreeComponentGroup.h
1#pragma once
2
4
5#include "ncutility/NcError.h"
6
7#include <concepts>
8#include <memory>
9#include <set>
10#include <vector>
11
12namespace nc::ecs::detail
13{
15{
16 public:
17 FreeComponentGroup() = default;
19 FreeComponentGroup& operator=(FreeComponentGroup&&) = default;
21 FreeComponentGroup& operator=(const FreeComponentGroup&) = delete;
22
23 template<std::derived_from<FreeComponent> T, class... Args>
24 auto Add(Args&& ... args) -> T&;
25
26 template<std::derived_from<FreeComponent> T>
27 auto Remove() -> bool;
28
29 template<std::derived_from<FreeComponent> T>
30 bool Contains() const noexcept;
31
32 template<std::derived_from<FreeComponent> T>
33 auto Get() const -> T&;
34
35 void CommitStagedComponents();
36 auto IsPersistentGroup() -> bool;
37
38 private:
39 std::vector<std::unique_ptr<FreeComponent>> m_components;
40 std::vector<std::unique_ptr<FreeComponent>> m_toAdd;
41 std::set<size_t> m_toRemove;
42};
43
44template<std::derived_from<FreeComponent> T, class ... Args>
45auto FreeComponentGroup::Add(Args&& ... args) -> T&
46{
47 NC_ASSERT(!Contains<T>(), "Entity already has a component of this type");
48 auto newComponent = std::make_unique<T>(std::forward<Args>(args)...);
49 auto& out = *newComponent;
50 m_toAdd.push_back(std::move(newComponent));
51 return out;
52}
53
54template<std::derived_from<FreeComponent> T>
55auto FreeComponentGroup::Remove() -> bool
56{
57 for(size_t i = 0; auto& component : m_components)
58 {
59 if(dynamic_cast<T*>(component.get()))
60 {
61 m_toRemove.insert(i);
62 return true;
63 }
64
65 ++i;
66 }
67
68 return false;
69}
70
71template<std::derived_from<FreeComponent> T>
72bool FreeComponentGroup::Contains() const noexcept
73{
74 for(auto& item : m_components)
75 {
76 auto* ptr = dynamic_cast<T*>(item.get());
77 if(ptr)
78 return true;
79 }
80
81 for(auto& item : m_toAdd)
82 {
83 auto* ptr = dynamic_cast<T*>(item.get());
84 if(ptr)
85 return true;
86 }
87
88 return false;
89}
90
91template<std::derived_from<FreeComponent> T>
92auto FreeComponentGroup::Get() const -> T&
93{
94 for(auto& item : m_components)
95 {
96 auto* ptr = dynamic_cast<T*>(item.get());
97 if(ptr)
98 return *ptr;
99 }
100
101 for(auto& item : m_toAdd)
102 {
103 auto* ptr = dynamic_cast<T*>(item.get());
104 if(ptr)
105 return *ptr;
106 }
107
108 throw NcError("Component does not exist");
109}
110
111inline void FreeComponentGroup::CommitStagedComponents()
112{
113 for(auto i : m_toRemove)
114 {
115 m_components.at(i) = std::move(m_components.back());
116 m_components.pop_back();
117 }
118
119 m_toRemove.clear();
120
121 for(auto& toAdd : m_toAdd)
122 {
123 m_components.push_back(std::move(toAdd));
124 }
125
126 m_toAdd.clear();
127}
128
129inline auto FreeComponentGroup::IsPersistentGroup() -> bool
130{
131 return !m_components.empty()
132 ? m_components[0]->ParentEntity().IsPersistent()
133 : false;
134}
135} // namespace nc::ecs::detail
Definition: FreeComponentGroup.h:15