예제 #1
0
GCC_DIAG_UNUSED_PRIVATE_FIELD_ON

#include "Engine/EffectInstance.h"
#include "Engine/Node.h"
#include "Engine/NodeGroup.h"
#include "Engine/Settings.h"
#include "Engine/Utils.h" // convertFromPlainText

#include "Gui/BackdropGui.h"
#include "Gui/Edge.h"
#include "Gui/GuiApplicationManager.h"
#include "Gui/GuiMacros.h"
#include "Gui/NodeGui.h"
#include "Gui/TabWidget.h"



#include "Global/QtCompat.h"

NATRON_NAMESPACE_ENTER
void
NodeGraph::checkForHints(bool shiftdown,
                         bool controlDown,
                         const NodeGuiPtr& selectedNode,
                         const QRectF& visibleSceneR)
{
    NodePtr internalNode = selectedNode->getNode();
    if (!internalNode) {
        return;
    }
    bool doMergeHints = shiftdown && controlDown;
    bool doConnectionHints = controlDown;

    //Ignore hints for backdrops
    BackdropGuiPtr isBd = toBackdropGui( selectedNode );

    if (isBd) {
        return;
    }

    if (!doMergeHints) {
        ///for nodes already connected don't show hint
        if ( ( internalNode->getNInputs() == 0) && internalNode->hasOutputConnected() ) {
            doConnectionHints = false;
        } else if ( ( internalNode->getNInputs() > 0) && internalNode->hasAllInputsConnected() && internalNode->hasOutputConnected() ) {
            doConnectionHints = false;
        }
    }

    if (!doConnectionHints) {
        return;
    }

    QRectF selectedNodeBbox = selectedNode->boundingRectWithEdges(); //selectedNode->mapToParent( selectedNode->boundingRect() ).boundingRect();
    double tolerance = 10;
    selectedNodeBbox.adjust(-tolerance, -tolerance, tolerance, tolerance);

    NodeGuiPtr nodeToShowMergeRect;
    NodePtr selectedNodeInternalNode = selectedNode->getNode();
    bool selectedNodeIsReader = selectedNodeInternalNode->getEffectInstance()->isReader() || selectedNodeInternalNode->getNInputs() == 0;
    Edge* edge = 0;
    std::set<NodeGuiPtr> nodesWithinRect;
    getNodesWithinViewportRect(visibleWidgetRect(), &nodesWithinRect);

    {
        for (std::set<NodeGuiPtr>::iterator it = nodesWithinRect.begin(); it != nodesWithinRect.end(); ++it) {
            OutputNodesMap outputs;
            internalNode->getOutputs(outputs);

            OutputNodesMap::const_iterator foundAsOutput = outputs.find((*it)->getNode());
            if (foundAsOutput != outputs.end()) {
                continue;
            }
            QRectF nodeBbox = (*it)->boundingRectWithEdges();
            if ( ( (*it) != selectedNode ) && (*it)->isVisible() && nodeBbox.intersects(visibleSceneR) ) {
                if (doMergeHints) {
                    //QRectF nodeRect = (*it)->mapToParent((*it)->boundingRect()).boundingRect();

                    NodePtr internalNode = (*it)->getNode();


                    if ( !internalNode->isOutputNode() && nodeBbox.intersects(selectedNodeBbox) ) {
                        bool nHasInput = internalNode->hasInputConnected();
                        int nMaxInput = internalNode->getNInputs();
                        bool selectedHasInput = selectedNodeInternalNode->hasInputConnected();
                        int selectedMaxInput = selectedNodeInternalNode->getNInputs();
                        double nPAR = internalNode->getEffectInstance()->getAspectRatio(-1);
                        double selectedPAR = selectedNodeInternalNode->getEffectInstance()->getAspectRatio(-1);
                        double nFPS = internalNode->getEffectInstance()->getFrameRate();
                        double selectedFPS = selectedNodeInternalNode->getEffectInstance()->getFrameRate();
                        bool isValid = true;

                        if ( (selectedPAR != nPAR) || (std::abs(nFPS - selectedFPS) > 0.01) ) {
                            if (nHasInput || selectedHasInput) {
                                isValid = false;
                            } else if ( !nHasInput && (nMaxInput == 0) && !selectedHasInput && (selectedMaxInput == 0) ) {
                                isValid = false;
                            }
                        }
                        if (isValid) {
                            nodeToShowMergeRect = (*it)->shared_from_this();
                        }
                    } else {
                        (*it)->setMergeHintActive(false);
                    }
                } else { //!doMergeHints
                    edge = (*it)->hasEdgeNearbyRect(selectedNodeBbox);

                    ///if the edge input is the selected node don't continue
                    if ( edge && ( edge->getSource() == selectedNode) ) {
                        edge = 0;
                    }

                    if ( edge && edge->isOutputEdge() ) {
                        if (selectedNodeIsReader) {
                            continue;
                        }
                        int prefInput = selectedNodeInternalNode->getPreferredInputForConnection();
                        if (prefInput == -1) {
                            edge = 0;
                        } else {
                            Node::CanConnectInputReturnValue ret = selectedNodeInternalNode->canConnectInput(edge->getSource()->getNode(),
                                                                                                             prefInput);
                            if (ret != Node::eCanConnectInput_ok) {
                                edge = 0;
                            }
                        }
                    }

                    if ( edge && !edge->isOutputEdge() ) {
                        if ( (*it)->getNode()->getEffectInstance()->isReader() ||
                             ( (*it)->getNode()->getNInputs() == 0 ) ) {
                            edge = 0;
                            continue;
                        }

                        //Check that the edge can connect to the selected node
                        {
                            Node::CanConnectInputReturnValue ret = edge->getDest()->getNode()->canConnectInput( selectedNodeInternalNode, edge->getInputNumber() );
                            if ( (ret == Node::eCanConnectInput_inputAlreadyConnected) &&
                                 !selectedNodeIsReader ) {
                                ret = Node::eCanConnectInput_ok;
                            }

                            if (ret != Node::eCanConnectInput_ok) {
                                edge = 0;
                            }
                        }

                        //Check that the selected node can connect to the input of the edge

                        if (edge) {
                            NodeGuiPtr edgeHasSource = edge->getSource();
                            if (edgeHasSource) {
                                int prefInput = selectedNodeInternalNode->getPreferredInputForConnection();
                                if (prefInput != -1) {
                                    Node::CanConnectInputReturnValue ret = selectedNodeInternalNode->canConnectInput(edgeHasSource->getNode(), prefInput);
                                    if ( (ret == Node::eCanConnectInput_inputAlreadyConnected) &&
                                         !selectedNodeIsReader ) {
                                        ret = Node::eCanConnectInput_ok;
                                    }

                                    if (ret != Node::eCanConnectInput_ok) {
                                        edge = 0;
                                    }
                                }
                            }
                        }
                    }

                    if (edge) {
                        edge->setUseHighlight(true);
                        break;
                    }
                } // doMergeHints
            }
        }
    } // QMutexLocker l(&_imp->_nodesMutex);

    if ( _imp->_highLightedEdge && ( _imp->_highLightedEdge != edge) ) {
        _imp->_highLightedEdge->setUseHighlight(false);
        _imp->_hintInputEdge->hide();
        _imp->_hintOutputEdge->hide();
    }

    _imp->_highLightedEdge = edge;

    if ( edge && edge->getSource() && edge->getDest() ) {
        ///setup the hints edge

        ///find out if the node is already connected to what the edge is connected
        bool alreadyConnected = false;
        const std::vector<NodeWPtr> & inpNodes = selectedNode->getNode()->getInputs();
        for (std::size_t i = 0; i < inpNodes.size(); ++i) {
            if ( inpNodes[i].lock() == edge->getSource()->getNode() ) {
                alreadyConnected = true;
                break;
            }
        }

        if ( !_imp->_hintInputEdge->isVisible() ) {
            if (!alreadyConnected) {
                int prefInput = selectedNode->getNode()->getPreferredInputForConnection();
                _imp->_hintInputEdge->setInputNumber(prefInput != -1 ? prefInput : 0);
                _imp->_hintInputEdge->setSourceAndDestination(edge->getSource(), selectedNode);
                _imp->_hintInputEdge->setVisible(true);
            }
            _imp->_hintOutputEdge->setInputNumber( edge->getInputNumber() );
            _imp->_hintOutputEdge->setSourceAndDestination( selectedNode, edge->getDest() );
            _imp->_hintOutputEdge->setVisible(true);
        } else {
            if (!alreadyConnected) {
                _imp->_hintInputEdge->initLine();
            }
            _imp->_hintOutputEdge->initLine();
        }
    } else if (edge) {
        ///setup only 1 of the hints edge

        if ( _imp->_highLightedEdge && !_imp->_hintInputEdge->isVisible() ) {
            if ( edge->isOutputEdge() ) {
                int prefInput = selectedNode->getNode()->getPreferredInputForConnection();
                if (prefInput != -1) {
                    _imp->_hintInputEdge->setInputNumber(prefInput);
                    _imp->_hintInputEdge->setSourceAndDestination(edge->getSource(), selectedNode);
                    _imp->_hintInputEdge->setVisible(true);
                }
            } else {
                _imp->_hintInputEdge->setInputNumber( edge->getInputNumber() );
                _imp->_hintInputEdge->setSourceAndDestination( selectedNode, edge->getDest() );
                _imp->_hintInputEdge->setVisible(true);
            }
        } else if ( _imp->_highLightedEdge && _imp->_hintInputEdge->isVisible() ) {
            _imp->_hintInputEdge->initLine();
        }
    } else if (nodeToShowMergeRect) {
        nodeToShowMergeRect->setMergeHintActive(true);
        selectedNode->setMergeHintActive(true);
        _imp->_mergeHintNode = nodeToShowMergeRect;
    } else {
        selectedNode->setMergeHintActive(false);
        _imp->_mergeHintNode.reset();
    }
} // NodeGraph::checkForHints
예제 #2
0
void
NodeAnimPrivate::computeGroupRange()
{

    NodeGuiPtr nodeUI = nodeGui.lock();
    NodePtr node = nodeUI->getNode();
    if (!node) {
        return;
    }

    AnimationModulePtr isAnimModel = toAnimationModule(model.lock());
    if (!isAnimModel) {
        return;
    }
    NodeGroupPtr nodegroup = node->isEffectNodeGroup();
    assert(nodegroup);
    if (!nodegroup) {
        return;
    }


    AnimationModuleTreeView* treeView = isAnimModel->getEditor()->getTreeView();

    NodesList nodes = nodegroup->getNodes();

    std::set<double> times;

    for (NodesList::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
        NodeAnimPtr childAnim = isAnimModel->findNodeAnim(*it);

        if (!childAnim) {
            continue;
        }

        if (!treeView->isItemVisibleRecursive(childAnim->getTreeItem())) {
            continue;
        }

        childAnim->refreshFrameRange();
        RangeD childRange = childAnim->getFrameRange();
        times.insert(childRange.min);
        times.insert(childRange.max);

        // Also check the child knobs keyframes
        NodeGuiPtr childGui = childAnim->getNodeGui();
        const KnobsVec &knobs = childGui->getNode()->getKnobs();

        for (KnobsVec::const_iterator it2 = knobs.begin(); it2 != knobs.end(); ++it2) {

            if ( !(*it2)->isAnimationEnabled() || !(*it2)->hasAnimation() ) {
                continue;
            } else {
                // For each dimension and for each split view get the first/last keyframe (if any)
                int nDims = (*it2)->getNDimensions();
                std::list<ViewIdx> views = (*it2)->getViewsList();
                for (std::list<ViewIdx>::const_iterator it3 = views.begin(); it3 != views.end(); ++it3) {
                    for (int i = 0; i < nDims; ++i) {
                        CurvePtr curve = (*it2)->getAnimationCurve(*it3, DimIdx(i));
                        if (!curve) {
                            continue;
                        }
                        int nKeys = curve->getKeyFramesCount();
                        if (nKeys > 0) {
                            KeyFrame k;
                            if (curve->getKeyFrameWithIndex(0, &k)) {
                                times.insert( k.getTime() );
                            }
                            if (curve->getKeyFrameWithIndex(nKeys - 1, &k)) {
                                times.insert( k.getTime() );
                            }
                        }
                    }
                }
            }
        } // for all knobs
    } // for all children nodes

    if (times.size() <= 1) {
        frameRange.min = 0;
        frameRange.max = 0;
    } else {
        frameRange.min = *times.begin();
        frameRange.max = *times.rbegin();
    }

} // computeGroupRange
예제 #3
0
void
NodeAnimPrivate::computeRetimeRange()
{
    NodeGuiPtr nodeUI = nodeGui.lock();
    NodePtr node = nodeUI->getNode();
    if (!node) {
        return;
    }
    NodePtr input = node->getInput(0);
    if (!input) {
        return;
    }
    if (input) {
        RangeD inputRange = {0, 0};
        {
            GetFrameRangeResultsPtr results;
            ActionRetCodeEnum stat = input->getEffectInstance()->getFrameRange_public(&results);
            if (!isFailureRetCode(stat)) {
                results->getFrameRangeResults(&inputRange);
            }
        }

        FramesNeededMap framesFirst, framesLast;
        {
            GetFramesNeededResultsPtr results;
            ActionRetCodeEnum stat = node->getEffectInstance()->getFramesNeeded_public(TimeValue(inputRange.min), ViewIdx(0), &results);
            if (!isFailureRetCode(stat)) {
                results->getFramesNeeded(&framesFirst);
            }

            stat = node->getEffectInstance()->getFramesNeeded_public(TimeValue(inputRange.max), ViewIdx(0), &results);
            if (!isFailureRetCode(stat)) {
                results->getFramesNeeded(&framesLast);
            }
        }
        assert( !framesFirst.empty() && !framesLast.empty() );
        if ( framesFirst.empty() || framesLast.empty() ) {
            return;
        }

        {
            const FrameRangesMap& rangeFirst = framesFirst[0];
            assert( !rangeFirst.empty() );
            if ( rangeFirst.empty() ) {
                return;
            }
            FrameRangesMap::const_iterator it = rangeFirst.find( ViewIdx(0) );
            assert( it != rangeFirst.end() );
            if ( it == rangeFirst.end() ) {
                return;
            }
            const std::vector<OfxRangeD>& frames = it->second;
            assert( !frames.empty() );
            if ( frames.empty() ) {
                return;
            }
            frameRange.min = (frames.front().min);
        }
        {
            FrameRangesMap& rangeLast = framesLast[0];
            assert( !rangeLast.empty() );
            if ( rangeLast.empty() ) {
                return;
            }
            FrameRangesMap::const_iterator it = rangeLast.find( ViewIdx(0) );
            assert( it != rangeLast.end() );
            if ( it == rangeLast.end() ) {
                return;
            }
            const std::vector<OfxRangeD>& frames = it->second;
            assert( !frames.empty() );
            if ( frames.empty() ) {
                return;
            }
            frameRange.max = (frames.front().min);
        }
    }

} // computeRetimeRange
예제 #4
0
NATRON_NAMESPACE_ENTER


ViewerTab::ViewerTab(const std::string& scriptName,
                     const std::list<NodeGuiPtr> & existingNodesContext,
                     const std::list<NodeGuiPtr>& activePluginsContext,
                     Gui* gui,
                     const NodeGuiPtr& node_ui,
                     QWidget* parent)
    : QWidget(parent)
    , PanelWidget(scriptName, this, gui)
    , _imp( new ViewerTabPrivate(this, node_ui) )
{
    ViewerNodePtr node = node_ui->getNode()->isEffectViewerNode();
    installEventFilter(this);
    setMouseTracking(true);
    NodePtr internalNode = node->getNode();
    QObject::connect( internalNode.get(), SIGNAL(scriptNameChanged(QString)), this, SLOT(onInternalNodeScriptNameChanged(QString)) );
    QObject::connect( internalNode.get(), SIGNAL(labelChanged(QString,QString)), this, SLOT(onInternalNodeLabelChanged(QString,QString)) );
    QObject::connect( node.get(), SIGNAL(internalViewerCreated()), this, SLOT(onInternalViewerCreated()));

    _imp->mainLayout = new QVBoxLayout(this);
    setLayout(_imp->mainLayout);
    _imp->mainLayout->setSpacing(0);
    _imp->mainLayout->setContentsMargins(0, 0, 0, 0);

    QFontMetrics fm(font(), 0);


    _imp->viewerContainer = new QWidget(this);
    _imp->viewerLayout = new QHBoxLayout(_imp->viewerContainer);
    _imp->viewerLayout->setContentsMargins(0, 0, 0, 0);
    _imp->viewerLayout->setSpacing(0);

    _imp->viewerSubContainer = new QWidget(_imp->viewerContainer);
    _imp->viewerSubContainerLayout = new QVBoxLayout(_imp->viewerSubContainer);
    _imp->viewerSubContainerLayout->setContentsMargins(0, 0, 0, 0);
    _imp->viewerSubContainerLayout->setSpacing(1);


    // Info bars
    QString inputNames[2] = {
        QString::fromUtf8("A:"), QString::fromUtf8("B:")
    };

    bool infobarvisible = node->isInfoBarVisible();
    for (int i = 0; i < 2; ++i) {
        _imp->infoWidget[i] = new InfoViewerWidget(inputNames[i], this);

    }

    // Viewer
    _imp->viewer = new ViewerGL(this);

    GuiAppInstancePtr app = gui->getApp();

    // Init viewer to project format
    {
        Format projectFormat;
        app->getProject()->getProjectDefaultFormat(&projectFormat);

        RectD canonicalFormat = projectFormat.toCanonicalFormat();
        for (int i = 0; i < 2; ++i) {
            _imp->viewer->setInfoViewer(_imp->infoWidget[i], i);
            _imp->viewer->setRegionOfDefinition(canonicalFormat, projectFormat.getPixelAspectRatio(), i);
            setInfoBarAndViewerResolution(projectFormat, canonicalFormat, projectFormat.getPixelAspectRatio(), i);
        }
        _imp->viewer->resetWipeControls();
    }

    _imp->viewerSubContainerLayout->addWidget(_imp->viewer);
    for (int i = 0; i < 2; ++i) {
        _imp->viewerSubContainerLayout->addWidget(_imp->infoWidget[i]);
        _imp->viewer->setInfoViewer(_imp->infoWidget[i], i);
        if (i == 1 || !infobarvisible) {
            _imp->infoWidget[i]->hide();
        }
    }

    manageSlotsForInfoWidget(0, true);


    _imp->viewerLayout->addWidget(_imp->viewerSubContainer);
    _imp->mainLayout->addWidget(_imp->viewerContainer);

    TimeLinePtr timeline = app->getTimeLine();
    _imp->timeLineGui = new TimeLineGui(node, timeline, getGui(), this);
    QObject::connect( _imp->timeLineGui, SIGNAL(boundariesChanged(SequenceTime,SequenceTime)),
                      this, SLOT(onTimelineBoundariesChanged(SequenceTime,SequenceTime)) );
    QObject::connect( app->getProject().get(), SIGNAL(frameRangeChanged(int,int)), _imp->timeLineGui, SLOT(onProjectFrameRangeChanged(int,int)) );
    _imp->timeLineGui->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);

    if (!node->isTimelineVisible()) {
        _imp->timeLineGui->hide();
    }

    //Add some spacing because the timeline might be black as the info
    _imp->mainLayout->addSpacing( TO_DPIY(5) );
    _imp->mainLayout->addWidget(_imp->timeLineGui);

    double leftBound, rightBound;
    leftBound = node->getPlaybackInPointKnob()->getValue();
    rightBound = node->getPlaybackOutPointKnob()->getValue();

    TimeValue projectLeft, projectRight;
    app->getProject()->getFrameRange(&projectLeft, &projectRight);

    _imp->timeLineGui->setBoundaries(leftBound, rightBound);
    onTimelineBoundariesChanged(leftBound, rightBound);
    _imp->timeLineGui->setFrameRangeEdited(projectLeft != leftBound || projectRight != rightBound);;


    manageTimelineSlot(false, timeline);

    QObject::connect( node.get(), SIGNAL(renderStatsAvailable(int,double,RenderStatsMap)),
                      this, SLOT(onRenderStatsAvailable(int,double,RenderStatsMap)) );
    QObject::connect( _imp->viewer, SIGNAL(zoomChanged(int)), this, SLOT(updateZoomComboBox(int)) );
    QObject::connect( node.get(), SIGNAL(viewerDisconnected()), this, SLOT(disconnectViewer()) );


    createNodeViewerInterface(node_ui);
    setPluginViewerInterface(node_ui);
    
    for (std::list<NodeGuiPtr>::const_iterator it = existingNodesContext.begin(); it != existingNodesContext.end(); ++it) {
        ViewerNodePtr isViewerNode = (*it)->getNode()->isEffectViewerNode();
        // For viewers, create the viewer interface separately
        if (!isViewerNode) {
            createNodeViewerInterface(*it);
        }
    }
    for (std::list<NodeGuiPtr>::const_iterator it = activePluginsContext.begin(); it != activePluginsContext.end(); ++it) {
        ViewerNodePtr isViewerNode = (*it)->getNode()->isEffectViewerNode();
        // For viewers, create the viewer interface separately
        if (!isViewerNode) {
            setPluginViewerInterface(*it);
        }
    }


    setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);

    _imp->viewerNode.lock()->setUiContext( getViewer() );

    QTimer::singleShot( 25, _imp->timeLineGui, SLOT(recenterOnBounds()) );


    //Refresh the viewport lock state
    const std::list<ViewerTab*>& viewers = getGui()->getViewersList();
    if ( !viewers.empty() ) {
        ViewerTab* other = viewers.front();
        if ( other->getInternalNode()->isViewersSynchroEnabled() ) {
            double left, bottom, factor, par;
            other->getViewer()->getProjection(&left, &bottom, &factor, &par);
            _imp->viewer->setProjection(left, bottom, factor, par);
            node->setViewersSynchroEnabled(true);
        }
    }

    _imp->cachedFramesThread.reset(new CachedFramesThread(this));
    _imp->cachedFramesThread->start();
}
예제 #5
0
void
ProjectGuiSerialization::initialize(const ProjectGui* projectGui)
{
    NodesList activeNodes;

    projectGui->getInternalProject()->getActiveNodesExpandGroups(&activeNodes);

    _serializedNodes.clear();
    for (NodesList::iterator it = activeNodes.begin(); it != activeNodes.end(); ++it) {
        NodeGuiIPtr nodegui_i = (*it)->getNodeGui();
        if (!nodegui_i) {
            continue;
        }
        NodeGuiPtr nodegui = boost::dynamic_pointer_cast<NodeGui>(nodegui_i);

        if ( nodegui->isVisible() ) {
            NodeCollectionPtr isInCollection = (*it)->getGroup();
            NodeGroupPtr isCollectionAGroup = toNodeGroup( isInCollection );
            if (!isCollectionAGroup) {
                ///Nodes within a group will be serialized recursively in the node group serialization
                NodeGuiSerialization state;
                nodegui->serialize(&state);
                _serializedNodes.push_back(state);
            }
            ViewerInstancePtr viewer = (*it)->isEffectViewerInstance();
            if (viewer) {
                ViewerTab* tab = projectGui->getGui()->getViewerTabForInstance(viewer);
                assert(tab);
                ViewerData viewerData;
                double zoompar;
                tab->getViewer()->getProjection(&viewerData.zoomLeft, &viewerData.zoomBottom, &viewerData.zoomFactor, &zoompar);
                viewerData.userRoI = tab->getViewer()->getUserRegionOfInterest();
                viewerData.userRoIenabled = tab->getViewer()->isUserRegionOfInterestEnabled();
                viewerData.isClippedToProject = tab->isClippedToProject();
                viewerData.autoContrastEnabled = tab->isAutoContrastEnabled();
                viewerData.gain = tab->getGain();
                viewerData.gamma = tab->getGamma();
                viewerData.colorSpace = tab->getColorSpace();
                viewerData.channels = tab->getChannelsString();
                viewerData.renderScaleActivated = tab->getRenderScaleActivated();
                viewerData.mipMapLevel = tab->getMipMapLevel();
                viewerData.zoomOrPanSinceLastFit = tab->getZoomOrPannedSinceLastFit();
                viewerData.wipeCompositingOp = (int)tab->getCompositingOperator();
                viewerData.leftToolbarVisible = tab->isLeftToolbarVisible();
                viewerData.rightToolbarVisible = tab->isRightToolbarVisible();
                viewerData.topToolbarVisible = tab->isTopToolbarVisible();
                viewerData.infobarVisible = tab->isInfobarVisible();
                viewerData.playerVisible = tab->isPlayerVisible();
                viewerData.timelineVisible = tab->isTimelineVisible();
                viewerData.checkerboardEnabled = tab->isCheckerboardEnabled();
                viewerData.isFullFrameProcessEnabled = tab->isFullFrameProcessingEnabled();
                viewerData.fps = tab->getDesiredFps();
                viewerData.fpsLocked = tab->isFPSLocked();
                viewerData.isPauseEnabled[0] = tab->isViewerPaused(0);
                viewerData.isPauseEnabled[1] = tab->isViewerPaused(1);
                viewerData.layerName = tab->getCurrentLayerName().toStdString();
                viewerData.alphaLayerName = tab->getCurrentAlphaLayerName().toStdString();
                tab->getTimelineBounds(&viewerData.leftBound, &viewerData.rightBound);
                tab->getActiveInputs(&viewerData.aChoice, &viewerData.bChoice);
                viewerData.version = VIEWER_DATA_SERIALIZATION_VERSION;
                _viewersData.insert( std::make_pair(viewer->getNode()->getScriptName_mt_safe(), viewerData) );
            }
        }
    }

    ///Init windows
    _layoutSerialization.initialize( projectGui->getGui() );

    ///save histograms
    std::list<Histogram*> histograms = projectGui->getGui()->getHistograms_mt_safe();
    for (std::list<Histogram*>::const_iterator it = histograms.begin(); it != histograms.end(); ++it) {
        _histograms.push_back( (*it)->objectName().toStdString() );
    }

    ///save opened panels by order

    std::list<DockablePanel*> panels = projectGui->getGui()->getVisiblePanels_mt_safe();
    for (std::list<DockablePanel*>::iterator it = panels.begin(); it != panels.end(); ++it) {
        if ( (*it)->isVisible() ) {
            KnobHolderPtr holder = (*it)->getHolder();
            assert(holder);

            EffectInstancePtr isEffect = toEffectInstance(holder);
            ProjectPtr isProj = toProject(holder);

            if (isProj) {
                _openedPanelsOrdered.push_back(kNatronProjectSettingsPanelSerializationName);
            } else if (isEffect) {
                _openedPanelsOrdered.push_back( isEffect->getNode()->getFullyQualifiedName() );
            }
        }
    }

    _scriptEditorInput = projectGui->getGui()->getScriptEditor()->getAutoSavedScript().toStdString();

    std::map<NATRON_PYTHON_NAMESPACE::PyPanel*, std::string> pythonPanels = projectGui->getGui()->getPythonPanels();
    for (std::map<NATRON_PYTHON_NAMESPACE::PyPanel*, std::string>::iterator it = pythonPanels.begin(); it != pythonPanels.end(); ++it) {
        boost::shared_ptr<PythonPanelSerialization> s(new PythonPanelSerialization);
        s->initialize(it->first, it->second);
        _pythonPanels.push_back(s);
    }
} // initialize
예제 #6
0
void
NodeGraph::connectCurrentViewerToSelection(int inputNB)
{
    ViewerTab* lastUsedViewer =  getLastSelectedViewer();
    
    if (lastUsedViewer) {
        boost::shared_ptr<NodeCollection> collection = lastUsedViewer->getInternalNode()->getNode()->getGroup();
        if (collection && collection->getNodeGraph() != this) {
            //somehow the group doesn't belong to this nodegraph , pick another one
            const std::list<ViewerTab*>& tabs = getGui()->getViewersList();
            lastUsedViewer = 0;
            for (std::list<ViewerTab*>::const_iterator it = tabs.begin(); it!=tabs.end(); ++it) {
                
                boost::shared_ptr<NodeCollection> otherCollection = (*it)->getInternalNode()->getNode()->getGroup();
                if (otherCollection && otherCollection->getNodeGraph() == this) {
                    lastUsedViewer = *it;
                    break;
                }
            }
        }
    }
    
    
    boost::shared_ptr<InspectorNode> v;
    if ( lastUsedViewer ) {
        v = boost::dynamic_pointer_cast<InspectorNode>( lastUsedViewer->
                                                       getInternalNode()->getNode() );
    } else {
        CreateNodeArgs args(QString::fromUtf8(PLUGINID_NATRON_VIEWER),
                       eCreateNodeReasonUserCreate,
                       getGroup());
        NodePtr viewerNode = getGui()->getApp()->createNode(args);
        
        if (!viewerNode) {
            return;
        }
        v = boost::dynamic_pointer_cast<InspectorNode>(viewerNode);
    }

    if (!v) {
        return;
    }
    
    ///if the node is no longer active (i.e: it was deleted by the user), don't do anything.
    if ( !v->isActivated() ) {
        return;
    }

    ///get a ptr to the NodeGui
    boost::shared_ptr<NodeGuiI> gui_i = v->getNodeGui();
    NodeGuiPtr gui = boost::dynamic_pointer_cast<NodeGui>(gui_i);
    assert(gui);

    ///if there's no selected node or the viewer is selected, then try refreshing that input nb if it is connected.
    bool viewerAlreadySelected = std::find(_imp->_selection.begin(),_imp->_selection.end(),gui) != _imp->_selection.end();
    if (_imp->_selection.empty() || (_imp->_selection.size() > 1) || viewerAlreadySelected) {
        v->setActiveInputAndRefresh(inputNB, false);
        gui->refreshEdges();

        return;
    }

    NodeGuiPtr selected = _imp->_selection.front();


    if ( !selected->getNode()->canOthersConnectToThisNode() ) {
        return;
    }

    ///if the node doesn't have the input 'inputNb' created yet, populate enough input
    ///so it can be created.
    Edge* foundInput = gui->getInputArrow(inputNB);
    assert(foundInput);
  
    ///and push a connect command to the selected node.
    pushUndoCommand( new ConnectCommand(this,foundInput,foundInput->getSource(),selected) );

    ///Set the viewer as the selected node (also wipe the current selection)
    selectNode(gui,false);
} // connectCurrentViewerToSelection