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"
31 for (
int i = 0; i < level; i++) {
35 str +=
"ㄴ " + obj->GetName() +
'\n';
36 SafeLog::Log(str.c_str());
38 for (
auto child: obj->GetChildren()) {
39 Exploring(child, level + 1);
43SSceneLoader::SSceneLoader() =
default;
45SSceneLoader::~SSceneLoader() =
default;
47bool SSceneLoader::SaveScene(
SScene* scene, std::string path) {
49 std::stringstream value;
50 value <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
51 value <<
"<CSESCENE version = \"" <<
"1.0.0" <<
"\">\n";
53 value << GetGameObjectValue(scene->GetRoot());
55 value <<
"</CSESCENE>";
57 return Save(value.str(), std::move(path));
60std::string SSceneLoader::GetGameObjectValue(
SGameObject* obj,
bool ignorePrefab) {
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);
75 values += PrintGameObject(obj);
78 for (
auto child: obj->GetChildren()) {
79 values += GetGameObjectValue(child, ignorePrefab);
85bool SSceneLoader::SavePrefab(
SGameObject* root, std::string path) {
86 std::stringstream value;
88 value <<
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
89 value <<
"<CSEPREFAB version=\"" <<
"1.0.0" <<
"\">\n";
91 value << GetGameObjectValue(root);
93 value <<
"</CSEPREFAB>";
95 return Save(value.str(), std::move(path));
98bool SSceneLoader::Save(
const std::string& buf,
const std::string& path) {
100 std::ofstream file(path);
101 if (!file.is_open())
return false;
111SScene* SSceneLoader::LoadScene(
const std::string& path) {
115 m_root =
XFILE(path.c_str()).getRoot();
121 auto scene =
new SScene();
123 XNode sce_scene = m_root->getChild(
"CSESCENE");
125 auto node_gameobjects = sce_scene.children;
126 std::vector<NodeKey*> gameobjects;
127 std::vector<ComponentValue*> components;
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);
137 LinkingID(gameobjects, scene->GetRoot());
138 LinkingReference(components);
140 for (
auto gameobj: gameobjects) {
141 SAFE_DELETE(gameobj);
144 for (
auto comp: components) {
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;
160 for (
const auto& comp: node_components) {
161 if (comp.name !=
"component")
continue;
163 std::string comp_type = comp.getAttribute(
"type").value;
164 bool comp_enable = comp.getAttribute(
"enable").value ==
"1";
165 SComponent* component = (comp_type ==
"TransformComponent")
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);
175 comps.push_back(comp_val);
178 auto key =
new NodeKey();
186void SSceneLoader::LinkingID(std::vector<NodeKey*>& objs,
SGameObject* root) {
187 std::vector<NodeKey*> remain;
189 for (
auto node_obj: objs) {
190 auto obj = node_obj->obj;
191 std::string parent_hash = ConvertSpaceStr(node_obj->node.getChild(
"parent").value);
195 if (parent_hash ==
"__ROOT_OF_SCENE__") {
197 obj->SetParent(SGameObject::FindByID(parent_hash));
199 obj->SetParent(root);
204 for (
auto temp: objs) {
205 if (parent_hash == temp->hash) {
211 if (target ==
nullptr) {
212 remain.push_back(node_obj);
223 obj->SetParent(target);
226 for (
auto node_obj: remain) {
227 auto obj = node_obj->obj;
229 std::string parent_hash = ConvertSpaceStr(node_obj->node.getChild(
"parent").value);
231 auto parent = SGameObject::FindByHash(parent_hash);
232 obj->SetParent(parent);
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;
242 std::string v_name = value.getAttribute(
"name").value;
243 auto v_values = value.value.toStringVector();
245 for (
int i = 0; i < v_values.size(); ++i) {
246 v_values[i] = ConvertSpaceStr(v_values[i],
true);
249 comp->comp->SetValue(v_name, v_values);
254void SSceneLoader::ExploringPrefab(
const XNode& node, std::vector<NodeKey*>& objs, std::vector<ComponentValue*>& comps,
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);
262 auto prefab = SResource::Create<SPrefab>(file_id);
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);
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);
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);
291 auto key =
new NodeKey();
294 key->hash = obj_hash;
295 root->SetName(obj_name);
298 for (
const auto& comp: node.children) {
299 if (comp.name !=
"component")
continue;
301 std::string comp_type = comp.getAttribute(
"type").value;
304 for (
auto comp_obj: root->GetComponents()) {
305 if (comp_type == comp_obj->GetClassType()) {
306 component = comp_obj;
311 if (component ==
nullptr)
312 component = MoreComponentFunc::CreateComponent(root, comp_type);
314 auto comp_val =
new ComponentValue();
315 comp_val->id = obj_hash +
"?" + comp_type;
316 comp_val->node = comp;
317 comp_val->comp = component;
319 comps.push_back(comp_val);
323 auto children = root->GetChildren();
324 for (
const auto& child: children) {
325 LinkingResourceID(node, child, objs, comps);
329std::string SSceneLoader::ComparePrefab(
SGameObject* obj) {
330 const auto& prefab = SResource::Get<SPrefab>(obj->GetResourceID());
331 if (prefab ==
nullptr)
return "";
333 std::string str_p = GetGameObjectValue(prefab->GetRoot(),
true);
334 std::string str_o = GetGameObjectValue(obj,
true);
337 std::string absoluteID = obj->GetID();
342 result += std::string(
"<prefab name=\"") + ConvertSpaceStr(obj->GetName())
343 +
"\" fileid=\"" + ConvertSpaceStr(obj->GetResourceID()) +
344 "\" hash=\"" + obj->GetHash() +
347 for (
const auto& object_node: n_o->children) {
351 std::string obj_name = object_node.getAttribute(
"name").value;
354 if (object_node.hasAttribute(
"fileid")) {
355 obj_id = object_node.getAttribute(
"fileid").value;
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;
371 if (!isFind)
continue;
376 isChanged = obj_name != target_node.getAttribute(
"name").value;
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);
384 isChanged |= compare_o != compare_p;
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;
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;
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;
406 if (o_parent_resID.empty()) isChanged =
true;
408 isChanged = isChanged || p_parent_resID != o_parent_resID;
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>";
419 result +=
"</prefab>";
426std::string SSceneLoader::PrintGameObject(
SGameObject* obj) {
431 values.reserve(1024);
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 +
"\"";
439 if (objRef !=
nullptr) {
440 values +=
" ref=\"" + objRef->GetRefHash() +
"\"";
444 const auto& components = obj->GetComponents();
445 for (
const auto& component: components) {
446 values += component->PrintValue();
450 values +=
"<parent>" + ((parent ==
nullptr || parent->GetName() ==
"__ROOT_OF_SCENE__")
451 ?
"__ROOT_OF_SCENE__" : ConvertSpaceStr(parent->GetHash())) +
"</parent>\n";
453 values +=
"</gameobject>";