示例#1
0
void
KnobGuiColor::onDimensionsMadeVisible(bool visible)
{
    KnobColorPtr knob = _knob.lock();
    if (!knob) {
        return;
    }
    int nDims = knob->getNDimensions();

    QColor colors[4];
    colors[0].setRgbF(0.851643, 0.196936, 0.196936);
    colors[1].setRgbF(0, 0.654707, 0);
    colors[2].setRgbF(0.345293, 0.345293, 1);
    colors[3].setRgbF(0.398979, 0.398979, 0.398979);


    for (int i = 0; i < nDims; ++i) {
        SpinBox* sb = 0;
        getSpinBox(DimIdx(i), &sb);
        assert(sb);
        if (!visible) {
            sb->setAdditionalDecorationTypeEnabled(LineEdit::eAdditionalDecorationColoredUnderlinedText, false);
        } else {
            sb->setAdditionalDecorationTypeEnabled(LineEdit::eAdditionalDecorationColoredUnderlinedText, true, colors[i]);
        }
    }


}
示例#2
0
void
KnobGuiColor::onDialogCurrentColorChanged(const QColor & color)
{
    KnobColorPtr knob = _knob.lock();
    bool isSimple = _useSimplifiedUI;
    int nDims = knob->getDimension();

    if (nDims == 1) {
        knob->setValue(color.redF(), ViewSpec::all(), 0);
    } else if (nDims == 3) {
        knob->setValues(isSimple ? color.redF() : Color::from_func_srgb( color.redF() ),
                        isSimple ? color.greenF() : Color::from_func_srgb( color.greenF() ),
                        isSimple ? color.blueF() : Color::from_func_srgb( color.blueF() ),
                        ViewSpec::all(),
                        eValueChangedReasonNatronInternalEdited);
    } else if (nDims == 4) {
        knob->setValues(isSimple ? color.redF() : Color::from_func_srgb( color.redF() ),
                        isSimple ? color.greenF() : Color::from_func_srgb( color.greenF() ),
                        isSimple ? color.blueF() : Color::from_func_srgb( color.blueF() ),
                        color.alphaF(),
                        ViewSpec::all(),
                        eValueChangedReasonNatronInternalEdited);
    }
    if ( getGui() ) {
        getGui()->setDraftRenderEnabled(true);
    }
}
示例#3
0
KnobGuiColor::KnobGuiColor(const KnobGuiPtr& knobUI, ViewIdx view)
    : KnobGuiValue(knobUI, view)
    , _knob( toKnobColor(knobUI->getKnob()) )
    , _colorLabel(0)
    , _colorDialogButton(0)
    , _useSimplifiedUI(false)
    , _uiColorspaceLut(0)
    , _internalColorspaceLut(0)
{
    KnobColorPtr knob = _knob.lock();
    if (!knob) {
        return;
    }
    _useSimplifiedUI = knob && knob->isSimplified();
    if (!_useSimplifiedUI) {
        DimIdx singleDim;
        bool singleDimEnabled = knobUI->isSingleDimensionalEnabled(&singleDim);
        if (knobUI->getLayoutType() == KnobGui::eKnobLayoutTypeViewerUI && !singleDimEnabled) {
            _useSimplifiedUI = true;
        }
    }
    const std::string& uiName = knob->getUIColorspaceName();
    const std::string& internalName = knob->getInternalColorspaceName();
    _uiColorspaceLut = Color::LutManager::findLut(uiName);
    _internalColorspaceLut = Color::LutManager::findLut(internalName);
}
示例#4
0
void
KnobGuiColor::onDialogCurrentColorChanged(const QColor & color)
{
    KnobColorPtr knob = _knob.lock();
    bool isSimple = _useSimplifiedUI;
    int nDims = knob->getNDimensions();

    std::vector<double> values(nDims);
    values[0] = isSimple ? color.redF() : Color::from_func_srgb( color.redF() );


    if (nDims >= 3) {
        values[1] = isSimple ? color.greenF() : Color::from_func_srgb( color.greenF() );
        values[2] = isSimple ? color.blueF() : Color::from_func_srgb( color.blueF() );
        if (nDims == 4) {
            values[3] = color.alphaF();
        }
    }

    KnobGuiPtr knobUI = getKnobGui();
    knob->setValueAcrossDimensions(values, DimIdx(0), getView(), eValueChangedReasonUserEdited);
    if ( knobUI->getGui() ) {
        knobUI->getGui()->setDraftRenderEnabled(true);
    }
}
示例#5
0
void
KnobGuiColor::onDialogCurrentColorChanged(const QColor & color)
{
    KnobColorPtr knob = _knob.lock();
    if (!knob) {
        return;
    }
    int nDims = knob->getNDimensions();

    std::vector<double> values(nDims);
    values[0] = color.redF();
    convertFromUIToInternalColorspace(&values[0]);
    if (nDims > 1) {
        values[1] =  color.greenF();
        convertFromUIToInternalColorspace(&values[1]);
    }
    if (nDims > 2) {
        values[2] = color.blueF();
        convertFromUIToInternalColorspace(&values[2]);
    }
    if (nDims > 3) {
        values[3] = color.alphaF();
    }

    KnobGuiPtr knobUI = getKnobGui();
    knob->setValueAcrossDimensions(values, DimIdx(0), getView(), eValueChangedReasonUserEdited);
    if ( knobUI->getGui() ) {
        knobUI->getGui()->setDraftRenderEnabled(true);
    }
}
示例#6
0
void
KnobGuiColor::connectKnobSignalSlots()
{
    KnobColorPtr knob = _knob.lock();
    QObject::connect( this, SIGNAL(dimensionSwitchToggled(bool)), knob.get(), SLOT(onDimensionSwitchToggled(bool)) );
    QObject::connect( knob.get(), SIGNAL(mustActivateAllDimensions()), this, SLOT(onMustShowAllDimension()) );
    QObject::connect( knob.get(), SIGNAL(pickingEnabled(bool)), this, SLOT(setPickingEnabled(bool)) );
}
示例#7
0
void
KnobGuiColor::connectKnobSignalSlots()
{
    KnobColorPtr knob = _knob.lock();
    if (!knob) {
        return;
    }
    QObject::connect( knob.get(), SIGNAL(pickingEnabled(ViewSetSpec,bool)), this, SLOT(onInternalKnobPickingEnabled(ViewSetSpec,bool)) );
}
示例#8
0
void
KnobGuiColor::setPickingEnabledInternal(bool enabled)
{
    KnobColorPtr knob = _knob.lock();
    if ( knob->getHolder()->getApp() ) {
        if (enabled) {
            getKnobGui()->getGui()->registerNewColorPicker( knob, getView() );
        } else {
            getKnobGui()->getGui()->removeColorPicker( knob, getView() );
        }
    }
}
示例#9
0
void
KnobGuiColor::onColorLabelPickingEnabled(bool enabled)
{
    KnobColorPtr knob = _knob.lock();
    KnobGuiPtr knobUI = getKnobGui();
    if ( knob->getHolder()->getApp() ) {
        if (enabled) {
            knobUI->getGui()->registerNewColorPicker( _knob.lock(), getView() );
        } else {
            knobUI->getGui()->removeColorPicker( _knob.lock(), getView());
        }
    }
}
示例#10
0
void
KnobGuiColor::getIncrements(std::vector<double>* increments) const
{
    KnobColorPtr knob = _knob.lock();
    if (!knob) {
        return;
    }
    int nDims = knob->getNDimensions();

    increments->resize(nDims);
    for (int i = 0; i < nDims; ++i) {
        (*increments)[i] = 0.001;
    }
}
示例#11
0
void
KnobGuiColor::onDimensionsFolded()
{
    KnobColorPtr knob = _knob.lock();
    int nDims = knob->getDimension();

    for (int i = 0; i < nDims; ++i) {
        SpinBox* sb = 0;
        getSpinBox(i, &sb);
        assert(sb);
        sb->setUseLineColor(false, Qt::red);
    }
    Q_EMIT dimensionSwitchToggled(false);
}
示例#12
0
void
KnobGuiColor::getDecimals(std::vector<int>* decimals) const
{
    KnobColorPtr knob = _knob.lock();
    if (!knob) {
        return;
    }
    int nDims = knob->getNDimensions();

    decimals->resize(nDims);
    for (int i = 0; i < nDims; ++i) {
        (*decimals)[i] = 6;
    }
}
示例#13
0
void
KnobGuiColor::onDimensionsExpanded()
{
    QColor colors[4];

    colors[0].setRgbF(0.851643, 0.196936, 0.196936);
    colors[1].setRgbF(0, 0.654707, 0);
    colors[2].setRgbF(0.345293, 0.345293, 1);
    colors[3].setRgbF(0.398979, 0.398979, 0.398979);

    KnobColorPtr knob = _knob.lock();
    int nDims = knob->getDimension();
    for (int i = 0; i < nDims; ++i) {
        SpinBox* sb = 0;
        Label* label = 0;
        getSpinBox(i, &sb, &label);
        assert(sb);
        sb->setUseLineColor(true, colors[i]);
    }
    Q_EMIT dimensionSwitchToggled(true);
}
示例#14
0
NATRON_NAMESPACE_ENTER


// those parameters should be ignored (they are always secret in Natron)
#define kOCIOParamInputSpace "ocioInputSpace"
#define kOCIOParamOutputSpace "ocioOutputSpace"

// those parameters should not have their options in the help file if generating markdown,
// because the options are dinamlically constructed at run-time from the OCIO config.
#define kOCIOParamInputSpaceChoice "ocioInputSpaceIndex"
#define kOCIOParamOutputSpaceChoice "ocioOutputSpaceIndex"

#define kOCIODisplayPluginIdentifier "fr.inria.openfx.OCIODisplay"
#define kOCIODisplayParamDisplay "display"
#define kOCIODisplayParamDisplayChoice "displayIndex"
#define kOCIODisplayParamView "view"
#define kOCIODisplayParamViewChoice "viewIndex"

// not yet implemented (see OCIOCDLTransform.cpp)
//#define kOCIOCDLTransformPluginIdentifier "fr.inria.openfx.OCIOCDLTransform"
//#define kOCIOCDLTransformParamCCCID "cccId"
//#define kOCIOCDLTransformParamCCCIDChoice "cccIdIndex"

#define kOCIOFileTransformPluginIdentifier "fr.inria.openfx.OCIOFileTransform"
#define kOCIOFileTransformParamCCCID "cccId"
#define kOCIOFileTransformParamCCCIDChoice "cccIdIndex"

// genHTML: true for live HTML output for the internal web-server, false for markdown output
QString
Node::makeDocumentation(bool genHTML) const
{
    QString ret;
    QString markdown;
    QTextStream ts(&ret);
    QTextStream ms(&markdown);

    QString pluginID, pluginLabel, pluginDescription, pluginIcon;
    int majorVersion = getMajorVersion();
    int minorVersion = getMinorVersion();
    std::vector<std::string> pluginGroup;
    bool pluginDescriptionIsMarkdown = false;
    QVector<QStringList> inputs;
    QVector<QStringList> items;

    {
        PluginPtr plugin = getPlugin();
        assert(plugin);

        pluginID = QString::fromUtf8(plugin->getPluginID().c_str());
        pluginLabel =  QString::fromUtf8( Plugin::makeLabelWithoutSuffix( plugin->getPluginLabel() ).c_str());
        pluginDescription =  QString::fromUtf8( plugin->getPropertyUnsafe<std::string>(kNatronPluginPropDescription).c_str() );
        pluginIcon = QString::fromUtf8(plugin->getPropertyUnsafe<std::string>(kNatronPluginPropIconFilePath).c_str());
        pluginGroup = plugin->getPropertyNUnsafe<std::string>(kNatronPluginPropGrouping);
        pluginDescriptionIsMarkdown = plugin->getPropertyUnsafe<bool>(kNatronPluginPropDescriptionIsMarkdown);


        for (int i = 0; i < _imp->effect->getNInputs(); ++i) {
            QStringList input;
            input << convertFromPlainTextToMarkdown( QString::fromStdString( getInputLabel(i) ), genHTML, true );
            input << convertFromPlainTextToMarkdown( QString::fromStdString( getInputHint(i) ), genHTML, true );
            input << ( isInputOptional(i) ? tr("Yes") : tr("No") );
            inputs.push_back(input);

            // Don't show more than doc for 4 inputs otherwise it will just clutter the page
            if (i == 3) {
                break;
            }
        }
    }

    // check for plugin icon
    QString pluginIconUrl;
    if ( !pluginIcon.isEmpty() ) {
        QFile iconFile(pluginIcon);
        if ( iconFile.exists() ) {
            if (genHTML) {
                pluginIconUrl.append( QString::fromUtf8("/LOCAL_FILE/") );
                pluginIconUrl.append(pluginIcon);
                pluginIconUrl.replace( QString::fromUtf8("\\"), QString::fromUtf8("/") );
            } else {
                pluginIconUrl.append(pluginID);
                pluginIconUrl.append(QString::fromUtf8(".png"));
            }
        }
    }

    // check for extra markdown file
    QString extraMarkdown;
    QString pluginMD = pluginIcon;
    pluginMD.replace( QString::fromUtf8(".png"), QString::fromUtf8(".md") );
    QFile pluginMarkdownFile(pluginMD);
    if ( pluginMarkdownFile.exists() ) {
        if ( pluginMarkdownFile.open(QIODevice::ReadOnly | QIODevice::Text) ) {
            extraMarkdown = QString::fromUtf8( pluginMarkdownFile.readAll() );
            pluginMarkdownFile.close();
        }
    }

    // generate knobs info
    KnobsVec knobs = getEffectInstance()->getKnobs_mt_safe();
    for (KnobsVec::const_iterator it = knobs.begin(); it != knobs.end(); ++it) {

#pragma message WARN("TODO: restore getDefaultIsSecret from RB-2.2")
        //if ( (*it)->getDefaultIsSecret() ) {
        if ( (*it)->getIsSecret() ) {
            continue;
        }

        if ((*it)->getKnobDeclarationType() != KnobI::eKnobDeclarationTypePlugin) {
            continue;
        }

        // do not escape characters in the scriptName, since it will be put between backquotes
        QString knobScriptName = /*NATRON_NAMESPACE::convertFromPlainTextToMarkdown(*/ QString::fromUtf8( (*it)->getName().c_str() )/*, genHTML, true)*/;
        QString knobLabel = NATRON_NAMESPACE::convertFromPlainTextToMarkdown( QString::fromUtf8( (*it)->getLabel().c_str() ), genHTML, true);
        QString knobHint = NATRON_NAMESPACE::convertFromPlainTextToMarkdown( QString::fromUtf8( (*it)->getHintToolTip().c_str() ), genHTML, true);

        // totally ignore the documentation for these parameters (which are always secret in Natron)
        if ( knobScriptName.startsWith( QString::fromUtf8("NatronOfxParam") ) ||
             knobScriptName == QString::fromUtf8("exportAsPyPlug") ||
             knobScriptName == QString::fromUtf8(kOCIOParamInputSpace) ||
             knobScriptName == QString::fromUtf8(kOCIOParamOutputSpace) ||
             ( ( pluginID == QString::fromUtf8(kOCIODisplayPluginIdentifier) ) &&
               ( knobScriptName == QString::fromUtf8(kOCIODisplayParamDisplay) ) ) ||
             ( ( pluginID == QString::fromUtf8(kOCIODisplayPluginIdentifier) ) &&
               ( knobScriptName == QString::fromUtf8(kOCIODisplayParamView) ) ) ||
             //( ( pluginID == QString::fromUtf8(kOCIOCDLTransformPluginIdentifier) ) &&
             //  ( knobScriptName == QString::fromUtf8(kOCIOCDLTransformParamCCCID) ) ) ||
             ( ( pluginID == QString::fromUtf8(kOCIOFileTransformPluginIdentifier) ) &&
               ( knobScriptName == QString::fromUtf8(kOCIOFileTransformParamCCCID) ) ) ||
             false) {
            continue;
        }

        QString defValuesStr, knobType;
        std::vector<std::pair<QString, QString> > dimsDefaultValueStr;
        KnobIntPtr isInt = toKnobInt(*it);
        KnobChoicePtr isChoice = toKnobChoice(*it);
        KnobBoolPtr isBool = toKnobBool(*it);
        KnobDoublePtr isDbl = toKnobDouble(*it);
        KnobStringPtr isString = toKnobString(*it);
        bool isLabel = isString && isString->isLabel();
        KnobSeparatorPtr isSep = toKnobSeparator(*it);
        KnobButtonPtr isBtn = toKnobButton(*it);
        KnobParametricPtr isParametric = toKnobParametric(*it);
        KnobGroupPtr isGroup = toKnobGroup(*it);
        KnobPagePtr isPage = toKnobPage(*it);
        KnobColorPtr isColor = toKnobColor(*it);

        if (isInt) {
            knobType = tr("Integer");
        } else if (isChoice) {
            knobType = tr("Choice");
        } else if (isBool) {
            knobType = tr("Boolean");
        } else if (isDbl) {
            knobType = tr("Double");
        } else if (isString) {
            if (isLabel) {
                knobType = tr("Label");
            } else {
                knobType = tr("String");
            }
        } else if (isSep) {
            knobType = tr("Separator");
        } else if (isBtn) {
            knobType = tr("Button");
        } else if (isParametric) {
            knobType = tr("Parametric");
        } else if (isGroup) {
            knobType = tr("Group");
        } else if (isPage) {
            knobType = tr("Page");
        } else if (isColor) {
            knobType = tr("Color");
        } else {
            knobType = tr("N/A");
        }

        if (!isGroup && !isPage) {
            for (int i = 0; i < (*it)->getNDimensions(); ++i) {
                QString valueStr;

                if (!isBtn && !isSep && !isParametric) {
                    // If this is a ChoiceParam and we are not generating live HTML doc,
                    // only add the list of entries and their halp if this node should not be
                    // ignored (eg. OCIO colorspace knobs).
                    if ( isChoice &&
                         (genHTML || !( knobScriptName == QString::fromUtf8(kOCIOParamInputSpaceChoice) ||
                                        knobScriptName == QString::fromUtf8(kOCIOParamOutputSpaceChoice) ||
                                        ( ( pluginID == QString::fromUtf8(kOCIODisplayPluginIdentifier) ) &&
                                          ( knobScriptName == QString::fromUtf8(kOCIODisplayParamDisplayChoice) ) ) ||
                                        ( ( pluginID == QString::fromUtf8(kOCIODisplayPluginIdentifier) ) &&
                                          ( knobScriptName == QString::fromUtf8(kOCIODisplayParamViewChoice) ) ) ||
                                        //( ( pluginID == QString::fromUtf8(kOCIOCDLTransformPluginIdentifier) ) &&
                                        //   ( knobScriptName == QString::fromUtf8(kOCIOCDLTransformParamCCCIDChoice) ) ) ||
                                        ( ( pluginID == QString::fromUtf8(kOCIOFileTransformPluginIdentifier) ) &&
                                          ( knobScriptName == QString::fromUtf8(kOCIOFileTransformParamCCCIDChoice) ) ) ||
                                        ( ( pluginID == QString::fromUtf8("net.fxarena.openfx.Text") ) &&
                                          ( knobScriptName == QString::fromUtf8("name") ) ) || // font family from Text plugin
                                        ( ( pluginID == QString::fromUtf8("net.fxarena.openfx.Polaroid") ) &&
                                          ( knobScriptName == QString::fromUtf8("font") ) ) || // font family from Polaroid plugin
                                        ( ( pluginID == QString::fromUtf8(PLUGINID_NATRON_PRECOMP) ) &&
                                          ( knobScriptName == QString::fromUtf8("writeNode") ) ) ||
                                        ( ( pluginID == QString::fromUtf8(PLUGINID_NATRON_ONEVIEW) ) &&
                                          ( knobScriptName == QString::fromUtf8("view") ) ) ) ) ) {
                        // see also KnobChoice::getHintToolTipFull()
                        int index = isChoice->getDefaultValue(DimIdx(i));
                        std::vector<ChoiceOption> entries = isChoice->getEntries();
                        if ( (index >= 0) && ( index < (int)entries.size() ) ) {
                            valueStr = QString::fromUtf8( entries[index].id.c_str() );
                        }
                        bool first = true;
                        for (size_t i = 0; i < entries.size(); i++) {
                            QString entryHelp = QString::fromUtf8( entries[i].tooltip.c_str() );
                            QString entry;
                            if (entries[i].id != entries[i].label) {
                                entry = QString::fromUtf8( "%1 (%2)" ).arg(QString::fromUtf8( entries[i].label.c_str() )).arg(QString::fromUtf8( entries[i].id.c_str() ));
                            } else {
                                entry = QString::fromUtf8( entries[i].label.c_str() );
                            }
                            if (!entry.isEmpty()) {
                                if (first) {
                                    // empty line before the option descriptions
                                    if (genHTML) {
                                        if ( !knobHint.isEmpty() ) {
                                            knobHint.append( QString::fromUtf8("<br />") );
                                        }
                                        knobHint.append( tr("Possible values:") + QString::fromUtf8("<br />") );
                                    } else {
                                        // we do a hack for multiline elements, because the markdown->rst conversion by pandoc doesn't use the line block syntax.
                                        // what we do here is put a supplementary dot at the beginning of each line, which is then converted to a pipe '|' in the
                                        // genStaticDocs.sh script by a simple sed command after converting to RsT
                                        if ( !knobHint.isEmpty() ) {
                                            if (!knobHint.startsWith( QString::fromUtf8(". ") )) {
                                                knobHint.prepend( QString::fromUtf8(". ") );
                                            }
                                            knobHint.append( QString::fromUtf8("\\\n") );
                                        }
                                        knobHint.append( QString::fromUtf8(". ") + tr("Possible values:") +  QString::fromUtf8("\\\n") );
                                    }
                                    first = false;
                                }
                                if (genHTML) {
                                    knobHint.append( QString::fromUtf8("<br />") );
                                } else {
                                    knobHint.append( QString::fromUtf8("\\\n") );
                                    // we do a hack for multiline elements, because the markdown->rst conversion by pandoc doesn't use the line block syntax.
                                    // what we do here is put a supplementary dot at the beginning of each line, which is then converted to a pipe '|' in the
                                    // genStaticDocs.sh script by a simple sed command after converting to RsT
                                    knobHint.append( QString::fromUtf8(". ") );
                                }
                                if (entryHelp.isEmpty()) {
                                    knobHint.append( QString::fromUtf8("**%1**").arg( convertFromPlainTextToMarkdown(entry, genHTML, true) ) );
                                } else {
                                    knobHint.append( QString::fromUtf8("**%1**: %2").arg( convertFromPlainTextToMarkdown(entry, genHTML, true) ).arg( convertFromPlainTextToMarkdown(entryHelp, genHTML, true) ) );
                                }
                            }
                        }
                    } else if (isInt) {
                        valueStr = QString::number( isInt->getDefaultValue( DimIdx(i) ) );
                    } else if (isDbl) {
                        valueStr = QString::number( isDbl->getDefaultValue( DimIdx(i) ) );
                    } else if (isBool) {
                        valueStr = isBool->getDefaultValue( DimIdx(i) ) ? tr("On") : tr("Off");
                    } else if (isString) {
                        valueStr = QString::fromUtf8( isString->getDefaultValue( DimIdx(i) ).c_str() );
                    } else if (isColor) {
                        valueStr = QString::number( isColor->getDefaultValue( DimIdx(i) ) );
                    }
                }

                dimsDefaultValueStr.push_back( std::make_pair(convertFromPlainTextToMarkdown( QString::fromUtf8( (*it)->getDimensionName( DimIdx(i) ).c_str() ), genHTML, true ),
                                                              convertFromPlainTextToMarkdown(valueStr, genHTML, true)) );
            }

            for (std::size_t i = 0; i < dimsDefaultValueStr.size(); ++i) {
                if ( !dimsDefaultValueStr[i].second.isEmpty() ) {
                    if (dimsDefaultValueStr.size() > 1) {
                        defValuesStr.append(dimsDefaultValueStr[i].first);
                        defValuesStr.append( QString::fromUtf8(": ") );
                    }
                    defValuesStr.append(dimsDefaultValueStr[i].second);
                    if (i < dimsDefaultValueStr.size() - 1) {
                        defValuesStr.append( QString::fromUtf8(" ") );
                    }
                }
            }
            if ( defValuesStr.isEmpty() ) {
                defValuesStr = tr("N/A");
            }
        }

        if (!isPage && !isSep && !isGroup && !isLabel) {
            QStringList row;
            row << knobLabel << knobScriptName << knobType << defValuesStr << knobHint;
            items.append(row);
        }
    } // for (KnobsVec::const_iterator it = knobs.begin(); it!=knobs.end(); ++it) {


    // generate plugin info
    ms << tr("%1 node").arg(pluginLabel) << "\n==========\n\n";

    // a hack to avoid repeating the documentation for the various merge plugins
    if ( pluginID.startsWith( QString::fromUtf8("net.sf.openfx.Merge") ) ) {
        std::string id = pluginID.toStdString();
        std::string op;
        if (id == PLUGINID_OFX_MERGE) {
            // do nothing
        } else if (id == "net.sf.openfx.MergeDifference") {
            op = "difference (a.k.a. absminus)";
        } else if (id == "net.sf.openfx.MergeIn") {
            op = "in";
        } else if (id == "net.sf.openfx.MergeMatte") {
            op = "matte";
        } else if (id == "net.sf.openfx.MergeMax") {
            op = "max";
        } else if (id == "net.sf.openfx.MergeMin") {
            op = "min";
        } else if (id == "net.sf.openfx.MergeMultiply") {
            op = "multiply";
        } else if (id == "net.sf.openfx.MergeOut") {
            op = "out";
        } else if (id == "net.sf.openfx.MergePlus") {
            op = "plus";
        } else if (id == "net.sf.openfx.MergeScreen") {
            op = "screen";
        }
        if ( !op.empty() ) {
            // we should use the custom link "[Merge node](|http::/plugins/" PLUGINID_OFX_MERGE ".html||rst::net.sf.openfx.MergePlugin|)"
            // but pandoc borks it
            ms << tr("The *%1* node is a convenience node identical to the %2, except that the operator is set to *%3* by default.")
            .arg(pluginLabel)
            .arg(genHTML ? QString::fromUtf8("<a href=\"" PLUGINID_OFX_MERGE ".html\">Merge node</a>") :
                 QString::fromUtf8(":ref:`" PLUGINID_OFX_MERGE "`")
                 //QString::fromUtf8("[Merge node](http::/plugins/" PLUGINID_OFX_MERGE ".html)")
                 )
            .arg( QString::fromUtf8( op.c_str() ) );
            goto OUTPUT;
        }

    }

    if (!pluginIconUrl.isEmpty()) {
        // add a nonbreaking space so that pandoc doesn't use the alt-text as a caption
        // http://pandoc.org/MANUAL.html#images
        ms << "![pluginIcon](" << pluginIconUrl << ")";
        if (!genHTML) {
            // specify image width for pandoc-generated printed doc
            // (for hoedown-generated HTML, this handled by the CSS using the alt=pluginIcon attribute)
            // see http://pandoc.org/MANUAL.html#images
            // note that only % units are understood both by pandox and sphinx
            ms << "{ width=10% }";
        }
        ms << "&nbsp;\n\n"; // &nbsp; required so that there is no legend when converted to rst by pandoc
    }
    ms << tr("*This documentation is for version %2.%3 of %1.*").arg(pluginLabel).arg(majorVersion).arg(minorVersion) << "\n\n";

    ms << "\n" << tr("Description") << "\n--------------------------------------------------------------------------------\n\n";

    if (!pluginDescriptionIsMarkdown) {
        if (genHTML) {
            pluginDescription = NATRON_NAMESPACE::convertFromPlainText(pluginDescription, NATRON_NAMESPACE::WhiteSpaceNormal);

            // replace URLs with links
            QRegExp re( QString::fromUtf8("((http|ftp|https)://([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?)") );
            pluginDescription.replace( re, QString::fromUtf8("<a href=\"\\1\">\\1</a>") );
        } else {
            pluginDescription = convertFromPlainTextToMarkdown(pluginDescription, genHTML, false);
        }
    }

    ms << pluginDescription << "\n";

    // create markdown table
    ms << "\n" << tr("Inputs") << "\n--------------------------------------------------------------------------------\n\n";
    ms << tr("Input") << " | " << tr("Description") << " | " << tr("Optional") << "\n";
    ms << "--- | --- | ---\n";
    if (inputs.size() > 0) {
        Q_FOREACH(const QStringList &input, inputs) {
            QString inputName = input.at(0);
            QString inputDesc = input.at(1);
            QString inputOpt = input.at(2);

            ms << inputName << " | " << inputDesc << " | " << inputOpt << "\n";
        }
示例#15
0
void
KnobGuiColor::showColorDialog()
{
    QColorDialog dialog( _colorLabel->parentWidget() );

    dialog.setOption(QColorDialog::DontUseNativeDialog);
    KnobColorPtr knob = _knob.lock();
    const int nDims = knob->getDimension();
    double curR = knob->getValue(0);

    _lastColor[0] = curR;
    double curG = curR;
    double curB = curR;
    double curA = 1.;
    if (nDims > 1) {
        curG = knob->getValue(1);
        _lastColor[1] =  curG;
        curB = knob->getValue(2);
        _lastColor[2] = curB;
    }
    if (nDims > 3) {
        dialog.setOption(QColorDialog::ShowAlphaChannel);
        curA = knob->getValue(3);
        _lastColor[3] = curA;
    }

    bool isSimple = _useSimplifiedUI;
    QColor curColor;
    curColor.setRgbF( Image::clamp<qreal>(isSimple ? curR : Color::to_func_srgb(curR), 0., 1.),
                      Image::clamp<qreal>(isSimple ? curG : Color::to_func_srgb(curG), 0., 1.),
                      Image::clamp<qreal>(isSimple ? curB : Color::to_func_srgb(curB), 0., 1.),
                      Image::clamp<qreal>(curA, 0., 1.) );
    dialog.setCurrentColor(curColor);
    QObject::connect( &dialog, SIGNAL(currentColorChanged(QColor)), this, SLOT(onDialogCurrentColorChanged(QColor)) );
    if ( !dialog.exec() ) {
        if (nDims == 3) {
            knob->setValues(_lastColor[0], _lastColor[1], _lastColor[2], ViewSpec::all(), eValueChangedReasonNatronGuiEdited);
        } else if (nDims == 4) {
            knob->setValues(_lastColor[0], _lastColor[1], _lastColor[2], _lastColor[3], ViewSpec::all(), eValueChangedReasonNatronGuiEdited);
        } else if (nDims == 1) {
            knob->setValue(_lastColor[0], ViewSpec::all(), 0, eValueChangedReasonNatronGuiEdited);
        }
    } else {
        QColor userColor = dialog.currentColor();
        std::vector<double> color(4);
        color[0] = isSimple ? userColor.redF() : Color::from_func_srgb( userColor.redF() );
        color[1] = isSimple ? userColor.greenF() : Color::from_func_srgb( userColor.greenF() );
        color[2] = isSimple ? userColor.blueF() : Color::from_func_srgb( userColor.blueF() );
        color[3] = userColor.alphaF();

        for (int i = 0; i < 3; ++i) {
            SpinBox* sb = 0;
            getSpinBox(i, &sb);
            assert(sb);
            sb->setValue(color[i]);
        }

        // Refresh the last value so that the undo command retrieves the value that was prior to opening the dialog
        if (nDims == 3) {
            knob->setValues(_lastColor[0], _lastColor[1], _lastColor[2], ViewSpec::all(), eValueChangedReasonUserEdited);
        } else if (nDims == 4) {
            knob->setValues(_lastColor[0], _lastColor[1], _lastColor[2], _lastColor[3], ViewSpec::all(), eValueChangedReasonUserEdited);
        } else if (nDims == 1) {
            knob->setValue(_lastColor[0], ViewSpec::all(), 0, eValueChangedReasonUserEdited);
        }

        onSpinBoxValueChanged();

    }

    if ( getGui() ) {
        getGui()->setDraftRenderEnabled(false);
    }
    //knob->evaluateValueChange(0, knob->getCurrentTime(), ViewIdx(0), eValueChangedReasonNatronGuiEdited);
} // showColorDialog
示例#16
0
ActionRetCodeEnum
RotoShapeRenderNode::render(const RenderActionArgs& args)
{

#if !defined(ROTO_SHAPE_RENDER_CPU_USES_CAIRO) && !defined(HAVE_OSMESA)
    getNode()->setPersistentMessage(eMessageTypeError, kNatronPersistentErrorGenericRenderMessage, tr("Roto requires either OSMesa (CONFIG += enable-osmesa) or Cairo (CONFIG += enable-cairo) in order to render on CPU").toStdString());
    return eActionStatusFailed;
#endif

#if !defined(ROTO_SHAPE_RENDER_CPU_USES_CAIRO)
    if (args.backendType == eRenderBackendTypeCPU) {
        getNode()->setPersistentMessage(eMessageTypeError, kNatronPersistentErrorGenericRenderMessage, tr("An OpenGL context is required to draw with the Roto node. This might be because you are trying to render an image too big for OpenGL.").toStdString());
        return eActionStatusFailed;
    }
#endif

    RenderScale combinedScale = EffectInstance::getCombinedScale(args.mipMapLevel, args.proxyScale);

    // Get the Roto item attached to this node. It will be a render-local clone of the original item.
    RotoDrawableItemPtr rotoItem = getAttachedRotoItem();
    assert(rotoItem);
    if (!rotoItem) {
        return eActionStatusFailed;
    }

    // To be thread-safe we can only operate on a render clone.
    assert(rotoItem->isRenderClone());

    // Is it a smear or regular solid render ?
    assert(_imp->renderType.lock());
    RotoShapeRenderTypeEnum type = (RotoShapeRenderTypeEnum)_imp->renderType.lock()->getValue();

    // We only support rendering Bezier or strokes
    RotoStrokeItemPtr isStroke = toRotoStrokeItem(rotoItem);
    BezierPtr isBezier = toBezier(rotoItem);

    // Get the real stroke (the one the user interacts with)
    RotoStrokeItemPtr nonRenderStroke = toRotoStrokeItem(getOriginalAttachedItem());

    if (type == eRotoShapeRenderTypeSmear && !isStroke) {
        return eActionStatusFailed;
    }

    // Check that the item is really activated... it should have been caught in isIdentity otherwise.
    assert(rotoItem->isActivated(args.time, args.view) && (!isBezier || ((isBezier->isCurveFinished(args.view) || isBezier->isOpenBezier()) && ( isBezier->getControlPointsCount(args.view) > 1 ))));

    const OSGLContextPtr& glContext = args.glContext;

    // There must be an OpenGL context bound when using OpenGL.
    if ((args.backendType == eRenderBackendTypeOpenGL || args.backendType == eRenderBackendTypeOSMesa) && !glContext) {
        getNode()->setPersistentMessage(eMessageTypeError, kNatronPersistentErrorGenericRenderMessage, tr("An OpenGL context is required to draw with the Roto node").toStdString());
        return eActionStatusFailed;
    }

    // This is the image plane where we render, we are not multiplane so we only render out one plane
    assert(args.outputPlanes.size() == 1);
    const std::pair<ImagePlaneDesc,ImagePtr>& outputPlane = args.outputPlanes.front();

    // True if this render was trigger because the user is painting (with a pen or mouse)
    bool isDuringPainting = isStroke && isStroke->isCurrentlyDrawing();

    // These variables are useful to pick the stroke drawing algorithm where it was at the previous draw step.
    double distNextIn = 0.;
    Point lastCenterIn = { INT_MIN, INT_MIN };
    int strokeStartPointIndex = 0;
    int strokeMultiIndex = 0;

    // For strokes and open-bezier evaluate them to get the points and their pressure
    // We also compute the bounding box of the item taking into account the motion blur
    if (isStroke) {
        strokeStartPointIndex = isStroke->getRenderCloneCurrentStrokeStartPointIndex();
        strokeMultiIndex = isStroke->getRenderCloneCurrentStrokeIndex();
        isStroke->getStrokeState(&lastCenterIn, &distNextIn);
    }

    // Ensure that the indices of the draw step are valid.
#ifdef DEBUG
    if (isDuringPainting && isStroke->getRenderCloneCurrentStrokeEndPointIndex() >= strokeStartPointIndex) {
        if (strokeStartPointIndex == 0) {
            assert((isStroke->getRenderCloneCurrentStrokeEndPointIndex() + 1) == isStroke->getNumControlPoints(0));
        } else {
            // +2 because we also add the last point of the previous draw step in the call to cloneIndexRange(), otherwise it would make holes in the drawing
            assert((isStroke->getRenderCloneCurrentStrokeEndPointIndex() + 2 - strokeStartPointIndex) == isStroke->getNumControlPoints(0));
        }
    }
#endif

    // Now we are good to start rendering

    // This is the state of the stroke aglorithm in output of this draw step
    double distToNextOut = 0.;
    Point lastCenterOut;

    // Retrieve the OpenGL context local data that were allocated in attachOpenGLContext
    RotoShapeRenderNodeOpenGLDataPtr glData;
    if (args.glContextData) {
        glData = boost::dynamic_pointer_cast<RotoShapeRenderNodeOpenGLData>(args.glContextData);
        assert(glData);
    }

    // Firs time we draw this clear the background since we are not going to render the full image with OpenGL.
    if (strokeStartPointIndex == 0 && strokeMultiIndex == 0) {
        outputPlane.second->fillBoundsZero();
    }

    bool clipToFormat = _imp->clipToFormatKnob.lock()->getValue();

    switch (type) {
        case eRotoShapeRenderTypeSolid: {

            // Account for motion-blur
            RangeD range;
            int divisions;
            rotoItem->getMotionBlurSettings(args.time, args.view, &range, &divisions);

            if (isDuringPainting) {
                // Do not use motion-blur when drawing.
                range.min = range.max = args.time;
                divisions = 1;
            }

#ifdef ROTO_SHAPE_RENDER_CPU_USES_CAIRO
            // When cairo is enabled, render with it for a CPU render
            if (args.backendType == eRenderBackendTypeCPU) {
                RotoShapeRenderCairo::renderMaskInternal_cairo(rotoItem, args.roi, outputPlane.first, args.time, args.view, range, divisions, combinedScale, isDuringPainting, distNextIn, lastCenterIn, outputPlane.second, &distToNextOut, &lastCenterOut);
                if (isDuringPainting && isStroke) {
                    nonRenderStroke->updateStrokeData(lastCenterOut, distToNextOut, isStroke->getRenderCloneCurrentStrokeEndPointIndex());
                }
            } else
#endif
            // Otherwise render with OpenGL or OSMesa
            if (args.backendType == eRenderBackendTypeOpenGL || args.backendType == eRenderBackendTypeOSMesa) {

                // Figure out the shape color
                ColorRgbaD shapeColor;
                {
                    const double t = args.time;
                    KnobColorPtr colorKnob = rotoItem->getColorKnob();
                    if (colorKnob) {
                        shapeColor.r = colorKnob->getValueAtTime(TimeValue(t), DimIdx(0), args.view);
                        shapeColor.g = colorKnob->getValueAtTime(TimeValue(t), DimIdx(1), args.view);
                        shapeColor.b = colorKnob->getValueAtTime(TimeValue(t), DimIdx(2), args.view);
                        shapeColor.a = colorKnob->getValueAtTime(TimeValue(t), DimIdx(3), args.view);
                    }
                }


                // Figure out the opacity
                double opacity = rotoItem->getOpacityKnob() ? rotoItem->getOpacityKnob()->getValueAtTime(args.time, DimIdx(0), args.view) : 1.;

                // For a stroke or an opened Bezier, use the generic stroke algorithm
                if ( isStroke || ( isBezier && (isBezier->isOpenBezier() || !isBezier->isFillEnabled()) ) ) {
                    const bool doBuildUp = !isStroke ? false : isStroke->getBuildupKnob()->getValueAtTime(args.time, DimIdx(0), args.view);
                    RotoShapeRenderGL::renderStroke_gl(glContext, glData, args.roi, outputPlane.second, isDuringPainting, distNextIn, lastCenterIn, rotoItem, doBuildUp, opacity, args.time, args.view, range, divisions, combinedScale, &distToNextOut, &lastCenterOut);

                    // Update the stroke algorithm in output
                    if (isDuringPainting && isStroke) {
                        nonRenderStroke->updateStrokeData(lastCenterOut, distToNextOut, isStroke->getRenderCloneCurrentStrokeEndPointIndex());
                    }
                } else {
                    // Render a Bezier
                    //qDebug() << QThread::currentThread() << this  << isBezier.get()<< "RoD while render:";
                    //isBezier->getBoundingBox(args.time, args.view).debug();
                    RotoShapeRenderGL::renderBezier_gl(glContext, glData,
                                                       args.roi,
                                                       isBezier, outputPlane.second, clipToFormat, opacity, args.time, args.view, range, divisions, combinedScale, GL_TEXTURE_2D);
                }
            } // useOpenGL
        }   break;
        case eRotoShapeRenderTypeSmear: {

            OSGLContextAttacherPtr contextAttacher;
            if (args.backendType == eRenderBackendTypeOSMesa && !glContext->isGPUContext()) {
                // When rendering smear with OSMesa we need to write to the full image bounds and not only the RoI, so re-attach the default framebuffer
                // with the image bounds
                Image::CPUData imageData;
                outputPlane.second->getCPUData(&imageData);

                contextAttacher = OSGLContextAttacher::create(glContext, imageData.bounds.width(), imageData.bounds.height(), imageData.bounds.width(), imageData.ptrs[0]);
            }

            // Ensure that initially everything in the background is the source image
            if (strokeStartPointIndex == 0 && strokeMultiIndex == 0) {

                GetImageOutArgs outArgs;
                GetImageInArgs inArgs(&args.mipMapLevel, &args.proxyScale, &args.roi, &args.backendType);
                inArgs.inputNb = 0;
                if (!getImagePlane(inArgs, &outArgs)) {
                    getNode()->setPersistentMessage(eMessageTypeError, kNatronPersistentErrorGenericRenderMessage, tr("Failed to fetch source image").toStdString());
                    return eActionStatusFailed;
                }

                ImagePtr bgImage = outArgs.image;


                if (args.backendType == eRenderBackendTypeCPU || glContext->isGPUContext()) {

                    // Copy the BG image to the output image
                    Image::CopyPixelsArgs cpyArgs;
                    cpyArgs.roi = outputPlane.second->getBounds();
                    outputPlane.second->copyPixels(*bgImage, cpyArgs);
                } else {

                    // With OSMesa we cannot re-use the existing output plane as source because mesa clears the framebuffer out upon the first draw
                    // after a binding.
                    // The only option is to draw in a tmp texture that will live for the whole stroke painting life

                    Image::InitStorageArgs initArgs;
                    initArgs.bounds = bgImage->getBounds();
                    initArgs.bitdepth = outputPlane.second->getBitDepth();
                    initArgs.storage = eStorageModeGLTex;
                    initArgs.glContext = glContext;
                    initArgs.textureTarget = GL_TEXTURE_2D;
                    _imp->osmesaSmearTmpTexture = Image::create(initArgs);
                    if (!_imp->osmesaSmearTmpTexture) {
                        return eActionStatusFailed;
                    }

                    // Make sure the texture is ready before rendering the smear
                    GL_CPU::Flush();
                    GL_CPU::Finish();
                }
            } else {
                if (args.backendType == eRenderBackendTypeOSMesa && !glContext->isGPUContext() && strokeStartPointIndex == 0) {
                    // Ensure the tmp texture has correct size
                    assert(_imp->osmesaSmearTmpTexture);
                    ActionRetCodeEnum stat = _imp->osmesaSmearTmpTexture->ensureBounds(outputPlane.second->getBounds(), args.mipMapLevel, std::vector<RectI>(), shared_from_this());
                    if (isFailureRetCode(stat)) {
                        return stat;
                    }
                }
            }

            bool renderedDot;
#ifdef ROTO_SHAPE_RENDER_CPU_USES_CAIRO
            // Render with cairo if we need to render on CPU
            if (args.backendType == eRenderBackendTypeCPU) {
                renderedDot = RotoShapeRenderCairo::renderSmear_cairo(args.time, args.view, combinedScale, isStroke, args.roi, outputPlane.second, distNextIn, lastCenterIn, &distToNextOut, &lastCenterOut);
            } else
#endif
            if (args.backendType == eRenderBackendTypeOpenGL || args.backendType == eRenderBackendTypeOSMesa) {

                // Render with OpenGL
                ImagePtr dstImage = glContext->isGPUContext() ? outputPlane.second : _imp->osmesaSmearTmpTexture;
                assert(dstImage);
                renderedDot = RotoShapeRenderGL::renderSmear_gl(glContext, glData, args.roi, dstImage, distNextIn, lastCenterIn, isStroke, 1., args.time, args.view, combinedScale, &distToNextOut, &lastCenterOut);
            }

            // Update the stroke algorithm in output
            if (isDuringPainting) {
                Q_UNUSED(renderedDot);
                nonRenderStroke->updateStrokeData(lastCenterOut, distToNextOut, isStroke->getRenderCloneCurrentStrokeEndPointIndex());
            }

        }   break;
    } // type



    return eActionStatusOK;

} // RotoShapeRenderNode::render
示例#17
0
void
KnobGuiColor::showColorDialog()
{
    QColorDialog dialog( _colorLabel->parentWidget() );

    dialog.setOption(QColorDialog::DontUseNativeDialog);
    KnobColorPtr knob = _knob.lock();
    if (!knob) {
        return;
    }
    const int nDims = knob->getNDimensions();
    ViewIdx view = getView();
    double curR = knob->getValue(DimIdx(0), view, false /*clampToMinmax*/);

    _lastColor.resize(nDims);
    _lastColor[0] = curR;
    double curG = curR;
    double curB = curR;
    double curA = 1.;
    if (nDims > 1) {
        curG = knob->getValue(DimIdx(1), view, false /*clampToMinmax*/);
        _lastColor[1] =  curG;
        curB = knob->getValue(DimIdx(2), view, false /*clampToMinmax*/);
        _lastColor[2] = curB;
    }
    if (nDims > 3) {
        dialog.setOption(QColorDialog::ShowAlphaChannel);
        curA = knob->getValue(DimIdx(3), view, false /*clampToMinmax*/);
        _lastColor[3] = curA;
    }

    convertFromInternalToUIColorspace(&curR, &curG, &curB);


    QColor curColor;
    curColor.setRgbF( Image::clamp<qreal>(curR, 0., 1.),
                      Image::clamp<qreal>(curG, 0., 1.),
                      Image::clamp<qreal>(curB, 0., 1.),
                      Image::clamp<qreal>(curA, 0., 1.) );
    dialog.setCurrentColor(curColor);
    QObject::connect( &dialog, SIGNAL(currentColorChanged(QColor)), this, SLOT(onDialogCurrentColorChanged(QColor)) );
    if ( !dialog.exec() ) {
        knob->setValueAcrossDimensions(_lastColor, DimIdx(0), view, eValueChangedReasonUserEdited);
    } else {
        QColor userColor = dialog.currentColor();
        std::vector<double> color(nDims);
        color[0] = userColor.redF();
        convertFromUIToInternalColorspace(&color[0]);
        if (nDims > 1) {
            color[1] =  userColor.greenF();
            convertFromUIToInternalColorspace(&color[1]);
        }
        if (nDims > 2) {
            color[2] = userColor.blueF();
            convertFromUIToInternalColorspace(&color[2]);
        }
        if (nDims > 3) {
            color[3] = userColor.alphaF();
        }



        for (int i = 0; i < 3; ++i) {
            SpinBox* sb = 0;
            getSpinBox(DimIdx(i), &sb);
            if (sb) {
                sb->setValue(color[i]);
            }
        }

        std::vector<double> oldColor(nDims);
        for (int i = 0; i < nDims; ++i) {
            oldColor[i] = _lastColor[i];
        }
        KnobGuiPtr knobUI = getKnobGui();
        knobUI->pushUndoCommand( new KnobUndoCommand<double>(knob, oldColor, color, getView()) );

    }
    KnobGuiPtr knobUI = getKnobGui();
    if ( knobUI->getGui() ) {
        knobUI->getGui()->setDraftRenderEnabled(false);
    }
} // showColorDialog