PixelBullet  0.0.1
A C++ game engine
Loading...
Searching...
No Matches
Scene.hpp
1#pragma once
2
3#include "PixelBullet/Filesystem/Resources/TypeInfo.hpp"
4#include "PixelBullet/Math/ID.hpp"
5#include "PixelBullet/Scene/ComponentStorage.hpp"
6
7#include <fstream>
8#include <memory>
9#include <sstream>
10#include <stdexcept>
11#include <type_traits>
12#include <unordered_map>
13#include <vector>
14
15namespace PixelBullet
16{
17 class Scene
18 {
19 public:
20 ID CreateEntity()
21 {
22 ID id(static_cast<uint32_t>(m_Entities.size()), 0);
23 m_Entities.push_back(id);
24 return id;
25 }
26
27 void DestroyEntity(ID id)
28 {
29 if (id.Index() < m_Entities.size())
30 {
31 m_Entities[id.Index()] = ID::Invalid();
32 }
33 for (auto& pair : m_ComponentStorage)
34 {
35 pair.second->RemoveComponent(id.Index());
36 }
37 }
38
39 template <typename T, typename... Args>
40 T& AddComponent(ID id, Args&&... args)
41 {
42 auto storage = GetOrCreateComponentStorage<T>();
43 T component{ std::forward<Args>(args)... };
44 storage->Set.Insert(id.Index(), component);
45 return storage->Set.Get(id.Index());
46 }
47
48 template <typename T>
49 void RemoveComponent(ID id)
50 {
51 auto storage = GetOrCreateComponentStorage<T>();
52 storage->Set.Erase(id.Index());
53 }
54
55 template <typename T>
56 bool HasComponent(ID id) const
57 {
58 const TypeID typeId = TypeInfo<ComponentStorageBase>::template Get<ComponentStorage<T>>();
59 auto it = m_ComponentStorage.find(typeId);
60 if (it != m_ComponentStorage.end())
61 {
62 auto storage = static_cast<ComponentStorage<T>*>(it->second.get());
63 return storage->Set.Has(id.Index());
64 }
65 return false;
66 }
67
68 template <typename T>
69 T& GetComponent(ID id)
70 {
71 auto storage = GetOrCreateComponentStorage<T>();
72 return storage->Set.Get(id.Index());
73 }
74
75 template <typename T>
76 const SparseSet<T>& GetComponentSet() const
77 {
78 const TypeID typeId = TypeInfo<ComponentStorageBase>::template Get<ComponentStorage<T>>();
79 auto it = m_ComponentStorage.find(typeId);
80 if (it != m_ComponentStorage.end())
81 {
82 auto storage = static_cast<ComponentStorage<T>*>(it->second.get());
83 return storage->Set;
84 }
85 throw std::runtime_error("Component not found");
86 }
87
88 void SaveToFile(const std::string& path) const
89 {
90 Node root;
91 root["entities"] << m_Entities;
92 Node comps;
93 for (const auto& pair : m_ComponentStorage)
94 {
95 Node compNode;
96 pair.second->Serialize(compNode);
97 comps[pair.second->GetTypeName()] = compNode;
98 }
99 root["components"] = comps;
100 std::ofstream ofs(path);
101 if (!ofs)
102 {
103 throw std::runtime_error("Failed to open file for writing: " + path);
104 }
105 Node::WriteYAML(root, ofs);
106 }
107
108 void LoadFromFile(const std::string& path)
109 {
110 std::ifstream ifs(path);
111 if (!ifs)
112 {
113 throw std::runtime_error("Failed to open file for reading: " + path);
114 }
115 std::stringstream buffer;
116 buffer << ifs.rdbuf();
117 Node root;
118 if (!Node::ParseYAML(root, buffer.str()))
119 {
120 throw std::runtime_error("Failed to parse YAML");
121 }
122 root["entities"] >> m_Entities;
123 Node comps = root["components"];
124 for (const auto& [key, compNode] : comps.GetProperties())
125 {
126 for (auto& pair : m_ComponentStorage)
127 {
128 if (pair.second->GetTypeName() == key)
129 {
130 pair.second->Deserialize(compNode);
131 break;
132 }
133 }
134 }
135 }
136
137 friend Node& operator<<(Node& node, const Scene& scene)
138 {
139 node["entities"] << scene.m_Entities;
140 Node comps;
141 for (const auto& pair : scene.m_ComponentStorage)
142 {
143 Node compNode;
144 pair.second->Serialize(compNode);
145 comps[pair.second->GetTypeName()] = compNode;
146 }
147 node["components"] = comps;
148 return node;
149 }
150
151 friend const Node& operator>>(const Node& node, Scene& scene)
152 {
153 node["entities"] >> scene.m_Entities;
154 Node comps = node["components"];
155 for (const auto& [key, compNode] : comps.GetProperties())
156 {
157 for (auto& pair : scene.m_ComponentStorage)
158 {
159 if (pair.second->GetTypeName() == key)
160 {
161 pair.second->Deserialize(compNode);
162 break;
163 }
164 }
165 }
166 return node;
167 }
168
169 private:
170 std::vector<ID> m_Entities;
171 std::unordered_map<TypeID, std::unique_ptr<ComponentStorageBase>> m_ComponentStorage;
172
173 private:
174 template <typename T>
175 ComponentStorage<T>* GetOrCreateComponentStorage()
176 {
177 const TypeID typeId = TypeInfo<ComponentStorageBase>::template Get<ComponentStorage<T>>();
178 auto it = m_ComponentStorage.find(typeId);
179 if (it != m_ComponentStorage.end())
180 {
181 return static_cast<ComponentStorage<T>*>(it->second.get());
182 }
183 else
184 {
185 auto storage = std::make_unique<ComponentStorage<T>>();
186 ComponentStorage<T>* ptr = storage.get();
187 m_ComponentStorage[typeId] = std::move(storage);
188 return ptr;
189 }
190 }
191 };
192
193 inline Node& operator<<(Node& node, const ID& id)
194 {
195 node.SetValue(std::to_string(id.Raw()));
196 node.SetType(NodeType::Integer);
197 return node;
198 }
199
200 inline const Node& operator>>(const Node& node, ID& id)
201 {
202 uint32_t raw = static_cast<uint32_t>(std::stoul(node.GetValue()));
203 id = ID::FromRaw(raw);
204 return node;
205 }
206} // namespace PixelBullet
Definition ID.hpp:9
Represents a hierarchical node capable of storing various data types and supporting YAML serializatio...
Definition Node.hpp:51
Definition Scene.hpp:18
Definition SparseSet.hpp:12
Definition TypeInfo.hpp:14
Definition ComponentStorage.hpp:23