13 tinyxml2::XMLDocument doc;
14 if (doc.LoadFile(filename.c_str()))
25 std::shared_ptr<SceneGraph> scn = std::make_shared<SceneGraph>();
27 tinyxml2::XMLElement* root = doc.RootElement();
29 scn->setUpperBound(
decodeVec3f(root->Attribute(
"UpperBound")));
30 scn->setLowerBound(
decodeVec3f(root->Attribute(
"LowerBound")));
32 std::vector<std::shared_ptr<Node>> nodes;
33 tinyxml2::XMLElement* nodeXML = root->FirstChildElement(
"Node");
35 std::map<std::shared_ptr<Node>, tinyxml2::XMLElement*> node2xml;
42 nodes.push_back(node);
44 node2xml[node] = nodeXML;
46 nodeXML = nodeXML->NextSiblingElement(
"Node");
49 std::map<ObjectId, std::shared_ptr<Node>> objID2Node;
50 std::map<uint, ObjectId> index2ObjectId;
53 for (
auto it : nodes) {
55 objID2Node[it->objectId()] = it;
56 index2ObjectId[radix] = it->objectId();
60 for (
auto it : node2xml)
68 for (
size_t j = 0; j < connections.size(); j++)
70 auto info = connections[j];
72 auto expNode = nodes[info.src];
73 auto inpNode = nodes[info.dst];
75 auto& outFields = expNode->getOutputFields();
76 auto& FieldsSrc = expNode->getAllFields();
78 auto& inPorts = inpNode->getImportNodes();
79 auto& inFields = inpNode->getInputFields();
81 if (info.srcModuleId != -1)
83 std::shared_ptr<Pipeline> pipline;
84 switch (info.srcModulePipline)
87 pipline = expNode->animationPipeline();
90 pipline = expNode->graphicsPipeline();
93 pipline = expNode->resetPipeline();
98 auto& activemodules = pipline->activeModules();
99 std::vector<std::shared_ptr<Module>> modules;
100 for (
const auto& elem : activemodules) {
101 modules.push_back(elem);
103 FBase* fout = modules[info.srcModuleId]->getAllFields()[info.id0];
104 FBase* fin = inpNode->getAllFields()[info.id1];
108 pipline->promoteOutputToNode(fout);
114 expNode->connect(inPorts[info.id1]);
118 FieldsSrc[info.id0]->connect(inpNode->getAllFields()[info.id1]);
125 scn->markQueueUpdateRequired();
132 tinyxml2::XMLDocument doc;
137 tinyxml2::XMLElement* root = doc.NewElement(
"SceneGraph");
139 root->SetAttribute(
"LowerBound",
encodeVec3f(scn->getLowerBound()).c_str());
140 root->SetAttribute(
"UpperBound",
encodeVec3f(scn->getUpperBound()).c_str());
142 doc.InsertEndChild(root);
145 tinyxml2::XMLElement* version = doc.NewElement(
"Version");
146 version->SetText(
TOSTRING(PERIDYNO_VERSION));
147 root->InsertEndChild(version);
152 std::map<ObjectId, uint> indices;
154 for (; itor != scn->end(); itor++) {
155 auto node = itor.
get();
156 indices[node->objectId()] = radix;
160 for (itor = scn->begin(); itor != scn->end(); itor++)
162 auto node = itor.
get();
164 tinyxml2::XMLElement* nodeXml = doc.NewElement(
"Node");
165 nodeXml->SetAttribute(
"Class", node->getClassInfo()->getClassName().c_str());
166 nodeXml->SetAttribute(
"Coordinate",
encodeVec2f(
Vec2f(node->bx(), node->by())).c_str());
167 nodeXml->SetAttribute(
"Dt",node->getDt());
168 nodeXml->SetAttribute(
"AutoSync", node->isAutoSync());
169 nodeXml->SetAttribute(
"AutoHidden", node->isAutoHidden());
170 nodeXml->SetAttribute(
"PhysicsEnabled", node->isActive());
171 nodeXml->SetAttribute(
"RenderingEnabled", node->isVisible());
173 root->InsertEndChild(nodeXml);
175 tinyxml2::XMLElement* varsXml = doc.NewElement(
"Variables");
176 nodeXml->InsertEndChild(varsXml);
179 auto& params = node->getParameters();
180 for (
auto var : params)
182 tinyxml2::XMLElement* field = doc.NewElement(
"Field");
183 field->SetAttribute(
"Name", var->getObjectName().c_str());
185 tinyxml2::XMLText* val = doc.NewText(var->serialize().c_str());
186 field->InsertEndChild(val);
188 varsXml->InsertEndChild(field);
192 tinyxml2::XMLElement* nodeConnectionsXml = doc.NewElement(
"Connections");
193 nodeXml->InsertEndChild(nodeConnectionsXml);
195 auto ports = node->getImportNodes();
197 for (
int i = 0; i < ports.size(); i++)
199 auto NodesSrc = ports[i]->getNodes();
200 bool fieldFound =
false;
201 Node* nSrcPar =
nullptr;
202 for (
auto nSrc : NodesSrc)
204 auto nSrcExports = nSrc->getExportNodes();
205 for (
auto x : nSrcExports)
212 tinyxml2::XMLElement* connection = doc.NewElement(
"Connection");
213 connection->SetAttribute(
"SourceId", indices[nSrcPar->
objectId()]);
214 connection->SetAttribute(
"From", 0);
215 connection->SetAttribute(
"TargetId", indices[node->objectId()]);
216 connection->SetAttribute(
"To",
uint(i));
217 nodeConnectionsXml->InsertEndChild(connection);
223 auto fieldInp = node->getInputFields();
225 for (
int i = 0; i < fieldInp.size(); i++)
228 auto InNodeFields = node->getAllFields();
229 for (ToIndex = 0; ToIndex < InNodeFields.size(); ToIndex++)
231 if (fieldInp[i] == InNodeFields[ToIndex])
235 switch (fieldInp[i]->inputPolicy())
239 auto manySrc = fieldInp[i]->getSources();
240 for (
size_t j = 0; j < manySrc.size(); j++)
242 auto fieldSrc = manySrc[j];
244 if (fieldSrc !=
nullptr)
253 auto fieldSrc = fieldInp[i]->getSource();
254 if (fieldSrc !=
nullptr)
266 for (
auto s : node->getOutputFields())
268 auto fieldSrc = s->getSource();
269 if (fieldSrc !=
nullptr)
271 auto parSrc = fieldSrc->parent();
273 auto fields = node->getAllFields();
274 for (
size_t i = 0; i < fields.size(); i++)
283 Node* nodeSrc =
dynamic_cast<Node*
>(parSrc);
284 if (nodeSrc !=
nullptr)
288 bool fieldFound =
false;
291 for (FromIndex = 0; FromIndex < fieldsSrc.size(); FromIndex++)
293 if (fieldsSrc[FromIndex] == fieldSrc)
302 tinyxml2::XMLElement* connection = doc.NewElement(
"Connection");
303 connection->SetAttribute(
"SourceId", indices[parSrc->objectId()]);
305 connection->SetAttribute(
"TargetId", indices[node->objectId()]);
306 connection->SetAttribute(
"To", ToIndex);
307 connection->SetAttribute(
"From", FromIndex);
308 nodeConnectionsXml->InsertEndChild(connection);
314 if (moduleSrc !=
nullptr)
316 std::map<ObjectId, uint> ModuleIndices;
317 auto getModuleData = [&](
Module* module,
int& index,
int& channel)
323 auto& animModules =
module->getParentNode()->animationPipeline()->activeModules();
324 for (
auto m : animModules) {
325 if (module == m.get())
335 auto& renderModules =
module->getParentNode()->graphicsPipeline()->activeModules();
336 for (
auto m : renderModules) {
337 if (module == m.get())
347 auto& resetModules =
module->getParentNode()->resetPipeline()->activeModules();
348 for (
auto m : resetModules) {
349 if (module == m.get())
365 bool fieldFound =
false;
366 for (
auto f : moduleFieldsSrc)
379 tinyxml2::XMLElement* connection = doc.NewElement(
"Connection");
383 int moduleIndex = -1;
385 getModuleData(moduleSrc, moduleIndex, pipline);
386 connection->SetAttribute(
"SourceModuleId", moduleIndex);
387 connection->SetAttribute(
"SourceModulePipline", pipline);
388 connection->SetAttribute(
"TargetId", indices[node->objectId()]);
389 connection->SetAttribute(
"To", ToIndex);
390 connection->SetAttribute(
"From", Index);
391 nodeConnectionsXml->InsertEndChild(connection);
399 auto savePipeline = [&](std::shared_ptr<Pipeline> pipeline,
const char* tag) {
400 tinyxml2::XMLElement* pipelineXml = doc.NewElement(tag);
401 nodeXml->InsertEndChild(pipelineXml);
403 std::map<ObjectId, uint> ModuleIndices;
404 std::map<ObjectId, std::shared_ptr<Module>> moduleMap;
407 auto& activeModules = pipeline->activeModules();
408 for (
auto m : activeModules) {
409 tinyxml2::XMLElement* moduleXml = doc.NewElement(
"Module");
410 moduleXml->SetAttribute(
"Class", m->getClassInfo()->getClassName().c_str());
411 moduleXml->SetAttribute(
"Coordinate",
encodeVec2f(
Vec2f(m->bx(), m->by())).c_str());
412 pipelineXml->InsertEndChild(moduleXml);
414 tinyxml2::XMLElement* varsModuleXml = doc.NewElement(
"Variables");
415 moduleXml->InsertEndChild(varsModuleXml);
418 auto& params = m->getParameters();
419 for (
auto var : params)
421 tinyxml2::XMLElement* field = doc.NewElement(
"Field");
422 field->SetAttribute(
"Name", var->getObjectName().c_str());
424 tinyxml2::XMLText* val = doc.NewText(var->serialize().c_str());
425 field->InsertEndChild(val);
427 varsModuleXml->InsertEndChild(field);
430 ModuleIndices[m->objectId()] = radix;
431 moduleMap[m->objectId()] = m;
435 tinyxml2::XMLElement* moduleConnectionsXml = doc.NewElement(
"Connections");
436 pipelineXml->InsertEndChild(moduleConnectionsXml);
438 for (
auto m : activeModules)
441 auto& ports = m->getImportModules();
443 for (
int i = 0; i < ports.size(); i++)
445 auto ModuleSrc = ports[i]->getModules();
446 for (
auto mSrc : ModuleSrc)
449 tinyxml2::XMLElement* moduleConnectionXml = doc.NewElement(
"Connection");
450 moduleConnectionXml->SetAttribute(
"SourceModulePortId", ModuleIndices[mSrc->objectId()]);
451 moduleConnectionXml->SetAttribute(
"TargetModulePortId", ModuleIndices[m->objectId()]);
452 moduleConnectionsXml->InsertEndChild(moduleConnectionXml);
459 auto& fieldIn = m->getInputFields();
460 for (
int i = 0; i < fieldIn.size(); i++)
462 auto fieldSrc = fieldIn[i]->getSource();
463 if (fieldSrc !=
nullptr) {
464 auto parSrc = fieldSrc->parent();
465 if (parSrc !=
nullptr)
467 uint inFieldIndex = 0;
468 bool infieldFound =
false;
470 auto infields = m->getAllFields();
471 for (
auto f : infields)
487 uint outFieldIndex = 0;
488 bool fieldFound =
false;
489 for (
auto f : srcfields)
499 if (fieldFound && moduleMap.find(outId) != moduleMap.end())
501 auto outBlock = moduleMap[outId];
503 tinyxml2::XMLElement* moduleConnectionXml = doc.NewElement(
"Connection");
504 moduleConnectionXml->SetAttribute(
"SourceId", ModuleIndices[outBlock->objectId()]);
505 moduleConnectionXml->SetAttribute(
"From", outFieldIndex);
506 moduleConnectionXml->SetAttribute(
"TargetId", ModuleIndices[m->objectId()]);
507 moduleConnectionXml->SetAttribute(
"To", inFieldIndex);
508 moduleConnectionsXml->InsertEndChild(moduleConnectionXml);
512 Node* src =
dynamic_cast<Node*
>(parSrc);
516 bool fieldFound =
false;
520 int nodeExportIndex = 0;
521 for (
auto f : fields)
526 type = f->getFieldType();
534 tinyxml2::XMLElement* moduleConnectionXml = doc.NewElement(
"Connection");
535 moduleConnectionXml->SetAttribute(
"SourceId", -1 *
int((indices[src->
objectId()]) + 1));
536 moduleConnectionXml->SetAttribute(
"From", nodeExportIndex);
537 moduleConnectionXml->SetAttribute(
"TargetId", ModuleIndices[m->objectId()]);
538 moduleConnectionXml->SetAttribute(
"To", inFieldIndex);
540 moduleConnectionsXml->InsertEndChild(moduleConnectionXml);
549 ModuleIndices.clear();
552 savePipeline(node->animationPipeline(),
"Simulation");
554 savePipeline(node->graphicsPipeline(),
"Rendering");
559 doc.SaveFile(filename.c_str());
568 const char* name = nodeXML->Attribute(
"Class");
575 std::cout << name <<
" does not exist! " << std::endl;
579 const char* coordStr = nodeXML->Attribute(
"Coordinate");
583 node->setBlockCoord(coord.x, coord.y);
585 const char* dtStr = nodeXML->Attribute(
"Dt");
586 node->setDt(std::stod(dtStr));
588 const char* syncStr = nodeXML->Attribute(
"AutoSync");
589 node->setAutoSync(std::string(syncStr) ==
"false" ?
false :
true);
591 const char* hiddenStr = nodeXML->Attribute(
"AutoHidden");
592 node->setAutoHidden(std::string(hiddenStr) ==
"false" ?
false :
true);
594 const char* activeStr = nodeXML->Attribute(
"PhysicsEnabled");
595 node->setActive(std::string(activeStr) ==
"false" ?
false :
true);
597 const char* visibleStr = nodeXML->Attribute(
"RenderingEnabled");
598 node->setVisible(std::string(visibleStr) ==
"false" ?
false :
true);
600 const char* nodeName = nodeXML->Attribute(
"Name");
602 node->setName(nodeName);
604 std::map<std::string, FBase*> str2Field;
605 auto& params = node->getParameters();
606 for (
auto var : params) {
607 str2Field[var->getObjectName()] = var;
609 tinyxml2::XMLElement* varsXmls = nodeXML->FirstChildElement(
"Variables");
610 tinyxml2::XMLElement* fieldXml = varsXmls->FirstChildElement(
"Field");
613 std::string name = fieldXml->Attribute(
"Name");
614 std::string str = fieldXml->GetText() ==
nullptr ?
"" : fieldXml->GetText();
615 str2Field[name]->deserialize(str);
617 fieldXml = fieldXml->NextSiblingElement(
"Field");
621 std::vector<ConnectionInfo> infoVec;
626 tinyxml2::XMLElement* cnnXmls = nodeXML->FirstChildElement(
"Connections");
627 tinyxml2::XMLElement* connectionXml = cnnXmls->FirstChildElement(
"Connection");
629 while (connectionXml)
633 info.
src = atoi(connectionXml->Attribute(
"SourceId"));
634 info.
dst = atoi(connectionXml->Attribute(
"TargetId"));
636 info.
id0 = atoi(connectionXml->Attribute(
"From"));
637 info.
id1 = atoi(connectionXml->Attribute(
"To"));
639 auto sourceModuleId = connectionXml->Attribute(
"SourceModuleId");
640 auto sourceModulePiplineId = connectionXml->Attribute(
"SourceModulePipline");
641 if (sourceModuleId !=
nullptr && sourceModulePiplineId !=
nullptr)
643 info.
srcModuleId = atoi(connectionXml->Attribute(
"SourceModuleId"));
644 info.
srcModulePipline = atoi(connectionXml->Attribute(
"SourceModulePipline"));
648 infoVec.push_back(info);
650 connectionXml = connectionXml->NextSiblingElement(
"Connection");
657 auto& fields = node->getAllFields();
723 tinyxml2::XMLDocument& doc,
724 std::map<ObjectId, uint> indices,
725 std::shared_ptr<Node> node,
727 tinyxml2::XMLElement* nodeConnectionsXml
730 auto parSrc = fieldSrc->
parent();
731 if (parSrc !=
nullptr)
733 Node* nodeSrc =
dynamic_cast<Node*
>(parSrc);
734 if (nodeSrc !=
nullptr)
738 bool fieldFound =
false;
741 for (FromIndex = 0; FromIndex < fieldsSrc.size(); FromIndex++)
743 if (fieldsSrc[FromIndex] == fieldSrc)
752 tinyxml2::XMLElement* connection = doc.NewElement(
"Connection");
753 connection->SetAttribute(
"SourceId", indices[parSrc->objectId()]);
755 connection->SetAttribute(
"TargetId", indices[node->objectId()]);
756 connection->SetAttribute(
"To", ToIndex);
757 connection->SetAttribute(
"From", FromIndex);
758 nodeConnectionsXml->InsertEndChild(connection);
764 if (moduleSrc !=
nullptr)
766 std::map<ObjectId, uint> ModuleIndices;
767 auto getModuleData = [&](
Module* module,
int& index,
int& channel)
772 auto& animModules =
module->getParentNode()->animationPipeline()->activeModules();
773 for (
auto m : animModules) {
774 if (module == m.get())
784 auto& renderModules =
module->getParentNode()->graphicsPipeline()->activeModules();
785 for (
auto m : renderModules) {
786 if (module == m.get())
796 auto& resetModules =
module->getParentNode()->resetPipeline()->activeModules();
797 for (
auto m : resetModules) {
798 if (module == m.get())
814 bool fieldFound =
false;
815 for (
auto f : moduleFieldsSrc)
828 tinyxml2::XMLElement* connection = doc.NewElement(
"Connection");
832 int moduleIndex = -1;
834 getModuleData(moduleSrc, moduleIndex, pipline);
835 connection->SetAttribute(
"SourceModuleId", moduleIndex);
836 connection->SetAttribute(
"SourceModulePipline", pipline);
837 connection->SetAttribute(
"TargetId", indices[node->objectId()]);
838 connection->SetAttribute(
"To", ToIndex);
839 connection->SetAttribute(
"From", Index);
840 nodeConnectionsXml->InsertEndChild(connection);