Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
EnumCatalogManager.cpp
Go to the documentation of this file.
1/*
2 * Olympe Blueprint Editor - Enum Catalog Manager Implementation
3 */
4
6#include "../json_helper.h"
7#include <fstream>
8#include <iostream>
9
11
12namespace Olympe
13{
14 // Singleton instance
20
22 : m_Initialized(false)
23 , m_CatalogsPath("Blueprints/Catalogues/")
24 {
25 }
26
31
33 {
34 if (m_Initialized)
35 return;
36
37 std::cout << "[EnumCatalogManager] Initializing...\n";
38
39 // Load all catalogs
41 {
42 std::cerr << "[EnumCatalogManager] Failed to load catalogs: " << m_LastError << "\n";
43 return;
44 }
45
46 m_Initialized = true;
47 std::cout << "[EnumCatalogManager] Initialized successfully\n";
48 }
49
51 {
52 if (!m_Initialized)
53 return;
54
55 std::cout << "[EnumCatalogManager] Shutting down...\n";
56
57 m_ActionCatalog.reset();
58 m_ConditionCatalog.reset();
59 m_DecoratorCatalog.reset();
60
61 m_Initialized = false;
62 }
63
65 {
67 m_LastError.clear();
68
69 // Load each catalog
70 bool success = true;
71
72 if (!LoadCatalog(m_CatalogsPath + "ActionTypes.json"))
73 {
74 std::cerr << "[EnumCatalogManager] Failed to load ActionTypes catalog\n";
75 success = false;
76 }
77
78 if (!LoadCatalog(m_CatalogsPath + "ConditionTypes.json"))
79 {
80 std::cerr << "[EnumCatalogManager] Failed to load ConditionTypes catalog\n";
81 success = false;
82 }
83
84 if (!LoadCatalog(m_CatalogsPath + "DecoratorTypes.json"))
85 {
86 std::cerr << "[EnumCatalogManager] Failed to load DecoratorTypes catalog\n";
87 success = false;
88 }
89
90 return success;
91 }
92
93 bool EnumCatalogManager::LoadCatalog(const std::string& filepath)
94 {
95 std::cout << "[EnumCatalogManager] Loading catalog: " << filepath << "\n";
96
97 // Read JSON file
98 std::ifstream file(filepath);
99 if (!file.is_open())
100 {
101 m_LastError = "Failed to open file: " + filepath;
102 return false;
103 }
104 json j;
105 std::string jsonText((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
106 try
107 {
108 j = json::parse(jsonText);
109 }
110 catch (const std::exception& e)
111 {
112 m_LastError = "JSON parse error: " + std::string(e.what());
113 return false;
114 }
115
116 // Parse catalog
117 auto catalog = std::make_unique<EnumCatalog>();
118 catalog->filepath = filepath;
119
120 if (!ParseCatalogJson(j, *catalog))
121 {
122 m_LastError = "Failed to parse catalog: " + filepath;
123 return false;
124 }
125
126 // Validate catalog
127 std::string validationError;
129 {
130 m_LastError = "Catalog validation failed: " + validationError;
131 return false;
132 }
133
134 // Store catalog based on type
135 if (catalog->catalogType == "Actions")
136 {
137 m_ActionCatalog = std::move(catalog);
138 std::cout << "[EnumCatalogManager] Loaded " << m_ActionCatalog->types.size() << " action types\n";
139 }
140 else if (catalog->catalogType == "Conditions")
141 {
142 m_ConditionCatalog = std::move(catalog);
143 std::cout << "[EnumCatalogManager] Loaded " << m_ConditionCatalog->types.size() << " condition types\n";
144 }
145 else if (catalog->catalogType == "Decorators")
146 {
147 m_DecoratorCatalog = std::move(catalog);
148 std::cout << "[EnumCatalogManager] Loaded " << m_DecoratorCatalog->types.size() << " decorator types\n";
149 }
150 else
151 {
152 m_LastError = "Unknown catalog type: " + catalog->catalogType;
153 return false;
154 }
155
156 return true;
157 }
158
160 {
161 std::cout << "[EnumCatalogManager] Hot-reloading catalogs...\n";
162
163 // Clear existing catalogs
164 m_ActionCatalog.reset();
165 m_ConditionCatalog.reset();
166 m_DecoratorCatalog.reset();
167
168 // Reload from disk
170 }
171
173 {
174 // Parse version
175 catalog.version = JsonHelper::GetString(j, "version", "1.0");
176
177 // Parse catalog type
178 catalog.catalogType = JsonHelper::GetString(j, "catalogType", "");
179 if (catalog.catalogType.empty())
180 {
181 m_LastError = "Missing catalogType field";
182 return false;
183 }
184
185 // Parse types array
186 if (!JsonHelper::IsArray(j, "types"))
187 {
188 m_LastError = "Missing or invalid 'types' array";
189 return false;
190 }
191
192 JsonHelper::ForEachInArray(j, "types", [&](const json& typeJson, size_t idx)
193 {
194 CatalogType type;
195 if (ParseCatalogType(typeJson, type))
196 {
197 catalog.types.push_back(type);
198 }
199 });
200
201 return true;
202 }
203
205 {
206 type.id = JsonHelper::GetString(j, "id", "");
207 type.name = JsonHelper::GetString(j, "name", type.id);
208 type.description = JsonHelper::GetString(j, "description", "");
209 type.category = JsonHelper::GetString(j, "category", "");
210 type.tooltip = JsonHelper::GetString(j, "tooltip", type.description);
211
212 // Parse parameters if present
213 if (JsonHelper::IsArray(j, "parameters"))
214 {
215 JsonHelper::ForEachInArray(j, "parameters", [&](const json& paramJson, size_t idx)
216 {
219 {
220 type.parameters.push_back(param);
221 }
222 });
223 }
224
225 return !type.id.empty();
226 }
227
229 {
230 param.name = JsonHelper::GetString(j, "name", "");
231 param.type = JsonHelper::GetString(j, "type", "string");
232 param.required = JsonHelper::GetBool(j, "required", false);
233
234 // Get default value
235 if (j.contains("default"))
236 {
237 const auto& defaultVal = j["default"];
238 if (defaultVal.is_string())
239 param.defaultValue = defaultVal.get<std::string>();
240 else if (defaultVal.is_number())
241 param.defaultValue = std::to_string(defaultVal.get<double>());
242 else if (defaultVal.is_boolean())
243 param.defaultValue = defaultVal.get<bool>() ? "true" : "false";
244 }
245
246 return !param.name.empty();
247 }
248
250 {
251 if (catalog.types.empty())
252 {
253 errorMsg = "Catalog has no types";
254 return false;
255 }
256
257 // Check for duplicate IDs
258 std::map<std::string, int> idCount;
259 for (const auto& type : catalog.types)
260 {
261 if (type.id.empty())
262 {
263 errorMsg = "Type with empty ID found";
264 return false;
265 }
266 idCount[type.id]++;
267 }
268
269 for (const auto& pair : idCount)
270 {
271 if (pair.second > 1)
272 {
273 errorMsg = "Duplicate type ID: " + pair.first;
274 return false;
275 }
276 }
277
278 return true;
279 }
280
281 // Type queries
282 std::vector<std::string> EnumCatalogManager::GetActionTypes() const
283 {
284 if (m_ActionCatalog)
285 return m_ActionCatalog->GetTypeIds();
286 return {};
287 }
288
289 std::vector<std::string> EnumCatalogManager::GetConditionTypes() const
290 {
292 return m_ConditionCatalog->GetTypeIds();
293 return {};
294 }
295
296 std::vector<std::string> EnumCatalogManager::GetDecoratorTypes() const
297 {
299 return m_DecoratorCatalog->GetTypeIds();
300 return {};
301 }
302
303 // Type lookup
304 const CatalogType* EnumCatalogManager::FindActionType(const std::string& id) const
305 {
306 if (m_ActionCatalog)
307 return m_ActionCatalog->FindType(id);
308 return nullptr;
309 }
310
311 const CatalogType* EnumCatalogManager::FindConditionType(const std::string& id) const
312 {
314 return m_ConditionCatalog->FindType(id);
315 return nullptr;
316 }
317
318 const CatalogType* EnumCatalogManager::FindDecoratorType(const std::string& id) const
319 {
321 return m_DecoratorCatalog->FindType(id);
322 return nullptr;
323 }
324
325 // Validation
326 bool EnumCatalogManager::IsValidActionType(const std::string& id) const
327 {
328 return FindActionType(id) != nullptr;
329 }
330
331 bool EnumCatalogManager::IsValidConditionType(const std::string& id) const
332 {
333 return FindConditionType(id) != nullptr;
334 }
335
336 bool EnumCatalogManager::IsValidDecoratorType(const std::string& id) const
337 {
338 return FindDecoratorType(id) != nullptr;
339 }
340}
nlohmann::json json
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
EnumCatalogManager - Singleton manager for enum catalogs Loads and manages dynamic type definitions f...
const CatalogType * FindActionType(const std::string &id) const
bool IsValidActionType(const std::string &id) const
std::vector< std::string > GetDecoratorTypes() const
std::vector< std::string > GetActionTypes() const
bool ParseCatalogParameter(const nlohmann::json &j, CatalogParameter &param)
bool ValidateCatalog(const EnumCatalog &catalog, std::string &errorMsg)
const CatalogType * FindDecoratorType(const std::string &id) const
bool IsValidDecoratorType(const std::string &id) const
bool IsValidConditionType(const std::string &id) const
std::vector< std::string > GetConditionTypes() const
bool ParseCatalogType(const nlohmann::json &j, CatalogType &type)
bool ParseCatalogJson(const nlohmann::json &j, EnumCatalog &catalog)
bool LoadCatalog(const std::string &filepath)
bool LoadCatalogs(const std::string &catalogsPath)
static EnumCatalogManager & Instance()
std::unique_ptr< EnumCatalog > m_ConditionCatalog
std::unique_ptr< EnumCatalog > m_ActionCatalog
const CatalogType * FindConditionType(const std::string &id) const
std::unique_ptr< EnumCatalog > m_DecoratorCatalog
std::string GetString(const json &j, const std::string &key, const std::string &defaultValue="")
Safely get a string value from JSON.
void ForEachInArray(const json &j, const std::string &key, std::function< void(const json &, size_t)> callback)
Iterate over an array with a callback function.
bool IsArray(const json &j, const std::string &key)
Check if a key contains an array.
bool GetBool(const json &j, const std::string &key, bool defaultValue=false)
Safely get a boolean value from JSON.
nlohmann::json json
nlohmann::json json
std::vector< CatalogParameter > parameters