PeriDyno 1.0.0
Loading...
Searching...
No Matches
QtNodeFlowScene.cpp
Go to the documentation of this file.
1#include "QtNodeFlowScene.h"
2#include "QtNodeWidget.h"
3
4#include "nodes/QNode"
5
6#include "Format.h"
7
8#include "Object.h"
9#include "NodeIterator.h"
10#include "NodePort.h"
11#include "Action.h"
13#include "AutoLayoutDAG.h"
14#include "SceneGraphFactory.h"
15
16#include <QtWidgets/QMessageBox>
17#include <QKeySequence>
18#include <QShortcut>
19#include <QMenu>
20#include "iostream"
21
22namespace Qt
23{
24 QtNodeFlowScene::QtNodeFlowScene(std::shared_ptr<QtDataModelRegistry> registry, QObject* parent)
25 : QtFlowScene(registry, parent)
26 {
27 }
28
30 : QtFlowScene(parent)
31 {
32 auto classMap = dyno::Object::getClassMap();
33
34 auto ret = std::make_shared<QtDataModelRegistry>();
35 int id = 0;
36 for (auto const c : *classMap)
37 {
38 id++;
39
40 QString str = QString::fromStdString(c.first);
41 auto obj = dyno::Object::createObject(str.toStdString());
42 std::shared_ptr<dyno::Node> node(dynamic_cast<dyno::Node*>(obj));
43
44 if (node != nullptr)
45 {
46 QtDataModelRegistry::RegistryItemCreator creator = [str]() {
47 auto node_obj = dyno::Object::createObject(str.toStdString());
48 std::shared_ptr<dyno::Node> new_node(dynamic_cast<dyno::Node*>(node_obj));
49 auto dat = std::make_unique<QtNodeWidget>(std::move(new_node));
50 return dat;
51 };
52
53 QString category = dyno::FormatBlockCaptionName(node->getNodeType());
54 ret->registerModel<QtNodeWidget>(category, creator);
55 }
56 }
57
58 this->setRegistry(ret);
59
62
63 connect(this, &QtFlowScene::nodeMoved, this, &QtNodeFlowScene::moveNode);
64 connect(this, &QtFlowScene::nodePlaced, this, &QtNodeFlowScene::addNode);
65 connect(this, &QtFlowScene::nodeDeleted, this, &QtNodeFlowScene::deleteNode);
66
67 connect(this, &QtFlowScene::nodeHotKey0Checked, this, &QtNodeFlowScene::enableRendering);
68 connect(this, &QtFlowScene::nodeHotKey1Checked, this, &QtNodeFlowScene::enablePhysics);
69 //connect(this, &QtFlowScene::nodeHotKey2Checked, this, &QtNodeFlowScene::Key2_Signal);
70
71 connect(this, &QtFlowScene::nodeContextMenu, this, &QtNodeFlowScene::showContextMenu);
72 }
73
75 {
76 clearScene();
77 }
78
80 {
82
83 std::map<dyno::ObjectId, QtNode*> nodeMap;
84
85 //auto root = scn->getRootNode();
86
87 //SceneGraph::Iterator it_end(nullptr);
88
89 auto addNodeWidget = [&](std::shared_ptr<Node> m) -> void
90 {
91 auto mId = m->objectId();
92
93 auto type = std::make_unique<QtNodeWidget>(m);
94
95 auto& node = this->createNode(std::move(type));
96
97 nodeMap[mId] = &node;
98
99 QPointF posView(m->bx(), m->by());
100
101 node.nodeGraphicsObject().setPos(posView);
102
103 this->nodePlaced(node);
104 };
105
106 for (auto it = scn->begin(); it != scn->end(); it++)
107 {
108 addNodeWidget(it.get());
109 }
110
111 auto createNodeConnections = [&](std::shared_ptr<Node> nd) -> void
112 {
113 auto inId = nd->objectId();
114
115 if (nodeMap.find(inId) != nodeMap.end())
116 {
117 auto inBlock = nodeMap[nd->objectId()];
118
119 auto ports = nd->getImportNodes();
120
121 for (int i = 0; i < ports.size(); i++)
122 {
123 dyno::NodePortType pType = ports[i]->getPortType();
124 if (dyno::Single == pType)
125 {
126 auto node = ports[i]->getNodes()[0];
127 if (node != nullptr)
128 {
129 auto outId = node->objectId();
130 if (nodeMap.find(outId) != nodeMap.end())
131 {
132 auto outBlock = nodeMap[node->objectId()];
133 createConnection(*inBlock, i, *outBlock, 0);
134 }
135 }
136 }
137 else if (dyno::Multiple == pType)
138 {
139 //TODO: a weird problem exist here, if the expression "auto& nodes = ports[i]->getNodes()" is used,
140 //we still have to call clear to avoid memory leak.
141 auto& nodes = ports[i]->getNodes();
142 //ports[i]->clear();
143 for (int j = 0; j < nodes.size(); j++)
144 {
145 if (nodes[j] != nullptr)
146 {
147 auto outId = nodes[j]->objectId();
148 if (nodeMap.find(outId) != nodeMap.end())
149 {
150 auto outBlock = nodeMap[outId];
151 createConnection(*inBlock, i, *outBlock, 0);
152 }
153 }
154 }
155 //nodes.clear();
156 }
157 }
158
159 auto fieldInp = nd->getInputFields();
160 for (int i = 0; i < fieldInp.size(); i++)
161 {
162 auto fieldSrc = fieldInp[i]->getSource();
163 if (fieldSrc != nullptr) {
164 auto parSrc = fieldSrc->parent();
165 if (parSrc != nullptr)
166 {
167 //To handle fields from node states or outputs
168 dyno::Node* nodeSrc = dynamic_cast<dyno::Node*>(parSrc);
169
170 //To handle fields that are exported from module outputs
171 if (nodeSrc == nullptr)
172 {
173 dyno::Module* moduleSrc = dynamic_cast<dyno::Module*>(parSrc);
174 if (moduleSrc != nullptr)
175 nodeSrc = moduleSrc->getParentNode();
176 }
177
178 if (nodeSrc != nullptr)
179 {
180 auto outId = nodeSrc->objectId();
181 auto fieldsOut = nodeSrc->getOutputFields();
182
183 uint outFieldIndex = 0;
184 bool fieldFound = false;
185 for (auto f : fieldsOut)
186 {
187 if (f == fieldSrc)
188 {
189 fieldFound = true;
190 break;
191 }
192 outFieldIndex++;
193 }
194
195 if (nodeMap[outId]->nodeDataModel()->allowExported()) outFieldIndex++;
196
197 if (fieldFound && nodeMap.find(outId) != nodeMap.end())
198 {
199 auto outBlock = nodeMap[outId];
200 createConnection(*inBlock, i + ports.size(), *outBlock, outFieldIndex);
201 }
202 }
203 }
204 }
205 }
206 }
207 };
208
209 for (auto it = scn->begin(); it != scn->end(); it++)
210 {
211 createNodeConnections(it.get());
212 }
213
214// // clearScene();
215// //
216// for (auto it = scn->begin(); it != scn->end(); it++)
217// {
218// auto node_ptr = it.get();
219// std::cout << node_ptr->getClassInfo()->getClassName() << ": " << node_ptr.use_count() << std::endl;
220// }
221
222 nodeMap.clear();
223 }
224
226 {
228
229 clearScene();
230
232
234 }
235
237 {
239
240 clearScene();
241
242 auto f = status == Qt::Checked ? field->promoteOuput() : field->demoteOuput();
243
245
247 }
248
249 void QtNodeFlowScene::moveNode(QtNode& n, const QPointF& newLocation)
250 {
251 auto nodeData = dynamic_cast<QtNodeWidget*>(n.nodeDataModel());
252
253 if (mEditingEnabled && nodeData != nullptr) {
254 auto node = nodeData->getNode();
255 node->setBlockCoord(newLocation.x(), newLocation.y());
256 }
257 }
258
260 {
261 auto nodeData = dynamic_cast<QtNodeWidget*>(n.nodeDataModel());
262
263 if (mEditingEnabled && nodeData != nullptr) {
265 scn->addNode(nodeData->getNode());
266 }
267 }
268
269 void QtNodeFlowScene::addNodeByString(std::string NodeName) {
270 std::cout << NodeName << std::endl;
271
272 auto node_obj = dyno::Object::createObject(NodeName);
273 std::shared_ptr<dyno::Node> new_node(dynamic_cast<dyno::Node*>(node_obj));
274 auto dat = std::make_unique<QtNodeWidget>(std::move(new_node));
275
276 if (dat != nullptr) {
278 scn->addNode(dat->getNode());
279 }
280 else {
281 std::cout << "nullptr" << std::endl;
282 }
283 int mId;
284 auto addNodeWidget = [&](std::shared_ptr<Node> m) -> void
285 {
286 mId = m->objectId();
287
288 auto type = std::make_unique<QtNodeWidget>(m);
289
290 auto& node = this->createNode(std::move(type));
291
292 QPointF posView(m->bx(), m->by());
293
294 node.nodeGraphicsObject().setPos(posView);
295
296 this->nodePlaced(node);
297 };
299 int x = 0;
300 for (auto it = scn->begin(); it != scn->end(); it++)
301 {
302 if(x== mId){
303 addNodeWidget(it.get());
304 break;
305 }
306 x++;
307 }
308 addNodeWidget(dat->getNode());
309 }
310
312 {
313 mEditingEnabled = true;
314
315 auto allNodes = this->allNodes();
316
317 for (auto node : allNodes)
318 {
319 auto model = dynamic_cast<QtNodeWidget*>(node->nodeDataModel());
320 if (model != nullptr)
321 {
322 model->enableEditing();
323 }
324 }
325 }
326
328 {
329 mEditingEnabled = false;
330
331 auto allNodes = this->allNodes();
332
333 for (auto node : allNodes)
334 {
335 auto model = dynamic_cast<QtNodeWidget*>(node->nodeDataModel());
336 if (model != nullptr)
337 {
338 model->disableEditing();
339 }
340 }
341 }
342
344 {
345 auto nodeData = dynamic_cast<QtNodeWidget*>(n.nodeDataModel());
346
347 if (mEditingEnabled && nodeData != nullptr) {
349 scn->deleteNode(nodeData->getNode());
350
351 emit this->nodeDeselected();
352 }
353 }
354
355 void QtNodeFlowScene::createQtNode(std::shared_ptr<dyno::Node> node)
356 {
357 if (node == nullptr)
358 return;
359
360 auto qNodeWdiget = std::make_unique<QtNodeWidget>(node);
361 auto& qNode = createNode(std::move(qNodeWdiget));
362
363 //Calculate the position for the newly create node to avoid overlapping
364 auto& _nodes = this->nodes();
365 float y = -10000.0f;
366 for (auto const& _node : _nodes)
367 {
368 NodeGeometry& geo = _node.second->nodeGeometry();
369 QtNodeGraphicsObject& obj = _node.second->nodeGraphicsObject();
370
371 float h = geo.height();
372
373 QPointF pos = obj.pos();
374
375 y = std::max(y, float(pos.y() + h));
376 }
377
378 QPointF posView(0.0f, y + 50.0f);
379
380 qNode.nodeGraphicsObject().setPos(posView);
381
382 emit nodePlaced(qNode);
383 }
384
385 void QtNodeFlowScene::enableRendering(QtNode& n, bool checked)
386 {
387 auto nodeData = dynamic_cast<QtNodeWidget*>(n.nodeDataModel());
388
389 if (mEditingEnabled && nodeData != nullptr) {
390 auto node = nodeData->getNode();
391 node->setVisible(checked);
392 }
393 }
394
395 void QtNodeFlowScene::enablePhysics(QtNode& n, bool checked)
396 {
397 auto nodeData = dynamic_cast<QtNodeWidget*>(n.nodeDataModel());
398
399 if (mEditingEnabled && nodeData != nullptr) {
400 auto node = nodeData->getNode();
401 node->setActive(checked);
402 }
403 }
404
405 void QtNodeFlowScene::showContextMenu(QtNode& n, const QPointF& pos)
406 {
407 auto qDataModel = dynamic_cast<QtNodeWidget*>(n.nodeDataModel());
408 auto node = qDataModel->getNode();
409 if (node == nullptr) {
410 return;
411 }
412
413 auto menu = new QMenu;
414 menu->setStyleSheet("QMenu{color:white;border: 1px solid black;} "); //QMenu::item:selected {background-color : #4b586a;}
415
416 auto openAct = new QAction("Open", this);
417
418 auto showAllNodesAct = new QAction("Show All Nodes", this);
419 auto showThisNodeOnlyAct = new QAction("Show This Only", this);
420
421 showAllNodesAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_V));
422 showThisNodeOnlyAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_H));
423
424 auto delAct = new QAction("Delete", this);
425 auto helpAct = new QAction("Help", this);
426
427 menu->addAction(openAct);
428
429 menu->addSeparator();
430 menu->addAction(showThisNodeOnlyAct);
431 menu->addAction(showAllNodesAct);
432
433
434 auto resetNodeAct = new QAction("Reset This Node", this);
435 auto activateThisNodeOnlyAct = new QAction("Activate This Only", this);
436 auto activateAllNodesAct = new QAction("Activate All Nodes", this);
437 menu->addSeparator();
438 menu->addAction(resetNodeAct);
439
440 menu->addSeparator();
441 menu->addAction(activateThisNodeOnlyAct);
442 menu->addAction(activateAllNodesAct);
443
444 menu->addSeparator();
445 auto autoSyncAct = new QAction("Auto-Sync", this);
446 autoSyncAct->setCheckable(true);
447 autoSyncAct->setChecked(node->isAutoSync());
448
449 auto enableDiscendants = new QAction("Enable Descendants' Auto-Sync(s)", this);
450 auto disableDiscendants = new QAction("Disable Descendants' Auto-Sync(s)", this);
451 auto enableAutoSync = new QAction("Enable All Auto-Sync(s)", this);
452 auto disableAutoSync = new QAction("Disable All Auto-Sync(s)", this);
453 menu->addAction(autoSyncAct);
454 menu->addAction(enableDiscendants);
455 menu->addAction(disableDiscendants);
456 menu->addAction(enableAutoSync);
457 menu->addAction(disableAutoSync);
458
459 menu->addSeparator();
460 menu->addAction(delAct);
461
462 menu->addSeparator();
463 menu->addAction(helpAct);
464
465 connect(openAct, &QAction::triggered, this, [&]() { nodeDoubleClicked(n); });
466
467
468 connect(showAllNodesAct, &QAction::triggered, this, [&]() {
469 showAllNodes();
470 });
471
472 connect(showThisNodeOnlyAct, &QAction::triggered, this, [&]() {
474 });
475
476 connect(resetNodeAct, &QAction::triggered, this, [=]() {
477 node->reset();
478 });
479
480 connect(activateAllNodesAct, &QAction::triggered, this, [&]() {
482 });
483
484 connect(activateThisNodeOnlyAct, &QAction::triggered, this, [&]() {
486 });
487
488 connect(autoSyncAct, &QAction::triggered, this, [=](bool checked) {
489 node->setAutoSync(checked);
490 });
491
492 connect(enableDiscendants, &QAction::triggered, this, [&]() {
493 autoSyncAllDescendants(n, true);
494 });
495
496 connect(disableDiscendants, &QAction::triggered, this, [&]() {
497 autoSyncAllDescendants(n, false);
498 });
499
500 connect(enableAutoSync, &QAction::triggered, this, [=]() {
501 autoSyncAllNodes(true);
502 });
503
504 connect(disableAutoSync, &QAction::triggered, this, [=]() {
505 autoSyncAllNodes(false);
506 });
507
508 connect(delAct, &QAction::triggered, this, [&](){ this->removeNode(n); });
509 connect(helpAct, &QAction::triggered, this, [&]() { this->showHelper(n); });
510
511 menu->move(QCursor().pos().x() + 4, QCursor().pos().y() + 4);
512 menu->show();
513 }
514
516 {
517 auto nodes = this->allNodes();
518 for (auto node : nodes)
519 {
520 if (node->id() == n.id())
521 {
522 node->nodeGraphicsObject().setHotKey1Hovered(true);
523 this->enableRendering(*node, true);
524 }
525 else
526 {
527 node->nodeGraphicsObject().setHotKey1Hovered(false);
528 this->enableRendering(*node, false);
529 }
530 }
531
532 this->updateNodeGraphView();
533
534 nodes.clear();
535 }
536
538 {
539 auto nodes = this->allNodes();
540 for (auto node : nodes)
541 {
542 this->enableRendering(*node, true);
543 }
544
545 this->updateNodeGraphView();
546
547 nodes.clear();
548 }
549
551 {
552 auto nodes = this->allNodes();
553 for (auto node : nodes)
554 {
555 if (node->id() == n.id())
556 {
557 node->nodeGraphicsObject().setHotKey0Hovered(true);
558 this->enablePhysics(*node, true);
559 }
560 else
561 {
562 node->nodeGraphicsObject().setHotKey0Hovered(false);
563 this->enablePhysics(*node, false);
564 }
565 }
566
567 this->updateNodeGraphView();
568
569 nodes.clear();
570 }
571
573 {
574 auto nodes = this->allNodes();
575 for (auto node : nodes)
576 {
577 auto a = node->nodeDataModel();
578 }
579
580 this->updateNodeGraphView();
581
582 nodes.clear();
583 }
584
586 {
587 auto nodes = this->allNodes();
588 for (auto node : nodes)
589 {
590 auto dataModel = dynamic_cast<QtNodeWidget*>(node->nodeDataModel());
591 if (dataModel != nullptr)
592 {
593 auto dNode = dataModel->getNode();
594 dNode->setAutoSync(autoSync);
595 }
596 }
597
598 nodes.clear();
599 }
600
601 void QtNodeFlowScene::autoSyncAllDescendants(QtNode& n, bool autoSync)
602 {
604
605 class ToggleAutoSyncAct : public dyno::Action
606 {
607 public:
608 ToggleAutoSyncAct(bool autoSync) { mAutoSync = autoSync; }
609
610 void process(Node* node) override {
611 node->setAutoSync(mAutoSync);
612 }
613
614 private:
615 bool mAutoSync = true;
616 };
617
618 ToggleAutoSyncAct act(autoSync);
619
620 auto dataModel = dynamic_cast<QtNodeWidget*>(n.nodeDataModel());
621 if (dataModel != nullptr)
622 {
623 auto dNode = dataModel->getNode();
624 if (dNode == nullptr) return;
625
626 scn->traverseForward(dNode, &act);
627 }
628 }
629
630 //TODO: show a message on how to use this node
632 {
633 QMessageBox::information(nullptr, "Node Info", "Show something about this node");
634 }
635
637 {
639
641
642 auto constructDAG = [&](std::shared_ptr<Node> nd) -> void
643 {
644
645 auto inId = nd->objectId();
646
647 auto ports = nd->getImportNodes();
648
649 graph.addOtherVertices(inId);
650 graph.removeID();
651
652 bool NodeConnection = false;
653 bool FieldConnection = false;
654 for (int i = 0; i < ports.size(); i++)
655 {
656 dyno::NodePortType pType = ports[i]->getPortType();
657 if (dyno::Single == pType)
658 {
659 auto node = ports[i]->getNodes()[0];
660 if (node != nullptr)
661 {
662 auto outId = node->objectId();
663
664 graph.addEdge(outId, inId);
665
666 graph.removeID(outId, inId);
667 }
668 }
669 else if (dyno::Multiple == pType)
670 {
671 auto& nodes = ports[i]->getNodes();
672 for (int j = 0; j < nodes.size(); j++)
673 {
674 if (nodes[j] != nullptr)
675 {
676 auto outId = nodes[j]->objectId();
677
678 graph.addEdge(outId, inId);
679 graph.removeID(outId, inId);
680
681 }
682 }
683 //nodes.clear();
684 }
685
686 }
687
688
689 auto fieldInp = nd->getInputFields();
690 for (int i = 0; i < fieldInp.size(); i++)//遍历每个Node的Inputfield
691 {
692 auto fieldSrc = fieldInp[i]->getSource();
693 if (fieldSrc != nullptr) {
694 auto parSrc = fieldSrc->parent();
695 if (parSrc != nullptr)
696 {
697 Node* nodeSrc = dynamic_cast<Node*>(parSrc);
698
699 // Otherwise parSrc is a field of Module
700 if (nodeSrc == nullptr)
701 {
702 dyno::Module* moduleSrc = dynamic_cast<dyno::Module*>(parSrc);
703 if (moduleSrc != nullptr)
704 nodeSrc = moduleSrc->getParentNode();
705 }
706
707 if (nodeSrc != nullptr)
708 {
709 auto outId = nodeSrc->objectId();
710
711 graph.addEdge(outId, inId);
712
713 graph.removeID(outId, inId);
714 }
715 }
716 }
717 }
718 };
719 for (auto it = scn->begin(); it != scn->end(); it++)
720 {
721 constructDAG(it.get());
722 }
723
724
725 dyno::AutoLayoutDAG layout(&graph);
726 layout.update();
727
728 //Set up the mapping from ObjectId to QtNode
729 auto& _nodes = this->nodes();
730 std::map<dyno::ObjectId, QtNode*> qtNodeMapper;
731 std::map<dyno::ObjectId, Node*> nodeMapper;
732 for (auto const& _node : _nodes)
733 {
734 auto const& qtNode = _node.second;
735 auto model = qtNode->nodeDataModel();
736
737 auto nodeData = dynamic_cast<QtNodeWidget*>(model);
738
739 if (model != nullptr)
740 {
741 auto node = nodeData->getNode();
742 if (node != nullptr)
743 {
744 qtNodeMapper[node->objectId()] = qtNode.get();
745 nodeMapper[node->objectId()] = node.get();
746 }
747 }
748 }
749 float tempOffsetY = 0.0f;
750
751 float offsetX = 0.0f;
752 for (size_t l = 0; l < layout.layerNumber(); l++)
753 {
754 auto& xc = layout.layer(l);
755
756 float offsetY = 0.0f;
757 float xMax = 0.0f;
758 for (size_t index = 0; index < xc.size(); index++)
759 {
760 dyno::ObjectId id = xc[index];
761 if (qtNodeMapper.find(id) != qtNodeMapper.end())
762 {
763 QtNode* qtNode = qtNodeMapper[id];
764 NodeGeometry& geo = qtNode->nodeGeometry();
765
766 float w = geo.width();
767 float h = geo.height();
768
769 xMax = std::max(xMax, w);
770
771 Node* node = nodeMapper[id];
772
773 node->setBlockCoord(offsetX, offsetY);
774
775 offsetY += (h + mDy);
776
777 }
778 }
779
780 offsetX += (xMax + mDx);
781
782 tempOffsetY = std::max(tempOffsetY,offsetY);
783
784
785
786 }
787
788 //离散节点的排序
789 auto otherVertices = layout.getOtherVertices();
790 float width = 0;
791 float heigth = 0;
792 std::set<dyno::ObjectId>::iterator it;
793
794 float ofstY = tempOffsetY;
795 float ofstX = 0;
796 for (it = otherVertices.begin(); it != otherVertices.end(); it++)
797 {
798 dyno::ObjectId id = *it;
799 if (qtNodeMapper.find(id) != qtNodeMapper.end())
800 {
801 QtNode* qtNode = qtNodeMapper[id];
802 NodeGeometry& geo = qtNode->nodeGeometry();
803 width = geo.width();
804 heigth = geo.height();
805
806 Node* node = nodeMapper[id];
807
808
809 node->setBlockCoord(ofstX, ofstY);
810 ofstX += width + mDx;
811
812 }
813
814 }
815
816
817 qtNodeMapper.clear();
818 nodeMapper.clear();
819
821 }
822}
unsigned int uint
Definition VkReduce.h:5
void deleteNode(QtNode &n)
void showHelper(QtNode &n)
void enableRendering(QtNode &n, bool checked)
void createQtNode(std::shared_ptr< dyno::Node > node)
void enablePhysics(QtNode &n, bool checked)
void autoSyncAllNodes(bool autoSync)
void updateNodeGraphView()
Update the view only for the active scene graph, the data model will not be changed.
void showThisNodeOnly(QtNode &n)
void moveNode(QtNode &n, const QPointF &newLocation)
void addNodeByString(std::string NodeName)
void createNodeGraphView()
create a QT-based view for the active scene graph.
void addNode(QtNode &n)
void autoSyncAllDescendants(QtNode &n, bool autoSync)
void showContextMenu(QtNode &n, const QPointF &pos)
void activateThisNodeOnly(QtNode &n)
void fieldUpdated(dyno::FBase *field, int status)
QtNodeFlowScene(std::shared_ptr< QtDataModelRegistry > registry, QObject *parent=Q_NULLPTR)
The model dictates the number of inputs and outputs for the Node.
std::shared_ptr< Node > getNode()
Automatic layout for directed acyclic graph Refer to "Sugiyama Algorithm" by Nikola S....
std::set< ObjectId > & getOtherVertices()
std::vector< ObjectId > & layer(size_t l)
Graph class represents a directed graph.
void removeID(ObjectId v=-1, ObjectId w=-1)
void addEdge(ObjectId v, ObjectId w)
FBase * promoteOuput()
Display a state field as an ouput field.
Definition FBase.cpp:57
FBase * demoteOuput()
Hide a state field from outputs.
Definition FBase.cpp:81
Node * getParentNode()
Definition Module.cpp:203
void setAutoSync(bool con)
Whether the node can be automatically synchronized when its ancestor is updated.
Definition Node.cpp:63
std::vector< FBase * > & getOutputFields()
Definition OBase.h:179
void setBlockCoord(float x, float y)
Definition OBase.h:161
static std::map< std::string, ClassInfo * > * getClassMap()
Definition Object.cpp:41
static Object * createObject(std::string name)
Definition Object.cpp:32
ObjectId objectId()
Definition Object.h:129
static SceneGraphFactory * instance()
std::shared_ptr< SceneGraph > active()
QString FormatBlockCaptionName(std::string name)
Definition Format.cpp:64
uint32_t ObjectId
Definition Object.h:110
NodePortType
Definition NodePort.h:27
@ Multiple
Definition NodePort.h:29
@ Single
Definition NodePort.h:28