コード例 #1
0
ファイル: KnobGuiChoice.cpp プロジェクト: litlight/Natron
void
KnobGuiChoice::onItemNewSelected()
{
    NewLayerDialog dialog( ImageComponents::getNoneComponents(), getGui() );

    if ( dialog.exec() ) {
        ImageComponents comps = dialog.getComponents();
        if ( comps == ImageComponents::getNoneComponents() ) {
            Dialogs::errorDialog( tr("Layer").toStdString(), tr("A layer must contain at least 1 channel and channel names must be "
                                                                "Python compliant.").toStdString() );

            return;
        }
        KnobHolderPtr holder = _knob.lock()->getHolder();
        assert(holder);
        EffectInstancePtr effect = toEffectInstance(holder);
        assert(effect);
        if (effect) {
            assert( effect->getNode() );
            if ( !effect->getNode()->addUserComponents(comps) ) {
                Dialogs::errorDialog( tr("Layer").toStdString(), tr("A Layer with the same name already exists").toStdString() );
            }
        }
    }
}
コード例 #2
0
ファイル: TimeLine.cpp プロジェクト: ebrayton/Natron
void
TimeLine::seekFrame(SequenceTime frame,
                    bool updateLastCaller,
                    const EffectInstancePtr& caller,
                    TimelineChangeReasonEnum reason)
{
    if (reason != eTimelineChangeReasonPlaybackSeek) {
        Q_EMIT frameAboutToChange();
    }
    bool changed = false;
    {
        QMutexLocker l(&_lock);
        if (_currentFrame != frame) {
            _currentFrame = frame;
            changed = true;
        }
        _lastSeekReason = reason;
    }

    if (_project && updateLastCaller) {
        _project->getApp()->setLastViewerUsingTimeline( caller ? caller->getNode() : NodePtr() );
    }
    if (changed) {
        Q_EMIT frameChanged(frame, (int)reason);
    }
}
コード例 #3
0
ファイル: KnobUndoCommand.cpp プロジェクト: azerupi/Natron
MultipleKnobEditsUndoCommand::MultipleKnobEditsUndoCommand(const KnobIPtr& knob,
                                                           const QString& commandName,
                                                           ValueChangedReasonEnum reason,
                                                           ValueChangedReturnCodeEnum setValueRetCode,
                                                           bool createNew,
                                                           bool setKeyFrame,
                                                           const PerDimViewVariantMap& oldValue,
                                                           const Variant & newValue,
                                                           DimSpec dimension,
                                                           double time,
                                                           ViewSetSpec view)
    : QUndoCommand()
    , knobs()
    , createNew(createNew)
    , firstRedoCalled(false)
{
    assert(knob);
    std::list<ValueToSet>& vlist = knobs[knob];
    vlist.push_back(ValueToSet());

    // Add the new value to set to the list (which may be not empty)
    ValueToSet &v = vlist.back();
    v.newValue = newValue;
    v.dimension = dimension;
    assert(dimension != -1);

    if (!setKeyFrame) {
        // Ensure the time is correct in case auto-keying is on and we add a keyframe
        v.time = knob->getCurrentTime();
    } else {
        v.time = time;
    }
    v.setKeyFrame = setKeyFrame;
    v.view = view;
    v.setValueRetCode = setValueRetCode;
    v.reason = reason;
    v.oldValues = oldValue;

    KnobHolderPtr holder = knob->getHolder();
    EffectInstancePtr effect = toEffectInstance(holder);
    QString holderName;
    if (effect) {
        holderName = QString::fromUtf8( effect->getNode()->getLabel().c_str() );
    }

    // Set the command name in the Edit menu
    if (!commandName.isEmpty()) {
        setText(QString::fromUtf8("%1: ").arg(holderName) + commandName);
    } else {
        // If no command name passed, make up a generic command name
        setText( tr("%1: Multiple Parameters Edits").arg(holderName) );
    }
}
コード例 #4
0
ファイル: FrameViewRequest.cpp プロジェクト: ebrayton/Natron
    FrameViewRequestPrivate(const ImagePlaneDesc& plane,
                            unsigned int mipMapLevel,
                            const RenderScale& proxyScale,
                            const EffectInstancePtr& effect,
                            const TreeRenderPtr& render)
    : lock()
    , renderLock()
    , isDrescribed(false)
    , renderClone(effect)
    , parentRender(render)
    , plane(plane)
    , proxyScale(proxyScale)
    , mipMapLevel(mipMapLevel)
    , renderMappedMipMapLevel(mipMapLevel)
    , cachingPolicy(eCacheAccessModeReadWrite)
    , renderDevice(eRenderBackendTypeCPU)
    , renderDeviceSet(false)
    , fallbackRenderDevice(eRenderBackendTypeCPU)
    , fallbackRenderDeviceEnabled(false)
    , retCode(eActionStatusOK)
    , fullScaleImage()
    , requestedScaleImage()
    , finalRoi()
    , requestData()
    , status(FrameViewRequest::eFrameViewRequestStatusNotRendered)
    , frameViewsNeeded()
    , neededComps()
    , distortion()
    , distortionStack()
    , canonicalRoDs()
    , pixelRoDs()
    , byPassCache(false)
    {
#ifdef TRACE_REQUEST_LIFETIME
        nodeName = effect->getNode()->getScriptName_mt_safe();
        qDebug() << "Create request" << nodeName.c_str();
#endif
        if (effect->getCurrentRender()->isByPassCacheEnabled()) {
            byPassCache = true;
        }

        if (effect->getOpenGLRenderSupport() == ePluginOpenGLRenderSupportNeeded) {
            // The plug-in can only use GPU, so make the device fallback be GPU
            fallbackRenderDevice = eRenderBackendTypeOpenGL;
        }
    }
コード例 #5
0
ファイル: KnobGuiChoice.cpp プロジェクト: MrKepzie/Natron
QString
KnobGuiChoice::getPixmapPathFromFilePath(const KnobHolderPtr& holder, const QString& filePath)
{
    if ( QFile::exists(filePath) ) {
        return filePath;
    }

    QString customFilePath = filePath;

    EffectInstancePtr instance = toEffectInstance(holder);
    if (instance) {
        QString resourcesPath = QString::fromUtf8( instance->getNode()->getPluginResourcesPath().c_str() );
        if ( !resourcesPath.endsWith( QLatin1Char('/') ) ) {
            resourcesPath += QLatin1Char('/');
        }
        customFilePath.prepend(resourcesPath);
    }

    return customFilePath;
}
コード例 #6
0
ファイル: KnobGuiButton.cpp プロジェクト: kcotugno/Natron
QPixmap
KnobGuiButton::loadPixmapInternal(bool checked, bool applyColorOverlay, const QColor& overlayColor)
{
    KnobGuiPtr knobUI = getKnobGui();
    KnobButtonPtr knob = _knob.lock();
    EffectInstancePtr isEffect = toEffectInstance( knob->getHolder() );
    KnobTableItemPtr isTableItem = toKnobTableItem(knob->getHolder());
    if (isTableItem) {
        isEffect = isTableItem->getModel()->getNode()->getEffectInstance();
    }

    QString filePath;
    if (knobUI->getLayoutType() == KnobGui::eKnobLayoutTypeViewerUI) {
        filePath = QString::fromUtf8( knob->getInViewerContextIconFilePath(checked).c_str() );
    } else {
        filePath = QString::fromUtf8( knob->getIconLabel(checked).c_str() );
    }
    if ( !filePath.isEmpty() && !QFile::exists(filePath) ) {
        if (isEffect) {
            //Prepend the resources path
            QString resourcesPath = QString::fromUtf8( isEffect->getNode()->getPluginResourcesPath().c_str() );
            if ( !resourcesPath.endsWith( QLatin1Char('/') ) ) {
                resourcesPath += QLatin1Char('/');
            }
            filePath.prepend(resourcesPath);
        }
    }

    if ( !filePath.isEmpty() ) {
#if 0
        QPixmap pix;
        if (pix.load(filePath)) {
            return pix;
        }
#else
        QImage img;
        if ( img.load(filePath) ) {
            if (applyColorOverlay) {

                int depth = img.depth();
                if (depth != 32) {
                    img = img.convertToFormat(QImage::Format_ARGB32);
                }
                depth = img.depth();
                assert(depth == 32);
                for (int y = 0; y < img.height(); ++y) {
                    QRgb* pix = (QRgb*)img.scanLine(y);
                    for (int x = 0; x < img.width(); ++x) {
                        QRgb srcPix = pix[x];
                        double a = qAlpha(srcPix) / 255.f;
                        double r = qRed(srcPix) / 255.f * a;
                        double g = qGreen(srcPix) / 255.f * a;
                        double b = qBlue(srcPix) / 255.f * a;

                        r = Image::clamp(overFunctor(overlayColor.redF(), r, overlayColor.alphaF()), 0., 1.);
                        g = Image::clamp(overFunctor(overlayColor.greenF(), g, overlayColor.alphaF()), 0., 1.);
                        b = Image::clamp(overFunctor(overlayColor.blueF(), b, overlayColor.alphaF()), 0., 1.);
                        a = Image::clamp(overFunctor(overlayColor.alphaF(), a, overlayColor.alphaF()) * a, 0., 1.);

                        QRgb p = qRgba(r * 255, g * 255, b * 255, a * 255);
                        img.setPixel(x, y, p);
                    }
                }
            }
            QPixmap pix = QPixmap::fromImage(img);
            return pix;
        }
#endif
    }
    return QPixmap();
} // loadPixmapInternal
コード例 #7
0
void
moveGroupNode(DopeSheetEditor* model,
              const NodePtr& node,
              double dt)
{
    NodeGroupPtr group = node->isEffectNodeGroup();

    assert(group);
    NodesList nodes;
    group->getNodes_recursive(nodes, true);

    for (NodesList::iterator it = nodes.begin(); it != nodes.end(); ++it) {
        NodeGuiPtr nodeGui = boost::dynamic_pointer_cast<NodeGui>( (*it)->getNodeGui() );
        assert(nodeGui);
        std::string pluginID = (*it)->getPluginID();
        NodeGroupPtr isChildGroup = (*it)->isEffectNodeGroup();

        // Move readers
#ifndef NATRON_ENABLE_IO_META_NODES
        if ( ReadNode::isBundledReader( pluginID, node->getApp()->wasProjectCreatedWithLowerCaseIDs() ) ) {
#else
        if (pluginID == PLUGINID_NATRON_READ) {
#endif
            moveReader(*it, dt);
        } else if (pluginID == PLUGINID_OFX_TIMEOFFSET) {
            moveTimeOffset(*it, dt);
        } else if (pluginID == PLUGINID_OFX_FRAMERANGE) {
            moveFrameRange(*it, dt);
        } else if (isChildGroup) {
            moveGroupNode(model, *it, dt);
        }

        // Move keyframes
        const KnobsVec &knobs = (*it)->getKnobs();

        for (KnobsVec::const_iterator knobIt = knobs.begin(); knobIt != knobs.end(); ++knobIt) {
            const KnobIPtr& knob = *knobIt;
            if ( !knob->hasAnimation() ) {
                continue;
            }

            for (int dim = 0; dim < knob->getDimension(); ++dim) {
                if ( !knob->isAnimated( dim, ViewIdx(0) ) ) {
                    continue;
                }
                KeyFrameSet keyframes = knob->getCurve(ViewIdx(0), dim)->getKeyFrames_mt_safe();

                for (KeyFrameSet::iterator kfIt = keyframes.begin(); kfIt != keyframes.end(); ++kfIt) {
                    KeyFrame kf = (*kfIt);
                    KeyFrame fake;

                    knob->moveValueAtTime(eCurveChangeReasonDopeSheet, kf.getTime(), ViewSpec::all(), dim, dt, 0, &fake);
                }
            }
        }
    }
} // moveGroupNode

NATRON_NAMESPACE_ANONYMOUS_EXIT


////////////////////////// DSMoveKeysCommand //////////////////////////

DSMoveKeysAndNodesCommand::DSMoveKeysAndNodesCommand(const DSKeyPtrList &keys,
                                                     const std::vector<DSNodePtr >& nodes,
                                                     double dt,
                                                     DopeSheetEditor *model,
                                                     QUndoCommand *parent)
    : QUndoCommand(parent),
    _keys(keys),
    _nodes(),
    _dt(dt),
    _model(model)
{
    setText( tr("Move selected keys") );
    std::set<NodePtr > nodesSet;
    for (std::vector<DSNodePtr >::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
        DopeSheetItemType type = (*it)->getItemType();
        if ( (type != eDopeSheetItemTypeReader) &&
             ( type != eDopeSheetItemTypeGroup) &&
             ( type != eDopeSheetItemTypeTimeOffset) &&
             ( type != eDopeSheetItemTypeFrameRange) ) {
            //Note that Retime nodes cannot be moved
            continue;
        }
        _nodes.push_back(*it);
        nodesSet.insert( (*it)->getInternalNode() );
        NodeGroupPtr isGroup = (*it)->getInternalNode()->isEffectNodeGroup();
        if (isGroup) {
            NodesList recurseNodes;
            isGroup->getNodes_recursive(recurseNodes, true);
            for (NodesList::iterator it = recurseNodes.begin(); it != recurseNodes.end(); ++it) {
                nodesSet.insert(*it);
            }
        }
    }

    for (DSKeyPtrList::iterator it = _keys.begin(); it != _keys.end(); ++it) {
        KnobHolderPtr holder = (*it)->getContext()->getInternalKnob()->getHolder();
        assert(holder);
        EffectInstancePtr isEffect = toEffectInstance(holder);
        if (isEffect) {
            nodesSet.insert( isEffect->getNode() );
        }
    }

    for (std::set<NodePtr >::iterator it = nodesSet.begin(); it != nodesSet.end(); ++it) {
        _allDifferentNodes.push_back(*it);
    }
}

void
DSMoveKeysAndNodesCommand::undo()
{
    moveSelection(-_dt);
}
コード例 #8
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
コード例 #9
0
ファイル: KnobGuiChoice.cpp プロジェクト: MrKepzie/Natron
void
KnobGuiChoice::onEntriesPopulated()
{
    KnobChoicePtr knob = _knob.lock();
    if (!knob) {
        return;
    }

    _comboBox->clear();
    std::vector<ChoiceOption> entries = knob->getEntries();

    std::string pluginShortcutGroup;
    EffectInstancePtr isEffect = toEffectInstance(knob->getHolder());
    if (isEffect) {
        PluginPtr plugin = isEffect->getNode()->getOriginalPlugin();
        if (plugin) {
            pluginShortcutGroup = plugin->getPluginShortcutGroup();
        }
    }


    const std::map<int, std::string>& shortcutsMap = knob->getShortcuts();
    const std::map<int, std::string>& iconsMap = knob->getIcons();

    for (U32 i = 0; i < entries.size(); ++i) {

        std::string shortcutID;
        std::string iconFilePath;
        if (!pluginShortcutGroup.empty()) {
            std::map<int, std::string>::const_iterator foundShortcut = shortcutsMap.find(i);
            if (foundShortcut != shortcutsMap.end()) {
                shortcutID = foundShortcut->second;
            }
        }

        std::map<int, std::string>::const_iterator foundIcon = iconsMap.find(i);
        if (foundIcon != iconsMap.end()) {
            iconFilePath = foundIcon->second;
        }

        
        QIcon icon;
        if (!iconFilePath.empty()) {
            QPixmap pix( getPixmapPathFromFilePath( QString::fromUtf8( iconFilePath.c_str() ) ) );
            if (!pix.isNull()) {
                pix = pix.scaled(TO_DPIX(NATRON_MEDIUM_BUTTON_ICON_SIZE), TO_DPIY(NATRON_MEDIUM_BUTTON_ICON_SIZE));
                icon.addPixmap(pix);
            }
        }

        if (!shortcutID.empty() && !pluginShortcutGroup.empty() && !_comboBox->isCascading()) {
            QAction* action = new ActionWithShortcut(pluginShortcutGroup,
                                                     shortcutID,
                                                     entries[i].label,
                                                     _comboBox);
            if (!icon.isNull()) {
                action->setIcon(icon);
            }
            _comboBox->addAction(action);

        } else {
            _comboBox->addItem( QString::fromUtf8( entries[i].label.c_str() ), icon, QKeySequence(), QString::fromUtf8( entries[i].tooltip.c_str() ) );
            
        }
    } // for all entries

    const std::vector<int>& separators = knob->getSeparators();
    for (std::size_t i = 0; i < separators.size(); ++i) {
        _comboBox->insertSeparator(separators[i]);
    }

    // the "New" menu is only added to known parameters (e.g. the choice of output channels)
    if (knob->getNewOptionCallback()) {
        _comboBox->addItemNew();
    }

    updateGUI();

} // onEntriesPopulated
コード例 #10
0
ファイル: KnobUndoCommand.cpp プロジェクト: azerupi/Natron
std::string
PasteKnobClipBoardUndoCommand::makeLinkExpression(const std::vector<std::string>& projectViewNames,
                                                  const KnobIPtr& targetKnob,
                                                  bool multCurve,
                                                  const KnobIPtr& fromKnob,
                                                  DimSpec fromDimension,
                                                  ViewSetSpec fromView,
                                                  DimSpec targetDimension,
                                                  ViewSetSpec targetView)
{
    EffectInstancePtr fromEffect = toEffectInstance( fromKnob->getHolder() );
    EffectInstancePtr toEffect = toEffectInstance( targetKnob->getHolder() );
    assert(fromEffect && toEffect);
    if (!fromEffect || !toEffect) {
        return std::string();
    }

    std::stringstream ss;
    if (fromEffect == toEffect) {
        // Same node, use thisNode
        ss << "thisNode.";
    } else {
        // If the container of the effect is a group, prepend thisGroup, otherwise use
        // the canonical app prefix
        NodeGroupPtr isEffectContainerGroup;
        {
            NodeCollectionPtr effectContainer = fromEffect->getNode()->getGroup();
            isEffectContainerGroup = toNodeGroup(effectContainer);
        }
        if (isEffectContainerGroup) {
            ss << "thisGroup.";
        } else {
            ss << fromEffect->getApp()->getAppIDString() << ".";
        }
        ss << fromEffect->getNode()->getScriptName_mt_safe() << ".";
    }

    // Call getValue on the fromKnob
    ss << fromKnob->getName();
    ss << ".getValue(";
    if (fromKnob->getNDimensions() > 1) {
        if (fromDimension.isAll()) {
            ss << "dimension";
        } else {
            ss << fromDimension;
        }
    }
    std::list<ViewIdx> sourceViews = fromKnob->getViewsList();
    if (sourceViews.size() > 1) {
        ss << ", ";
        if (fromView.isAll()) {
            ss << "view";
        } else {
            if (fromView >= 0 && fromView < (int)projectViewNames.size()) {
                ss << projectViewNames[fromView];
            } else {
                ss << "Main";
            }
        }
    }
    ss << ")";

    // Also check if we need to multiply by the target knob's curve
    if (multCurve) {
        ss << " * curve(frame, ";
        if (targetDimension.isAll()) {
            ss << "dimension";
        } else {
            ss << targetDimension;
        }

        std::list<ViewIdx> targetKnobViews = targetKnob->getViewsList();
        if (targetKnobViews.size() > 1) {
            ss << ", ";
            if (targetView.isAll()) {
                ss << "view";
            } else {

                if (targetView >= 0 && targetView < (int)projectViewNames.size()) {
                    ss << projectViewNames[targetView];
                } else {
                    ss << "Main";
                }
            }
        }

        ss << ")";
    }
    return ss.str();
} // makeLinkExpression