PeriDyno 1.2.1
Loading...
Searching...
No Matches
WtNodeFlowScene.cpp
Go to the documentation of this file.
1#include "WtNodeFlowScene.h"
2
3
4WtNodeFlowScene::WtNodeFlowScene(Wt::WPainter* painter, std::shared_ptr<dyno::SceneGraph> scene, int selectType, int selectNum)
6{
7 _painter = painter;
8 mScene = scene;
9 _selectNum = selectNum;
10 _selectType = selectType;
11
12 auto classMap = dyno::Object::getClassMap();
13 auto ret = std::make_shared<WtDataModelRegistry>();
14 int id = 0;
15
16 this->setRegistry(ret);
17
19}
20
22
24{
25 //auto scn = dyno::SceneGraphFactory::instance()->active();
26 auto scn = mScene;
27
28 std::map<dyno::ObjectId, WtNode*> nodeMap;
29
30 //auto root = scn->getRootNode();
31
32 //SceneGraph::Iterator it_end(nullptr);
33
34 auto addNodeWidget = [&](std::shared_ptr<Node> m) -> void
35 {
36 auto mId = m->objectId();
37
38 auto type = std::make_unique<WtNodeWidget>(m);
39
40 int b = -1;
41 if (_selectType)
42 {
43 if (_selectNum == mId)
44 {
45 b = _selectType;
46 }
47 }
48
49 auto& node = this->createNode(std::move(type), _painter, b);
50
51 node.setNode(m);
52 nodeMap[mId] = &node;
53 OutNodeMap[mId] = &node;
54
55 Wt::WPointF posView(m->bx(), m->by());
56
57 node.nodeGraphicsObject().setHotKey0Checked(m->isVisible());
58 node.nodeGraphicsObject().setHotKey1Checked(m->isActive());
59 node.nodeGraphicsObject().setPos(posView);
60
61 };
62
63 for (auto it = scn->begin(); it != scn->end(); it++)
64 {
65 addNodeWidget(it.get());
66 }
67
68 auto createNodeConnections = [&](std::shared_ptr<Node> nd) -> void
69 {
70 auto inId = nd->objectId();
71
72 if (nodeMap.find(inId) != nodeMap.end())
73 {
74 auto inBlock = nodeMap[nd->objectId()];
75
76 auto ports = nd->getImportNodes();
77
78 for (int i = 0; i < ports.size(); i++)
79 {
80 dyno::NodePortType pType = ports[i]->getPortType();
81 if (dyno::Single == pType)
82 {
83 auto node = ports[i]->getNodes()[0];
84 if (node != nullptr)
85 {
86 auto outId = node->objectId();
87 if (nodeMap.find(outId) != nodeMap.end())
88 {
89 auto outBlock = nodeMap[node->objectId()];
90 createConnection(*inBlock, i, *outBlock, 0, _painter);
91 }
92 }
93 }
94 else if (dyno::Multiple == pType)
95 {
96 //TODO: a weird problem exist here, if the expression "auto& nodes = ports[i]->getNodes()" is used,
97 //we still have to call clear to avoid memory leak.
98 auto& nodes = ports[i]->getNodes();
99 //ports[i]->clear();
100 for (int j = 0; j < nodes.size(); j++)
101 {
102 if (nodes[j] != nullptr)
103 {
104 auto outId = nodes[j]->objectId();
105 if (nodeMap.find(outId) != nodeMap.end())
106 {
107 auto outBlock = nodeMap[outId];
108 createConnection(*inBlock, i, *outBlock, 0, _painter);
109 }
110 }
111 }
112 //nodes.clear();
113 }
114 }
115
116 auto fieldInp = nd->getInputFields();
117 for (int i = 0; i < fieldInp.size(); i++)
118 {
119 auto fieldSrc = fieldInp[i]->getSource();
120 if (fieldSrc != nullptr) {
121 auto parSrc = fieldSrc->parent();
122 if (parSrc != nullptr)
123 {
124 //To handle fields from node states or outputs
125 dyno::Node* nodeSrc = dynamic_cast<dyno::Node*>(parSrc);
126
127 //To handle fields that are exported from module outputs
128 if (nodeSrc == nullptr)
129 {
130 dyno::Module* moduleSrc = dynamic_cast<dyno::Module*>(parSrc);
131 if (moduleSrc != nullptr)
132 nodeSrc = moduleSrc->getParentNode();
133 }
134
135 if (nodeSrc != nullptr)
136 {
137 auto outId = nodeSrc->objectId();
138 auto fieldsOut = nodeSrc->getOutputFields();
139
140 unsigned int outFieldIndex = 0;
141 bool fieldFound = false;
142 for (auto f : fieldsOut)
143 {
144 if (f == fieldSrc)
145 {
146 fieldFound = true;
147 break;
148 }
149 outFieldIndex++;
150 }
151
152 if (nodeMap[outId]->nodeDataModel()->allowExported()) outFieldIndex++;
153
154 if (fieldFound && nodeMap.find(outId) != nodeMap.end())
155 {
156 auto outBlock = nodeMap[outId];
157 createConnection(*inBlock, i + ports.size(), *outBlock, outFieldIndex, _painter);
158 }
159 }
160 }
161 }
162 }
163 }
164 };
165
166 for (auto it = scn->begin(); it != scn->end(); it++)
167 {
168 createNodeConnections(it.get());
169 }
170
171 nodeMap.clear();
172}
173
184
186{
188
189 clearScene();
190
191 //auto f = status == Qt::Checked ? field->promoteOuput() : field->demoteOuput();
192
194
196}
197
199{
200 mEditingEnabled = true;
201
202 auto allNodes = this->allNodes();
203
204 for (auto node : allNodes)
205 {
206 auto model = dynamic_cast<WtNodeWidget*>(node->nodeDataModel());
207 if (model != nullptr)
208 {
209 model->enableEditing();
210 }
211 }
212}
213
215{
216 mEditingEnabled = false;
217
218 auto allNodes = this->allNodes();
219
220 for (auto node : allNodes)
221 {
222 auto model = dynamic_cast<WtNodeWidget*>(node->nodeDataModel());
223 if (model != nullptr)
224 {
225 model->disableEditing();
226 }
227 }
228}
229
230void WtNodeFlowScene::addNodeByString(std::string NodeName)
231{
232 Wt::log("info") << NodeName;
233
234 auto node_obj = dyno::Object::createObject(NodeName);
235 std::shared_ptr<dyno::Node> new_node(dynamic_cast<dyno::Node*>(node_obj));
236 auto dat = std::make_unique<WtNodeWidget>(std::move(new_node));
237
238 if (dat != nullptr)
239 {
241 scn->addNode(dat->getNode());
242 }
243 else
244 {
245 Wt::log("info") << "nullptr";
246 }
247
248 int mId;
249
250 auto addNodeWidget = [&](std::shared_ptr<Node> m) -> void
251 {
252 mId = m->objectId();
253
254 auto type = std::make_unique<WtNodeWidget>(m);
255
256 auto& node = this->createNode(std::move(type), _painter, false);
257
258 Wt::WPointF posView(m->bx(), m->by());
259
260 node.nodeGraphicsObject().setPos(posView);
261
262 // signal
263 //this->nodePlaced(node);
264 };
265
267
268 int x = 0;
269
270 for (auto it = scn->begin(); it != scn->end(); it++)
271 {
272 if (x == mId)
273 {
274 addNodeWidget(it.get());
275 break;
276 }
277 x++;
278 }
279 addNodeWidget(dat->getNode());
280}
281
283{
284 auto nodeData = dynamic_cast<WtNodeWidget*>(n.nodeDataModel());
285
286 if (mEditingEnabled && nodeData != nullptr)
287 {
289 scn->addNode(nodeData->getNode());
290 }
291}
292
293void WtNodeFlowScene::createWtNode(std::shared_ptr<dyno::Node> node)
294{
295 if (node == nullptr)
296 return;
297
298 auto qNodeWidget = std::make_unique<WtNodeWidget>(node);
299 auto& qNode = createNode(std::move(qNodeWidget), _painter, false);
300
301 //Calculate the position for the newly create node to avoid overlapping
302 auto& _nodes = this->nodes();
303 float y = -10000.0f;
304 for (auto const& _node : _nodes)
305 {
306 WtNodeGeometry& geo = _node.second->nodeGeometry();
307 WtNodeGraphicsObject& obj = _node.second->nodeGraphicsObject();
308
309 float h = geo.height();
310
311 Wt::WPointF pos = obj.getPos();
312
313 y = std::max(y, float(pos.y() + h));
314 }
315
316 Wt::WPointF posView(0.0f, y + 50.0f);
317
318 qNode.nodeGraphicsObject().setPos(posView);
319
320 // signal
321 // emit nodePlaced(qNode);
322}
323
325{
326 auto nodeData = dynamic_cast<WtNodeWidget*>(n.nodeDataModel());
327
328 if (mEditingEnabled && nodeData != nullptr) {
329 auto node = nodeData->getNode();
330 node->setVisible(checked);
331 //node->setForceUpdate(true);
332 }
333}
334
336{
337 auto nodeData = dynamic_cast<WtNodeWidget*>(n.nodeDataModel());
338
339 if (mEditingEnabled && nodeData != nullptr) {
340 auto node = nodeData->getNode();
341 node->setActive(checked);
342 }
343}
344
345void WtNodeFlowScene::showContextMenu(WtNode& n, const Wt::WPointF& pos)
346{
347}
348
350{
351 auto nodes = this->allNodes();
352 for (auto node : nodes)
353 {
354 if (node->id() == n.id())
355 {
356 node->nodeGraphicsObject().setHotKey1Hovered(true);
357 this->enableRendering(*node, true);
358 }
359 else
360 {
361 node->nodeGraphicsObject().setHotKey1Hovered(false);
362 this->enableRendering(*node, false);
363 }
364 }
365
366 this->updateNodeGraphView();
367
368 nodes.clear();
369}
370
372{
373 auto nodes = this->allNodes();
374 for (auto node : nodes)
375 {
376 this->enableRendering(*node, true);
377 }
378
379 this->updateNodeGraphView();
380
381 nodes.clear();
382}
383
385{
386 auto nodes = this->allNodes();
387 for (auto node : nodes)
388 {
389 if (node->id() == n.id())
390 {
391 node->nodeGraphicsObject().setHotKey0Hovered(true);
392 this->enablePhysics(*node, true);
393 }
394 else
395 {
396 node->nodeGraphicsObject().setHotKey0Hovered(false);
397 this->enablePhysics(*node, false);
398 }
399 }
400
401 this->updateNodeGraphView();
402
403 nodes.clear();
404}
405
407{
408 auto nodes = this->allNodes();
409 for (auto node : nodes)
410 {
411 auto a = node->nodeDataModel();
412 }
413
414 this->updateNodeGraphView();
415
416 nodes.clear();
417}
418
420{
421 auto nodes = this->allNodes();
422 for (auto node : nodes)
423 {
424 auto dataModel = dynamic_cast<WtNodeWidget*>(node->nodeDataModel());
425 if (dataModel != nullptr)
426 {
427 auto dNode = dataModel->getNode();
428 dNode->setAutoSync(autoSync);
429 }
430 }
431
432 nodes.clear();
433}
434
436{
438
439 class ToggleAutoSyncAct : public dyno::Action
440 {
441 public:
442 ToggleAutoSyncAct(bool autoSync) { mAutoSync = autoSync; }
443
444 void process(Node* node) override {
445 node->setAutoSync(mAutoSync);
446 }
447
448 private:
449 bool mAutoSync = true;
450 };
451
452 ToggleAutoSyncAct act(autoSync);
453
454 auto dataModel = dynamic_cast<WtNodeWidget*>(n.nodeDataModel());
455 if (dataModel != nullptr)
456 {
457 auto dNode = dataModel->getNode();
458 if (dNode == nullptr) return;
459
460 scn->traverseForward(dNode, &act);
461 }
462}
463
464//TODO: show a message on how to use this node
466{
467 Wt::log("info") << "Show something about this node";
468}
469
471{
472 //auto scn = dyno::SceneGraphFactory::instance()->active();
473
474 auto scn = mScene;
475
477
478 auto constructDAG = [&](std::shared_ptr<Node> nd) -> void
479 {
480 auto inId = nd->objectId();
481 auto ports = nd->getImportNodes();
482
483 graph.addOtherVertices(inId);
484 graph.removeID();
485
486 bool NodeConnection = false;
487 bool FieldConnection = false;
488
489 for (int i = 0; i < ports.size(); i++)
490 {
491 dyno::NodePortType pType = ports[i]->getPortType();
492
493 if (dyno::Single == pType)
494 {
495 auto node = ports[i]->getNodes()[0];
496 if (node != nullptr)
497 {
498 auto outId = node->objectId();
499
500 graph.addEdge(outId, inId);
501
502 graph.removeID(outId, inId);
503 }
504 }
505 else if (dyno::Multiple == pType)
506 {
507 auto& nodes = ports[i]->getNodes();
508
509 for (int j = 0; j < nodes.size(); j++)
510 {
511 if (nodes[j] != nullptr)
512 {
513 auto outId = nodes[j]->objectId();
514
515 graph.addEdge(outId, inId);
516 graph.removeID(outId, inId);
517 }
518 }
519 //nodes.clear();
520 }
521 }
522
523 auto fieldInp = nd->getInputFields();
524
525 for (int i = 0; i < fieldInp.size(); i++)//����ÿ��Node��Inputfield
526 {
527 auto fieldSrc = fieldInp[i]->getSource();
528
529 if (fieldSrc != nullptr) {
530 auto parSrc = fieldSrc->parent();
531
532 if (parSrc != nullptr)
533 {
534 Node* nodeSrc = dynamic_cast<Node*>(parSrc);
535
536 // Otherwise parSrc is a field of Module
537 if (nodeSrc == nullptr)
538 {
539 dyno::Module* moduleSrc = dynamic_cast<dyno::Module*>(parSrc);
540 if (moduleSrc != nullptr)
541 nodeSrc = moduleSrc->getParentNode();
542 }
543
544 if (nodeSrc != nullptr)
545 {
546 auto outId = nodeSrc->objectId();
547
548 graph.addEdge(outId, inId);
549
550 graph.removeID(outId, inId);
551 }
552 }
553 }
554 }
555 };
556
557 for (auto it = scn->begin(); it != scn->end(); it++)
558 {
559 constructDAG(it.get());
560 }
561
562 dyno::AutoLayoutDAG layout(&graph);
563 layout.update();
564
565 //Set up the mapping from ObjectId to QtNode
566 auto& _nodes = this->nodes();
567 std::map<dyno::ObjectId, WtNode*> qtNodeMapper;
568 std::map<dyno::ObjectId, Node*> nodeMapper;
569
570 for (auto const& _node : _nodes)
571 {
572 auto const& qtNode = _node.second;
573 auto model = qtNode->nodeDataModel();
574
575 auto nodeData = dynamic_cast<WtNodeWidget*>(model);
576
577 if (model != nullptr)
578 {
579 auto node = nodeData->getNode();
580 if (node != nullptr)
581 {
582 qtNodeMapper[node->objectId()] = qtNode.get();
583 nodeMapper[node->objectId()] = node.get();
584 }
585 }
586 }
587
588 float tempOffsetY = 0.0f;
589 float offsetX = 0.0f;
590
591 for (size_t l = 0; l < layout.layerNumber(); l++)
592 {
593 auto& xc = layout.layer(l);
594
595 float offsetY = 0.0f;
596 float xMax = 0.0f;
597
598 for (size_t index = 0; index < xc.size(); index++)
599 {
600 dyno::ObjectId id = xc[index];
601 if (qtNodeMapper.find(id) != qtNodeMapper.end())
602 {
603 WtNode* qtNode = qtNodeMapper[id];
604 WtNodeGeometry& geo = qtNode->nodeGeometry();
605
606 float w = geo.width();
607 float h = geo.height();
608
609 xMax = std::max(xMax, w);
610
611 Node* node = nodeMapper[id];
612
613 node->setBlockCoord(offsetX, offsetY);
614
615 offsetY += (h + mDy);
616 }
617 }
618
619 offsetX += (xMax + mDx);
620
621 tempOffsetY = std::max(tempOffsetY, offsetY);
622 }
623
624 //��ɢ�ڵ������
625 auto otherVertices = layout.getOtherVertices();
626 float width = 0;
627 float heigth = 0;
628 std::set<dyno::ObjectId>::iterator it;
629
630 float ofstY = tempOffsetY;
631 float ofstX = 0;
632
633 for (it = otherVertices.begin(); it != otherVertices.end(); it++)
634 {
635 dyno::ObjectId id = *it;
636
637 if (qtNodeMapper.find(id) != qtNodeMapper.end())
638 {
639 WtNode* qtNode = qtNodeMapper[id];
640 WtNodeGeometry& geo = qtNode->nodeGeometry();
641 width = geo.width();
642 heigth = geo.height();
643
644 Node* node = nodeMapper[id];
645
646 node->setBlockCoord(ofstX, ofstY);
647 ofstX += width + mDx;
648 }
649 }
650
651 qtNodeMapper.clear();
652 nodeMapper.clear();
653
654 //updateNodeGraphView();
655}
656
657//std::map<dyno::ObjectId, WtNode*> WtNodeFlowScene::getNodeMap()
658//{
659// return OutNodeMap;
660//}
661
void setRegistry(std::shared_ptr< WtDataModelRegistry > registry)
std::vector< WtNode * > allNodes() const
WtNode & createNode(std::unique_ptr< WtNodeDataModel > &&dataModel, Wt::WPainter *painter, int selectType)
std::map< dyno::ObjectId, WtNode * > OutNodeMap
std::shared_ptr< WtConnection > createConnection(PortType connectedPort, WtNode &node, PortIndex portIndex, Wt::WPainter *painter)
std::unordered_map< Wt::Guid, std::unique_ptr< WtNode > > const & nodes() const
void clearScene()
std::unordered_map< Wt::Guid, UniqueNode > _nodes
void enableRendering(WtNode &n, bool checked)
Wt::WPainter * _painter
void fieldUpdated(dyno::FBase *field, int status)
void addNode(WtNode &n)
void showContextMenu(WtNode &n, const Wt::WPointF &pos)
void autoSyncAllDescendants(WtNode &n, bool autoSync)
void enablePhysics(WtNode &n, bool checked)
std::shared_ptr< dyno::SceneGraph > mScene
void addNodeByString(std::string NodeName)
void updateNodeGraphView()
Update the view only for the active scene graph, the data model will not be changed.
void autoSyncAllNodes(bool autoSync)
void createNodeGraphView()
create a QT-based view for the active scene graph.
void showThisNodeOnly(WtNode &n)
void createWtNode(std::shared_ptr< dyno::Node > node)
void activateThisNodeOnly(WtNode &n)
void showHelper(WtNode &n)
WtNodeFlowScene(std::shared_ptr< WtDataModelRegistry > registry, Wt::WPainter *painter)
unsigned int width() const
Definition WtNode.h:35
unsigned int height() const
Definition WtNode.h:31
WtNodeDataModel * nodeDataModel() const
Definition WtNode.cpp:727
Wt::Guid id() const
Definition WtNode.cpp:679
WtNodeGeometry & nodeGeometry()
Definition WtNode.cpp:707
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)
Node * getParentNode()
Definition Module.cpp:246
void setAutoSync(bool con)
Whether the node can be automatically synchronized when its ancestor is updated.
Definition Node.cpp:54
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:42
static Object * createObject(std::string name)
Definition Object.cpp:33
ObjectId objectId()
Definition Object.h:129
static SceneGraphFactory * instance()
std::shared_ptr< SceneGraph > active()
uint32_t ObjectId
Definition Object.h:110
NodePortType
Definition NodePort.h:27
@ Multiple
Definition NodePort.h:29
@ Single
Definition NodePort.h:28