PeriDyno 1.0.0
Loading...
Searching...
No Matches
QtModuleFlowScene.cpp
Go to the documentation of this file.
1#include "QtModuleFlowScene.h"
2
3#include "Object.h"
4#include "SceneGraph.h"
5#include "QtModuleWidget.h"
6#include "SceneGraph.h"
7
8#include "nodes/QNode"
9
11#include "AutoLayoutDAG.h"
12
13#include <QtWidgets/QMenu>
14#include <QLineEdit>
15#include <QtWidgets>
16
17namespace dyno
18{
19 class States : public Module
20 {
22 public:
23 States() {};
24 };
25
27}
28
29namespace Qt
30{
31 QPointF SimStatePos = QPointF(0.0f, 0.0f);
32 QPointF RenStatePos = QPointF(0.0f, 0.0f);
33
34 QtModuleFlowScene::QtModuleFlowScene(std::shared_ptr<QtDataModelRegistry> registry,
35 QObject* parent)
36 : QtFlowScene(registry, parent)
37 {
38 connect(this, &QtFlowScene::nodeMoved, this, &QtModuleFlowScene::moveModule);
39 }
40
42 : QtFlowScene(parent)
43 {
44 mNode = widget->getNode();
45
46 auto classMap = dyno::Object::getClassMap();
47 auto ret = std::make_shared<QtDataModelRegistry>();
48 int id = 0;
49 for (auto const c : *classMap)
50 {
51 id++;
52
53 QString str = QString::fromStdString(c.first);
54 dyno::Object* obj = dyno::Object::createObject(str.toStdString());
55 std::shared_ptr<dyno::Module> module(dynamic_cast<dyno::Module*>(obj));
56
57 if (module != nullptr)
58 {
59 QtDataModelRegistry::RegistryItemCreator creator = [str]() {
60 auto new_obj = dyno::Object::createObject(str.toStdString());
61 std::shared_ptr<dyno::Module> new_module(dynamic_cast<dyno::Module*>(new_obj));
62 auto dat = std::make_unique<QtModuleWidget>(new_module);
63 return dat;
64 };
65
66 QString category = QString::fromStdString(module->getModuleType());
67 ret->registerModel<QtModuleWidget>(category, creator);
68 }
69 }
70
71 this->setRegistry(ret);
72
73 if (mNode != nullptr)
74 showModuleFlow(mNode.get());
75
77
79
80 connect(this, &QtFlowScene::nodeMoved, this, &QtModuleFlowScene::moveModule);
81 connect(this, &QtFlowScene::nodePlaced, this, &QtModuleFlowScene::addModule);
82 connect(this, &QtFlowScene::nodeDeleted, this, &QtModuleFlowScene::deleteModule);
83
84 connect(this, &QtFlowScene::outPortConextMenu, this, &QtModuleFlowScene::promoteOutput);
85 }
86
88 {
89 //To avoid editing the the module flow inside the node when the widget is closed.
91 }
92
94 {
95 mEditingEnabled = true;
96
97 auto allNodes = this->allNodes();
98
99 for (auto node : allNodes)
100 {
101 auto model = dynamic_cast<QtModuleWidget*>(node->nodeDataModel());
102 if (model != nullptr)
103 {
104 model->enableEditing();
105 }
106 }
107 }
108
110 {
111 mEditingEnabled = false;
112
113 auto allNodes = this->allNodes();
114
115 for (auto node : allNodes)
116 {
117 auto model = dynamic_cast<QtModuleWidget*>(node->nodeDataModel());
118 if (model != nullptr)
119 {
120 model->disableEditing();
121 }
122 }
123 }
124
126 {
127 clearScene();
128
129 if (node == nullptr)
130 return;
131
132 auto& mlist = node->getModuleList();
133
134 std::map<dyno::ObjectId, QtNode*> moduleMap;
135
136 //To show the animation pipeline in default
137 if (mActivePipeline == nullptr)
139
140 auto& modules = mActivePipeline->allModules();
141
142 auto addModuleWidget = [&](std::shared_ptr<Module> m) -> void
143 {
144 auto mId = m->objectId();
145
146 auto type = std::make_unique<QtModuleWidget>(m);
147
148 auto& node = this->createNode(std::move(type));
149
150 moduleMap[mId] = &node;
151
152 QPointF posView(m->bx(), m->by());
153
154 node.nodeGraphicsObject().setPos(posView);
155
156 this->nodePlaced(node);
157 };
158
159 //Create a dummy module to store all state variables
160 mStates = std::make_shared<dyno::States>();
161
162 auto& fields = node->getAllFields();
163 for (auto field : fields)
164 {
165 if (field->getFieldType() == dyno::FieldTypeEnum::State
166 || field->getFieldType() == dyno::FieldTypeEnum::In)
167 {
168 mStates->addOutputField(field);
169 }
170 }
171
172
173 QPointF pos = mActivePipeline == node->animationPipeline() ? SimStatePos : RenStatePos;
174 mStates->setBlockCoord(pos.x(), pos.y());
175
176 addModuleWidget(mStates);
177
178 for (auto m : modules)
179 {
180 addModuleWidget(m.second);
181 }
182
183 auto createModuleConnections = [&](std::shared_ptr<Module> m) -> void
184 {
185 auto inId = m->objectId();
186
187 if (moduleMap.find(inId) != moduleMap.end()) {
188 auto inBlock = moduleMap[m->objectId()];
189
190 auto fieldIn = m->getInputFields();
191
192 for (int i = 0; i < fieldIn.size(); i++)
193 {
194 auto fieldSrc = fieldIn[i]->getSource();
195 if (fieldSrc != nullptr) {
196 auto parSrc = fieldSrc->parent();
197 if (parSrc != nullptr)
198 {
199 Module* nodeSrc = dynamic_cast<Module*>(parSrc);
200 if (nodeSrc == nullptr)
201 {
202 nodeSrc = mStates.get();
203 }
204
205 auto outId = nodeSrc->objectId();
206 auto fieldsOut = nodeSrc->getOutputFields();
207
208 uint outFieldIndex = 0;
209 bool fieldFound = false;
210 for (auto f : fieldsOut)
211 {
212 if (f == fieldSrc)
213 {
214 fieldFound = true;
215 break;
216 }
217 outFieldIndex++;
218 }
219
220 if (fieldFound && moduleMap.find(outId) != moduleMap.end())
221 {
222 auto outBlock = moduleMap[outId];
223 createConnection(*inBlock, i, *outBlock, outFieldIndex);
224 }
225 }
226 }
227 }
228 }
229 };
230
231 for (auto m : modules)
232 {
233 createModuleConnections(m.second);
234 }
235 }
236
237 void QtModuleFlowScene::moveModule(QtNode& n, const QPointF& newLocation)
238 {
239 QtModuleWidget* mw = dynamic_cast<QtModuleWidget*>(n.nodeDataModel());
240
241 auto m = mw == nullptr ? nullptr : mw->getModule();
242
243 if (m != nullptr)
244 {
245 m->setBlockCoord(newLocation.x(), newLocation.y());
246 }
247 }
248
250 {
251 auto pipeline = mNode->resetPipeline();
252
253 if (mNode == nullptr || mActivePipeline == pipeline)
254 return;
255
256 mActivePipeline = pipeline;
257
259
262 mReorderResetPipeline = false;
263 }
264 }
265
267 {
268 auto pipeline = mNode->animationPipeline();
269
270 if (mNode == nullptr || mActivePipeline == pipeline)
271 return;
272
273 mActivePipeline = mNode->animationPipeline();
274
276 }
277
279 {
280 auto pipeline = mNode->graphicsPipeline();
281
282 if (mNode == nullptr || mActivePipeline == pipeline)
283 return;
284
285 mActivePipeline = mNode->graphicsPipeline();
286
288
292 }
293 }
294
295 void QtModuleFlowScene::promoteOutput(QtNode& n, const PortIndex index, const QPointF& pos)
296 {
297 QMenu portMenu;
298
299 portMenu.setObjectName("PortMenu");
300
301
302 auto exportAction = portMenu.addAction("Export");
303
304 connect(exportAction, &QAction::triggered, [&]()
305 {
306 auto dataModel = dynamic_cast<QtModuleWidget*>(n.nodeDataModel());
307
308 if (dataModel != nullptr)
309 {
310 auto m = dataModel->getModule();
311 if (m != nullptr)
312 {
313 auto fieldOut = m->getOutputFields();
314
315 mActivePipeline->promoteOutputToNode(fieldOut[index]);
316 }
317
318 emit nodeExportChanged();
319 }
320 });
321
322 QPoint p(pos.x(), pos.y());
323
324 portMenu.exec(p);
325 }
326
328 {
330
331 clearScene();
332
333 if (mNode != nullptr)
334 showModuleFlow(mNode.get());
335
337 }
338
340 {
341 if (mActivePipeline == nullptr)
342 return;
343
345
346 auto constructDAG = [&](std::shared_ptr<Module> m) -> void
347 {
348 auto outId = m->objectId();
349
350 auto fieldOut = m->getOutputFields();
351 for (int i = 0; i < fieldOut.size(); i++)
352 {
353 auto& sinks = fieldOut[i]->getSinks();
354 for (auto sink : sinks)
355 {
356 if (sink != nullptr) {
357 auto parSrc = sink->parent();
358 if (parSrc != nullptr)
359 {
360 Module* nodeSrc = dynamic_cast<Module*>(parSrc);
361
362 if (nodeSrc != nullptr)
363 {
364 auto inId = nodeSrc->objectId();
365 graph.addEdge(outId, inId);
366 }
367 }
368 }
369 }
370 }
371 };
372
373 constructDAG(mStates);
374
375 auto& mlists = mActivePipeline->activeModules();
376 for (auto it = mlists.begin(); it != mlists.end(); it++)
377 {
378 constructDAG(*it);
379 }
380
381
382 dyno::AutoLayoutDAG layout(&graph);
383 layout.update();
384
385 //Set up the mapping from ObjectId to QtNode
386 auto& _nodes = this->nodes();
387 std::map<dyno::ObjectId, QtNode*> qtNodeMapper;
388 std::map<dyno::ObjectId, Module*> moduleMapper;
389 for (auto const& _node : _nodes)
390 {
391 auto const& qtNode = _node.second;
392 auto model = qtNode->nodeDataModel();
393
394 auto nodeData = dynamic_cast<QtModuleWidget*>(model);
395
396 if (model != nullptr)
397 {
398 auto m = nodeData->getModule();
399 if (m != nullptr)
400 {
401 qtNodeMapper[m->objectId()] = qtNode.get();
402 moduleMapper[m->objectId()] = m.get();
403 }
404 }
405 }
406
407 float offsetX = 0.0f;
408 for (size_t l = 0; l < layout.layerNumber(); l++)
409 {
410 auto& xc = layout.layer(l);
411
412 float offsetY = 0.0f;
413 float xMax = 0.0f;
414 for (size_t index = 0; index < xc.size(); index++)
415 {
416 dyno::ObjectId id = xc[index];
417 if (qtNodeMapper.find(id) != qtNodeMapper.end())
418 {
419 QtNode* qtNode = qtNodeMapper[id];
420 NodeGeometry& geo = qtNode->nodeGeometry();
421
422 float w = geo.width();
423 float h = geo.height();
424
425 xMax = std::max(xMax, w);
426
427 Module* node = moduleMapper[id];
428
429 node->setBlockCoord(offsetX, offsetY);
430
431 offsetY += (h + mDy);
432 }
433 }
434
435 offsetX += (xMax + mDx);
436 }
437
438 if (mActivePipeline == mNode->animationPipeline()) {
439 SimStatePos = QPointF(mStates->bx(), mStates->by());
440 }
441 else {
442 RenStatePos = QPointF(mStates->bx(), mStates->by());
443 }
444
445
446 qtNodeMapper.clear();
447 moduleMapper.clear();
448
450 }
451
453 {
454 if (mActivePipeline == nullptr)
455 return;
456
457 auto nodeData = dynamic_cast<QtModuleWidget*>(n.nodeDataModel());
458
459 if (mEditingEnabled && nodeData != nullptr) {
460 mActivePipeline->pushModule(nodeData->getModule());
461 }
462 }
463
465 {
466 if (mActivePipeline == nullptr)
467 return;
468
469 auto nodeData = dynamic_cast<QtModuleWidget*>(n.nodeDataModel());
470
471 if (mEditingEnabled && nodeData != nullptr) {
472 mActivePipeline->popModule(nodeData->getModule());
473
474 emit this->nodeDeselected();
475 }
476 }
477}
#define IMPLEMENT_CLASS(name)
Definition Object.h:79
unsigned int uint
Definition VkReduce.h:5
std::shared_ptr< dyno::Module > mStates
std::shared_ptr< dyno::Pipeline > mActivePipeline
QtModuleFlowScene(std::shared_ptr< QtDataModelRegistry > registry, QObject *parent=Q_NULLPTR)
std::shared_ptr< dyno::Node > mNode
void moveModule(QtNode &n, const QPointF &newLocation)
void showModuleFlow(Node *node)
void promoteOutput(QtNode &n, const PortIndex index, const QPointF &pos)
std::shared_ptr< Module > getModule()
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::vector< ObjectId > & layer(size_t l)
Graph class represents a directed graph.
void addEdge(ObjectId v, ObjectId w)
Module(std::string name="default")
Definition Module.cpp:7
std::list< std::shared_ptr< Module > > & getModuleList()
Definition Node.h:149
std::shared_ptr< AnimationPipeline > animationPipeline()
Definition Node.cpp:311
std::vector< FBase * > & getAllFields()
Definition OBase.cpp:202
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
DECLARE_CLASS(States)
QPointF RenStatePos
QPointF SimStatePos
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
uint32_t ObjectId
Definition Object.h:110
@ In
Definition FBase.h:31
@ State
Definition FBase.h:35