Beispiel #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;
}
Beispiel #2
0
void
NodeGraph::setSelection(const NodesGuiList& nodes)
{
    clearSelection();
    for (NodesGuiList::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
        selectNode(*it, true);
    }
}
Beispiel #3
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) );
}
Beispiel #4
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
Beispiel #5
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
Beispiel #6
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