diff --git a/toonz/sources/include/toonzqt/fxschematicnode.h b/toonz/sources/include/toonzqt/fxschematicnode.h index 0c5a299..1c7088c 100644 --- a/toonz/sources/include/toonzqt/fxschematicnode.h +++ b/toonz/sources/include/toonzqt/fxschematicnode.h @@ -224,8 +224,8 @@ private: void resetSnappedLinksOnDynamicPortFx(); - void hideSnappedLinks() override; - void showSnappedLinks() override; + void hideSnappedLinks(SchematicPort *) override; + void showSnappedLinks(SchematicPort *) override; }; //***************************************************** diff --git a/toonz/sources/include/toonzqt/schematicnode.h b/toonz/sources/include/toonzqt/schematicnode.h index d50a859..70e5174 100644 --- a/toonz/sources/include/toonzqt/schematicnode.h +++ b/toonz/sources/include/toonzqt/schematicnode.h @@ -245,6 +245,8 @@ public: void updatePath(SchematicPort *startPort, SchematicPort *endPort); void updatePath() { updatePath(m_startPort, m_endPort); } + void updateEndPos(const QPointF &endPos); + //! Sets the start SchematicPort of the link to \b startPort. void setStartPort(SchematicPort *startPort) { m_startPort = startPort; } //! Sets the start SchematicPort of the link to \b startPort. @@ -309,7 +311,7 @@ protected: SchematicNode *m_node; QPointF m_hook; bool m_highlighted; - SchematicLink *m_ghostLink; + QList m_ghostLinks; SchematicPort *m_linkingTo; QList m_links; int m_type; @@ -390,8 +392,11 @@ protected: private: virtual SchematicPort *searchPort(const QPointF &scenePos) = 0; - virtual void hideSnappedLinks() = 0; - virtual void showSnappedLinks() = 0; + + // linkingPort is used only for stage schematic port - + // in order to enable to connect from multiple node at the same time. + virtual void hideSnappedLinks(SchematicPort *linkingPort) = 0; + virtual void showSnappedLinks(SchematicPort *linkingPort) = 0; signals: void isClicked(); diff --git a/toonz/sources/include/toonzqt/stageschematicnode.h b/toonz/sources/include/toonzqt/stageschematicnode.h index c70a8c2..49862ba 100644 --- a/toonz/sources/include/toonzqt/stageschematicnode.h +++ b/toonz/sources/include/toonzqt/stageschematicnode.h @@ -222,8 +222,8 @@ public: private: SchematicPort *searchPort(const QPointF &scenePos) override; - void hideSnappedLinks() override; - void showSnappedLinks() override; + void hideSnappedLinks(SchematicPort *linkingPort) override; + void showSnappedLinks(SchematicPort *linkingPort) override; }; //======================================================== @@ -247,8 +247,8 @@ public: private: SchematicPort *searchPort(const QPointF &scenePos) override; - void hideSnappedLinks() override; - void showSnappedLinks() override; + void hideSnappedLinks(SchematicPort *) override; + void showSnappedLinks(SchematicPort *) override; }; //======================================================== diff --git a/toonz/sources/toonzqt/fxschematicnode.cpp b/toonz/sources/toonzqt/fxschematicnode.cpp index b83d8e0..cb6a78d 100644 --- a/toonz/sources/toonzqt/fxschematicnode.cpp +++ b/toonz/sources/toonzqt/fxschematicnode.cpp @@ -1373,7 +1373,7 @@ void FxSchematicPort::linkEffects(TFx *inputFx, TFx *fx, int inputId) { //----------------------------------------------------- -void FxSchematicPort::hideSnappedLinks() { +void FxSchematicPort::hideSnappedLinks(SchematicPort *) { if (!m_linkingTo) return; if (m_linkingTo->getType() == eFxInputPort && m_linkingTo->getLinkCount() == 1) { @@ -1405,7 +1405,7 @@ void FxSchematicPort::hideSnappedLinks() { //----------------------------------------------------- -void FxSchematicPort::showSnappedLinks() { +void FxSchematicPort::showSnappedLinks(SchematicPort *) { if (!m_linkingTo) return; if (m_linkingTo->getType() == eFxInputPort && m_linkingTo->getLinkCount() == 1) { @@ -1591,7 +1591,8 @@ void FxSchematicPort::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) { void FxSchematicPort::mouseMoveEvent(QGraphicsSceneMouseEvent *me) { SchematicPort::mouseMoveEvent(me); - if (m_ghostLink && !m_ghostLink->isVisible()) m_ghostLink->show(); + if (!m_ghostLinks.isEmpty() && !m_ghostLinks[0]->isVisible()) + m_ghostLinks[0]->show(); bool cntr = me->modifiers() == Qt::ControlModifier; if (m_currentTargetPort) { m_currentTargetPort->resetSnappedLinksOnDynamicPortFx(); @@ -1623,7 +1624,12 @@ void FxSchematicPort::mouseMoveEvent(QGraphicsSceneMouseEvent *me) { if (targetFx != m_ownerFx && cntr && getType() == eFxOutputPort) targetPort->handleSnappedLinksOnDynamicPortFx(groupedPorts, portId); else if (targetFx == m_ownerFx && getType() == eFxInputPort) { - if (m_ghostLink) m_ghostLink->hide(); + if (!m_ghostLinks.isEmpty()) { + for (SchematicLink *ghostLink : m_ghostLinks) + scene()->removeItem(ghostLink); + qDeleteAll(m_ghostLinks.begin(), m_ghostLinks.end()); + m_ghostLinks.clear(); + } FxSchematicNode *thisNode = dynamic_cast(getNode()); int thisId = thisNode->getInputDockId(getDock()); TFxPort *thisFxPort = targetFx->getInputPort(thisId); diff --git a/toonz/sources/toonzqt/schematicnode.cpp b/toonz/sources/toonzqt/schematicnode.cpp index 7daf2b6..8b59bd5 100644 --- a/toonz/sources/toonzqt/schematicnode.cpp +++ b/toonz/sources/toonzqt/schematicnode.cpp @@ -527,6 +527,12 @@ void SchematicLink::updatePath(SchematicPort *startPort, //-------------------------------------------------------- +void SchematicLink::updateEndPos(const QPointF &endPos) { + if (m_startPort) updatePath(m_startPort->getLinkEndPoint(), endPos); +} + +//-------------------------------------------------------- + SchematicPort *SchematicLink::getOtherPort(const SchematicPort *port) const { if (port == m_startPort) return m_endPort; @@ -624,7 +630,6 @@ SchematicPort::SchematicPort(QGraphicsItem *parent, SchematicNode *node, , m_node(node) , m_buttonState(Qt::NoButton) , m_highlighted(false) - , m_ghostLink(0) , m_linkingTo(0) , m_hook(0, 0) , m_type(type) { @@ -645,27 +650,28 @@ SchematicPort::~SchematicPort() { m_links.clear(); } void SchematicPort::mouseMoveEvent(QGraphicsSceneMouseEvent *me) { if (m_buttonState != Qt::LeftButton) return; - if (!m_ghostLink) return; + if (m_ghostLinks.isEmpty()) return; - if (m_linkingTo) { - showSnappedLinks(); - m_linkingTo = 0; - } // Snapping SchematicPort *linkingTo = searchPort(me->scenePos()); if (!linkingTo) { + for (SchematicLink *ghostLink : m_ghostLinks) { + ghostLink->updateEndPos(me->scenePos()); + ghostLink->getStartPort()->showSnappedLinks(m_linkingTo); + } if (m_linkingTo) { m_linkingTo->highLight(false); m_linkingTo->update(); + m_linkingTo = nullptr; } - m_ghostLink->updatePath(this->getLinkEndPoint(), me->scenePos()); - m_linkingTo = linkingTo; } // if to be connected something else if (linkingTo != this) { - m_ghostLink->updatePath(this, linkingTo); m_linkingTo = linkingTo; - hideSnappedLinks(); + for (SchematicLink *ghostLink : m_ghostLinks) { + ghostLink->updatePath(ghostLink->getStartPort(), linkingTo); + ghostLink->getStartPort()->hideSnappedLinks(m_linkingTo); + } } // autopan QGraphicsView *viewer = scene()->views()[0]; @@ -697,9 +703,32 @@ void SchematicPort::mousePressEvent(QGraphicsSceneMouseEvent *me) { m_buttonState = Qt::LeftButton; QPointF endPos(me->pos()); - m_ghostLink = new SchematicLink(0, scene()); - m_ghostLink->setZValue(3.0); - m_ghostLink->updatePath(this->getLinkEndPoint(), me->scenePos()); + // Enable to connect multiple links from all selected nodes + // only when ( Ctrl + ) dragging from the eStageParentPort. + if (getType() == 101) { // eStageParentPort + QList items = scene()->selectedItems(); + if (items.empty()) return; + for (auto const &item : items) { + SchematicNode *node = dynamic_cast(item); + if (node) { + SchematicPort *parentPort = + node->getPort(0); // id 0 is for parent port. + if (parentPort) { + SchematicLink *ghostLink = new SchematicLink(0, scene()); + ghostLink->setStartPort(parentPort); + ghostLink->setZValue(3.0); + ghostLink->updateEndPos(me->scenePos()); + m_ghostLinks.push_back(ghostLink); + } + } + } + } else { + SchematicLink *ghostLink = new SchematicLink(0, scene()); + ghostLink->setStartPort(this); + ghostLink->setZValue(3.0); + ghostLink->updateEndPos(me->scenePos()); + m_ghostLinks.push_back(ghostLink); + } emit(isClicked()); } } @@ -710,22 +739,39 @@ void SchematicPort::mouseReleaseEvent(QGraphicsSceneMouseEvent *me) { if (me->modifiers() != Qt::ControlModifier && me->button() != Qt::RightButton) QGraphicsItem::mouseReleaseEvent(me); - if (m_ghostLink) m_ghostLink->hide(); - if (m_buttonState == Qt::LeftButton) emit(isReleased(me->scenePos())); // The link is added to the scene only if the user released the left mouse // button over // a SchematicPort different from SchematicPort of the parent node. - if (m_buttonState == Qt::LeftButton && m_linkingTo && - !isLinkedTo(m_linkingTo) && linkTo(m_linkingTo, true)) { - linkTo(m_linkingTo); + bool somethingChanged = false; + if (m_buttonState == Qt::LeftButton && m_linkingTo) { + TUndoManager::manager()->beginBlock(); + for (SchematicLink *ghostLink : m_ghostLinks) { + SchematicPort *port = ghostLink->getStartPort(); + if (!port) continue; + if (!port->isLinkedTo(m_linkingTo) && port->linkTo(m_linkingTo, true)) { + port->linkTo(m_linkingTo); + somethingChanged = true; + } else + port->showSnappedLinks(m_linkingTo); + } m_buttonState = Qt::NoButton; m_linkingTo = 0; + TUndoManager::manager()->endBlock(); + } + + if (!m_ghostLinks.isEmpty()) { + for (SchematicLink *ghostLink : m_ghostLinks) + scene()->removeItem(ghostLink); + qDeleteAll(m_ghostLinks.begin(), m_ghostLinks.end()); + m_ghostLinks.clear(); + } + + if (somethingChanged) { emit sceneChanged(); emit xsheetChanged(); - } else - showSnappedLinks(); + } } //-------------------------------------------------------- diff --git a/toonz/sources/toonzqt/stageschematicnode.cpp b/toonz/sources/toonzqt/stageschematicnode.cpp index 4b57ebe..750f26a 100644 --- a/toonz/sources/toonzqt/stageschematicnode.cpp +++ b/toonz/sources/toonzqt/stageschematicnode.cpp @@ -836,33 +836,33 @@ SchematicPort *StageSchematicNodePort::searchPort(const QPointF &scenePos) { //-------------------------------------------------------- -void StageSchematicNodePort::hideSnappedLinks() { - if (!m_linkingTo) return; +void StageSchematicNodePort::hideSnappedLinks(SchematicPort *linkingPort) { + if (!linkingPort) return; if (getType() == eStageChildPort && - m_linkingTo->getType() == eStageParentPort && - m_linkingTo->getLinkCount() == 1) - m_linkingTo->getLink(0)->hide(); + linkingPort->getType() == eStageParentPort && + linkingPort->getLinkCount() == 1) + linkingPort->getLink(0)->hide(); if (getType() == eStageParentPort && - m_linkingTo->getType() == eStageChildPort && getLinkCount() == 1) + linkingPort->getType() == eStageChildPort && getLinkCount() == 1) getLink(0)->hide(); } //-------------------------------------------------------- -void StageSchematicNodePort::showSnappedLinks() { - if (!m_linkingTo) return; +void StageSchematicNodePort::showSnappedLinks(SchematicPort *linkingPort) { + if (!linkingPort) return; if (getType() == eStageChildPort && - m_linkingTo->getType() == eStageParentPort && - m_linkingTo->getLinkCount() == 1) { - m_linkingTo->getLink(0)->show(); - m_linkingTo->highLight(true); - m_linkingTo->update(); + linkingPort->getType() == eStageParentPort && + linkingPort->getLinkCount() == 1) { + linkingPort->getLink(0)->show(); + linkingPort->highLight(true); + linkingPort->update(); } if (getType() == eStageParentPort && - m_linkingTo->getType() == eStageChildPort && getLinkCount() == 1) { + linkingPort->getType() == eStageChildPort && getLinkCount() == 1) { getLink(0)->show(); - m_linkingTo->highLight(true); - m_linkingTo->update(); + linkingPort->highLight(true); + linkingPort->update(); } } @@ -970,7 +970,7 @@ SchematicPort *StageSchematicSplinePort::searchPort(const QPointF &scenePos) { //-------------------------------------------------------- -void StageSchematicSplinePort::hideSnappedLinks() { +void StageSchematicSplinePort::hideSnappedLinks(SchematicPort *) { if (!m_linkingTo) return; StageSchematicNode *node = dynamic_cast(getNode()); StageSchematicSplineNode *splineNode = @@ -982,7 +982,7 @@ void StageSchematicSplinePort::hideSnappedLinks() { //-------------------------------------------------------- -void StageSchematicSplinePort::showSnappedLinks() { +void StageSchematicSplinePort::showSnappedLinks(SchematicPort *) { if (!m_linkingTo) return; StageSchematicNode *node = dynamic_cast(getNode()); StageSchematicSplineNode *splineNode =