CSEngine
Loading...
Searching...
No Matches
SSceneLoader.cpp
1//
2// Created by ounols on 19. 4. 28.
3//
4
5#include "SSceneLoader.h"
6#include "../../../Object/SScene.h"
7#include "../../AssetsDef.h"
8#include "../../MoreComponentFunc.h"
9#include "../../../MacroDef.h"
10#include "../../../Object/SPrefab.h"
11#include "../../SafeLog.h"
12#include "../../../Component/TransformComponent.h"
13#include "../../../Object/SGameObjectFromSPrefab.h"
14
15#include <sstream>
16#include <functional>
17
18#ifndef __ANDROID__
19
20#include <fstream>
21#include <iostream>
22#include <utility>
23
24#endif
25
26using namespace CSE;
27
28void Exploring(SGameObject* obj, int level = 0) {
29 std::string str;
30
31 for (int i = 0; i < level; i++) {
32 str += " ";
33 }
34
35 str += "ㄴ " + obj->GetName() + '\n';
36 SafeLog::Log(str.c_str());
37
38 for (auto child: obj->GetChildren()) {
39 Exploring(child, level + 1);
40 }
41}
42
43SSceneLoader::SSceneLoader() = default;
44
45SSceneLoader::~SSceneLoader() = default;
46
47bool SSceneLoader::SaveScene(SScene* scene, std::string path) {
48
49 std::stringstream value;
50 value << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
51 value << "<CSESCENE version = \"" << "1.0.0" << "\">\n";
52
53 value << GetGameObjectValue(scene->GetRoot());
54
55 value << "</CSESCENE>";
56
57 return Save(value.str(), std::move(path));
58}
59
60std::string SSceneLoader::GetGameObjectValue(SGameObject* obj, bool ignorePrefab) {
61 std::string values;
62
63 if (obj->GetName() != "__ROOT_OF_SCENE__") {
64 std::string resID = obj->GetResourceID();
65 if (!ignorePrefab && !resID.empty()) {
66 if (resID.find('*') == std::string::npos) {
67 values += ComparePrefab(obj);
68 return values;
69 }
70 //루트가 아닌 오브젝트
71 //차후 추가바람
72 return values;
73 }
74
75 values += PrintGameObject(obj);
76 }
77
78 for (auto child: obj->GetChildren()) {
79 values += GetGameObjectValue(child, ignorePrefab);
80 }
81
82 return values;
83}
84
85bool SSceneLoader::SavePrefab(SGameObject* root, std::string path) {
86 std::stringstream value;
87
88 value << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
89 value << "<CSEPREFAB version=\"" << "1.0.0" << "\">\n";
90
91 value << GetGameObjectValue(root);
92
93 value << "</CSEPREFAB>";
94
95 return Save(value.str(), std::move(path));
96}
97
98bool SSceneLoader::Save(const std::string& buf, const std::string& path) {
99#ifndef __ANDROID__
100 std::ofstream file(path);
101 if (!file.is_open()) return false;
102 file << buf;
103 file.close();
104
105 return true;
106#endif
107
108 return false;
109}
110
111SScene* SSceneLoader::LoadScene(const std::string& path) {
112 const XNode* m_root;
113
114 try {
115 m_root = XFILE(path.c_str()).getRoot();
116 }
117 catch (int e) {
118 return nullptr;
119 }
120
121 auto scene = new SScene();
122
123 XNode sce_scene = m_root->getChild("CSESCENE");
124
125 auto node_gameobjects = sce_scene.children;
126 std::vector<NodeKey*> gameobjects;
127 std::vector<ComponentValue*> components;
128
129 for (const auto& node_obj: node_gameobjects) {
130 if (node_obj.name == "gameobject") {
131 ExploringScene(node_obj, gameobjects, components);
132 } else if (node_obj.name == "prefab") {
133 ExploringPrefab(node_obj, gameobjects, components, scene);
134 }
135 }
136
137 LinkingID(gameobjects, scene->GetRoot());
138 LinkingReference(components);
139
140 for (auto gameobj: gameobjects) {
141 SAFE_DELETE(gameobj);
142 }
143
144 for (auto comp: components) {
145 SAFE_DELETE(comp);
146 }
147
148// Exploring(scene->GetRoot());
149 SAFE_DELETE(m_root);
150
151 return scene;
152}
153
154void SSceneLoader::ExploringScene(const XNode& node, std::vector<NodeKey*>& objs, std::vector<ComponentValue*>& comps) {
155 std::string name = ConvertSpaceStr(node.getAttribute("name").value, true);
156 auto node_components = node.children;
157 std::string hash = node.getAttribute("hash").value;
158 auto obj_new = new SGameObject(name, hash);
159
160 for (const auto& comp: node_components) {
161 if (comp.name != "component") continue;
162
163 std::string comp_type = comp.getAttribute("type").value;
164 bool comp_enable = comp.getAttribute("enable").value == "1";
165 SComponent* component = (comp_type == "TransformComponent")
166 ? static_cast<TransformComponent*>(obj_new->GetTransform())
167 : MoreComponentFunc::CreateComponent(obj_new, comp_type);
168
169 auto comp_val = new ComponentValue();
170 comp_val->id = hash + "?" + comp_type;
171 comp_val->node = comp;
172 comp_val->comp = component;
173 component->SetIsEnable(comp_enable);
174
175 comps.push_back(comp_val);
176 }
177
178 auto key = new NodeKey();
179 key->node = node;
180 key->obj = obj_new;
181 key->hash = hash;
182
183 objs.push_back(key);
184}
185
186void SSceneLoader::LinkingID(std::vector<NodeKey*>& objs, SGameObject* root) {
187 std::vector<NodeKey*> remain;
188
189 for (auto node_obj: objs) {
190 auto obj = node_obj->obj;
191 std::string parent_hash = ConvertSpaceStr(node_obj->node.getChild("parent").value);
192 obj->RemoveParent();
193 //parent_hash = parent_hash.substr(1, parent_hash.size() - 2);
194
195 if (parent_hash == "__ROOT_OF_SCENE__") {
196 if (root == nullptr)
197 obj->SetParent(SGameObject::FindByID(parent_hash));
198 else
199 obj->SetParent(root);
200 continue;
201 }
202
203 SGameObject* target = nullptr;
204 for (auto temp: objs) {
205 if (parent_hash == temp->hash) {
206 target = temp->obj;
207 break;
208 }
209 }
210
211 if (target == nullptr) {
212 remain.push_back(node_obj);
213 continue;
214 }
215 // if(target == nullptr) {
216 // target = SGameObject::FindByID(parent_hash);
217 // if(target == nullptr) {
218 // obj->SetParent(SGameObject::FindByID("__ROOT_OF_SCENE__"));
219 // continue;
220 // }
221 // }
222
223 obj->SetParent(target);
224 }
225
226 for (auto node_obj: remain) {
227 auto obj = node_obj->obj;
228 obj->RemoveParent();
229 std::string parent_hash = ConvertSpaceStr(node_obj->node.getChild("parent").value);
230
231 auto parent = SGameObject::FindByHash(parent_hash);
232 obj->SetParent(parent);
233 }
234}
235
236void SSceneLoader::LinkingReference(std::vector<ComponentValue*>& comps) {
237 for (auto comp: comps) {
238 auto node = comp->node;
239 for (const auto& value: node.children) {
240 if (value.name != "value") continue;
241
242 std::string v_name = value.getAttribute("name").value;
243 auto v_values = value.value.toStringVector();
244
245 for (int i = 0; i < v_values.size(); ++i) {
246 v_values[i] = ConvertSpaceStr(v_values[i], true);
247 }
248
249 comp->comp->SetValue(v_name, v_values);
250 }
251 }
252}
253
254void SSceneLoader::ExploringPrefab(const XNode& node, std::vector<NodeKey*>& objs, std::vector<ComponentValue*>& comps,
255 SScene* scene) {
256 std::string name = ConvertSpaceStr(node.getAttribute("name").value, true);
257 auto node_values = node.children;
258 std::string file_id = ConvertSpaceStr(node.getAttribute("fileid").value, true);
259 std::string hash = ConvertSpaceStr(node.getAttribute("hash").value, true);
260
261 //Create!
262 auto prefab = SResource::Create<SPrefab>(file_id);
263 SGameObject* root = prefab->Clone(vec3(), scene->GetRoot());
264 root->SetHash(hash);
265
266 //Change objects value
267 for (const auto& child: node_values) {
268 if (child.name == "gameobject") {
269 ExploringScene(child, objs, comps);
270 } else if (child.name == "changegameobject") {
271 LinkingResourceID(child, root, objs, comps);
272 }
273 }
274
275 // NodeKey* key = new NodeKey();
276 // key->node = node;
277 // key->id = id;
278 // key->obj = root;
279 //
280 // objs.push_back(key);
281}
282
283void SSceneLoader::LinkingResourceID(const XNode& node, SGameObject* root, std::vector<NodeKey*>& objs,
284 std::vector<ComponentValue*>& comps) {
285 std::string obj_fileid = ConvertSpaceStr(node.getAttribute("fileid").value, true);
286
287 if (root->GetResourceID() == obj_fileid) {
288 std::string obj_name = ConvertSpaceStr(node.getAttribute("name").value, true);
289 std::string obj_hash = ConvertSpaceStr(node.getAttribute("hash").value, true);
290
291 auto key = new NodeKey();
292 key->obj = root;
293 key->node = node;
294 key->hash = obj_hash;
295 root->SetName(obj_name);
296 objs.push_back(key);
297
298 for (const auto& comp: node.children) {
299 if (comp.name != "component") continue;
300
301 std::string comp_type = comp.getAttribute("type").value;
302 SComponent* component = nullptr;
303
304 for (auto comp_obj: root->GetComponents()) {
305 if (comp_type == comp_obj->GetClassType()) {
306 component = comp_obj;
307 break;
308 }
309 }
310
311 if (component == nullptr)
312 component = MoreComponentFunc::CreateComponent(root, comp_type);
313
314 auto comp_val = new ComponentValue();
315 comp_val->id = obj_hash + "?" + comp_type;
316 comp_val->node = comp;
317 comp_val->comp = component;
318
319 comps.push_back(comp_val);
320 }
321 }
322
323 auto children = root->GetChildren();
324 for (const auto& child: children) {
325 LinkingResourceID(node, child, objs, comps);
326 }
327}
328
329std::string SSceneLoader::ComparePrefab(SGameObject* obj) {
330 const auto& prefab = SResource::Get<SPrefab>(obj->GetResourceID());
331 if (prefab == nullptr) return "";
332
333 std::string str_p = GetGameObjectValue(prefab->GetRoot(), true);
334 std::string str_o = GetGameObjectValue(obj, true);
335 std::string result;
336 // std::string addedObject_str;
337 std::string absoluteID = obj->GetID();
338
339 const XNode* n_p = XFILE().loadBuffer(str_p);
340 const XNode* n_o = XFILE().loadBuffer(str_o);
341
342 result += std::string("<prefab name=\"") + ConvertSpaceStr(obj->GetName())
343 + "\" fileid=\"" + ConvertSpaceStr(obj->GetResourceID()) +
344 "\" hash=\"" + obj->GetHash() +
345 "\">\n";
346
347 for (const auto& object_node: n_o->children) {
348 bool isFind = false;
349 XNode target_node;
350 std::string obj_id;
351 std::string obj_name = object_node.getAttribute("name").value;
352
353 // fileID가 있는지 확인
354 if (object_node.hasAttribute("fileid")) {
355 obj_id = object_node.getAttribute("fileid").value;
356 } else {
357 // std::string id = object_node.getAttribute("id").value;
358 // addedObject_str += PrintGameObject(SGameObject::FindByID(id));
359 continue;
360 }
361
362 for (const auto& prefab_node: n_p->children) {
363 std::string prefab_id = prefab_node.getAttribute("fileid").value;
364 if (obj_id == prefab_id) {
365 target_node = prefab_node;
366 isFind = true;
367 break;
368 }
369 }
370
371 if (!isFind) continue;
372
373 bool isChanged;
374
375 //이름 확인
376 isChanged = obj_name != target_node.getAttribute("name").value;
377 //컴포넌트 갯수 확인
378 isChanged |= object_node.children.size() != target_node.children.size();
379 auto compare_o = str_o.substr(object_node.sub_index,
380 object_node.getChild("parent").sub_index - object_node.sub_index);
381 auto compare_p = str_p.substr(target_node.sub_index,
382 target_node.getChild("parent").sub_index - target_node.sub_index);
383
384 isChanged |= compare_o != compare_p;
385
386 if (!isChanged) {
387 std::string o_parent_resID;
388 std::string p_parent_resID;
389 std::string parent_o = object_node.getChild("parent").value;
390 std::string parent_p = target_node.getChild("parent").value;
391
392 for (const auto& obj_node: n_o->children) {
393 if (obj_node.getAttribute("hash").value == parent_o) {
394 o_parent_resID = obj_node.getAttribute("ref").value;
395 break;
396 }
397 }
398
399 for (const auto& prf_node: n_p->children) {
400 if (prf_node.getAttribute("hash").value == parent_p) {
401 p_parent_resID = prf_node.getAttribute("ref").value;
402 break;
403 }
404 }
405
406 if (o_parent_resID.empty()) isChanged = true;
407
408 isChanged = isChanged || p_parent_resID != o_parent_resID;
409 }
410
411 if (isChanged) {
412 std::string hash = object_node.getAttribute("hash").value;
413 std::string str = PrintGameObject(SGameObject::FindByHash(hash));
414 result += std::string("<change") + str.substr(1, str.size() - 14) + "</changegameobject>";
415 }
416 }
417
418 // result += addedObject_str;
419 result += "</prefab>";
420
421 SAFE_DELETE(n_p);
422 SAFE_DELETE(n_o);
423 return result;
424}
425
426std::string SSceneLoader::PrintGameObject(SGameObject* obj) {
427 std::string values;
428 const auto& objRef = dynamic_cast<SGameObjectFromSPrefab*>(obj);
429
430 // Pre-allocate space for the string to avoid costly re-allocations
431 values.reserve(1024);
432
433 const std::string& res_id = obj->GetResourceID();
434 values += "<gameobject name=\"" + ConvertSpaceStr(obj->GetName())
435 + "\" hash=\"" + obj->GetHash() + "\"";
436 if (!res_id.empty()) {
437 values += " fileid=\"" + res_id + "\"";
438 }
439 if (objRef != nullptr) {
440 values += " ref=\"" + objRef->GetRefHash() + "\"";
441 }
442 values += ">\n";
443
444 const auto& components = obj->GetComponents();
445 for (const auto& component: components) {
446 values += component->PrintValue();
447 }
448
449 const SGameObject* parent = obj->GetParent();
450 values += "<parent>" + ((parent == nullptr || parent->GetName() == "__ROOT_OF_SCENE__")
451 ? "__ROOT_OF_SCENE__" : ConvertSpaceStr(parent->GetHash())) + "</parent>\n";
452
453 values += "</gameobject>";
454
455 return values;
456}
Definition XML.h:77
Definition XML.h:43