1
2
3 #include "toonzqt/fxschematicscene.h"
4
5 // TnzQt includes
6 #include "toonzqt/fxtypes.h"
7 #include "toonzqt/fxschematicnode.h"
8 #include "toonzqt/gutil.h"
9 #include "toonzqt/dvdialog.h"
10 #include "toonzqt/fxselection.h"
11 #include "toonzqt/schematicgroupeditor.h"
12 #include "toonzqt/swatchviewer.h"
13 #include "toonzqt/tselectionhandle.h"
14
15 // TnzLib includes
16 #include "toonz/txsheet.h"
17 #include "toonz/toonzscene.h"
18 #include "toonz/tcolumnfxset.h"
19 #include "toonz/fxdag.h"
20 #include "toonz/txshlevelcolumn.h"
21 #include "toonz/tcolumnfx.h"
22 #include "toonz/txshpalettecolumn.h"
23 #include "toonz/txshzeraryfxcolumn.h"
24 #include "toonz/fxcommand.h"
25 #include "toonz/txsheethandle.h"
26 #include "toonz/tfxhandle.h"
27 #include "toonz/tscenehandle.h"
28 #include "toonz/tcolumnhandle.h"
29 #include "toonz/tframehandle.h"
30 #include "toonz/tobjecthandle.h"
31 #include "toonz/childstack.h"
32
33 // TnzBase includes
34 #include "tmacrofx.h"
35 #include "fxdata.h"
36 #include "tpassivecachemanager.h"
37 #include "tfxattributes.h"
38
39 // TnzCore includes
40 #include "tconst.h"
41 #include "tenv.h"
42
43 // Qt includes
44 #include <QMenu>
45 #include <QApplication>
46 #include <QGraphicsSceneContextMenuEvent>
47
48 TEnv::IntVar IconifyFxSchematicNodes("IconifyFxSchematicNodes", 0);
49
50 namespace {
51
52 class MatchesFx {
53 TFxP m_fx;
54
55 public:
MatchesFx(const TFxP & fx)56 MatchesFx(const TFxP &fx) : m_fx(fx) {}
57
operator ()(const TFxP & fx)58 bool operator()(const TFxP &fx) {
59 TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx.getPointer());
60 return (m_fx.getPointer() == fx.getPointer()) ||
61 (zfx && m_fx.getPointer() == zfx->getZeraryFx());
62 }
63 };
64
65 //-----------------------------------------------------------
66
keepSubgroup(QMap<int,QList<SchematicNode * >> & editedGroup)67 void keepSubgroup(QMap<int, QList<SchematicNode *>> &editedGroup) {
68 QMap<int, QList<SchematicNode *>>::iterator it;
69 for (it = editedGroup.begin(); it != editedGroup.end(); it++) {
70 QList<SchematicNode *> groupedNodes = it.value();
71 int i;
72 for (i = 0; i < groupedNodes.size(); i++) {
73 FxSchematicNode *node = dynamic_cast<FxSchematicNode *>(groupedNodes[i]);
74 if (!node) continue;
75 TFx *fx = node->getFx();
76 assert(fx);
77 QMap<int, QList<SchematicNode *>>::iterator it2;
78 for (it2 = editedGroup.begin(); it2 != editedGroup.end(); it2++) {
79 if (fx->getAttributes()->isContainedInGroup(it2.key()) &&
80 !editedGroup[it2.key()].contains(node))
81 editedGroup[it2.key()].append(node);
82 }
83 }
84 }
85 }
86
87 //-----------------------------------------------------------
88
89 //! Find the input and the output fx contained in \b visitedFxs.
90 //! \b visitedFxs must be a connected fx selection. In \b outputFx is put the
91 //! root of the connected fx selection.
92 //! In \b inputFx is put a leaf of the connected fx selection.
findBoundariesFxs(TFx * & inputFx,TFx * & outputFx,QMap<TFx *,bool> & visitedFxs,TFx * currentFx=0)93 void findBoundariesFxs(TFx *&inputFx, TFx *&outputFx,
94 QMap<TFx *, bool> &visitedFxs, TFx *currentFx = 0) {
95 if (visitedFxs.isEmpty()) return;
96 if (!currentFx) currentFx = visitedFxs.begin().key();
97 int inputPortCount = currentFx->getInputPortCount();
98 int outputConnectionCount = currentFx->getOutputConnectionCount();
99
100 if (inputPortCount > 0 && !visitedFxs[currentFx]) {
101 visitedFxs[currentFx] = true;
102 TFxPort *fxPort = currentFx->getInputPort(0);
103 TFx *fx = fxPort->getFx();
104 if (fx && visitedFxs.count(fx) == 1) {
105 if (!visitedFxs[fx]) findBoundariesFxs(inputFx, outputFx, visitedFxs, fx);
106 } else
107 inputFx = currentFx;
108 } else
109 inputFx = currentFx;
110 if (!outputFx) {
111 if (outputConnectionCount > 0) {
112 TFx *fx = currentFx->getOutputConnection(0)->getOwnerFx();
113 if (fx && visitedFxs.count(fx) == 1) {
114 if (!visitedFxs[fx])
115 findBoundariesFxs(inputFx, outputFx, visitedFxs, fx);
116 } else
117 outputFx = currentFx;
118 } else
119 outputFx = currentFx;
120 }
121 }
122
123 //-----------------------------------------------------------
124
canDisconnectSelection(FxSelection * selection)125 bool canDisconnectSelection(FxSelection *selection) {
126 QList<TFxP> selectedFx = selection->getFxs();
127 int i;
128 for (i = 0; i < selectedFx.size(); i++) // .....
129 {
130 TFx *fx = selectedFx[i].getPointer();
131
132 TLevelColumnFx *lcFx = dynamic_cast<TLevelColumnFx *>(fx);
133 TPaletteColumnFx *pfx = dynamic_cast<TPaletteColumnFx *>(fx);
134 TXsheetFx *xfx = dynamic_cast<TXsheetFx *>(fx);
135 TOutputFx *ofx = dynamic_cast<TOutputFx *>(fx);
136 TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx);
137
138 return (!lcFx && !pfx && !xfx && !ofx &&
139 (!zfx || zfx->getInputPortCount() > 0)); // !!!!!
140 }
141 return false;
142 }
143
144 //------------------------------------------------------------------
145
getRoots(const QList<TFxP> & fxs,TFxSet * terminals)146 QList<TFxP> getRoots(const QList<TFxP> &fxs, TFxSet *terminals) {
147 QList<TFxP> roots;
148 int i;
149 for (i = 0; i < fxs.size(); i++) {
150 TFx *fx = fxs[i].getPointer();
151 int j;
152 bool isRoot = true;
153 for (j = 0; j < fx->getOutputConnectionCount(); j++) {
154 TFx *outFx = fx->getOutputConnection(j)->getOwnerFx();
155 if (outFx &&
156 std::find_if(fxs.begin(), fxs.end(), MatchesFx(outFx)) != fxs.end() &&
157 !terminals->containsFx(fx))
158 isRoot = false;
159 }
160 if (isRoot) roots.append(fx);
161 }
162 return roots;
163 }
164
165 bool resizingNodes = false;
166 bool updatingScene = false;
167 } // namespace
168
169 //==================================================================
170 //
171 // FxSchematicScene::SupportLinks
172 //
173 //==================================================================
174
addBridgeLink(SchematicLink * link)175 void FxSchematicScene::SupportLinks::addBridgeLink(SchematicLink *link) {
176 if (link && !m_bridges.contains(link)) m_bridges.push_back(link);
177 }
178
179 //------------------------------------------------------------------
180
addOutputLink(SchematicLink * link)181 void FxSchematicScene::SupportLinks::addOutputLink(SchematicLink *link) {
182 if (link && !m_outputs.contains(link)) m_outputs.push_back(link);
183 }
184
185 //------------------------------------------------------------------
186
addInputLink(SchematicLink * link)187 void FxSchematicScene::SupportLinks::addInputLink(SchematicLink *link) {
188 if (link && !m_inputs.contains(link)) m_inputs.push_back(link);
189 }
190
191 //------------------------------------------------------------------
192
hideBridgeLinks()193 void FxSchematicScene::SupportLinks::hideBridgeLinks() {
194 int i;
195 for (i = 0; i < m_bridges.size(); i++) m_bridges[i]->hide();
196 }
197
198 //------------------------------------------------------------------
199
hideInputLinks()200 void FxSchematicScene::SupportLinks::hideInputLinks() {
201 int i;
202 for (i = 0; i < m_inputs.size(); i++) m_inputs[i]->hide();
203 }
204
205 //------------------------------------------------------------------
206
hideOutputLinks()207 void FxSchematicScene::SupportLinks::hideOutputLinks() {
208 int i;
209 for (i = 0; i < m_outputs.size(); i++) m_outputs[i]->hide();
210 }
211
212 //------------------------------------------------------------------
213
showBridgeLinks()214 void FxSchematicScene::SupportLinks::showBridgeLinks() {
215 int i;
216 for (i = 0; i < m_bridges.size(); i++) m_bridges[i]->show();
217 }
218
219 //------------------------------------------------------------------
220
showInputLinks()221 void FxSchematicScene::SupportLinks::showInputLinks() {
222 int i;
223 for (i = 0; i < m_inputs.size(); i++) m_inputs[i]->show();
224 }
225
226 //------------------------------------------------------------------
227
showOutputLinks()228 void FxSchematicScene::SupportLinks::showOutputLinks() {
229 int i;
230 for (i = 0; i < m_outputs.size(); i++) m_outputs[i]->show();
231 }
232
233 //------------------------------------------------------------------
234
removeBridgeLinks(bool deleteLink)235 void FxSchematicScene::SupportLinks::removeBridgeLinks(bool deleteLink) {
236 int i;
237 for (i = 0; i < m_bridges.size(); i++) {
238 SchematicLink *link = m_bridges[i];
239 m_bridges.removeAt(i);
240 if (deleteLink) {
241 link->getStartPort()->removeLink(link);
242 link->getEndPort()->removeLink(link);
243 delete link;
244 }
245 }
246 }
247
248 //------------------------------------------------------------------
249
removeInputLinks(bool deleteLink)250 void FxSchematicScene::SupportLinks::removeInputLinks(bool deleteLink) {
251 int i;
252 for (i = 0; i < m_inputs.size(); i++) {
253 SchematicLink *link = m_inputs[i];
254 m_inputs.removeAt(i);
255 if (deleteLink) {
256 link->getStartPort()->removeLink(link);
257 link->getEndPort()->removeLink(link);
258 delete link;
259 }
260 }
261 }
262
263 //------------------------------------------------------------------
264
removeOutputLinks(bool deleteLink)265 void FxSchematicScene::SupportLinks::removeOutputLinks(bool deleteLink) {
266 int i;
267 for (i = 0; i < m_outputs.size(); i++) {
268 SchematicLink *link = m_outputs[i];
269 m_outputs.removeAt(i);
270 if (deleteLink) {
271 link->getStartPort()->removeLink(link);
272 link->getEndPort()->removeLink(link);
273 delete link;
274 }
275 }
276 }
277
278 //------------------------------------------------------------------
279
clearAll()280 void FxSchematicScene::SupportLinks::clearAll() {
281 m_bridges.clear();
282 m_inputs.clear();
283 m_outputs.clear();
284 }
285
286 //------------------------------------------------------------------
287
size()288 int FxSchematicScene::SupportLinks::size() {
289 return m_bridges.size() + m_inputs.size() + m_outputs.size();
290 }
291
292 //==================================================================
293 //
294 // FxSchematicScene
295 //
296 //==================================================================
297
FxSchematicScene(QWidget * parent)298 FxSchematicScene::FxSchematicScene(QWidget *parent)
299 : SchematicScene(parent)
300 , m_firstPoint(sceneRect().center())
301 , m_xshHandle(0)
302 , m_fxHandle(0)
303 , m_addFxContextMenu()
304 , m_disconnectionLinks()
305 , m_connectionLinks()
306 , m_isConnected(false)
307 , m_linkUnlinkSimulation(false)
308 , m_altPressed(false)
309 , m_lastPos(0, 0)
310 , m_currentFxNode(0)
311 , m_gridDimension(eSmall)
312 , m_isNormalIconView(!IconifyFxSchematicNodes)
313 , m_viewer() {
314 m_viewer = (SchematicViewer *)parent;
315
316 m_selection = new FxSelection();
317 m_selection->setFxSchematicScene(this);
318
319 connect(m_selection, SIGNAL(doCollapse(const QList<TFxP> &)), this,
320 SLOT(onCollapse(const QList<TFxP> &)));
321 connect(m_selection, SIGNAL(doExplodeChild(const QList<TFxP> &)), this,
322 SIGNAL(doExplodeChild(const QList<TFxP> &)));
323 connect(this, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
324
325 m_addFxContextMenu.setSelection(m_selection);
326 m_highlightedLinks.clear();
327 }
328
329 //------------------------------------------------------------------
330
~FxSchematicScene()331 FxSchematicScene::~FxSchematicScene() {
332 if (m_selection) delete m_selection;
333 }
334
335 //------------------------------------------------------------------
336
setApplication(TApplication * app)337 void FxSchematicScene::setApplication(TApplication *app) {
338 m_app = app;
339
340 m_xshHandle = app->getCurrentXsheet();
341 m_fxHandle = app->getCurrentFx();
342 m_frameHandle = app->getCurrentFrame();
343 m_columnHandle = app->getCurrentColumn();
344
345 if (m_fxHandle)
346 connect(m_fxHandle, SIGNAL(fxSwitched()), this,
347 SLOT(onCurrentFxSwitched()));
348
349 m_addFxContextMenu.setApplication(app);
350
351 m_selection->setXsheetHandle(m_xshHandle);
352 m_selection->setFxHandle(m_fxHandle);
353 }
354
355 //------------------------------------------------------------------
356
updateScene()357 void FxSchematicScene::updateScene() {
358 if (updatingScene) return;
359 updatingScene = true;
360 if (!views().empty()) m_disconnectionLinks.clearAll();
361 m_connectionLinks.clearAll();
362 m_selectionOldPos.clear();
363
364 clearSelection();
365 clearAllItems();
366
367 m_table.clear();
368 m_groupedTable.clear();
369 m_groupEditorTable.clear();
370 m_macroEditorTable.clear();
371
372 m_currentFxNode = 0;
373
374 // GroupId->Fx
375 QMap<int, QList<TFxP>> groupedFxs;
376 QMap<int, QList<SchematicNode *>> editedGroup;
377 QMap<TMacroFx *, QList<SchematicNode *>> editedMacro;
378
379 TXsheet *xsh = m_xshHandle->getXsheet();
380 m_gridDimension = xsh->getFxDag()->getDagGridDimension();
381 TFxSet *fxSet = xsh->getFxDag()->getInternalFxs();
382 int i;
383
384 FxDag *fxDag = xsh->getFxDag();
385 // Add XSheetFX node
386 addFxSchematicNode(fxDag->getXsheetFx());
387
388 // Add outputFx nodes
389 int k;
390 for (k = 0; k < fxDag->getOutputFxCount(); k++) {
391 TOutputFx *fx = fxDag->getOutputFx(k);
392 if (fx->getAttributes()->isGrouped() &&
393 !fx->getAttributes()->isGroupEditing()) {
394 groupedFxs[fx->getAttributes()->getGroupId()].push_back(fx);
395 continue;
396 }
397 SchematicNode *node = addFxSchematicNode(fx);
398 if (fx->getAttributes()->isGrouped())
399 editedGroup[fx->getAttributes()->getEditingGroupId()].append(node);
400 }
401
402 // Add columnFx and zeraryFx nodes
403 for (i = 0; i < xsh->getColumnCount(); i++) {
404 TXshColumn *column = xsh->getColumn(i);
405 TFx *fx = 0;
406 if (TXshLevelColumn *lc = column->getLevelColumn())
407 fx = lc->getLevelColumnFx();
408 else if (TXshPaletteColumn *pc = dynamic_cast<TXshPaletteColumn *>(column))
409 fx = pc->getPaletteColumnFx();
410 else if (TXshZeraryFxColumn *zc =
411 dynamic_cast<TXshZeraryFxColumn *>(column))
412 fx = zc->getZeraryColumnFx();
413 if (!fx) continue;
414
415 if (fx->getAttributes()->isGrouped() &&
416 !fx->getAttributes()->isGroupEditing()) {
417 groupedFxs[fx->getAttributes()->getGroupId()].push_back(fx);
418 continue;
419 }
420 if (column->isEmpty() && fx && fx->getOutputConnectionCount() == 0)
421 continue;
422 SchematicNode *node = addFxSchematicNode(fx);
423 if (fx->getAttributes()->isGrouped())
424 editedGroup[fx->getAttributes()->getEditingGroupId()].append(node);
425 }
426
427 // Add normalFx
428 for (i = 0; i < fxSet->getFxCount(); i++) {
429 TFx *fx = fxSet->getFx(i);
430 TMacroFx *macro = dynamic_cast<TMacroFx *>(fx);
431 if (fx->getAttributes()->isGrouped() &&
432 !fx->getAttributes()->isGroupEditing()) {
433 groupedFxs[fx->getAttributes()->getGroupId()].push_back(fx);
434 continue;
435 } else if (macro && macro->isEditing()) {
436 std::vector<TFxP> fxs = macro->getFxs();
437 int j;
438 for (j = 0; j < (int)fxs.size(); j++) {
439 SchematicNode *node = addFxSchematicNode(fxs[j].getPointer());
440 editedMacro[macro].append(node);
441 if (fxs[j]->getAttributes()->isGrouped() &&
442 macro->getAttributes()->isGroupEditing())
443 editedGroup[fx->getAttributes()->getEditingGroupId()].append(node);
444 }
445 continue;
446 }
447 SchematicNode *node = addFxSchematicNode(fx);
448 if (fx->getAttributes()->isGrouped())
449 editedGroup[fx->getAttributes()->getEditingGroupId()].append(node);
450 // If adding an unedited macro and nodes are not yet set, let's position the
451 // internal nodes now
452 if (macro) {
453 double minY = macro->getAttributes()->getDagNodePos().y;
454 double maxX = macro->getAttributes()->getDagNodePos().x;
455 double y = minY;
456 double x = maxX;
457 std::vector<TFxP> fxs = macro->getFxs();
458 for (int j = 0; j < (int)fxs.size(); j++) {
459 TFx *macroFx = fxs[j].getPointer();
460 if (macroFx && !m_placedFxs.contains(macroFx)) {
461 placeNodeAndParents(macroFx, x, maxX, minY);
462 y -= (m_gridDimension == eLarge ? 100 : 50);
463 minY = std::min(y, minY);
464 }
465 }
466 }
467 }
468
469 // grouped node
470 QMap<int, QList<TFxP>>::const_iterator it;
471 for (it = groupedFxs.begin(); it != groupedFxs.end(); it++) {
472 FxSchematicNode *node = addGroupedFxSchematicNode(it.key(), it.value());
473 TFx *fx = node->getFx();
474 assert(fx);
475 int editingGroupId = fx->getAttributes()->getEditingGroupId();
476 if (editingGroupId != -1) editedGroup[editingGroupId].append(node);
477 }
478
479 keepSubgroup(editedGroup);
480 updateEditedGroups(editedGroup);
481 updateEditedMacros(editedMacro);
482 updateLink();
483 m_nodesToPlace.clear();
484 updatingScene = false;
485 }
486
487 //------------------------------------------------------------------
488
updateEditedGroups(const QMap<int,QList<SchematicNode * >> & editedGroup)489 void FxSchematicScene::updateEditedGroups(
490 const QMap<int, QList<SchematicNode *>> &editedGroup) {
491 QMap<int, QList<SchematicNode *>>::const_iterator it;
492 for (it = editedGroup.begin(); it != editedGroup.end(); it++) {
493 int zValue = 2;
494 QMap<int, QList<SchematicNode *>>::const_iterator it2 = editedGroup.begin();
495 while (it2 != editedGroup.end()) {
496 FxSchematicNode *placedFxNode =
497 dynamic_cast<FxSchematicNode *>(it2.value()[0]);
498 FxSchematicNode *fxNode = dynamic_cast<FxSchematicNode *>(it.value()[0]);
499 if (!placedFxNode || !fxNode) {
500 it2++;
501 continue;
502 }
503 int placedGroupedId =
504 placedFxNode->getFx()->getAttributes()->getEditingGroupId();
505 if (fxNode->getFx()->getAttributes()->isContainedInGroup(
506 placedGroupedId) &&
507 fxNode->getFx()->getAttributes()->getEditingGroupId() != it2.key())
508 zValue += 2;
509 it2++;
510 }
511 FxSchematicGroupEditor *node =
512 addEditedGroupedFxSchematicNode(it.key(), it.value());
513 node->setZValue(zValue);
514 node->setGroupedNodeZValue(zValue + 1);
515 }
516 }
517
518 //------------------------------------------------------------------
519
updateEditedMacros(const QMap<TMacroFx *,QList<SchematicNode * >> & editedMacro)520 void FxSchematicScene::updateEditedMacros(
521 const QMap<TMacroFx *, QList<SchematicNode *>> &editedMacro) {
522 QMap<TMacroFx *, QList<SchematicNode *>>::const_iterator it;
523 for (it = editedMacro.begin(); it != editedMacro.end(); it++) {
524 TMacroFx *macro = it.key();
525 int zValue = 2;
526 if (macro->getAttributes()->isGrouped()) {
527 FxSchematicGroupEditor *containingGroup =
528 m_groupEditorTable[macro->getAttributes()->getEditingGroupId()];
529 assert(containingGroup);
530 zValue = containingGroup->zValue() + 2;
531 }
532 FxSchematicMacroEditor *node =
533 addEditedMacroFxSchematicNode(it.key(), it.value());
534 node->setZValue(zValue);
535 node->setGroupedNodeZValue(zValue + 1);
536 }
537 }
538
539 //------------------------------------------------------------------
540
addFxSchematicNode(TFx * fx)541 FxSchematicNode *FxSchematicScene::addFxSchematicNode(TFx *fx) {
542 FxSchematicNode *node = createFxSchematicNode(fx);
543 if (!node) return 0;
544 connect(node, SIGNAL(sceneChanged()), this, SLOT(onSceneChanged()));
545 connect(node, SIGNAL(xsheetChanged()), this, SLOT(onXsheetChanged()));
546 connect(node, SIGNAL(switchCurrentFx(TFx *)), this,
547 SLOT(onSwitchCurrentFx(TFx *)));
548 connect(node, SIGNAL(currentColumnChanged(int)), this,
549 SLOT(onCurrentColumnChanged(int)));
550
551 connect(node, SIGNAL(fxNodeDoubleClicked()), this,
552 SLOT(onFxNodeDoubleClicked()));
553
554 connect(node, SIGNAL(nodeChangedSize()), this, SLOT(onNodeChangedSize()));
555
556 if (fx->getAttributes()->getDagNodePos() == TConst::nowhere) {
557 node->resize(m_gridDimension == 0);
558 placeNode(node);
559 } else
560 updatePosition(node, fx->getAttributes()->getDagNodePos());
561 m_table[fx] = node;
562 return node;
563 }
564
565 //------------------------------------------------------------------
566
addGroupedFxSchematicNode(int groupId,const QList<TFxP> & groupedFxs)567 FxSchematicNode *FxSchematicScene::addGroupedFxSchematicNode(
568 int groupId, const QList<TFxP> &groupedFxs) {
569 TFxSet *terminals = getXsheet()->getFxDag()->getTerminalFxs();
570 QList<TFxP> roots = getRoots(groupedFxs, terminals);
571 if (roots.isEmpty()) return 0;
572 std::wstring name = roots[0]->getAttributes()->getGroupName(false);
573 FxGroupNode *node = new FxGroupNode(this, groupedFxs, roots, groupId, name);
574 if (!node) return 0;
575 connect(node, SIGNAL(sceneChanged()), this, SLOT(onSceneChanged()));
576 connect(node, SIGNAL(xsheetChanged()), this, SLOT(onXsheetChanged()));
577 connect(node, SIGNAL(switchCurrentFx(TFx *)), this,
578 SLOT(onSwitchCurrentFx(TFx *)));
579 connect(node, SIGNAL(currentColumnChanged(int)), this,
580 SLOT(onCurrentColumnChanged(int)));
581 connect(node, SIGNAL(fxNodeDoubleClicked()), this,
582 SLOT(onFxNodeDoubleClicked()));
583 m_groupedTable[groupId] = node;
584 return node;
585 }
586
587 //------------------------------------------------------------------
588
addEditedGroupedFxSchematicNode(int groupId,const QList<SchematicNode * > & groupedFxs)589 FxSchematicGroupEditor *FxSchematicScene::addEditedGroupedFxSchematicNode(
590 int groupId, const QList<SchematicNode *> &groupedFxs) {
591 FxSchematicGroupEditor *editorGroup =
592 new FxSchematicGroupEditor(groupId, groupedFxs, this);
593 m_groupEditorTable[groupId] = editorGroup;
594 return editorGroup;
595 }
596
597 //------------------------------------------------------------------
598
addEditedMacroFxSchematicNode(TMacroFx * macro,const QList<SchematicNode * > & groupedFxs)599 FxSchematicMacroEditor *FxSchematicScene::addEditedMacroFxSchematicNode(
600 TMacroFx *macro, const QList<SchematicNode *> &groupedFxs) {
601 FxSchematicMacroEditor *editorMacro =
602 new FxSchematicMacroEditor(macro, groupedFxs, this);
603 m_macroEditorTable[macro] = editorMacro;
604 return editorMacro;
605 }
606
607 //------------------------------------------------------------------
608
updatePosition(FxSchematicNode * node,const TPointD & pos)609 void FxSchematicScene::updatePosition(FxSchematicNode *node,
610 const TPointD &pos) {
611 node->setPos(QPointF(pos.x, pos.y));
612 node->getFx()->getAttributes()->setDagNodePos(pos);
613 QVector<SchematicNode *> placedNodes = getPlacedNode(node);
614 int step = m_gridDimension == eLarge ? 100 : 50;
615 TPointD offset(0, -step);
616 int i;
617 for (i = 0; i < placedNodes.size(); i++) {
618 FxSchematicNode *placedNode =
619 dynamic_cast<FxSchematicNode *>(placedNodes[i]);
620 assert(placedNode);
621 TPointD newPos =
622 placedNode->getFx()->getAttributes()->getDagNodePos() + offset;
623 updatePosition(placedNode, newPos);
624 }
625 }
626
627 //------------------------------------------------------------------
628 /*! create node depends on the fx type
629 */
createFxSchematicNode(TFx * fx)630 FxSchematicNode *FxSchematicScene::createFxSchematicNode(TFx *fx) {
631 if (TLevelColumnFx *lcFx = dynamic_cast<TLevelColumnFx *>(fx))
632 return new FxSchematicColumnNode(this, lcFx);
633 else if (TPaletteColumnFx *pfx = dynamic_cast<TPaletteColumnFx *>(fx))
634 return new FxSchematicPaletteNode(this, pfx);
635 else if (TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx))
636 return new FxSchematicZeraryNode(this, zfx);
637 else if (TXsheetFx *xfx = dynamic_cast<TXsheetFx *>(fx))
638 return new FxSchematicXSheetNode(this, xfx);
639 else if (TOutputFx *ofx = dynamic_cast<TOutputFx *>(fx))
640 return new FxSchematicOutputNode(this, ofx);
641 else
642 return new FxSchematicNormalFxNode(this, fx);
643 }
644
645 //------------------------------------------------------------------
646 /*! place nodes of which positions are not specified manually
647 */
placeNode(FxSchematicNode * node)648 void FxSchematicScene::placeNode(FxSchematicNode *node) {
649 if (!node) return;
650 int step = m_gridDimension == eLarge ? 100 : 50;
651 FxDag *fxDag = m_xshHandle->getXsheet()->getFxDag();
652 QRectF nodeRect = node->boundingRect();
653 if (node->isA(eOutpuFx)) {
654 // I'm placing an output node
655 TFx *xsheetFx = fxDag->getXsheetFx();
656 TFxPort *outPort = xsheetFx->getOutputConnection(0);
657 TFx *connectedOutput = outPort ? outPort->getOwnerFx() : 0;
658 if (connectedOutput && connectedOutput == node->getFx()) {
659 // The output node is connected to the xsheet node
660 TPointD pos = xsheetFx->getAttributes()->getDagNodePos();
661 if (pos != TConst::nowhere)
662 nodeRect.translate(pos.x + 120, pos.y);
663 else
664 nodeRect.translate(sceneRect().center());
665 while (!isAnEmptyZone(nodeRect)) nodeRect.translate(0, step);
666 } else {
667 // The output node is not connected to the xsheet node
668 TFx *fx = node->getFx();
669 TFxPort *port = fx->getInputPort(0);
670 TFx *inputFx = port->getFx();
671 if (inputFx) {
672 // The output node is connected to another node
673 TPointD pos = inputFx->getAttributes()->getDagNodePos();
674 if (pos != TConst::nowhere)
675 nodeRect.translate(pos.x + 120, pos.y);
676 else {
677 m_nodesToPlace[inputFx].append(node);
678 return;
679 }
680 } else {
681 // The output node is not connected
682 QPointF pos = sceneRect().center();
683 nodeRect.translate(pos);
684 }
685 }
686 while (!isAnEmptyZone(nodeRect)) nodeRect.translate(0, step);
687 QPointF newPos = nodeRect.topLeft();
688 node->getFx()->getAttributes()->setDagNodePos(
689 TPointD(newPos.x(), newPos.y()));
690 node->setPos(newPos);
691 return;
692 } else if (node->isA(eXSheetFx)) {
693 // I'm placing the xsheet node
694 TFxSet *terminalFxs = fxDag->getTerminalFxs();
695 int i;
696 double maxX = m_firstPoint.x();
697 for (i = 0; i < terminalFxs->getFxCount(); i++) {
698 TFx *terminalFx = terminalFxs->getFx(i);
699 if (terminalFx->getAttributes()->getDagNodePos() == TConst::nowhere)
700 continue;
701 maxX = std::max(maxX, terminalFx->getAttributes()->getDagNodePos().x);
702 }
703 TPointD oldPos = node->getFx()->getAttributes()->getDagNodePos();
704 QPointF pos;
705 if (oldPos == TConst::nowhere)
706 pos = QPointF(maxX + 120, m_firstPoint.y());
707 else
708 pos = QPointF(maxX + 120 > oldPos.x ? maxX + 120 : oldPos.x, oldPos.y);
709 node->getFx()->getAttributes()->setDagNodePos(TPointD(pos.x(), pos.y()));
710 node->setPos(pos);
711 return;
712 } else if (node->isA(eMacroFx)) {
713 double minX = TConst::nowhere.x, minY = TConst::nowhere.y, maxY;
714 QPointF pos;
715 TMacroFx *macroFx = dynamic_cast<TMacroFx *>(node->getFx());
716 std::vector<TFxP> fxs = macroFx->getFxs();
717 int k;
718 for (k = 0; k < (int)fxs.size(); k++) {
719 TFx *fx = fxs[k].getPointer();
720 if (fx->getAttributes()->getDagNodePos() == TConst::nowhere) continue;
721 if (QPointF(minX, minY) ==
722 QPointF(TConst::nowhere.x, TConst::nowhere.y)) {
723 minX = fx->getAttributes()->getDagNodePos().x;
724 minY = maxY = fx->getAttributes()->getDagNodePos().y;
725 continue;
726 }
727 minX = std::min(fx->getAttributes()->getDagNodePos().x, minX);
728 minY = std::min(fx->getAttributes()->getDagNodePos().y, minY);
729 maxY = std::max(fx->getAttributes()->getDagNodePos().y, maxY);
730 }
731 if (QPointF(minX, minY) == QPointF(TConst::nowhere.x, TConst::nowhere.y)) {
732 TFx *inputFx = node->getFx()->getInputPort(0)->getFx();
733 if (inputFx &&
734 inputFx->getAttributes()->getDagNodePos() != TConst::nowhere) {
735 TPointD dagPos =
736 inputFx->getAttributes()->getDagNodePos() + TPointD(150, 0);
737 pos = QPointF(dagPos.x, dagPos.y);
738 } else
739 pos = sceneRect().center();
740 nodeRect.moveTopLeft(pos);
741 while (!isAnEmptyZone(nodeRect)) nodeRect.translate(0, -step);
742 pos = nodeRect.topLeft();
743 } else {
744 pos.setX(minX);
745 pos.setY((maxY + minY) / 2);
746 }
747 node->getFx()->getAttributes()->setDagNodePos(TPointD(pos.x(), pos.y()));
748 node->setPos(QPointF(pos));
749 if (m_nodesToPlace.contains(node->getFx())) {
750 QList<FxSchematicNode *> nodes = m_nodesToPlace[node->getFx()];
751 int i;
752 for (i = 0; i < nodes.size(); i++) placeNode(nodes[i]);
753 }
754 return;
755 } else if (node->isA(eNormalFx) || node->isA(eNormalLayerBlendingFx) ||
756 node->isA(eNormalMatteFx) || node->isA(eNormalImageAdjustFx)) {
757 // I'm placing an effect or a macro
758 TFx *inputFx = node->getFx()->getInputPort(0)->getFx();
759 QPointF pos;
760 if (inputFx) {
761 if (inputFx->getAttributes()->getDagNodePos() != TConst::nowhere) {
762 TPointD dagPos =
763 inputFx->getAttributes()->getDagNodePos() + TPointD(150, 0);
764 pos = QPointF(dagPos.x, dagPos.y);
765 nodeRect.moveTopLeft(pos);
766 while (!isAnEmptyZone(nodeRect)) nodeRect.translate(0, -step);
767 pos = nodeRect.topLeft();
768 } else {
769 m_nodesToPlace[inputFx].append(node);
770 return;
771 }
772 } else {
773 pos = sceneRect().center();
774 nodeRect.moveTopLeft(pos);
775 while (!isAnEmptyZone(nodeRect)) nodeRect.translate(0, -step);
776 pos = nodeRect.topLeft();
777 }
778 node->getFx()->getAttributes()->setDagNodePos(TPointD(pos.x(), pos.y()));
779 node->setPos(QPointF(pos));
780 if (m_nodesToPlace.contains(node->getFx())) {
781 QList<FxSchematicNode *> nodes = m_nodesToPlace[node->getFx()];
782 int i;
783 for (i = 0; i < nodes.size(); i++) placeNode(nodes[i]);
784 }
785 return;
786 } else if (node->isA(eZeraryFx) || node->isA(eColumnFx) ||
787 node->isA(eGroupedFx)) {
788 // I'm placing a column
789 nodeRect.translate(m_firstPoint);
790 nodeRect.translate(10, 10);
791 while (!isAnEmptyZone(nodeRect)) nodeRect.translate(0, -step);
792 QPointF newPos = nodeRect.topLeft();
793 node->getFx()->getAttributes()->setDagNodePos(
794 TPointD(newPos.x(), newPos.y()));
795 node->setPos(QPointF(newPos));
796 return;
797 }
798 }
799
800 //------------------------------------------------------------------
801
updateLink()802 void FxSchematicScene::updateLink() {
803 TXsheet *xsh = m_xshHandle->getXsheet();
804
805 // Iterate the fxs table
806 QMap<TFx *, FxSchematicNode *>::iterator it;
807 for (it = m_table.begin(); it != m_table.end(); ++it) {
808 FxSchematicNode *node = it.value();
809 if (!node) continue; // Should be asserted? Is it legal?
810
811 TFx *fx = it.key();
812 TFx *inputPortsFx = fx;
813
814 if (TZeraryColumnFx *fx2 = dynamic_cast<TZeraryColumnFx *>(fx)) {
815 inputPortsFx = fx2->getZeraryFx();
816 if (!inputPortsFx)
817 return; // Should really never happen. Should be asserted...
818 }
819
820 for (int i = 0; i != inputPortsFx->getInputPortCount(); ++i) {
821 TFxPort *port = inputPortsFx->getInputPort(i);
822
823 if (TFx *linkedFx = port->getFx()) {
824 if (!linkedFx->getAttributes()->isGrouped() ||
825 linkedFx->getAttributes()->isGroupEditing()) {
826 // Not in a group / open group case
827 assert(m_table.contains(linkedFx));
828
829 if (m_table.contains(linkedFx)) {
830 FxSchematicNode *linkedNode = m_table[linkedFx];
831 SchematicPort *p0 = linkedNode->getOutputPort();
832 SchematicPort *p1 = node->getInputPort(i);
833 if (p0 && p1) p0->makeLink(p1);
834 }
835 } else {
836 assert(
837 m_groupedTable.contains(linkedFx->getAttributes()->getGroupId()));
838
839 if (m_groupedTable.contains(
840 linkedFx->getAttributes()->getGroupId())) {
841 FxSchematicNode *linkedNode =
842 m_groupedTable[linkedFx->getAttributes()->getGroupId()];
843 SchematicPort *p0 = linkedNode->getOutputPort();
844 SchematicPort *p1 = node->getInputPort(i);
845 if (p0 && p1) p0->makeLink(p1);
846 }
847 }
848 }
849 }
850 if (xsh->getFxDag()->getTerminalFxs()->containsFx(fx)) {
851 SchematicPort *p0 = node->getOutputPort();
852 SchematicPort *p1 =
853 m_table[xsh->getFxDag()->getXsheetFx()]->getInputPort(0);
854 p0->makeLink(p1);
855 }
856 }
857 QMap<int, FxGroupNode *>::iterator it2;
858 for (it2 = m_groupedTable.begin(); it2 != m_groupedTable.end(); it2++) {
859 FxGroupNode *node = it2.value();
860 if (!node) continue;
861 int i, fxCount = node->getFxCount();
862 bool xsheetConnected = false;
863 for (i = 0; i < fxCount; i++) {
864 TFx *fx = node->getFx(i);
865 if (xsh->getFxDag()->getTerminalFxs()->containsFx(fx) &&
866 !xsheetConnected) {
867 SchematicPort *p0 = node->getOutputPort();
868 SchematicPort *p1 =
869 m_table[xsh->getFxDag()->getXsheetFx()]->getInputPort(0);
870 p0->makeLink(p1);
871 xsheetConnected = true;
872 }
873
874 TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx);
875 if (zfx) fx = zfx->getZeraryFx();
876 if (fx) {
877 int j;
878 for (j = 0; j < fx->getInputPortCount(); j++) {
879 TFx *linkedFx = fx->getInputPort(j)->getFx();
880 if (!linkedFx) continue;
881 if (!linkedFx->getAttributes()->isGrouped() ||
882 linkedFx->getAttributes()->isGroupEditing()) {
883 assert(m_table.contains(linkedFx));
884 if (m_table.contains(linkedFx)) {
885 FxSchematicNode *linkedNode = m_table[linkedFx];
886 SchematicPort *p0 = linkedNode->getOutputPort();
887 SchematicPort *p1 = node->getInputPort(0);
888 if (p0 && p1) p0->makeLink(p1);
889 }
890 } else {
891 int linkedGroupId = linkedFx->getAttributes()->getGroupId();
892 assert(m_groupedTable.contains(linkedGroupId));
893 if (m_groupedTable.contains(linkedGroupId)) {
894 FxGroupNode *linkedNode = m_groupedTable[linkedGroupId];
895 if (linkedNode == node) continue;
896 SchematicPort *p0 = linkedNode->getOutputPort();
897 SchematicPort *p1 = node->getInputPort(0);
898 if (p0 && p1 && !p0->isLinkedTo(p1)) p0->makeLink(p1);
899 }
900 }
901 }
902 }
903 }
904 }
905
906 // to solve an edit macro problem: create a dummy link
907 QMap<TMacroFx *, FxSchematicMacroEditor *>::iterator it3;
908 for (it3 = m_macroEditorTable.begin(); it3 != m_macroEditorTable.end();
909 it3++) {
910 TMacroFx *macro = it3.key();
911 int i;
912 FxSchematicNode *root = m_table[macro->getRoot()];
913 SchematicPort *p0 = root->getOutputPort();
914 for (i = 0; i < macro->getOutputConnectionCount(); i++) {
915 TFxPort *outConnection = macro->getOutputConnection(i);
916 TFx *outFx = outConnection->getOwnerFx();
917 TMacroFx *outMacroFx = dynamic_cast<TMacroFx *>(outFx);
918 if (outMacroFx && outMacroFx->isEditing()) {
919 std::vector<TFxP> fxs = outMacroFx->getFxs();
920 int k;
921 for (k = 0; k < (int)fxs.size(); k++) {
922 TFx *fx = fxs[k].getPointer();
923 int j;
924 for (j = 0; j < fx->getInputPortCount(); j++)
925 if (outConnection == fx->getInputPort(j)) {
926 outFx = fx;
927 break;
928 }
929 if (outFx != outMacroFx) break;
930 }
931 }
932
933 int j;
934 for (j = 0; j < outFx->getInputPortCount(); j++)
935 if (outFx->getInputPort(j)->getFx() == macro) {
936 SchematicPort *p1 = m_table[outFx]->getInputPort(j);
937 p0->makeLink(p1);
938 break;
939 }
940 }
941 if (xsh->getFxDag()->getTerminalFxs()->containsFx(macro)) {
942 assert(root);
943 if (!root) continue;
944 SchematicPort *p1 =
945 m_table[xsh->getFxDag()->getXsheetFx()]->getInputPort(0);
946 p0->makeLink(p1);
947 }
948 }
949 updateDuplcatedNodesLink();
950 }
951
952 //------------------------------------------------------------------
953
contextMenuEvent(QGraphicsSceneContextMenuEvent * cme)954 void FxSchematicScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {
955 QPointF scenePos = cme->scenePos();
956 QList<QGraphicsItem *> itemList = items(scenePos);
957 if (!itemList.isEmpty()) {
958 SchematicScene::contextMenuEvent(cme);
959 return;
960 }
961
962 QMenu menu(views()[0]);
963
964 if (cme->modifiers() & Qt::ControlModifier) {
965 menu.addAction(m_addFxContextMenu.getAgainCommand(AddFxContextMenu::Add));
966 if (!menu.actions().isEmpty()) {
967 menu.exec(cme->screenPos());
968 return;
969 }
970 }
971
972 QAction *addOutputFx =
973 CommandManager::instance()->getAction("MI_NewOutputFx");
974 QAction *copy = CommandManager::instance()->getAction("MI_Copy");
975 QAction *cut = CommandManager::instance()->getAction("MI_Cut");
976 QAction *paste = CommandManager::instance()->getAction("MI_Paste");
977
978 m_addFxContextMenu.setCurrentCursorScenePos(cme->scenePos());
979
980 menu.addMenu(m_addFxContextMenu.getAddMenu());
981 if (addOutputFx) menu.addAction(addOutputFx);
982
983 // Close sub xsheet and move to parent sheet
984 ToonzScene *scene = getXsheet()->getScene();
985 ChildStack *childStack = scene->getChildStack();
986 if (childStack && childStack->getAncestorCount() > 0) {
987 menu.addSeparator();
988 menu.addAction(CommandManager::instance()->getAction("MI_CloseChild"));
989 }
990
991 menu.addSeparator();
992 menu.addAction(copy);
993 menu.addAction(cut);
994 menu.addAction(paste);
995 m_selection->setPastePosition(TPointD(scenePos.x(), scenePos.y()));
996 menu.exec(cme->screenPos());
997 m_selection->setPastePosition(TConst::nowhere);
998 }
999
1000 //------------------------------------------------------------------
1001
nearestPoint(const QPointF & point)1002 QPointF FxSchematicScene::nearestPoint(const QPointF &point) {
1003 QRectF rect(0, 0, 0.1, 0.1);
1004 rect.moveCenter(point);
1005 QList<QGraphicsItem *> itemList = items(rect);
1006 while (itemList.isEmpty()) {
1007 rect.adjust(-0.1, -0.1, 0.1, 0.1);
1008 itemList = items(rect);
1009 }
1010 #if QT_VERSION >= 0x050000
1011 /*
1012 FIXME: QTransform() のデフォルトは Qt4.8 の itemAt() と比べて equivant
1013 だろうか?
1014 */
1015 QGraphicsItem *item = itemAt(rect.bottomLeft(), QTransform());
1016 if (item) return rect.bottomLeft();
1017 item = itemAt(rect.bottomRight(), QTransform());
1018 if (item) return rect.bottomRight();
1019 item = itemAt(rect.topLeft(), QTransform());
1020 if (item) return rect.topLeft();
1021 item = itemAt(rect.topRight(), QTransform());
1022 #else
1023 QGraphicsItem *item = itemAt(rect.bottomLeft());
1024 if (item) return rect.bottomLeft();
1025 item = itemAt(rect.bottomRight());
1026 if (item) return rect.bottomRight();
1027 item = itemAt(rect.topLeft());
1028 if (item) return rect.topLeft();
1029 item = itemAt(rect.topRight());
1030 #endif
1031 if (item) return rect.topRight();
1032 return QPointF();
1033 }
1034
1035 //------------------------------------------------------------------
1036
getFxNodeFromPosition(const QPointF & pos)1037 FxSchematicNode *FxSchematicScene::getFxNodeFromPosition(const QPointF &pos) {
1038 QList<QGraphicsItem *> pickedItems = items(pos);
1039 for (int i = 0; i < pickedItems.size(); i++) {
1040 FxSchematicNode *fxNode =
1041 dynamic_cast<FxSchematicNode *>(pickedItems.at(i));
1042 if (fxNode) return fxNode;
1043 FxSchematicPort *fxPort =
1044 dynamic_cast<FxSchematicPort *>(pickedItems.at(i));
1045 if (fxPort) return fxPort->getDock()->getNode();
1046 }
1047 return 0;
1048 }
1049
1050 //------------------------------------------------------------------
1051
updateDuplcatedNodesLink()1052 void FxSchematicScene::updateDuplcatedNodesLink() {
1053 QMap<TFx *, FxSchematicNode *>::iterator it;
1054
1055 // fx2node contains only duplicated nodes
1056 // and zerary duplicated node s
1057 QMap<TFx *, FxSchematicNode *> fx2node;
1058 for (it = m_table.begin(); it != m_table.end(); ++it) {
1059 TFx *fx = it.key();
1060 FxSchematicNode *node = it.value();
1061 if (TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(fx)) {
1062 fx = zcfx->getZeraryFx();
1063 if (!fx) return;
1064 }
1065 assert(fx2node.count(fx) == 0);
1066 if (fx->getLinkedFx() == fx) continue;
1067 fx2node[fx] = node;
1068 }
1069
1070 // trovo i link
1071 std::set<TFx *> visited;
1072 for (it = fx2node.begin(); it != fx2node.end(); ++it) {
1073 TFx *fx = it.key();
1074 FxSchematicNode *node = it.value();
1075 assert(fx->getLinkedFx() != fx);
1076 if (visited.count(fx) > 0) continue;
1077 visited.insert(fx);
1078 FxSchematicNode *lastNode = node;
1079 assert(lastNode);
1080 FxSchematicPort *lastPort = lastNode->getLinkPort();
1081 assert(lastPort);
1082 for (fx = fx->getLinkedFx(); fx != it.key(); fx = fx->getLinkedFx()) {
1083 assert(visited.count(fx) == 0);
1084 if (visited.count(fx) > 0) break;
1085 visited.insert(fx);
1086 QMap<TFx *, FxSchematicNode *>::iterator h;
1087 h = fx2node.find(fx);
1088 if (h == fx2node.end()) continue;
1089
1090 assert(h != fx2node.end());
1091 FxSchematicNode *node = h.value();
1092 assert(node);
1093 FxSchematicPort *port = node->getLinkPort();
1094 assert(port);
1095 if (port && lastPort) port->makeLink(lastPort);
1096 lastNode = node;
1097 lastPort = port;
1098 }
1099 }
1100 }
1101
1102 //------------------------------------------------------------------
1103
getCurrentNode()1104 QGraphicsItem *FxSchematicScene::getCurrentNode() {
1105 QList<QGraphicsItem *> allItems = items();
1106
1107 for (auto const item : allItems) {
1108 FxSchematicNode *node = dynamic_cast<FxSchematicNode *>(item);
1109 if (node && node->getFx() == m_fxHandle->getFx()) return node;
1110 }
1111 return 0;
1112 }
1113
1114 //------------------------------------------------------------------
1115
onSelectionSwitched(TSelection * oldSel,TSelection * newSel)1116 void FxSchematicScene::onSelectionSwitched(TSelection *oldSel,
1117 TSelection *newSel) {
1118 if (m_selection == oldSel && m_selection != newSel) clearSelection();
1119 }
1120
1121 //------------------------------------------------------------------
1122
onSelectionChanged()1123 void FxSchematicScene::onSelectionChanged() {
1124 m_selection->selectNone();
1125 int i, size = m_highlightedLinks.size();
1126 for (i = 0; i < size; i++) {
1127 SchematicLink *link = m_highlightedLinks[i];
1128 link->setHighlighted(false);
1129 link->update();
1130 }
1131 m_highlightedLinks.clear();
1132 QList<QGraphicsItem *> slcItems = selectedItems();
1133 QList<QGraphicsItem *>::iterator it;
1134 for (it = slcItems.begin(); it != slcItems.end(); it++) {
1135 FxSchematicNode *node = dynamic_cast<FxSchematicNode *>(*it);
1136 if (node) {
1137 if (!node->isA(eGroupedFx)) {
1138 if (node->isA(eXSheetFx)) continue;
1139 m_selection->select(node->getFx());
1140 if (node->isA(eColumnFx)) {
1141 FxSchematicColumnNode *columnNode =
1142 dynamic_cast<FxSchematicColumnNode *>(node);
1143 if (columnNode)
1144 m_selection->select(columnNode->getColumnIndex());
1145 else {
1146 FxSchematicPaletteNode *paletteNode =
1147 dynamic_cast<FxSchematicPaletteNode *>(node);
1148 if (paletteNode) m_selection->select(paletteNode->getColumnIndex());
1149 }
1150 }
1151 } else {
1152 FxGroupNode *groupNode = dynamic_cast<FxGroupNode *>(node);
1153 assert(groupNode);
1154 QList<TFxP> fxs = groupNode->getGroupedFxs();
1155 for (i = 0; i < fxs.size(); i++) {
1156 m_selection->select(fxs[i].getPointer());
1157 TLevelColumnFx *colFx =
1158 dynamic_cast<TLevelColumnFx *>(fxs[i].getPointer());
1159 if (colFx) {
1160 if (TXshLevelColumn *column = colFx->getColumn()) {
1161 int colIndex = column->getIndex();
1162 m_selection->select(colIndex);
1163 }
1164 }
1165 }
1166 }
1167 highlightLinks(node, true);
1168 }
1169 SchematicLink *link = dynamic_cast<SchematicLink *>(*it);
1170 if (link) m_selection->select(link);
1171 }
1172 m_selection->makeCurrent();
1173 TSelectionHandle *selHandle = TSelectionHandle::getCurrent();
1174 selHandle->notifySelectionChanged();
1175 }
1176
1177 //------------------------------------------------------------------
1178
reorderScene()1179 void FxSchematicScene::reorderScene() {
1180 int step = m_gridDimension == eLarge ? 100 : 50;
1181 m_placedFxs.clear();
1182 QPointF sceneCenter = sceneRect().center();
1183 double minY = sceneCenter.y();
1184 double maxX = sceneCenter.x();
1185 double y = minY;
1186 double x = maxX;
1187
1188 TXsheet *xsh = m_xshHandle->getXsheet();
1189 int i = 0;
1190
1191 FxDag *fxDag = xsh->getFxDag();
1192 TFxSet *fxSet = fxDag->getInternalFxs();
1193
1194 // Let's reset every position to nowhere first
1195 fxDag->getXsheetFx()->getAttributes()->setDagNodePos(TConst::nowhere);
1196
1197 for (i = 0; i < fxDag->getOutputFxCount(); i++) {
1198 TOutputFx *fx = fxDag->getOutputFx(i);
1199 if (!fx) continue;
1200 fx->getAttributes()->setDagNodePos(TConst::nowhere);
1201 }
1202
1203 for (i = 0; i < xsh->getColumnCount(); i++) {
1204 TXshColumn *column = xsh->getColumn(i);
1205 TFx *fx = column->getFx();
1206 if (!fx) continue;
1207 fx->getAttributes()->setDagNodePos(TConst::nowhere);
1208 }
1209
1210 for (i = 0; i < fxSet->getFxCount(); i++) {
1211 TFx *fx = fxSet->getFx(i);
1212 fx->getAttributes()->setDagNodePos(TConst::nowhere);
1213 TMacroFx *macro = dynamic_cast<TMacroFx *>(fx);
1214 if (macro && macro->isEditing()) {
1215 std::vector<TFxP> fxs = macro->getFxs();
1216 int j;
1217 for (j = 0; j < (int)fxs.size(); j++) {
1218 fxs[j]->getAttributes()->setDagNodePos(TConst::nowhere);
1219 }
1220 }
1221 }
1222
1223 // Let's start placing them now
1224 for (i = 0; i < xsh->getColumnCount(); i++) {
1225 TXshColumn *column = xsh->getColumn(i);
1226 TFx *fx = column->getFx();
1227
1228 if (column->isEmpty() || !fx) continue;
1229
1230 TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx);
1231 if (zfx && (zfx->getZeraryFx()->getInputPortCount() > 0)) {
1232 TFxPort *port = zfx->getZeraryFx()->getInputPort(0);
1233 if (port && port->getFx()) continue;
1234 }
1235
1236 if (zfx && m_placedFxs.contains(zfx->getZeraryFx())) continue;
1237
1238 x = sceneCenter.x();
1239 placeNodeAndParents(fx, x, maxX, minY);
1240 y -= step;
1241 minY = std::min(y, minY);
1242 }
1243
1244 // remove retrolink
1245 for (i = 0; i < xsh->getColumnCount(); i++) {
1246 TXshColumn *column = xsh->getColumn(i);
1247 TFx *fx = column->getFx();
1248 if (column->isEmpty() || !fx) continue;
1249
1250 TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx);
1251 if (zfx && m_placedFxs.contains(zfx->getZeraryFx())) continue;
1252
1253 if (zfx && (zfx->getZeraryFx()->getInputPortCount() > 0)) {
1254 TFxPort *port = zfx->getZeraryFx()->getInputPort(0);
1255 if (port && port->getFx()) continue;
1256 }
1257
1258 for (int j = 0; j < fx->getOutputConnectionCount(); j++) {
1259 TFx *outFx = fx->getOutputConnection(j)->getOwnerFx();
1260 removeRetroLinks(outFx, maxX);
1261 }
1262 }
1263
1264 double middleY = (sceneCenter.y() + minY + step) * 0.5;
1265 placeNodeAndParents(xsh->getFxDag()->getXsheetFx(), maxX, maxX, middleY);
1266 y -= step;
1267 minY = std::min(y, minY);
1268
1269 for (i = 0; i < fxSet->getFxCount(); i++) {
1270 TFx *fx = fxSet->getFx(i);
1271 if (m_placedFxs.contains(fx)) continue;
1272
1273 placeNodeAndParents(fx, (sceneCenter.x() + 120), maxX, minY);
1274 y -= step;
1275 minY = std::min(y, minY);
1276 }
1277 updateScene();
1278 }
1279
1280 //------------------------------------------------------------------
1281
removeRetroLinks(TFx * fx,double & maxX)1282 void FxSchematicScene::removeRetroLinks(TFx *fx, double &maxX) {
1283 if (!fx) return;
1284 for (int i = 0; i < fx->getInputPortCount(); i++) {
1285 TFx *inFx = fx->getInputPort(i)->getFx();
1286 if (!inFx) continue;
1287 TPointD inFxPos = inFx->getAttributes()->getDagNodePos();
1288 TPointD fxPos = fx->getAttributes()->getDagNodePos();
1289 if (inFxPos != TConst::nowhere && fxPos != TConst::nowhere &&
1290 fxPos.x <= inFxPos.x) {
1291 while (fxPos.x <= inFxPos.x) fxPos.x += 150;
1292 maxX = std::max(fxPos.x + 150, maxX);
1293 fx->getAttributes()->setDagNodePos(fxPos);
1294 for (int j = 0; j < fx->getOutputConnectionCount(); j++) {
1295 TFx *outFx = fx->getOutputConnection(j)->getOwnerFx();
1296 removeRetroLinks(outFx, maxX);
1297 }
1298 }
1299 }
1300 }
1301
1302 //------------------------------------------------------------------
1303
placeNodeAndParents(TFx * fx,double x,double & maxX,double & minY)1304 void FxSchematicScene::placeNodeAndParents(TFx *fx, double x, double &maxX,
1305 double &minY) {
1306 int step = m_gridDimension == eLarge ? 100 : 50;
1307 if (!fx) return;
1308 m_placedFxs.append(fx);
1309 if (fx->getFxType() == "STD_particlesFx" ||
1310 fx->getFxType() == "STD_Iwa_ParticlesFx") {
1311 TXsheet *xsh = m_xshHandle->getXsheet();
1312 int i = 0;
1313 for (i = 0; i < xsh->getColumnCount(); i++) {
1314 TFx *columnFx = xsh->getColumn(i)->getFx();
1315 TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(columnFx);
1316 if (zfx && zfx->getZeraryFx() == fx) {
1317 fx = zfx;
1318 break;
1319 }
1320 }
1321 }
1322 double y = minY;
1323 TMacroFx *macro = dynamic_cast<TMacroFx *>(fx);
1324 if (macro) {
1325 int tmpY = y;
1326 std::vector<TFxP> fxs = macro->getFxs();
1327 for (int j = 0; j < (int)fxs.size(); j++) {
1328 TFx *macroFx = fxs[j].getPointer();
1329 if (macroFx && !m_placedFxs.contains(macroFx)) {
1330 placeNodeAndParents(macroFx, x, maxX, minY);
1331 y -= step;
1332 minY = std::min(y, minY);
1333 }
1334 }
1335 tmpY = (minY + tmpY + step) * 0.5;
1336 fx->getAttributes()->setDagNodePos(TPointD(x, tmpY));
1337 } else
1338 fx->getAttributes()->setDagNodePos(TPointD(x, y));
1339 if (fx->getOutputConnectionCount() == 0) minY -= step;
1340 x += 120;
1341 maxX = std::max(maxX, x);
1342 int i;
1343 for (i = 0; i < fx->getOutputConnectionCount(); i++) {
1344 TFx *outputFx = fx->getOutputConnection(i)->getOwnerFx();
1345 // controllo se e' una porta sorgente
1346 TFxPort *port = outputFx->getInputPort(0);
1347 if (port && port->getFx() != fx) continue;
1348 if (!m_placedFxs.contains(outputFx) ||
1349 outputFx->getAttributes()->getDagNodePos().x < x) {
1350 placeNodeAndParents(outputFx, x, maxX, minY);
1351 y -= step;
1352 minY = std::min(y, minY);
1353 }
1354 }
1355 }
1356
1357 //------------------------------------------------------------------
1358
onDisconnectFromXSheet()1359 void FxSchematicScene::onDisconnectFromXSheet() {
1360 std::list<TFxP, std::allocator<TFxP>> list =
1361 m_selection->getFxs().toStdList();
1362 TFxCommand::disconnectNodesFromXsheet(list, m_xshHandle);
1363 }
1364
1365 //------------------------------------------------------------------
1366
onConnectToXSheet()1367 void FxSchematicScene::onConnectToXSheet() {
1368 std::list<TFxP, std::allocator<TFxP>> list =
1369 m_selection->getFxs().toStdList();
1370 TFxCommand::connectNodesToXsheet(list, m_xshHandle);
1371 }
1372
1373 //------------------------------------------------------------------
1374
onDeleteFx()1375 void FxSchematicScene::onDeleteFx() {
1376 std::list<TFxP, std::allocator<TFxP>> fxList =
1377 m_selection->getFxs().toStdList();
1378 std::list<TFxCommand::Link> linkList = m_selection->getLinks().toStdList();
1379 std::list<int> columnIndexList = m_selection->getColumnIndexes().toStdList();
1380 TFxCommand::deleteSelection(fxList, linkList, columnIndexList, m_xshHandle,
1381 m_fxHandle);
1382 }
1383
1384 //------------------------------------------------------------------
1385
onDuplicateFx()1386 void FxSchematicScene::onDuplicateFx() {
1387 QList<TFxP> fxs = m_selection->getFxs();
1388 if (fxs.empty()) return;
1389
1390 TUndoManager::manager()->beginBlock();
1391
1392 int i, size = fxs.size();
1393 for (i = 0; i != size; ++i)
1394 TFxCommand::duplicateFx(fxs[i].getPointer(), m_xshHandle, m_fxHandle);
1395
1396 TUndoManager::manager()->endBlock();
1397 }
1398
1399 //------------------------------------------------------------------
1400
onUnlinkFx()1401 void FxSchematicScene::onUnlinkFx() {
1402 QList<TFxP> fxs = m_selection->getFxs();
1403 if (fxs.empty()) return;
1404
1405 TUndoManager::manager()->beginBlock();
1406
1407 int i, size = fxs.size();
1408 for (i = 0; i != size; ++i)
1409 TFxCommand::unlinkFx(fxs[i].getPointer(), m_fxHandle, m_xshHandle);
1410
1411 TUndoManager::manager()->endBlock();
1412 }
1413
1414 //------------------------------------------------------------------
1415
onMacroFx()1416 void FxSchematicScene::onMacroFx() {
1417 TFxCommand::makeMacroFx(m_selection->getFxs().toVector().toStdVector(),
1418 m_app);
1419 }
1420
1421 //------------------------------------------------------------------
1422
onExplodeMacroFx()1423 void FxSchematicScene::onExplodeMacroFx() {
1424 if (TMacroFx *macroFx = dynamic_cast<TMacroFx *>(m_fxHandle->getFx()))
1425 TFxCommand::explodeMacroFx(macroFx, m_app);
1426 }
1427
1428 //------------------------------------------------------------------
1429
onOpenMacroFx()1430 void FxSchematicScene::onOpenMacroFx() {
1431 if (TMacroFx *macroFx = dynamic_cast<TMacroFx *>(m_fxHandle->getFx())) {
1432 macroFx->editMacro(true);
1433 updateScene();
1434 }
1435 }
1436
1437 //------------------------------------------------------------------
1438
onSavePresetFx()1439 void FxSchematicScene::onSavePresetFx() {
1440 CommandManager::instance()->getAction("MI_SavePreset")->trigger();
1441 }
1442
1443 //------------------------------------------------------------------
1444
onRemoveOutput()1445 void FxSchematicScene::onRemoveOutput() {
1446 TFxCommand::removeOutputFx(m_fxHandle->getFx(), m_xshHandle, m_fxHandle);
1447 }
1448
1449 //------------------------------------------------------------------
1450
onActivateOutput()1451 void FxSchematicScene::onActivateOutput() {
1452 TFxCommand::makeOutputFxCurrent(m_fxHandle->getFx(), m_xshHandle);
1453 }
1454
1455 //------------------------------------------------------------------
1456
onPreview()1457 void FxSchematicScene::onPreview() { emit showPreview(m_fxHandle->getFx()); }
1458
1459 //------------------------------------------------------------------
1460
onCacheFx()1461 void FxSchematicScene::onCacheFx() { setEnableCache(true); }
1462
1463 //------------------------------------------------------------------
1464
onUncacheFx()1465 void FxSchematicScene::onUncacheFx() { setEnableCache(false); }
1466
1467 //------------------------------------------------------------------
1468
setEnableCache(bool toggle)1469 void FxSchematicScene::setEnableCache(bool toggle) {
1470 QList<TFxP> selectedFxs = m_selection->getFxs();
1471 for (int i = 0; i < selectedFxs.size(); i++) {
1472 TFx *fx = selectedFxs[i].getPointer();
1473 TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(fx);
1474 if (zcfx) fx = zcfx->getZeraryFx();
1475 TFxAttributes *attr = fx->getAttributes();
1476 if (!attr->isGrouped() || attr->isGroupEditing()) {
1477 if (toggle) {
1478 TPassiveCacheManager::instance()->enableCache(fx);
1479 } else {
1480 TPassiveCacheManager::instance()->disableCache(fx);
1481 }
1482 } else {
1483 QMap<int, FxGroupNode *>::iterator it;
1484 for (it = m_groupedTable.begin(); it != m_groupedTable.end(); it++) {
1485 FxGroupNode *group = it.value();
1486 QList<TFxP> roots = group->getRootFxs();
1487 for (int j = 0; j < roots.size(); j++) {
1488 if (fx == roots[j].getPointer()) {
1489 if (toggle) {
1490 TPassiveCacheManager::instance()->enableCache(fx);
1491 } else {
1492 TPassiveCacheManager::instance()->disableCache(fx);
1493 }
1494 }
1495 }
1496 group->update();
1497 }
1498 }
1499 }
1500 }
1501
1502 //------------------------------------------------------------------
1503
onCollapse(const QList<TFxP> & fxs)1504 void FxSchematicScene::onCollapse(const QList<TFxP> &fxs) {
1505 emit doCollapse(fxs);
1506 }
1507
1508 //------------------------------------------------------------------
1509
getXsheet()1510 TXsheet *FxSchematicScene::getXsheet() { return m_xshHandle->getXsheet(); }
1511
1512 //------------------------------------------------------------------
1513
onXsheetChanged()1514 void FxSchematicScene::onXsheetChanged() { m_xshHandle->notifyXsheetChanged(); }
1515
1516 //------------------------------------------------------------------
1517
onSceneChanged()1518 void FxSchematicScene::onSceneChanged() {
1519 m_app->getCurrentScene()->notifySceneChanged();
1520 }
1521
1522 //------------------------------------------------------------------
1523
onSwitchCurrentFx(TFx * fx)1524 void FxSchematicScene::onSwitchCurrentFx(TFx *fx) {
1525 if (m_fxHandle->getFx() == fx) return;
1526 if (fx) {
1527 // Forbid update of the swatch upon column switch. This could generate
1528 // a further useless render...
1529 SwatchViewer::suspendRendering(true, false);
1530
1531 int columnIndex = fx->getReferenceColumnIndex();
1532 if (columnIndex >= 0) {
1533 m_columnHandle->setColumnIndex(columnIndex);
1534 m_app->getCurrentObject()->setObjectId(
1535 TStageObjectId::ColumnId(columnIndex));
1536 }
1537
1538 SwatchViewer::suspendRendering(false);
1539
1540 m_fxHandle->setFx(fx, false); // Setting the fx updates the swatch
1541
1542 emit editObject();
1543 } else {
1544 m_fxHandle->setFx(0, false);
1545 }
1546 }
1547
1548 //------------------------------------------------------------------
1549
onFxNodeDoubleClicked()1550 void FxSchematicScene::onFxNodeDoubleClicked() {
1551 // emitting fxSettingsShouldBeSwitched
1552 m_fxHandle->onFxNodeDoubleClicked();
1553 }
1554
1555 //------------------------------------------------------------------
1556
onCurrentFxSwitched()1557 void FxSchematicScene::onCurrentFxSwitched() {
1558 if (m_currentFxNode) m_currentFxNode->setIsCurrentFxLinked(false, 0);
1559 if (m_table.contains(m_fxHandle->getFx())) {
1560 m_currentFxNode = m_table[m_fxHandle->getFx()];
1561 m_currentFxNode->setIsCurrentFxLinked(true, 0);
1562 } else
1563 m_currentFxNode = 0;
1564 }
1565
1566 //------------------------------------------------------------------
1567
onCurrentColumnChanged(int index)1568 void FxSchematicScene::onCurrentColumnChanged(int index) {
1569 m_app->getCurrentColumn()->setColumnIndex(index);
1570 m_app->getCurrentObject()->setObjectId(TStageObjectId::ColumnId(index));
1571 }
1572
1573 //------------------------------------------------------------------
1574
onIconifyNodesToggled(bool iconified)1575 void FxSchematicScene::onIconifyNodesToggled(bool iconified) {
1576 m_isNormalIconView = !iconified;
1577 IconifyFxSchematicNodes = (iconified) ? 1 : 0;
1578 updateScene();
1579 }
1580
1581 //------------------------------------------------------------------
1582
getCurrentFx()1583 TFx *FxSchematicScene::getCurrentFx() { return m_fxHandle->getFx(); }
1584
1585 //------------------------------------------------------------------
1586
mousePressEvent(QGraphicsSceneMouseEvent * me)1587 void FxSchematicScene::mousePressEvent(QGraphicsSceneMouseEvent *me) {
1588 QList<QGraphicsItem *> items = selectedItems();
1589 #if QT_VERSION >= 0x050000
1590 QGraphicsItem *item = itemAt(me->scenePos(), QTransform());
1591 #else
1592 QGraphicsItem *item = itemAt(me->scenePos());
1593 #endif
1594 FxSchematicPort *port = dynamic_cast<FxSchematicPort *>(item);
1595 FxSchematicLink *link = dynamic_cast<FxSchematicLink *>(item);
1596 SchematicScene::mousePressEvent(me);
1597 onSelectionChanged();
1598 if (me->button() == Qt::MidButton) {
1599 int i;
1600 for (i = 0; i < items.size(); i++) items[i]->setSelected(true);
1601 }
1602 /*
1603 m_selection may not be updated here, so I use QGraphicsScene::selectedItems()
1604 instead of m_selection->isEmpty() to check whether any node is selected or
1605 not.
1606 */
1607 if (selectedItems().isEmpty()) {
1608 if (me->button() != Qt::MidButton && !item) m_fxHandle->setFx(0, false);
1609 return;
1610 }
1611 m_isConnected = false;
1612 if (!canDisconnectSelection(m_selection)) return;
1613 m_selectionOldPos.clear();
1614 QList<TFxP> selectedFxs = m_selection->getFxs();
1615 int i;
1616 for (i = 0; i < selectedFxs.size(); i++) {
1617 TFxP selectedFx = selectedFxs[i];
1618 TPointD pos = selectedFx->getAttributes()->getDagNodePos();
1619 m_selectionOldPos.append(QPair<TFxP, TPointD>(selectedFx, pos));
1620 }
1621 FxsData fxsData;
1622 fxsData.setFxs(m_selection->getFxs(), m_selection->getLinks(),
1623 m_selection->getColumnIndexes(), m_xshHandle->getXsheet());
1624 // m_isConnected indicates that the all selected nodes are connected
1625 if (fxsData.isConnected() && me->button() == Qt::LeftButton && !port && !link)
1626 m_isConnected = true;
1627 }
1628
1629 //------------------------------------------------------------------
1630
mouseMoveEvent(QGraphicsSceneMouseEvent * me)1631 void FxSchematicScene::mouseMoveEvent(QGraphicsSceneMouseEvent *me) {
1632 SchematicScene::mouseMoveEvent(me);
1633
1634 m_lastPos = me->scenePos();
1635
1636 bool leftButton = (QApplication::mouseButtons() == Qt::LeftButton);
1637 bool altButton = (QApplication::keyboardModifiers() == Qt::AltModifier);
1638
1639 if (leftButton && m_isConnected && altButton) {
1640 m_linkUnlinkSimulation = true;
1641
1642 simulateDisconnectSelection(true);
1643 m_connectionLinks.showBridgeLinks();
1644
1645 #if QT_VERSION >= 0x050000
1646 SchematicLink *link =
1647 dynamic_cast<SchematicLink *>(itemAt(m_lastPos, QTransform()));
1648 #else
1649 SchematicLink *link = dynamic_cast<SchematicLink *>(itemAt(m_lastPos));
1650 #endif
1651 if (link && (link->getEndPort() && link->getStartPort())) {
1652 TFxCommand::Link fxLink = m_selection->getBoundingFxs(link);
1653 if (fxLink == TFxCommand::Link()) return;
1654
1655 TFx *inputFx = fxLink.m_inputFx.getPointer();
1656 TFx *outputFx = fxLink.m_outputFx.getPointer();
1657
1658 TFxSet *internalFxs = getXsheet()->getFxDag()->getInternalFxs();
1659 if (!internalFxs->containsFx(inputFx) &&
1660 !dynamic_cast<TColumnFx *>(inputFx) &&
1661 !dynamic_cast<TXsheetFx *>(inputFx) &&
1662 !dynamic_cast<TOutputFx *>(inputFx))
1663 return;
1664 if (!internalFxs->containsFx(outputFx) &&
1665 !dynamic_cast<TColumnFx *>(outputFx) &&
1666 !dynamic_cast<TXsheetFx *>(outputFx) &&
1667 !dynamic_cast<TOutputFx *>(outputFx))
1668 return;
1669 }
1670
1671 m_connectionLinks.hideBridgeLinks();
1672 simulateInsertSelection(link, altButton && !!link);
1673 }
1674 }
1675
1676 //------------------------------------------------------------------
1677
mouseReleaseEvent(QGraphicsSceneMouseEvent * me)1678 void FxSchematicScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *me) {
1679 SchematicScene::mouseReleaseEvent(me);
1680
1681 m_linkUnlinkSimulation = false;
1682
1683 if ((m_disconnectionLinks.size() == 0) && (m_connectionLinks.size() == 0))
1684 return;
1685
1686 TUndoManager::manager()->beginBlock();
1687
1688 bool altButton = QApplication::keyboardModifiers() == Qt::AltModifier;
1689 if (altButton && m_isConnected) {
1690 if (m_connectionLinks.size() > 0) {
1691 const QList<SchematicLink *> &bridgeLinks =
1692 m_connectionLinks.getBridgeLinks();
1693 assert(bridgeLinks.size() <= 1);
1694
1695 SchematicLink *link = bridgeLinks[0];
1696
1697 if (link) {
1698 FxSchematicNode *outputNode =
1699 dynamic_cast<FxSchematicNode *>(link->getEndPort()->getNode());
1700 FxSchematicNode *inputNode =
1701 dynamic_cast<FxSchematicNode *>(link->getStartPort()->getNode());
1702
1703 if (inputNode && outputNode) {
1704 SchematicPort *port = link->getStartPort();
1705 if (port->getType() == 200 || port->getType() == 204)
1706 port = link->getOtherPort(port);
1707
1708 int i;
1709 for (i = 0; i < outputNode->getInputPortCount(); i++)
1710 if (port == outputNode->getInputPort(i)) break;
1711
1712 TFxCommand::Link fxLink;
1713 fxLink.m_outputFx = outputNode->getFx();
1714 fxLink.m_inputFx = inputNode->getFx();
1715 if (!outputNode->isA(eXSheetFx)) fxLink.m_index = i;
1716
1717 TFxCommand::connectFxs(fxLink, m_selection->getFxs().toStdList(),
1718 m_xshHandle, m_selectionOldPos);
1719 }
1720 }
1721 } else if (m_disconnectionLinks.size() > 0) {
1722 QList<TFxP> fxs = m_selection->getFxs();
1723 TFxCommand::disconnectFxs(fxs.toStdList(), m_xshHandle,
1724 m_selectionOldPos);
1725 m_selectionOldPos.clear();
1726 }
1727 }
1728
1729 TUndoManager::manager()->endBlock();
1730
1731 m_isConnected = false;
1732 }
1733
1734 //------------------------------------------------------------------
1735
event(QEvent * e)1736 bool FxSchematicScene::event(QEvent *e) {
1737 bool ret = SchematicScene::event(e);
1738 bool altPressed = QApplication::keyboardModifiers() == Qt::AltModifier;
1739 if (m_altPressed != altPressed) {
1740 // When Alt key is pressed, put the link lines on top of other items
1741 // in order to enable to pick them up with itemAt() function.
1742 double z = (altPressed) ? 5.0 : 0.0;
1743 QList<QGraphicsItem *> sceneItems = items();
1744 for (int i = 0; i < sceneItems.size(); i++) {
1745 SchematicLink *link = dynamic_cast<SchematicLink *>(sceneItems.at(i));
1746 if (link) link->setZValue(z);
1747 }
1748
1749 if (m_linkUnlinkSimulation) onAltModifierChanged(altPressed);
1750 m_altPressed = altPressed;
1751 }
1752 return ret;
1753 }
1754
1755 //------------------------------------------------------------------
1756
onInsertPaste()1757 void FxSchematicScene::onInsertPaste() {
1758 if (!m_selection->insertPasteSelection())
1759 DVGui::error(
1760 tr("Cannot Paste Insert a selection of unconnected FX nodes.\nSelect "
1761 "FX nodes and related links before copying or cutting the selection "
1762 "you want to paste."));
1763 }
1764
1765 //------------------------------------------------------------------
1766
onAddPaste()1767 void FxSchematicScene::onAddPaste() {
1768 if (!m_selection->addPasteSelection())
1769 DVGui::error(
1770 tr("Cannot Paste Add a selection of unconnected FX nodes.\nSelect FX "
1771 "nodes and related links before copying or cutting the selection "
1772 "you want to paste."));
1773 }
1774
1775 //------------------------------------------------------------------
1776
onReplacePaste()1777 void FxSchematicScene::onReplacePaste() {
1778 if (!m_selection->replacePasteSelection())
1779 DVGui::error(
1780 tr("Cannot Paste Replace a selection of unconnected FX nodes.\nSelect "
1781 "FX nodes and related links before copying or cutting the selection "
1782 "you want to paste."));
1783 }
1784
1785 //------------------------------------------------------------------
1786
onAltModifierChanged(bool altPressed)1787 void FxSchematicScene::onAltModifierChanged(bool altPressed) {
1788 if (altPressed) {
1789 if (m_disconnectionLinks.size() == 0 && m_linkUnlinkSimulation)
1790 simulateDisconnectSelection(altPressed);
1791 if (m_connectionLinks.size() == 0 && m_linkUnlinkSimulation) {
1792 #if QT_VERSION >= 0x050000
1793 SchematicLink *link =
1794 dynamic_cast<SchematicLink *>(itemAt(m_lastPos, QTransform()));
1795 #else
1796 SchematicLink *link = dynamic_cast<SchematicLink *>(itemAt(m_lastPos));
1797 #endif
1798 if (link && (!link->getEndPort() || !link->getStartPort())) return;
1799 simulateInsertSelection(link, altPressed && !!link);
1800 }
1801 } else {
1802 if (m_disconnectionLinks.size() > 0 && m_linkUnlinkSimulation)
1803 simulateDisconnectSelection(altPressed);
1804 if (m_connectionLinks.size() > 0 && m_linkUnlinkSimulation) {
1805 m_connectionLinks.showBridgeLinks();
1806 simulateInsertSelection(0, false);
1807 }
1808 }
1809 }
1810
1811 //------------------------------------------------------------------
1812
onEditGroup()1813 void FxSchematicScene::onEditGroup() {
1814 if (m_selection->isEmpty()) return;
1815 QList<TFxP> fxs = m_selection->getFxs();
1816 int i;
1817 for (i = 0; i < fxs.size(); i++) {
1818 if (fxs[i]->getAttributes()->isGrouped() &&
1819 !fxs[i]->getAttributes()->isGroupEditing()) {
1820 fxs[i]->getAttributes()->editGroup();
1821 TMacroFx *macro = dynamic_cast<TMacroFx *>(fxs[i].getPointer());
1822 if (macro) {
1823 std::vector<TFxP> macroFxs = macro->getFxs();
1824 int j;
1825 for (j = 0; j < (int)macroFxs.size(); j++)
1826 macroFxs[j]->getAttributes()->editGroup();
1827 }
1828 }
1829 }
1830 updateScene();
1831 }
1832
1833 //------------------------------------------------------------------
1834
highlightLinks(FxSchematicNode * node,bool value)1835 void FxSchematicScene::highlightLinks(FxSchematicNode *node, bool value) {
1836 int i, portCount = node->getInputPortCount();
1837 // SchematicLink* ghostLink = m_supportLinks.getDisconnectionLink(eGhost);
1838 for (i = 0; i < portCount; i++) {
1839 FxSchematicPort *port = node->getInputPort(i);
1840 int j, linkCount = port->getLinkCount();
1841 for (j = 0; j < linkCount; j++) {
1842 SchematicLink *link = port->getLink(j);
1843 if (!link) continue;
1844 if (m_disconnectionLinks.isABridgeLink(link)) continue;
1845 link->setHighlighted(value);
1846 link->update();
1847 m_highlightedLinks.push_back(link);
1848 }
1849 }
1850
1851 FxSchematicPort *port = node->getOutputPort();
1852 if (port) {
1853 int linkCount = port->getLinkCount();
1854 for (i = 0; i < linkCount; i++) {
1855 SchematicLink *link = port->getLink(i);
1856 if (!link) continue;
1857 if (m_disconnectionLinks.isABridgeLink(link)) continue;
1858 link->setHighlighted(value);
1859 link->update();
1860 m_highlightedLinks.push_back(link);
1861 }
1862 }
1863 port = node->getLinkPort();
1864 if (port) {
1865 SchematicLink *link = port->getLink(0);
1866 if (link && !m_disconnectionLinks.isABridgeLink(link)) {
1867 link->setHighlighted(value);
1868 link->update();
1869 m_highlightedLinks.push_back(link);
1870 }
1871 }
1872 }
1873
1874 //------------------------------------------------------------------
1875
simulateDisconnectSelection(bool disconnect)1876 void FxSchematicScene::simulateDisconnectSelection(bool disconnect) {
1877 if (disconnect) {
1878 if (m_selection->isEmpty()) return;
1879 QList<TFxP> selectedFxs = m_selection->getFxs();
1880 if (selectedFxs.isEmpty()) return;
1881 QMap<TFx *, bool> visitedFxs;
1882 int i;
1883 for (i = 0; i < selectedFxs.size(); i++)
1884 visitedFxs[selectedFxs[i].getPointer()] = false;
1885
1886 TFx *inputFx = 0, *outputFx = 0;
1887 findBoundariesFxs(inputFx, outputFx, visitedFxs);
1888 FxSchematicNode *inputNode = m_table[inputFx];
1889 FxSchematicNode *outputNode = m_table[outputFx];
1890 assert(inputNode && outputNode);
1891
1892 FxSchematicPort *inputPort = 0, *outputPort = 0;
1893 SchematicPort *otherInputPort = 0;
1894 QList<SchematicPort *> otherOutputPorts;
1895 if (inputNode->getInputPortCount() > 0) {
1896 inputPort = inputNode->getInputPort(0);
1897 if (inputPort) {
1898 SchematicLink *inputLink = inputPort->getLink(0);
1899 if (inputLink && !m_connectionLinks.isAnInputLink(inputLink)) {
1900 if (!m_disconnectionLinks.isAnInputLink(inputLink))
1901 m_disconnectionLinks.addInputLink(inputLink);
1902 otherInputPort = inputLink->getOtherPort(inputPort);
1903 }
1904 }
1905 }
1906 outputPort = outputNode->getOutputPort();
1907 if (outputPort) {
1908 for (i = 0; i < outputPort->getLinkCount(); i++) {
1909 SchematicLink *outputLink = outputPort->getLink(i);
1910 if (outputLink && !m_connectionLinks.isAnOutputLink(outputLink)) {
1911 if (!m_disconnectionLinks.isAnOutputLink(outputLink))
1912 m_disconnectionLinks.addOutputLink(outputLink);
1913 otherOutputPorts.push_back(outputLink->getOtherPort(outputPort));
1914 }
1915 }
1916 }
1917 m_disconnectionLinks.hideInputLinks();
1918 m_disconnectionLinks.hideOutputLinks();
1919
1920 if (otherInputPort) {
1921 for (i = 0; i < otherOutputPorts.size(); i++)
1922 m_disconnectionLinks.addBridgeLink(
1923 otherOutputPorts[i]->makeLink(otherInputPort));
1924 }
1925 } else {
1926 m_disconnectionLinks.showInputLinks();
1927 m_disconnectionLinks.showOutputLinks();
1928 m_disconnectionLinks.removeInputLinks();
1929 m_disconnectionLinks.removeOutputLinks();
1930 m_disconnectionLinks.removeBridgeLinks(true);
1931 }
1932 }
1933
1934 //------------------------------------------------------------------
1935
simulateInsertSelection(SchematicLink * link,bool connect)1936 void FxSchematicScene::simulateInsertSelection(SchematicLink *link,
1937 bool connect) {
1938 // first, remove all connected links
1939 m_connectionLinks.showBridgeLinks();
1940 m_connectionLinks.hideInputLinks();
1941 m_connectionLinks.hideOutputLinks();
1942 m_connectionLinks.removeBridgeLinks();
1943 m_connectionLinks.removeInputLinks(true);
1944 m_connectionLinks.removeOutputLinks(true);
1945 if (!link || !connect) return;
1946
1947 if (m_disconnectionLinks.isABridgeLink(link) || m_selection->isEmpty())
1948 return;
1949
1950 m_connectionLinks.addBridgeLink(link);
1951 m_connectionLinks.hideBridgeLinks();
1952
1953 SchematicPort *inputPort = 0, *outputPort = 0;
1954 if (link) {
1955 if (link->getStartPort()->getType() == eFxInputPort) {
1956 inputPort = link->getStartPort();
1957 outputPort = link->getEndPort();
1958 } else {
1959 inputPort = link->getEndPort();
1960 outputPort = link->getStartPort();
1961 }
1962 }
1963
1964 QMap<TFx *, bool> visitedFxs;
1965 QList<TFxP> selectedFxs = m_selection->getFxs();
1966 if (selectedFxs.isEmpty()) return;
1967 int i;
1968 for (i = 0; i < selectedFxs.size(); i++)
1969 visitedFxs[selectedFxs[i].getPointer()] = false;
1970
1971 TFx *inputFx = 0, *outputFx = 0;
1972 findBoundariesFxs(inputFx, outputFx, visitedFxs);
1973 FxSchematicNode *inputNode = m_table[inputFx];
1974 FxSchematicNode *outputNode = m_table[outputFx];
1975 assert(inputNode && outputNode);
1976
1977 if (inputNode->getInputPortCount() > 0) {
1978 SchematicPort *inputNodePort = inputNode->getInputPort(0);
1979 if (inputNodePort && outputPort)
1980 m_connectionLinks.addInputLink(inputNodePort->makeLink(outputPort));
1981 }
1982
1983 SchematicPort *outputNodePort = outputNode->getOutputPort();
1984 if (outputNodePort && inputPort)
1985 m_connectionLinks.addOutputLink(inputPort->makeLink(outputNodePort));
1986
1987 m_connectionLinks.showInputLinks();
1988 m_connectionLinks.showOutputLinks();
1989 }
1990
1991 //------------------------------------------------------------
1992 /*! in order to select nods after pasting the copied fx nodes from FxSelection
1993 */
selectNodes(QList<TFxP> & fxs)1994 void FxSchematicScene::selectNodes(QList<TFxP> &fxs) {
1995 clearSelection();
1996 for (int i = 0; i < (int)fxs.size(); i++) {
1997 TFx *tempFx = fxs[i].getPointer();
1998
1999 QMap<TFx *, FxSchematicNode *>::iterator it;
2000 it = m_table.find(tempFx);
2001 if (it == m_table.end()) continue;
2002
2003 it.value()->setSelected(true);
2004 }
2005 update();
2006 }
2007
2008 //------------------------------------------------------------------
2009
updateNestedGroupEditors(FxSchematicNode * node,const QPointF & newPos)2010 void FxSchematicScene::updateNestedGroupEditors(FxSchematicNode *node,
2011 const QPointF &newPos) {
2012 if (!node) return;
2013 QStack<int> groupIdStack = node->getFx()->getAttributes()->getGroupIdStack();
2014 int i;
2015 QRectF rect;
2016 for (i = 0; i < groupIdStack.size(); i++) {
2017 if (m_groupEditorTable.contains(groupIdStack[i])) {
2018 QRectF app = m_groupEditorTable[groupIdStack[i]]->sceneBoundingRect();
2019 if (rect.isEmpty())
2020 rect = app;
2021 else
2022 #if QT_VERSION >= 0x050000
2023 rect = rect.united(app);
2024 #else
2025 rect = rect.unite(app);
2026 #endif
2027 }
2028 }
2029 QMap<TMacroFx *, FxSchematicMacroEditor *>::iterator it;
2030 for (it = m_macroEditorTable.begin(); it != m_macroEditorTable.end(); it++) {
2031 if (it.value()->contains(node)) {
2032 QRectF app = it.value()->sceneBoundingRect();
2033 if (rect.isEmpty())
2034 rect = app;
2035 else
2036 #if QT_VERSION >= 0x050000
2037 rect = rect.united(app);
2038 #else
2039 rect = rect.unite(app);
2040 #endif
2041 }
2042 }
2043 node->setPos(newPos);
2044 for (i = 0; i < groupIdStack.size(); i++) {
2045 if (!m_groupEditorTable.contains(groupIdStack[i])) continue;
2046 #if QT_VERSION >= 0x050000
2047 rect =
2048 rect.united(m_groupEditorTable[groupIdStack[i]]->sceneBoundingRect());
2049 #else
2050 rect = rect.unite(m_groupEditorTable[groupIdStack[i]]->sceneBoundingRect());
2051 #endif
2052 QRectF app = m_groupEditorTable[groupIdStack[i]]->boundingSceneRect();
2053 if (m_groupEditorTable[groupIdStack[i]]->scenePos() != app.topLeft())
2054 m_groupEditorTable[groupIdStack[i]]->setPos(app.topLeft());
2055 }
2056 for (it = m_macroEditorTable.begin(); it != m_macroEditorTable.end(); it++) {
2057 FxSchematicMacroEditor *editor = it.value();
2058 if (editor->contains(node)) {
2059 QRectF app = editor->sceneBoundingRect();
2060 #if QT_VERSION >= 0x050000
2061 rect = rect.united(app);
2062 #else
2063 rect = rect.unite(app);
2064 #endif
2065 app = editor->boundingSceneRect();
2066 if (editor->scenePos() != app.topLeft()) editor->setPos(app.topLeft());
2067 }
2068 }
2069 update(rect);
2070 }
2071
2072 //------------------------------------------------------------------
2073
closeInnerMacroEditor(int groupId)2074 void FxSchematicScene::closeInnerMacroEditor(int groupId) {
2075 assert(m_groupEditorTable.contains(groupId));
2076 QMap<TMacroFx *, FxSchematicMacroEditor *>::iterator it;
2077 for (it = m_macroEditorTable.begin(); it != m_macroEditorTable.end(); it++) {
2078 TMacroFx *macro = it.key();
2079 assert(macro);
2080 if (macro->getAttributes()->isContainedInGroup(groupId)) {
2081 macro->editMacro(false);
2082 macro->getAttributes()->closeEditingGroup(groupId);
2083 }
2084 }
2085 }
2086
2087 //------------------------------------------------------------------
2088
resizeNodes(bool maximizedNode)2089 void FxSchematicScene::resizeNodes(bool maximizedNode) {
2090 resizingNodes = true;
2091
2092 // resize nodes
2093 m_gridDimension = maximizedNode ? eLarge : eSmall;
2094 m_xshHandle->getXsheet()->getFxDag()->setDagGridDimension(m_gridDimension);
2095 QMap<TFx *, FxSchematicNode *>::iterator it1;
2096 for (it1 = m_table.begin(); it1 != m_table.end(); it1++) {
2097 if (!it1.value()) continue;
2098 it1.value()->resize(maximizedNode);
2099 TFx *fx = it1.value()->getFx();
2100 updatePositionOnResize(fx, maximizedNode);
2101 }
2102 QMap<int, FxGroupNode *>::iterator it2;
2103 for (it2 = m_groupedTable.begin(); it2 != m_groupedTable.end(); it2++) {
2104 if (!it2.value()) continue;
2105 it2.value()->resize(maximizedNode);
2106 QList<TFxP> groupedFxs = it2.value()->getGroupedFxs();
2107 for (int i = 0; i < groupedFxs.size(); i++)
2108 updatePositionOnResize(groupedFxs[i].getPointer(), maximizedNode);
2109 }
2110
2111 QMap<TMacroFx *, FxSchematicMacroEditor *>::iterator it3;
2112 for (it3 = m_macroEditorTable.begin(); it3 != m_macroEditorTable.end();
2113 it3++) {
2114 if (!it3.value()) continue;
2115 it3.value()->resizeNodes(maximizedNode);
2116 }
2117 updateScene();
2118
2119 resizingNodes = false;
2120 }
2121
2122 //------------------------------------------------------------------
2123
updatePositionOnResize(TFx * fx,bool maximizedNode)2124 void FxSchematicScene::updatePositionOnResize(TFx *fx, bool maximizedNode) {
2125 TPointD oldPos = fx->getAttributes()->getDagNodePos();
2126 if (oldPos == TConst::nowhere) return;
2127 double oldPosY = oldPos.y - 25000;
2128 double newPosY = maximizedNode ? oldPosY * 2 : oldPosY * 0.5;
2129 fx->getAttributes()->setDagNodePos(TPointD(oldPos.x, newPosY + 25000));
2130 }
2131
2132 //------------------------------------------------------------------
2133
onNodeChangedSize()2134 void FxSchematicScene::onNodeChangedSize() {
2135 if (resizingNodes) return;
2136 updateScene();
2137 }
2138