예제 #1
0
void
GuiPrivate::notifyGuiClosing()
{
    ///This is to workaround an issue that when destroying a widget it calls the focusOut() handler hence can
    ///cause bad pointer dereference to the Gui object since we're destroying it.
    std::list<TabWidgetI*> tabs = _gui->getApp()->getTabWidgetsSerialization();

    for (std::list<TabWidgetI*>::iterator it = tabs.begin(); it != tabs.end(); ++it) {
        TabWidget* tab = dynamic_cast<TabWidget*>(*it);
        if (!tab) {
            continue;
        }
        tab->discardGuiPointer();
        for (int i = 0; i < tab->count(); ++i) {
            tab->tabAt(i)->notifyGuiClosingPublic();
        }
    }

    const NodesGuiList allNodes = _nodeGraphArea->getAllActiveNodes();


    // we do not need this list anymore, avoid using it
    _gui->getApp()->clearSettingsPanels();



    for (NodesGuiList::const_iterator it = allNodes.begin(); it != allNodes.end(); ++it) {
        DockablePanel* panel = (*it)->getSettingPanel();
        if (panel) {
            panel->onGuiClosing();
        }
    }
    _lastFocusedGraph = 0;
}
예제 #2
0
void
NodeGraph::setSelection(const NodesGuiList& nodes)
{
    clearSelection();
    for (NodesGuiList::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
        selectNode(*it, true);
    }
}
예제 #3
0
void
NodeGraph::setNodeToDefaultPosition(const NodeGuiPtr& node, const NodesGuiList& selectedNodes, const CreateNodeArgs& args)
{
    NodePtr internalNode = node->getNode();

    // Serializatino, don't do anything
    SERIALIZATION_NAMESPACE::NodeSerializationPtr serialization = args.getPropertyUnsafe<SERIALIZATION_NAMESPACE::NodeSerializationPtr >(kCreateNodeArgsPropNodeSerialization);
    if (serialization) {
        return;
    }

    bool hasPositionnedNode = false;


    // Try to autoconnect if there is a selection
    bool autoConnect = args.getPropertyUnsafe<bool>(kCreateNodeArgsPropAutoConnect);
    if ( selectedNodes.empty() || serialization) {
        autoConnect = false;
    }

    if (autoConnect) {
        BackdropGuiPtr isBd = toBackdropGui(node);
        if (!isBd) {
            NodeGuiPtr selectedNode;
            if ( !serialization && (selectedNodes.size() == 1) ) {
                selectedNode = selectedNodes.front();
                BackdropGuiPtr isBdGui = toBackdropGui(selectedNode);
                if (isBdGui) {
                    selectedNode.reset();
                }
            }
            if (selectedNode && node->getNode()->autoConnect(selectedNode->getNode())) {
                hasPositionnedNode = true;
            }
        }
    }

    if (!hasPositionnedNode) {
        // If there's a position hint, use it to position the node
        double xPosHint = args.getPropertyUnsafe<double>(kCreateNodeArgsPropNodeInitialPosition, 0);
        double yPosHint = args.getPropertyUnsafe<double>(kCreateNodeArgsPropNodeInitialPosition, 1);

        if ((xPosHint != INT_MIN) && (yPosHint != INT_MIN)) {
            QPointF pos = node->mapToParent( node->mapFromScene( QPointF(xPosHint, yPosHint) ) );
            node->refreshPosition( pos.x(), pos.y(), true );
            hasPositionnedNode = true;
        }
    }
    
    

    // Ok fallback with the node in the middle of the node graph
    if (!hasPositionnedNode) {
        moveNodeToCenterOfVisiblePortion(node);
    }


}
예제 #4
0
void
NodeGraph::removeNode(const NodeGuiPtr & node)
{
 
    NodeGroup* isGrp = node->getNode()->isEffectGroup();
    const KnobsVec & knobs = node->getNode()->getKnobs();

    
    for (U32 i = 0; i < knobs.size(); ++i) {
        KnobI::ListenerDimsMap listeners;
        knobs[i]->getListeners(listeners);
        ///For all listeners make sure they belong to a node
        bool foundEffect = false;
        for (KnobI::ListenerDimsMap::iterator it2 = listeners.begin(); it2 != listeners.end(); ++it2) {
            KnobPtr listener = it2->first.lock();
            if (!listener) {
                continue;
            }
            EffectInstance* isEffect = dynamic_cast<EffectInstance*>(listener->getHolder());
            if (!isEffect) {
                continue;
            }
            if (isGrp && isEffect->getNode()->getGroup().get() == isGrp) {
                continue;
            }
            
            if ( isEffect && ( isEffect != node->getNode()->getEffectInstance().get() ) ) {
                foundEffect = true;
                break;
            }
        }
        if (foundEffect) {
            StandardButtonEnum reply = Dialogs::questionDialog( tr("Delete").toStdString(), tr("This node has one or several "
                                                                                                  "parameters from which other parameters "
                                                                                                  "of the project rely on through expressions "
                                                                                                  "or links. Deleting this node will "
                                                                                                  "remove these expressions  "
                                                                                                  "and undoing the action will not recover "
                                                                                                  "them. Do you wish to continue ?")
                                                                   .toStdString(), false );
            if (reply == eStandardButtonNo) {
                return;
            }
            break;
        }
    }

    node->setUserSelected(false);
    NodesGuiList nodesToRemove;
    nodesToRemove.push_back(node);
    pushUndoCommand( new RemoveMultipleNodesCommand(this,nodesToRemove) );
}
예제 #5
0
void
GuiAppInstance::onGroupCreationFinished(const NodePtr& node,
                                        CreateNodeReason reason)
{
    if (reason == eCreateNodeReasonUserCreate) {
        NodeGraph* graph = 0;
        boost::shared_ptr<NodeCollection> collection = node->getGroup();
        assert(collection);
        NodeGroup* isGrp = dynamic_cast<NodeGroup*>( collection.get() );
        if (isGrp) {
            NodeGraphI* graph_i = isGrp->getNodeGraph();
            assert(graph_i);
            graph = dynamic_cast<NodeGraph*>(graph_i);
        } else {
            graph = _imp->_gui->getNodeGraph();
        }
        assert(graph);
        if (!graph) {
            throw std::logic_error("");
        }
        NodesGuiList selectedNodes = graph->getSelectedNodes();
        NodeGuiPtr selectedNode;
        if ( !selectedNodes.empty() ) {
            selectedNode = selectedNodes.front();
            if ( dynamic_cast<BackdropGui*>( selectedNode.get() ) ) {
                selectedNode.reset();
            }
        }
        boost::shared_ptr<NodeGuiI> node_gui_i = node->getNodeGui();
        assert(node_gui_i);
        NodeGuiPtr nodeGui = boost::dynamic_pointer_cast<NodeGui>(node_gui_i);
        graph->moveNodesForIdealPosition(nodeGui, selectedNode, true);
    }

    AppInstance::onGroupCreationFinished(node, reason);

    /*std::list<ViewerInstance* > viewers;
       node->hasViewersConnected(&viewers);
       for (std::list<ViewerInstance* >::iterator it2 = viewers.begin(); it2 != viewers.end(); ++it2) {
        (*it2)->renderCurrentFrame(false);
       }*/
}
예제 #6
0
void
GuiAppInstance::onGroupCreationFinished(const NodePtr& node,
                                        const NodeSerializationPtr& serialization, bool autoConnect)
{
    NodeGuiIPtr node_gui_i = node->getNodeGui();
    if (autoConnect && !serialization && node_gui_i) {
        NodeGraph* graph = 0;
        NodeCollectionPtr collection = node->getGroup();
        assert(collection);
        NodeGroupPtr isGrp = toNodeGroup(collection);
        if (isGrp) {
            NodeGraphI* graph_i = isGrp->getNodeGraph();
            assert(graph_i);
            graph = dynamic_cast<NodeGraph*>(graph_i);
        } else {
            graph = _imp->_gui->getNodeGraph();
        }
        assert(graph);
        if (!graph) {
            throw std::logic_error("");
        }
        NodesGuiList selectedNodes = graph->getSelectedNodes();
        NodeGuiPtr selectedNode;
        if ( !selectedNodes.empty() ) {
            selectedNode = selectedNodes.front();
            if (toBackdropGui(selectedNode) ) {
                selectedNode.reset();
            }
        }
        NodeGuiPtr nodeGui = boost::dynamic_pointer_cast<NodeGui>(node_gui_i);
        graph->moveNodesForIdealPosition(nodeGui, selectedNode, true);
    }
 
    AppInstance::onGroupCreationFinished(node, serialization, autoConnect);

    /*std::list<ViewerInstancePtr> viewers;
       node->hasViewersConnected(&viewers);
       for (std::list<ViewerInstancePtr>::iterator it2 = viewers.begin(); it2 != viewers.end(); ++it2) {
        (*it2)->renderCurrentFrame(false);
       }*/
}
예제 #7
0
void
NodeGraph::decloneSelectedNodes()
{
    if ( _imp->_selection.empty() ) {
        Dialogs::warningDialog( tr("Declone").toStdString(), tr("You must select at least a node to declone first.").toStdString() );

        return;
    }
    std::map<NodeGuiPtr, NodePtr> nodesToDeclone;


    for (NodesGuiList::iterator it = _imp->_selection.begin(); it != _imp->_selection.end(); ++it) {
        BackdropGuiPtr isBd = toBackdropGui(*it);
        if (isBd) {
            // Also clone all nodes within the backdrop
            NodesGuiList nodesWithinBD = getNodesWithinBackdrop(*it);
            for (NodesGuiList::iterator it2 = nodesWithinBD.begin(); it2 != nodesWithinBD.end(); ++it2) {
                std::map<NodeGuiPtr, NodePtr>::iterator found = nodesToDeclone.find(*it2);
                if ( found == nodesToDeclone.end() ) {
                    std::list<NodePtr> linkedNodes;
                    (*it2)->getNode()->getCloneLinkedNodes(&linkedNodes);
                    if (!linkedNodes.empty()) {
                        nodesToDeclone[*it2] = linkedNodes.front();
                    }

                }
            }
        }
        std::list<NodePtr> linkedNodes;
        (*it)->getNode()->getCloneLinkedNodes(&linkedNodes);
        if (!linkedNodes.empty()) {
            nodesToDeclone[*it] = linkedNodes.front();
        }
    }

    pushUndoCommand( new DecloneMultipleNodesCommand(this, nodesToDeclone) );
}
예제 #8
0
void
NodeGraph::refreshNodeLinksNow()
{
    // First clear all previous links
    for (NodeGraphPrivate::LinkedNodesList::const_iterator it = _imp->linkedNodes.begin(); it != _imp->linkedNodes.end(); ++it) {
        delete it->arrow;
    }
    _imp->linkedNodes.clear();

    if (!_imp->_knobLinksVisible) {
        return;
    }

    NodesGuiList nodes;
    {
        QMutexLocker k(&_imp->_nodesMutex);
        nodes = _imp->_nodes;
    }

    QColor simpleLinkColor, cloneLinkColor;
    {
        double exprColor[3], cloneColor[3];
        appPTR->getCurrentSettings()->getExprColor(&exprColor[0], &exprColor[1], &exprColor[2]);
        appPTR->getCurrentSettings()->getCloneColor(&cloneColor[0], &cloneColor[1], &cloneColor[2]);
        simpleLinkColor.setRgbF(Image::clamp(exprColor[0], 0., 1.),
                                Image::clamp(exprColor[1], 0., 1.),
                                Image::clamp(exprColor[2], 0., 1.));
        cloneLinkColor.setRgbF(Image::clamp(cloneColor[0], 0., 1.),
                                Image::clamp(cloneColor[1], 0., 1.),
                                Image::clamp(cloneColor[2], 0., 1.));
    }
    
    
    for (NodesGuiList::const_iterator it = nodes.begin(); it!=nodes.end(); ++it) {
        NodePtr thisNode = (*it)->getNode();

        std::list<std::pair<NodePtr, bool> > linkedNodes;
        thisNode->getLinkedNodes(&linkedNodes);

        for (std::list<std::pair<NodePtr, bool> >::const_iterator it2 = linkedNodes.begin(); it2 != linkedNodes.end(); ++it2) {

            // If the linked node doesn't have a gui or it is not part of this nodegraph don't create a link at all
            NodeGuiPtr otherNodeGui = toNodeGui(it2->first->getNodeGui());
            if (!otherNodeGui || otherNodeGui->getDagGui() != this) {
                continue;
            }

            // Try to find an existing link
            NodeGraphPrivate::LinkedNodes link;
            link.nodes[0] = thisNode;
            link.nodes[1] = it2->first;
            link.isCloneLink = it2->second;

            NodeGraphPrivate::LinkedNodesList::iterator foundExistingLink = _imp->linkedNodes.end();
            {
                for (NodeGraphPrivate::LinkedNodesList::iterator it = _imp->linkedNodes.begin(); it != _imp->linkedNodes.end(); ++it) {
                    NodePtr a1 = it->nodes[0].lock();
                    NodePtr a2 = it->nodes[1].lock();
                    NodePtr b1 = link.nodes[0].lock();
                    NodePtr b2 = link.nodes[1].lock();
                    if ((a1 == b1 || a1 == b2) &&
                        (a2 == b1 || a2 == b2)) {
                        foundExistingLink = it;
                        break;
                    }
                }
            }

            if (foundExistingLink == _imp->linkedNodes.end()) {
                // A link did not exist, create it
                link.arrow = new LinkArrow( otherNodeGui, *it, (*it)->parentItem() );
                link.arrow->setWidth(2);
                link.arrow->setArrowHeadVisible(false);
                if (link.isCloneLink) {
                    link.arrow->setColor(cloneLinkColor);
                } else {
                    link.arrow->setColor(simpleLinkColor);
                }
                _imp->linkedNodes.push_back(link);
            } else {
                // A link existed, if this is a clone link and it was not before, upgrade it
                if (!foundExistingLink->isCloneLink && link.isCloneLink) {
                    foundExistingLink->arrow->setColor(cloneLinkColor);
                }
            }

        }

        (*it)->refreshLinkIndicators(linkedNodes);
    }

} // refreshNodeLinksNow
예제 #9
0
void
NodeGraph::showMenu(const QPoint & pos)
{
    _imp->_menu->clear();

    QAction* findAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphFindNode,
                                                 kShortcutActionGraphFindNodeLabel, _imp->_menu);
    _imp->_menu->addAction(findAction);
    _imp->_menu->addSeparator();

    //QFont font(appFont,appFontSize);
    Menu* editMenu = new Menu(tr("Edit"), _imp->_menu);
    //editMenu->setFont(font);
    _imp->_menu->addAction( editMenu->menuAction() );

    QAction* copyAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphCopy,
                                                 kShortcutActionGraphCopyLabel, editMenu);
    QObject::connect( copyAction, SIGNAL(triggered()), this, SLOT(copySelectedNodes()) );
    editMenu->addAction(copyAction);

    QAction* cutAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphCut,
                                                kShortcutActionGraphCutLabel, editMenu);
    QObject::connect( cutAction, SIGNAL(triggered()), this, SLOT(cutSelectedNodes()) );
    editMenu->addAction(cutAction);


    QAction* pasteAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphPaste,
                                                  kShortcutActionGraphPasteLabel, editMenu);
    bool cbEnabled = false;
    {
        QClipboard* clipboard = QApplication::clipboard();
        const QMimeData* data = clipboard->mimeData();
        if (data && data->hasFormat(QLatin1String("text/plain"))) {
            cbEnabled = true;
        }
    }
    pasteAction->setEnabled(cbEnabled);
    editMenu->addAction(pasteAction);

    QAction* deleteAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphRemoveNodes,
                                                   kShortcutActionGraphRemoveNodesLabel, editMenu);
    QObject::connect( deleteAction, SIGNAL(triggered()), this, SLOT(deleteSelection()) );
    editMenu->addAction(deleteAction);

    QAction* renameAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphRenameNode,
                                                   kShortcutActionGraphRenameNodeLabel, editMenu);
    QObject::connect( renameAction, SIGNAL(triggered()), this, SLOT(renameNode()) );
    editMenu->addAction(renameAction);

    QAction* duplicateAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphDuplicate,
                                                      kShortcutActionGraphDuplicateLabel, editMenu);
    editMenu->addAction(duplicateAction);

    QAction* cloneAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphClone,
                                                  kShortcutActionGraphCloneLabel, editMenu);
    editMenu->addAction(cloneAction);

    QAction* decloneAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphDeclone,
                                                    kShortcutActionGraphDecloneLabel, editMenu);
    QObject::connect( decloneAction, SIGNAL(triggered()), this, SLOT(decloneSelectedNodes()) );
    editMenu->addAction(decloneAction);

    QAction* switchInputs = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphExtractNode,
                                                   kShortcutActionGraphExtractNodeLabel, editMenu);
    QObject::connect( switchInputs, SIGNAL(triggered()), this, SLOT(extractSelectedNode()) );
    editMenu->addAction(switchInputs);

    QAction* extractNode = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphSwitchInputs,
                                                  kShortcutActionGraphSwitchInputsLabel, editMenu);
    QObject::connect( extractNode, SIGNAL(triggered()), this, SLOT(switchInputs1and2ForSelectedNodes()) );
    editMenu->addAction(extractNode);

    QAction* disableNodes = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphDisableNodes,
                                                   kShortcutActionGraphDisableNodesLabel, editMenu);
    QObject::connect( disableNodes, SIGNAL(triggered()), this, SLOT(toggleSelectedNodesEnabled()) );
    editMenu->addAction(disableNodes);

    QAction* groupFromSel = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphMakeGroup,
                                                   kShortcutActionGraphMakeGroupLabel, editMenu);
    QObject::connect( groupFromSel, SIGNAL(triggered()), this, SLOT(createGroupFromSelection()) );
    editMenu->addAction(groupFromSel);

    QAction* expandGroup = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphExpandGroup,
                                                  kShortcutActionGraphExpandGroupLabel, editMenu);
    QObject::connect( expandGroup, SIGNAL(triggered()), this, SLOT(expandSelectedGroups()) );
    editMenu->addAction(expandGroup);

    QAction* displayCacheInfoAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphShowCacheSize,
                                                             kShortcutActionGraphShowCacheSizeLabel, _imp->_menu);
    displayCacheInfoAction->setCheckable(true);
    displayCacheInfoAction->setChecked( _imp->_cacheSizeText->isVisible() );
    QObject::connect( displayCacheInfoAction, SIGNAL(triggered()), this, SLOT(toggleCacheInfo()) );
    _imp->_menu->addAction(displayCacheInfoAction);

    NodesGuiList selectedNodes = getSelectedNodes();
    if ( !selectedNodes.empty() ) {
        QAction* turnOffPreviewAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphTogglePreview,
                                                               kShortcutActionGraphTogglePreviewLabel, _imp->_menu);
        turnOffPreviewAction->setCheckable(true);
        turnOffPreviewAction->setChecked(false);
        QObject::connect( turnOffPreviewAction, SIGNAL(triggered()), this, SLOT(togglePreviewsForSelectedNodes()) );
        _imp->_menu->addAction(turnOffPreviewAction);

        if (selectedNodes.size() == 1) {
            QAction* openNodePanelAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphOpenNodePanel,
                                                                  kShortcutActionGraphOpenNodePanelLabel, _imp->_menu);
            openNodePanelAction->setCheckable(true);
            openNodePanelAction->setChecked(false);
            QObject::connect( openNodePanelAction, SIGNAL(triggered()), this, SLOT(showSelectedNodeSettingsPanel()) );
            _imp->_menu->addAction(openNodePanelAction);
        }
    }

    QAction* autoHideInputs = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphAutoHideInputs,
                                                     kShortcutActionGraphAutoHideInputsLabel, _imp->_menu);
    autoHideInputs->setCheckable(true);
    autoHideInputs->setChecked( appPTR->getCurrentSettings()->areOptionalInputsAutoHidden() );
    QObject::connect( autoHideInputs, SIGNAL(triggered()), this, SLOT(toggleAutoHideInputs()) );
    _imp->_menu->addAction(autoHideInputs);

    QAction* hideInputs = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphHideInputs,
                                                 kShortcutActionGraphHideInputsLabel, _imp->_menu);
    hideInputs->setCheckable(true);
    bool hideInputsVal = false;
    if ( !selectedNodes.empty() ) {
        hideInputsVal = selectedNodes.front()->getNode()->getEffectInstance()->getHideInputsKnobValue();
    }
    hideInputs->setChecked(hideInputsVal);
    QObject::connect( hideInputs, SIGNAL(triggered()), this, SLOT(toggleHideInputs()) );
    _imp->_menu->addAction(hideInputs);


    QAction* knobLinks = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphShowExpressions,
                                                kShortcutActionGraphShowExpressionsLabel, _imp->_menu);
    knobLinks->setCheckable(true);
    knobLinks->setChecked( areKnobLinksVisible() );
    QObject::connect( knobLinks, SIGNAL(triggered()), this, SLOT(toggleKnobLinksVisible()) );
    _imp->_menu->addAction(knobLinks);

    QAction* autoPreview = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphToggleAutoPreview,
                                                  kShortcutActionGraphToggleAutoPreviewLabel, _imp->_menu);
    autoPreview->setCheckable(true);
    autoPreview->setChecked( getGui()->getApp()->getProject()->isAutoPreviewEnabled() );
    QObject::connect( autoPreview, SIGNAL(triggered()), this, SLOT(toggleAutoPreview()) );
    QObject::connect( getGui()->getApp()->getProject().get(), SIGNAL(autoPreviewChanged(bool)), autoPreview, SLOT(setChecked(bool)) );
    _imp->_menu->addAction(autoPreview);

    QAction* autoTurbo = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphToggleAutoTurbo,
                                                kShortcutActionGraphToggleAutoTurboLabel, _imp->_menu);
    autoTurbo->setCheckable(true);
    autoTurbo->setChecked( appPTR->getCurrentSettings()->isAutoTurboEnabled() );
    QObject::connect( autoTurbo, SIGNAL(triggered()), this, SLOT(toggleAutoTurbo()) );
    _imp->_menu->addAction(autoTurbo);


    QAction* forceRefreshPreviews = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphForcePreview,
                                                           kShortcutActionGraphForcePreviewLabel, _imp->_menu);
    QObject::connect( forceRefreshPreviews, SIGNAL(triggered()), this, SLOT(forceRefreshAllPreviews()) );
    _imp->_menu->addAction(forceRefreshPreviews);

    QAction* frameAllNodes = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphFrameNodes,
                                                    kShortcutActionGraphFrameNodesLabel, _imp->_menu);
    QObject::connect( frameAllNodes, SIGNAL(triggered()), this, SLOT(centerOnAllNodes()) );
    _imp->_menu->addAction(frameAllNodes);

    _imp->_menu->addSeparator();

    std::list<ToolButton*> orederedToolButtons = getGui()->getToolButtonsOrdered();
    for (std::list<ToolButton*>::iterator it = orederedToolButtons.begin(); it != orederedToolButtons.end(); ++it) {
        (*it)->getMenu()->setIcon( (*it)->getMenuIcon() );
        _imp->_menu->addAction( (*it)->getMenu()->menuAction() );
    }

    QAction* ret = _imp->_menu->exec(pos);
    if (ret == findAction) {
        popFindDialog();
    } else if (ret == duplicateAction) {
        QRectF rect = visibleSceneRect();
        duplicateSelectedNodes( rect.center() );
    } else if (ret == cloneAction) {
        QRectF rect = visibleSceneRect();
        cloneSelectedNodes( rect.center() );
    } else if (ret == pasteAction) {
        QRectF rect = visibleSceneRect();
        pasteClipboard( rect.center() );
    }
} // NodeGraph::showMenu
예제 #10
0
void
Gui::renderSelectedNode()
{
    NodeGraph* graph = getLastSelectedGraph();

    if (!graph) {
        return;
    }

    NodesGuiList selectedNodes = graph->getSelectedNodes();

    if ( selectedNodes.empty() ) {
        Dialogs::warningDialog( tr("Render").toStdString(), tr("You must select a node to render first!").toStdString() );

        return;
    }
    std::list<AppInstance::RenderWork> workList;
    bool useStats = getApp()->isRenderStatsActionChecked();
    for (NodesGuiList::const_iterator it = selectedNodes.begin();
         it != selectedNodes.end(); ++it) {
        NodePtr internalNode = (*it)->getNode();
        if (!internalNode) {
            continue;
        }
        EffectInstPtr effect = internalNode->getEffectInstance();
        if (!effect) {
            continue;
        }
        if ( effect->isWriter() ) {
            if ( !effect->areKnobsFrozen() ) {
                //if ((*it)->getNode()->is)
                ///if the node is a writer, just use it to render!
                AppInstance::RenderWork w;
                w.writer = dynamic_cast<OutputEffectInstance*>( effect.get() );
                assert(w.writer);
                w.firstFrame = INT_MIN;
                w.lastFrame = INT_MAX;
                w.frameStep = INT_MIN;
                w.useRenderStats = useStats;
                workList.push_back(w);
            }
        } else {
            if (selectedNodes.size() == 1) {
                ///create a node and connect it to the node and use it to render
#ifndef NATRON_ENABLE_IO_META_NODES
                NodePtr writer = createWriter();
#else
                NodeGraph* graph = selectedNodes.front()->getDagGui();
                NodePtr writer = getApp()->createWriter( "", eCreateNodeReasonInternal, graph->getGroup() );
#endif
                if (writer) {
                    AppInstance::RenderWork w;
                    w.writer = dynamic_cast<OutputEffectInstance*>( writer->getEffectInstance().get() );
                    assert(w.writer);
                    w.firstFrame = INT_MIN;
                    w.lastFrame = INT_MAX;
                    w.frameStep = INT_MIN;
                    w.useRenderStats = useStats;
                    workList.push_back(w);
                }
            }
        }
    }
    _imp->_appInstance->startWritersRendering(false, workList);
} // Gui::renderSelectedNode
예제 #11
0
void
GuiAppInstance::createNodeGui(const NodePtr &node,
                              const NodePtr& parentMultiInstance,
                              const CreateNodeArgs& args)
{
    boost::shared_ptr<NodeCollection> group = node->getGroup();
    NodeGraph* graph;

    if (group) {
        NodeGraphI* graph_i = group->getNodeGraph();
        assert(graph_i);
        graph = dynamic_cast<NodeGraph*>(graph_i);
        assert(graph);
    } else {
        graph = _imp->_gui->getNodeGraph();
    }
    if (!graph) {
        throw std::logic_error("");
    }

    NodesGuiList selectedNodes = graph->getSelectedNodes();
    NodeGuiPtr nodegui = _imp->_gui->createNodeGUI(node, args);

    assert(nodegui);
    if (parentMultiInstance && nodegui) {
        nodegui->hideGui();


        boost::shared_ptr<NodeGuiI> parentNodeGui_i = parentMultiInstance->getNodeGui();
        assert(parentNodeGui_i);
        nodegui->setParentMultiInstance( boost::dynamic_pointer_cast<NodeGui>(parentNodeGui_i) );
    }

    ///It needs to be here because we rely on the _nodeMapping member
    bool isViewer = node->isEffectViewer() != 0;
    if (isViewer) {
        _imp->_gui->createViewerGui(node);
    }

    ///must be done after the viewer gui has been created
    if ( node->isRotoPaintingNode() ) {
        _imp->_gui->createNewRotoInterface( nodegui.get() );
    }

    if ( ( node->isTrackerNodePlugin() || node->getEffectInstance()->isBuiltinTrackerNode() ) && !parentMultiInstance ) {
        _imp->_gui->createNewTrackerInterface( nodegui.get() );
    }

    NodeGroup* isGroup = node->isEffectGroup();
    if ( isGroup && isGroup->isSubGraphUserVisible() ) {
        _imp->_gui->createGroupGui(node, args.reason);
    }

    ///Don't initialize inputs if it is a multi-instance child since it is not part of  the graph
    if (!parentMultiInstance) {
        nodegui->initializeInputs();
    }

    if ( (args.reason == eCreateNodeReasonUserCreate) && !isViewer ) {
        ///we make sure we can have a clean preview.
        node->computePreviewImage( getTimeLine()->currentFrame() );
        triggerAutoSave();
    }


    ///only move main instances
    if ( node->getParentMultiInstanceName().empty() ) {
        bool autoConnect = args.reason == eCreateNodeReasonUserCreate;

        if ( selectedNodes.empty() ) {
            autoConnect = false;
        }
        if ( (args.xPosHint != INT_MIN) && (args.yPosHint != INT_MIN) && (!autoConnect) ) {
            QPointF pos = nodegui->mapToParent( nodegui->mapFromScene( QPointF(args.xPosHint, args.yPosHint) ) );
            nodegui->refreshPosition( pos.x(), pos.y(), true );
        } else {
            BackdropGui* isBd = dynamic_cast<BackdropGui*>( nodegui.get() );
            if (!isBd) {
                NodeGuiPtr selectedNode;
                if ( (args.reason == eCreateNodeReasonUserCreate) && (selectedNodes.size() == 1) ) {
                    selectedNode = selectedNodes.front();
                    BackdropGui* isBackdropGui = dynamic_cast<BackdropGui*>( selectedNode.get() );
                    if (isBackdropGui) {
                        selectedNode.reset();
                    }
                }
                nodegui->getDagGui()->moveNodesForIdealPosition(nodegui, selectedNode, autoConnect);
            }
        }
    }
} // createNodeGui
예제 #12
0
void
GuiAppInstance::createNodeGui(const NodePtr &node,
                              const NodePtr& parentMultiInstance,
                              const CreateNodeArgs& args)
{
    NodeCollectionPtr group = node->getGroup();
    NodeGraph* graph;

    if (group) {
        NodeGraphI* graph_i = group->getNodeGraph();
        assert(graph_i);
        graph = dynamic_cast<NodeGraph*>(graph_i);
        assert(graph);
    } else {
        graph = _imp->_gui->getNodeGraph();
    }
    if (!graph) {
        throw std::logic_error("");
    }

    NodesGuiList selectedNodes = graph->getSelectedNodes();
    NodeGuiPtr nodegui = _imp->_gui->createNodeGUI(node, args);
    assert(nodegui);

    if (parentMultiInstance && nodegui) {
        nodegui->hideGui();


        NodeGuiIPtr parentNodeGui_i = parentMultiInstance->getNodeGui();
        assert(parentNodeGui_i);
        nodegui->setParentMultiInstance( boost::dynamic_pointer_cast<NodeGui>(parentNodeGui_i) );
    }

    bool isViewer = node->isEffectViewerInstance() != 0;
    if (isViewer) {
        _imp->_gui->createViewerGui(node);
    }

    // Must be done after the viewer gui has been created
    _imp->_gui->createNodeViewerInterface(nodegui);


    NodeGroupPtr isGroup = node->isEffectNodeGroup();
    if ( isGroup && isGroup->isSubGraphUserVisible() ) {
        _imp->_gui->createGroupGui(node, args);
    }

    ///Don't initialize inputs if it is a multi-instance child since it is not part of  the graph
    if (!parentMultiInstance) {
        nodegui->initializeInputs();
    }
    
    NodeSerializationPtr serialization = args.getProperty<NodeSerializationPtr >(kCreateNodeArgsPropNodeSerialization);
    if ( !serialization && !isViewer ) {
        ///we make sure we can have a clean preview.
        node->computePreviewImage( getTimeLine()->currentFrame() );
        triggerAutoSave();
    }


    ///only move main instances
    if ( node->getParentMultiInstanceName().empty() && !serialization) {
        bool autoConnect = args.getProperty<bool>(kCreateNodeArgsPropAutoConnect);

        if ( selectedNodes.empty() || serialization) {
            autoConnect = false;
        }
        double xPosHint = serialization ? INT_MIN : args.getProperty<double>(kCreateNodeArgsPropNodeInitialPosition, 0);
        double yPosHint = serialization ? INT_MIN : args.getProperty<double>(kCreateNodeArgsPropNodeInitialPosition, 1);
        if ( (xPosHint != INT_MIN) && (yPosHint != INT_MIN) && (!autoConnect) ) {
            QPointF pos = nodegui->mapToParent( nodegui->mapFromScene( QPointF(xPosHint, yPosHint) ) );
            nodegui->refreshPosition( pos.x(), pos.y(), true );
        } else {
            BackdropGuiPtr isBd = toBackdropGui(nodegui);
            if (!isBd) {
                NodeGuiPtr selectedNode;
                if ( !serialization && (selectedNodes.size() == 1) ) {
                    selectedNode = selectedNodes.front();
                    BackdropGuiPtr isBdGui = toBackdropGui(selectedNode);
                    if (isBdGui) {
                        selectedNode.reset();
                    }
                }
                nodegui->getDagGui()->moveNodesForIdealPosition(nodegui, selectedNode, autoConnect);
            }
        }
    }
} // createNodeGui
예제 #13
0
void
NodeGraph::deleteSelection()
{
    if ( !_imp->_selection.empty()) {
        NodesGuiList nodesToRemove = _imp->_selection;

        
        ///For all backdrops also move all the nodes contained within it
        for (NodesGuiList::iterator it = nodesToRemove.begin(); it != nodesToRemove.end(); ++it) {
            NodesGuiList nodesWithinBD = getNodesWithinBackdrop(*it);
            for (NodesGuiList::iterator it2 = nodesWithinBD.begin(); it2 != nodesWithinBD.end(); ++it2) {
                NodesGuiList::iterator found = std::find(nodesToRemove.begin(),nodesToRemove.end(),*it2);
                if ( found == nodesToRemove.end()) {
                    nodesToRemove.push_back(*it2);
                }
            }
        }


        for (NodesGuiList::iterator it = nodesToRemove.begin(); it != nodesToRemove.end(); ++it) {
            
            const KnobsVec & knobs = (*it)->getNode()->getKnobs();
            bool mustBreak = false;
            
            NodeGroup* isGrp = (*it)->getNode()->isEffectGroup();
            
            for (U32 i = 0; i < knobs.size(); ++i) {
                KnobI::ListenerDimsMap listeners;
                knobs[i]->getListeners(listeners);

                ///For all listeners make sure they belong to a node
                bool foundEffect = false;
                for (KnobI::ListenerDimsMap::iterator it2 = listeners.begin(); it2 != listeners.end(); ++it2) {
                    KnobPtr listener = it2->first.lock();
                    if (!listener) {
                        continue;
                    }
                    EffectInstance* isEffect = dynamic_cast<EffectInstance*>(listener->getHolder() );
                    
                    if (!isEffect) {
                        continue;
                    }
                    if (isGrp && isEffect->getNode()->getGroup().get() == isGrp) {
                        continue;
                    }
                    
                    if (!isEffect->getNode()->getGroup()) {
                        continue;
                    }
                    
                    if ( isEffect && ( isEffect != (*it)->getNode()->getEffectInstance().get() ) ) {
                        foundEffect = true;
                        break;
                    }
                }
                if (foundEffect) {
                    StandardButtonEnum reply = Dialogs::questionDialog( tr("Delete").toStdString(),
                                                                           tr("This node has one or several "
                                                                              "parameters from which other parameters "
                                                                              "of the project rely on through expressions "
                                                                              "or links. Deleting this node will "
                                                                              "may break these expressions."
                                                                              "\nContinue anyway ?")
                                                                           .toStdString(), false );
                    if (reply == eStandardButtonNo) {
                        return;
                    }
                    mustBreak = true;
                    break;
                }
            }
            if (mustBreak) {
                break;
            }
        }


        for (NodesGuiList::iterator it = nodesToRemove.begin(); it != nodesToRemove.end(); ++it) {
            (*it)->setUserSelected(false);
        }


        pushUndoCommand( new RemoveMultipleNodesCommand(this,nodesToRemove) );
        _imp->_selection.clear();
    }
} // deleteSelection