PeriDyno 1.2.1
Loading...
Searching...
No Matches
WtNodeFlowWidget.cpp
Go to the documentation of this file.
1#include "WtNodeFlowWidget.h"
2#include <Wt/WEnvironment.h>
3#include <Wt/WApplication.h>
4#include <Wt/WMessageBox.h>
5
6WtNodeFlowWidget::WtNodeFlowWidget(std::shared_ptr<dyno::SceneGraph> scene)
7 : WtFlowWidget(scene)
8{
9 setPreferredMethod(Wt::RenderMethod::HtmlCanvas);
10
11 this->mouseWentDown().connect(this, &WtNodeFlowWidget::onMouseWentDown);
12 this->mouseMoved().connect(this, &WtNodeFlowWidget::onMouseMove);
13 this->mouseWentUp().connect(this, &WtNodeFlowWidget::onMouseWentUp);
14}
15
17
18void WtNodeFlowWidget::onMouseWentDown(const Wt::WMouseEvent& event)
19{
20 isDragging = true;
21 mLastMousePos = Wt::WPointF(event.widget().x, event.widget().y);
22 mLastDelta = Wt::WPointF(0, 0);
23 if (!checkMouseInAllRect(Wt::WPointF(event.widget().x, event.widget().y)))
24 {
25 selectType = -1;
26 selectedNum = 0;
27 canMoveNode = false;
28 update();
29
30 }
31 if (selectType > 0)
32 {
33 auto origin = nodeMap[selectedNum]->flowNodeData().getNodeOrigin();
34 mTranslateNode = Wt::WPointF(origin.x(), origin.y());
36 {
37 drawLineFlag = true;
38
39 if (nodeMap.find(selectedNum) != nodeMap.end())
40 {
41 mOutNode = nodeMap.find(selectedNum)->second->getNode();
42 }
43
44 if (outPoint.portType == PortType::In)
45 {
46 auto existConnection = nodeMap[selectedNum]->getIndexConnection(outPoint.portIndex);
47 if (existConnection != nullptr)
48 {
49 auto outNode = existConnection->getNode(PortType::Out);
50 for (auto it = mScene->begin(); it != mScene->end(); it++)
51 {
52 auto m = it.get();
53 auto node = nodeMap[m->objectId()];
54 auto outPortIndex = existConnection->getPortIndex(PortType::Out);
55 auto exportPortsData = outNode->flowNodeData().getPointsData();
56 connectionPointData exportPointData;
57 for (auto point : exportPortsData)
58 {
59 if (point.portIndex == outPortIndex)
60 {
61 exportPointData = point;
62 break;
63 }
64 }
65
66 if (node == outNode)
67 {
68 for (auto it = sceneConnections.begin(); it != sceneConnections.end(); )
69 {
70 if (it->exportNode == mOutNode && it->inportNode == m && it->inPoint.portIndex == outPoint.portIndex && it->outPoint.portIndex == exportPointData.portIndex)
71 {
72 it = sceneConnections.erase(it);
73 }
74 else
75 {
76 ++it;
77 }
78 }
79
80 disconnect(m, mOutNode, outPoint, exportPointData, nodeMap[selectedNum], outNode);
81 sourcePoint = getPortPosition(outNode->flowNodeData().getNodeOrigin(), exportPointData);
82
83 }
84 }
85
86 }
87 }
88 }
89 else
90 {
91 // selectType = 2: selected & drag
92 // selectType = 1: mouse move node
93 // selectType = -1: no select
94 selectType = 2;
95 }
96 }
97
98}
99
100void WtNodeFlowWidget::onMouseMove(const Wt::WMouseEvent& event)
101{
102 sinkPoint = Wt::WPointF(event.widget().x / mZoomFactor - mTranslate.x(), event.widget().y / mZoomFactor - mTranslate.y());
103 if (isDragging && selectType < 0)
104 {
105 Wt::WPointF delta = Wt::WPointF(event.dragDelta().x, event.dragDelta().y);
106 mTranslate = Wt::WPointF(mTranslate.x() + delta.x() - mLastDelta.x(), mTranslate.y() + delta.y() - mLastDelta.y());
107 update();
108 mLastDelta = delta;
109 }
110 else if (isDragging && selectType > 0)
111 {
112 Wt::WPointF delta = Wt::WPointF(event.dragDelta().x, event.dragDelta().y);
113 mTranslateNode = Wt::WPointF(mTranslateNode.x() + delta.x() - mLastDelta.x(), mTranslateNode.y() + delta.y() - mLastDelta.y());
114 update();
115 mLastDelta = delta;
116 }
117 else
118 {
119 for (auto it = mScene->begin(); it != mScene->end(); it++)
120 {
121 auto m = it.get();
122 auto node = nodeMap[m->objectId()];
123 auto nodeData = node->flowNodeData();
124 auto mousePoint = Wt::WPointF(event.widget().x, event.widget().y);
125 if (checkMouseInRect(mousePoint, nodeData) && selectType != 2)
126 {
127 selectType = 1;
128 connectionOutNode = node;
129 selectedNum = m->objectId();
130 canMoveNode = true;
131 update();
132 break;
133 }
134 }
135 }
136}
137
138void WtNodeFlowWidget::onMouseWentUp(const Wt::WMouseEvent& event)
139{
140 isDragging = false;
141 mLastDelta = Wt::WPointF(0, 0);
142 mTranslateNode = Wt::WPointF(0, 0);
143 Wt::WPointF mouseWentUpPosition = Wt::WPointF(event.widget().x, event.widget().y);
144 if (selectType > 0)
145 {
146 auto node = nodeMap[selectedNum];
147 auto nodeData = node->flowNodeData();
148
150
151 Wt::WPointF mousePoint = Wt::WPointF(event.widget().x, event.widget().y);
152 if (!checkMouseInAllRect(mousePoint) && selectType == 2)
153 {
154 selectType = -1;
155 selectedNum = 0;
156 canMoveNode = false;
157 update();
158 _updateCanvas.emit();
159 }
160
161 if (checkMouseInHotKey0(mousePoint, nodeData))
162 {
163 auto nodeWidget = dynamic_cast<WtNodeWidget*>(node->nodeDataModel());
164 auto m = nodeWidget->getNode();
165 if (m->isVisible())
166 {
167 enableRendering(*node, false);
168 }
169 else
170 {
171 enableRendering(*node, true);
172 }
173 //mMainWindow->updateCanvas();
174 _updateCanvas.emit();
175 update();
176 }
177
178 if (checkMouseInHotKey1(mousePoint, nodeData))
179 {
180 auto nodeWidget = dynamic_cast<WtNodeWidget*>(node->nodeDataModel());
181 auto m = nodeWidget->getNode();
182 if (m->isActive())
183 {
184 enablePhysics(*node, false);
185 }
186 else
187 {
188 enablePhysics(*node, true);
189 }
190 //mMainWindow->updateCanvas();
191 _updateCanvas.emit();
192 update();
193 }
194 }
195 else
196 {
197 _selectNodeSignal.emit(-1);
198 }
199
200 if (drawLineFlag = true)
201 {
202 for (auto it = mScene->begin(); it != mScene->end(); it++)
203 {
204 auto m = it.get();
205 auto node = nodeMap[m->objectId()];
206 auto nodeData = node->flowNodeData();
207 if (checkMouseInPoints(mouseWentUpPosition, nodeData, PortState::in))
208 {
209 auto connectionInNode = node;
210
211 if (outPoint.portType == PortType::Out)
212 {
213 WtConnection connection(outPoint.portType, *connectionOutNode, outPoint.portIndex);
214 WtInteraction interaction(*connectionInNode, connection, *node_scene, inPoint, outPoint, m, mOutNode);
215 if (interaction.tryConnect())
216 {
217 sceneConnection temp;
218 temp.exportNode = m;
219 temp.inportNode = mOutNode;
220 temp.inPoint = inPoint;
221 temp.outPoint = outPoint;
222 sceneConnections.push_back(temp);
223 update();
224 }
225 }
226
227 }
228 }
229 }
230 drawLineFlag = false;
231 update();
232}
233
235{
236 if (selectType > 0)
237 {
238 auto node = nodeMap[selectedNum];
239 deleteNode(*node);
240 selectType = -1;
241 selectedNum = 0;
242 updateAll();
243 }
244}
245
246void WtNodeFlowWidget::setSelectNode(std::shared_ptr<dyno::Node> node)
247{
248 selectType = 2;
249 selectedNum = node->objectId();
250 update();
251}
252
253void WtNodeFlowWidget::paintEvent(Wt::WPaintDevice* paintDevice)
254{
255 Wt::WPainter painter(paintDevice);
256 painter.scale(mZoomFactor, mZoomFactor);
257 painter.translate(mTranslate);
258
259 if (reorderFlag)
260 {
262 node_scene->reorderAllNodes();
263 reorderFlag = false;
264 }
265
267
268 nodeMap = node_scene->getNodeMap();
269
270 if (isDragging && selectType > 0 && !drawLineFlag)
271 {
272 auto node = nodeMap[selectedNum];
273 moveNode(*node, mTranslateNode);
274 }
275
276 if (drawLineFlag)
277 {
279 }
280}
281
282bool WtNodeFlowWidget::checkMouseInAllRect(Wt::WPointF mousePoint)
283{
284 for (auto it = mScene->begin(); it != mScene->end(); it++)
285 {
286 auto m = it.get();
287 auto node = nodeMap[m->objectId()];
288 auto nodeData = node->flowNodeData();
289 if (checkMouseInRect(mousePoint, nodeData))
290 {
291 selectedNum = m->objectId();
292 canMoveNode = true;
293 return true;
294 }
295 }
296 return false;
297}
298
299bool WtNodeFlowWidget::checkMouseInHotKey0(Wt::WPointF mousePoint, WtFlowNodeData nodeData)
300{
301 Wt::WRectF relativeHotkey = nodeData.getHotKey0BoundingRect();
302 Wt::WPointF origin = nodeData.getNodeOrigin();
303
304 Wt::WPointF topLeft = Wt::WPointF(relativeHotkey.topLeft().x() + origin.x(), relativeHotkey.topLeft().y() + origin.y());
305 Wt::WPointF bottomRight = Wt::WPointF(relativeHotkey.bottomRight().x() + origin.x(), relativeHotkey.bottomRight().y() + origin.y());
306
307 Wt::WRectF absRect = Wt::WRectF(topLeft, bottomRight);
308
309 Wt::WPointF trueMouse = Wt::WPointF(mousePoint.x() / mZoomFactor - mTranslate.x(), mousePoint.y() / mZoomFactor - mTranslate.y());
310
311 return absRect.contains(trueMouse);
312}
313
314bool WtNodeFlowWidget::checkMouseInHotKey1(Wt::WPointF mousePoint, WtFlowNodeData nodeData)
315{
316 Wt::WRectF relativeHotkey = nodeData.getHotKey1BoundingRect();
317 Wt::WPointF origin = nodeData.getNodeOrigin();
318
319 Wt::WPointF topLeft = Wt::WPointF(relativeHotkey.topLeft().x() + origin.x(), relativeHotkey.topLeft().y() + origin.y());
320 Wt::WPointF bottomRight = Wt::WPointF(relativeHotkey.bottomRight().x() + origin.x(), relativeHotkey.bottomRight().y() + origin.y());
321
322 Wt::WRectF absRect = Wt::WRectF(topLeft, bottomRight);
323
324 Wt::WPointF trueMouse = Wt::WPointF(mousePoint.x() / mZoomFactor - mTranslate.x(), mousePoint.y() / mZoomFactor - mTranslate.y());
325
326 return absRect.contains(trueMouse);
327}
328
329Wt::WPointF WtNodeFlowWidget::getPortPosition(Wt::WPointF origin, connectionPointData portData)
330{
331 if (portData.portShape == PortShape::Bullet)
332 {
333 Wt::WPointF topLeft = Wt::WPointF(portData.diamond_out[3].x() + origin.x(), portData.diamond_out[2].y() + origin.y());
334 Wt::WPointF bottomRight = Wt::WPointF(portData.diamond_out[1].x() + origin.x(), portData.diamond_out[0].y() + origin.y());
335 Wt::WRectF diamondBoundingRect = Wt::WRectF(topLeft, bottomRight);
336 return Wt::WPointF((topLeft.x() + bottomRight.x()) / 2, (topLeft.y() + bottomRight.y()) / 2);
337 }
338 else if (portData.portShape == PortShape::Diamond)
339 {
340 Wt::WPointF topLeft = Wt::WPointF(portData.diamond[3].x() + origin.x(), portData.diamond[2].y() + origin.y());
341 Wt::WPointF bottomRight = Wt::WPointF(portData.diamond[1].x() + origin.x(), portData.diamond[0].y() + origin.y());
342 Wt::WRectF diamondBoundingRect = Wt::WRectF(topLeft, bottomRight);
343 return Wt::WPointF((topLeft.x() + bottomRight.x()) / 2, (topLeft.y() + bottomRight.y()) / 2);
344 }
345 else if (portData.portShape == PortShape::Point)
346 {
347 auto rectTopLeft = portData.pointRect.topLeft();
348 auto rectBottomRight = portData.pointRect.bottomRight();
349 Wt::WPointF topLeft = Wt::WPointF(rectTopLeft.x() + origin.x(), rectTopLeft.y() + origin.y());
350 Wt::WPointF bottomRight = Wt::WPointF(rectBottomRight.x() + origin.x(), rectBottomRight.y() + origin.y());
351 Wt::WRectF diamondBoundingRect = Wt::WRectF(topLeft, bottomRight);
352 return Wt::WPointF((topLeft.x() + bottomRight.x()) / 2, (topLeft.y() + bottomRight.y()) / 2);
353 }
354}
355
357{
358 auto nodeData = dynamic_cast<WtNodeWidget*>(n.nodeDataModel());
359
360 if (mEditingEnabled && nodeData != nullptr)
361 {
362 auto node = nodeData->getNode();
363
364 for (auto c : sceneConnections)
365 {
366 if (c.exportNode == node || c.inportNode == node)
367 {
368 Wt::WMessageBox::show("Error",
369 "<p>Please disconnect before deleting the node </p>",
370 Wt::StandardButton::Ok);
371 return;
372 }
373 }
374
375 mScene->deleteNode(node);
376 }
377}
378
383
384
385void WtNodeFlowWidget::moveNode(WtNode& n, const Wt::WPointF& newLocation)
386{
387 auto nodeData = dynamic_cast<WtNodeWidget*>(n.nodeDataModel());
388
389 if (mEditingEnabled && nodeData != nullptr)
390 {
391 auto node = nodeData->getNode();
392 node->setBlockCoord(newLocation.x(), newLocation.y());
393 }
394}
395
397{
398 auto nodeData = dynamic_cast<WtNodeWidget*>(n.nodeDataModel());
399
400 if (mEditingEnabled && nodeData != nullptr) {
401 auto node = nodeData->getNode();
402 node->setVisible(checked);
403 }
404}
405
407{
408 auto nodeData = dynamic_cast<WtNodeWidget*>(n.nodeDataModel());
409 if (mEditingEnabled && nodeData != nullptr) {
410 auto node = nodeData->getNode();
411 node->setActive(checked);
412 }
413}
414
415void WtNodeFlowWidget::disconnect(std::shared_ptr<Node> exportNode, std::shared_ptr<Node> inportNode, connectionPointData inPoint, connectionPointData outPoint, WtNode* inWtNode, WtNode* outWtNode)
416{
417 auto inportIndex = inPoint.portIndex;
418 if (inPoint.portShape == PortShape::Diamond || inPoint.portShape == PortShape::Bullet)
419 {
420 exportNode->disconnect(inportNode->getImportNodes()[inportIndex]);
421 }
422 else if (inPoint.portShape == PortShape::Point)
423 {
424 auto outFieldNum = 0;
425 auto outPoints = outWtNode->flowNodeData().getPointsData();
426 for (auto point : outPoints)
427 {
428 if (point.portShape == PortShape::Point)
429 {
430 outFieldNum = point.portIndex;
431 break;
432 }
433 }
434
435 auto field = exportNode->getOutputFields()[outPoint.portIndex - outFieldNum];
436
437 if (field != NULL)
438 {
439 auto node_data = inWtNode->flowNodeData();
440
441 auto points = node_data.getPointsData();
442
443 int fieldNum = 0;
444
445 for (auto point : points)
446 {
447 if (point.portType == PortType::In)
448 {
449 if (point.portShape == PortShape::Bullet || point.portShape == PortShape::Diamond)
450 {
451 fieldNum++;
452 }
453 }
454 }
455
456 auto inField = inportNode->getInputFields()[inPoint.portIndex - fieldNum];
457
458 field->disconnect(inField);
459 }
460 }
461}
@ in
@ out
Wt::WRectF getHotKey1BoundingRect()
Wt::WRectF getHotKey0BoundingRect()
std::vector< connectionPointData > getPointsData()
Wt::WPointF getNodeOrigin() const
connectionPointData outPoint
Wt::Signal _updateCanvas
WtFlowWidget(std::shared_ptr< dyno::SceneGraph > scene)
Wt::WPointF mTranslateNode
Wt::WPointF sourcePoint
Wt::WPointF mLastDelta
std::shared_ptr< dyno::SceneGraph > mScene
bool mEditingEnabled
connectionPointData inPoint
bool checkMouseInRect(Wt::WPointF mousePoint, WtFlowNodeData nodeData)
Wt::WPointF sinkPoint
void drawSketchLine(Wt::WPainter *painter, Wt::WPointF source, Wt::WPointF sink)
Wt::Signal< int > _selectNodeSignal
Wt::WPointF mLastMousePos
double mZoomFactor
Wt::WPointF mTranslate
bool checkMouseInPoints(Wt::WPointF mousePoint, WtFlowNodeData nodeData, PortState portState)
void onKeyWentDown() override
Wt::WPointF getPortPosition(Wt::WPointF origin, connectionPointData portData)
void disconnect(std::shared_ptr< Node > exportNode, std::shared_ptr< Node > inportNode, connectionPointData inPoint, connectionPointData outPoint, WtNode *inWtNode, WtNode *outWtNode)
void setSelectNode(std::shared_ptr< dyno::Node > node)
void disconnectionsFromNode(WtNode &node)
void onMouseWentUp(const Wt::WMouseEvent &event) override
void onMouseWentDown(const Wt::WMouseEvent &event) override
std::shared_ptr< Node > mOutNode
std::vector< sceneConnection > sceneConnections
void moveNode(WtNode &n, const Wt::WPointF &newLocaton)
void enablePhysics(WtNode &n, bool checked)
WtNodeFlowWidget(std::shared_ptr< dyno::SceneGraph > scene)
void onMouseMove(const Wt::WMouseEvent &event) override
std::map< dyno::ObjectId, WtNode * > nodeMap
void deleteNode(WtNode &n)
void enableRendering(WtNode &n, bool checked)
bool checkMouseInAllRect(Wt::WPointF mousePoint)
void paintEvent(Wt::WPaintDevice *paintDevice)
WtNodeFlowScene * node_scene
bool checkMouseInHotKey0(Wt::WPointF mousePoint, WtFlowNodeData nodeData)
bool checkMouseInHotKey1(Wt::WPointF mousePoint, WtFlowNodeData nodeData)
WtNodeDataModel * nodeDataModel() const
Definition WtNode.cpp:727
WtFlowNodeData & flowNodeData()
Definition WtNode.h:288
std::shared_ptr< Node > getNode()
Wt::WPointF diamond_out[4]
Wt::WPointF diamond[4]
std::shared_ptr< Node > inportNode
std::shared_ptr< Node > exportNode
connectionPointData inPoint
connectionPointData outPoint