void KnobGui::setInterpolationForDimensions(QAction* action, KeyframeTypeEnum interp) { if (!action) { return; } int dimension = action->data().toInt(); KnobPtr knob = getKnob(); for (int i = 0; i < knob->getDimension(); ++i) { if ( (dimension == -1) || (dimension == i) ) { boost::shared_ptr<Curve> c = knob->getCurve(ViewIdx(0), i); if (c) { int kfCount = c->getKeyFramesCount(); for (int j = 0; j < kfCount; ++j) { c->setKeyFrameInterpolation(interp, j); } boost::shared_ptr<Curve> guiCurve = getCurve(ViewIdx(0), i); if (guiCurve) { guiCurve->clone(*c); } } } } if ( knob->getHolder() ) { knob->getHolder()->incrHashAndEvaluate(knob->getEvaluateOnChange(), false); } Q_EMIT keyInterpolationChanged(); }
void SetExpressionCommand::redo() { KnobPtr knob = _knob.lock(); if (!knob) { return; } if (_dimension == -1) { for (int i = 0; i < knob->getDimension(); ++i) { try { knob->setExpression(i, _newExpr, _hasRetVar, false); } catch (...) { Dialogs::errorDialog( tr("Expression").toStdString(), tr("The expression is invalid.").toStdString() ); break; } } } else { try { knob->setExpression(_dimension, _newExpr, _hasRetVar, false); } catch (...) { Dialogs::errorDialog( tr("Expression").toStdString(), tr("The expression is invalid.").toStdString() ); } } knob->evaluateValueChange(_dimension == -1 ? 0 : _dimension, knob->getCurrentTime(), ViewIdx(0), eValueChangedReasonNatronGuiEdited); setText( tr("Set expression") ); }
void KnobGui::onRemoveAnimationActionTriggered() { QAction* action = qobject_cast<QAction*>( sender() ); assert(action); int dim = action->data().toInt(); KnobPtr knob = getKnob(); std::map<boost::shared_ptr<CurveGui>, std::vector<KeyFrame > > toRemove; KnobGuiPtr thisShared = shared_from_this(); for (int i = 0; i < knob->getDimension(); ++i) { if ( (dim == -1) || (dim == i) ) { std::list<boost::shared_ptr<CurveGui> > curves = getGui()->getCurveEditor()->findCurve(thisShared, i); for (std::list<boost::shared_ptr<CurveGui> >::iterator it = curves.begin(); it != curves.end(); ++it) { KeyFrameSet keys = (*it)->getInternalCurve()->getKeyFrames_mt_safe(); std::vector<KeyFrame > vect; for (KeyFrameSet::const_iterator it2 = keys.begin(); it2 != keys.end(); ++it2) { vect.push_back(*it2); } toRemove.insert( std::make_pair(*it, vect) ); } } } pushUndoCommand( new RemoveKeysCommand(getGui()->getCurveEditor()->getCurveWidget(), toRemove) ); //refresh the gui so it doesn't indicate the parameter is animated anymore updateGUI(dim); }
void KnobSerialization::restoreExpressions(const KnobPtr & knob, const std::map<std::string,std::string>& oldNewScriptNamesMapping) { int dims = std::min(knob->getDimension(), _knob->getDimension()); try { for (int i = 0; i < dims; ++i) { if (!_expressions[i].first.empty()) { QString expr(QString::fromUtf8(_expressions[i].first.c_str())); //Replace all occurrences of script-names that we know have changed for (std::map<std::string,std::string>::const_iterator it = oldNewScriptNamesMapping.begin(); it != oldNewScriptNamesMapping.end(); ++it) { expr.replace(QString::fromUtf8(it->first.c_str()), QString::fromUtf8(it->second.c_str())); } knob->restoreExpression(i, expr.toStdString(), _expressions[i].second); } } } catch (const std::exception& e) { QString err = QString::fromUtf8("Failed to restore expression on %1: %2").arg(QString::fromUtf8(knob->getName().c_str())).arg(QString::fromUtf8(e.what())); appPTR->writeToErrorLog_mt_safe(err); } }
void KnobGui::setAllKeyframeMarkersOnTimeline(int dimension) { KnobPtr knob = getKnob(); AppInstPtr app = knob->getHolder()->getApp(); assert(app); std::list<SequenceTime> times; if (dimension == -1) { int dim = knob->getDimension(); for (int i = 0; i < dim; ++i) { KeyFrameSet kfs = knob->getCurve(ViewIdx(0), i)->getKeyFrames_mt_safe(); for (KeyFrameSet::iterator it = kfs.begin(); it != kfs.end(); ++it) { times.push_back( it->getTime() ); } } } else { KeyFrameSet kfs = knob->getCurve(ViewIdx(0), dimension)->getKeyFrames_mt_safe(); for (KeyFrameSet::iterator it = kfs.begin(); it != kfs.end(); ++it) { times.push_back( it->getTime() ); } } app->addMultipleKeyframeIndicatorsAdded(times, true); }
void KnobGui::onRemoveKeyActionTriggered() { QAction* action = qobject_cast<QAction*>( sender() ); assert(action); int dim = action->data().toInt(); KnobPtr knob = getKnob(); assert( knob->getHolder()->getApp() ); //get the current time on the global timeline SequenceTime time = knob->getHolder()->getApp()->getTimeLine()->currentFrame(); std::map<boost::shared_ptr<CurveGui>, std::vector<KeyFrame > > toRemove; KnobGuiPtr thisShared = shared_from_this(); for (int i = 0; i < knob->getDimension(); ++i) { if ( (dim == -1) || (i == dim) ) { std::list<boost::shared_ptr<CurveGui> > curves = getGui()->getCurveEditor()->findCurve(thisShared, i); for (std::list<boost::shared_ptr<CurveGui> >::iterator it = curves.begin(); it != curves.end(); ++it) { KeyFrame kf; bool foundKey = knob->getCurve(ViewIdx(0), i)->getKeyFrameWithTime(time, &kf); if (foundKey) { std::vector<KeyFrame > vect; vect.push_back(kf); toRemove.insert( std::make_pair(*it, vect) ); } } } } pushUndoCommand( new RemoveKeysCommand(getGui()->getCurveEditor()->getCurveWidget(), toRemove) ); }
void KnobGui::onUnlinkActionTriggered() { QAction* action = qobject_cast<QAction*>( sender() ); if (!action) { return; } int dim = action->data().toInt(); KnobPtr thisKnob = getKnob(); int dims = thisKnob->getDimension(); KnobPtr aliasMaster = thisKnob->getAliasMaster(); if (aliasMaster) { thisKnob->setKnobAsAliasOfThis(aliasMaster, false); } else { thisKnob->beginChanges(); for (int i = 0; i < dims; ++i) { if ( (dim == -1) || (i == dim) ) { std::pair<int, KnobPtr > other = thisKnob->getMaster(i); thisKnob->onKnobUnSlaved(i); onKnobSlavedChanged(i, false); } } thisKnob->endChanges(); } getKnob()->getHolder()->getApp()->triggerAutoSave(); }
void KnobGui::onExprChanged(int dimension) { if (_imp->guiRemoved) { return; } KnobPtr knob = getKnob(); std::string exp = knob->getExpression(dimension); reflectExpressionState(dimension,!exp.empty()); if (exp.empty()) { reflectAnimationLevel(dimension, knob->getAnimationLevel(dimension)); } else { NodeSettingsPanel* isNodeSettings = dynamic_cast<NodeSettingsPanel*>(_imp->container); if (isNodeSettings) { NodeGuiPtr node = isNodeSettings->getNode(); if (node) { node->onKnobExpressionChanged(this); } } if (_imp->warningIndicator) { bool invalid = false; QString fullErrTooltip; int dims = knob->getDimension(); for (int i = 0; i < dims; ++i) { std::string err; if (!knob->isExpressionValid(i, &err)) { invalid = true; } if (dims > 1 && invalid) { fullErrTooltip += QString::fromUtf8("<p><b>"); fullErrTooltip += QString::fromUtf8(knob->getDimensionName(i).c_str()); fullErrTooltip += QString::fromUtf8("</b></p>"); } if (!err.empty()) { fullErrTooltip += QString::fromUtf8(err.c_str()); } } if (invalid) { QString toPrepend; toPrepend += QString::fromUtf8("<p>"); toPrepend += QObject::tr("Invalid expression(s), value returned is the underlying curve:"); toPrepend += QString::fromUtf8("</p>"); fullErrTooltip.prepend(toPrepend); setWarningValue(eKnobWarningExpressionInvalid, fullErrTooltip); } else { setWarningValue(eKnobWarningExpressionInvalid, QString()); } } onHelpChanged(); Q_EMIT expressionChanged(); } updateGUI(dimension); }
void KnobGui::pasteClipBoard(int targetDimension) { KnobPtr knob = getKnob(); if (!knob) { return; } //the dimension from which it was copied from int cbDim; KnobClipBoardType type; KnobPtr fromKnob; appPTR->getKnobClipBoard(&type, &fromKnob, &cbDim); if (!fromKnob) { return; } if (targetDimension == 0 && !getAllDimensionsVisible()) { targetDimension = -1; } if (!knob->isAnimationEnabled() && type == eKnobClipBoardTypeCopyAnim) { Dialogs::errorDialog(tr("Paste").toStdString(), tr("This parameter does not support animation").toStdString()); return; } if (!KnobI::areTypesCompatibleForSlave(fromKnob.get(),knob.get())) { Dialogs::errorDialog(tr("Paste").toStdString(), tr("You can only copy/paste between parameters of the same type. To overcome this, use an expression instead.").toStdString()); return; } if (cbDim != -1 && targetDimension == -1) { Dialogs::errorDialog(tr("Paste").toStdString(), tr("When copy/pasting on all dimensions, original and target parameters must have the same dimension.").toStdString()); return; } if ((targetDimension == -1 || cbDim == -1) && fromKnob->getDimension() != knob->getDimension()) { Dialogs::errorDialog(tr("Paste").toStdString(), tr("When copy/pasting on all dimensions, original and target parameters must have the same dimension.").toStdString()); return; } pushUndoCommand(new PasteUndoCommand(shared_from_this(),type, cbDim, targetDimension, fromKnob)); } // pasteClipBoard
void EditExpressionDialog::setTitle() { KnobPtr k = _knob->getKnob(); QString title( tr("Set expression on ") ); title.append( QString::fromUtf8( k->getName().c_str() ) ); if ( (_dimension != -1) && (k->getDimension() > 1) ) { title.append( QLatin1Char('.') ); title.append( QString::fromUtf8( k->getDimensionName(_dimension).c_str() ) ); } setWindowTitle(title); }
void KnobGui::onAnimationLevelChanged(ViewSpec /*idx*/, int dimension) { if (!_imp->customInteract) { KnobPtr knob = getKnob(); int dim = knob->getDimension(); for (int i = 0; i < dim; ++i) { if ( (i == dimension) || (dimension == -1) ) { reflectAnimationLevel( i, knob->getAnimationLevel(i) ); } } } }
void KnobGui::onSetKeyActionTriggered() { QAction* action = qobject_cast<QAction*>( sender() ); assert(action); int dim = action->data().toInt(); KnobPtr knob = getKnob(); assert( knob->getHolder()->getApp() ); //get the current time on the global timeline SequenceTime time = knob->getHolder()->getApp()->getTimeLine()->currentFrame(); AddKeysCommand::KeysToAddList toAdd; KnobGuiPtr thisShared = shared_from_this(); for (int i = 0; i < knob->getDimension(); ++i) { if ( (dim == -1) || (i == dim) ) { std::list<boost::shared_ptr<CurveGui> > curves = getGui()->getCurveEditor()->findCurve(thisShared, i); for (std::list<boost::shared_ptr<CurveGui> >::iterator it = curves.begin(); it != curves.end(); ++it) { AddKeysCommand::KeyToAdd keyToAdd; KeyFrame kf; kf.setTime(time); Knob<int>* isInt = dynamic_cast<Knob<int>*>( knob.get() ); Knob<bool>* isBool = dynamic_cast<Knob<bool>*>( knob.get() ); AnimatingKnobStringHelper* isString = dynamic_cast<AnimatingKnobStringHelper*>( knob.get() ); Knob<double>* isDouble = dynamic_cast<Knob<double>*>( knob.get() ); if (isInt) { kf.setValue( isInt->getValue(i) ); } else if (isBool) { kf.setValue( isBool->getValue(i) ); } else if (isDouble) { kf.setValue( isDouble->getValue(i) ); } else if (isString) { std::string v = isString->getValue(i); double dv; isString->stringToKeyFrameValue(time, ViewIdx(0), v, &dv); kf.setValue(dv); } keyToAdd.keyframes.push_back(kf); keyToAdd.curveUI = *it; keyToAdd.knobUI = thisShared; keyToAdd.dimension = i; toAdd.push_back(keyToAdd); } } } pushUndoCommand( new AddKeysCommand(getGui()->getCurveEditor()->getCurveWidget(), toAdd) ); }
void RestoreDefaultsCommand::undo() { assert( _clones.size() == _knobs.size() ); std::list<SequenceTime> times; KnobPtr first = _knobs.front().lock(); AppInstance* app = first->getHolder()->getApp(); assert(app); std::list<KnobWPtr >::const_iterator itClone = _clones.begin(); for (std::list<KnobWPtr >::const_iterator it = _knobs.begin(); it != _knobs.end(); ++it, ++itClone) { KnobPtr itKnob = it->lock(); if (!itKnob) { continue; } KnobPtr itCloneKnob = itClone->lock(); if (!itCloneKnob) { continue; } itKnob->cloneAndUpdateGui( itCloneKnob.get() ); if ( itKnob->getHolder()->getApp() ) { int dim = itKnob->getDimension(); for (int i = 0; i < dim; ++i) { if ( (i == _targetDim) || (_targetDim == -1) ) { boost::shared_ptr<Curve> c = itKnob->getCurve(ViewIdx(0), i); if (c) { KeyFrameSet kfs = c->getKeyFrames_mt_safe(); for (KeyFrameSet::iterator it = kfs.begin(); it != kfs.end(); ++it) { times.push_back( std::floor(it->getTime() + 0.5) ); } } } } } } app->addMultipleKeyframeIndicatorsAdded(times, true); first->getHolder()->incrHashAndEvaluate(true, true); if ( first->getHolder()->getApp() ) { first->getHolder()->getApp()->redrawAllViewers(); } setText( tr("Restore default value(s)") ); }
void KnobGui::onShowInCurveEditorActionTriggered() { KnobPtr knob = getKnob(); assert( knob->getHolder()->getApp() ); getGui()->setCurveEditorOnTop(); std::vector<boost::shared_ptr<Curve> > curves; for (int i = 0; i < knob->getDimension(); ++i) { boost::shared_ptr<Curve> c = getCurve(ViewIdx(0), i); if ( c->isAnimated() ) { curves.push_back(c); } } if ( !curves.empty() ) { getGui()->getCurveEditor()->centerOn(curves); } }
SetExpressionCommand::SetExpressionCommand(const KnobPtr & knob, bool hasRetVar, int dimension, const std::string& expr, QUndoCommand *parent) : QUndoCommand(parent) , _knob(knob) , _oldExprs() , _hadRetVar() , _newExpr(expr) , _hasRetVar(hasRetVar) , _dimension(dimension) { for (int i = 0; i < knob->getDimension(); ++i) { _oldExprs.push_back( knob->getExpression(i) ); _hadRetVar.push_back( knob->isExpressionUsingRetVariable(i) ); } }
void KnobGui::onFrozenChanged(bool frozen) { KnobPtr knob = getKnob(); KnobButton* isBtn = dynamic_cast<KnobButton*>(knob.get()); if (isBtn && !isBtn->isRenderButton()) { return; } int dims = knob->getDimension(); for (int i = 0; i < dims; ++i) { ///Do not unset read only if the knob is slaved in this dimension because we are still using it. if ( !frozen && knob->isSlave(i) ) { continue; } if (knob->isEnabled(i)) { setReadOnly_(frozen, i); } } }
KnobPtr MultipleKnobEditsUndoCommand::createCopyForKnob(const KnobPtr & originalKnob) { const std::string & typeName = originalKnob->typeName(); KnobPtr copy; int dimension = originalKnob->getDimension(); if ( typeName == KnobInt::typeNameStatic() ) { copy.reset( new KnobInt(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobBool::typeNameStatic() ) { copy.reset( new KnobBool(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobDouble::typeNameStatic() ) { copy.reset( new KnobDouble(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobChoice::typeNameStatic() ) { copy.reset( new KnobChoice(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobString::typeNameStatic() ) { copy.reset( new KnobString(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobParametric::typeNameStatic() ) { copy.reset( new KnobParametric(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobColor::typeNameStatic() ) { copy.reset( new KnobColor(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobPath::typeNameStatic() ) { copy.reset( new KnobPath(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobFile::typeNameStatic() ) { copy.reset( new KnobFile(NULL, std::string(), dimension, false) ); } else if ( typeName == KnobOutputFile::typeNameStatic() ) { copy.reset( new KnobOutputFile(NULL, std::string(), dimension, false) ); } ///If this is another type of knob this is wrong since they do not hold any value assert(copy); if (!copy) { return KnobPtr(); } copy->populate(); ///make a clone of the original knob at that time and stash it copy->clone(originalKnob); return copy; }
void KnobGui::removeAllKeyframeMarkersOnTimeline(int dimension) { KnobPtr knob = getKnob(); if ( knob->getHolder() && knob->getHolder()->getApp() && !knob->getIsSecret() && ( knob->isDeclaredByPlugin() || knob->isUserKnob() ) ) { AppInstPtr app = knob->getHolder()->getApp(); assert(app); std::list<SequenceTime> times; std::set<SequenceTime> tmpTimes; if (dimension == -1) { int dim = knob->getDimension(); for (int i = 0; i < dim; ++i) { boost::shared_ptr<Curve> curve = knob->getCurve(ViewIdx(0), i); if (curve) { KeyFrameSet kfs = curve->getKeyFrames_mt_safe(); for (KeyFrameSet::iterator it = kfs.begin(); it != kfs.end(); ++it) { tmpTimes.insert( it->getTime() ); } } } for (std::set<SequenceTime>::iterator it = tmpTimes.begin(); it != tmpTimes.end(); ++it) { times.push_back(*it); } } else { boost::shared_ptr<Curve> curve = knob->getCurve(ViewIdx(0), dimension); if (curve) { KeyFrameSet kfs = curve->getKeyFrames_mt_safe(); for (KeyFrameSet::iterator it = kfs.begin(); it != kfs.end(); ++it) { times.push_back( it->getTime() ); } } } if ( !times.empty() ) { app->removeMultipleKeyframeIndicator(times, true); } } }
void KnobGui::setEnabledSlot() { if ( !getGui() ) { return; } if (!_imp->customInteract) { setEnabled(); } KnobPtr knob = getKnob(); if (_imp->descriptionLabel) { _imp->descriptionLabel->setReadOnly( !knob->isEnabled(0) ); } KnobGuiPtr thisShared = shared_from_this(); if ( knob->getHolder() && knob->getHolder()->getApp() ) { for (int i = 0; i < knob->getDimension(); ++i) { if ( !knob->isEnabled(i) ) { getGui()->getCurveEditor()->hideCurve(thisShared, i); } else { getGui()->getCurveEditor()->showCurve(thisShared, i); } } } }
void KnobGui::linkTo(int dimension) { KnobPtr thisKnob = getKnob(); assert(thisKnob); EffectInstance* isEffect = dynamic_cast<EffectInstance*>( thisKnob->getHolder() ); if (!isEffect) { return; } for (int i = 0; i < thisKnob->getDimension(); ++i) { if ( (i == dimension) || (dimension == -1) ) { std::string expr = thisKnob->getExpression(dimension); if ( !expr.empty() ) { Dialogs::errorDialog( tr("Param Link").toStdString(), tr("This parameter already has an expression set, edit or clear it.").toStdString() ); return; } } } LinkToKnobDialog dialog( shared_from_this(), _imp->copyRightClickMenu->parentWidget() ); if ( dialog.exec() ) { KnobPtr otherKnob = dialog.getSelectedKnobs(); if (otherKnob) { if ( !thisKnob->isTypeCompatible(otherKnob) ) { Dialogs::errorDialog( tr("Param Link").toStdString(), tr("Types are incompatible!").toStdString() ); return; } for (int i = 0; i < thisKnob->getDimension(); ++i) { std::pair<int, KnobPtr > existingLink = thisKnob->getMaster(i); if (existingLink.second) { Dialogs::errorDialog( tr("Param Link").toStdString(), tr("Cannot link %1 because the knob is already linked to %2.") .arg( QString::fromUtf8( thisKnob->getLabel().c_str() ) ) .arg( QString::fromUtf8( existingLink.second->getLabel().c_str() ) ) .toStdString() ); return; } } EffectInstance* otherEffect = dynamic_cast<EffectInstance*>( otherKnob->getHolder() ); if (!otherEffect) { return; } std::stringstream expr; boost::shared_ptr<NodeCollection> thisCollection = isEffect->getNode()->getGroup(); NodeGroup* otherIsGroup = dynamic_cast<NodeGroup*>(otherEffect); if ( otherIsGroup == thisCollection.get() ) { expr << "thisGroup"; // make expression generic if possible } else { expr << otherEffect->getNode()->getFullyQualifiedName(); } expr << "." << otherKnob->getName() << ".get()"; if (otherKnob->getDimension() > 1) { expr << "[dimension]"; } thisKnob->beginChanges(); for (int i = 0; i < thisKnob->getDimension(); ++i) { if ( (i == dimension) || (dimension == -1) ) { thisKnob->setExpression(i, expr.str(), false, false); } } thisKnob->endChanges(); thisKnob->getHolder()->getApp()->triggerAutoSave(); } } } // KnobGui::linkTo
void KnobGuiValue::createWidget(QHBoxLayout* layout) { connectKnobSignalSlots(); _imp->container = new QWidget(layout->parentWidget()); QHBoxLayout *containerLayout = new QHBoxLayout(_imp->container); layout->addWidget(_imp->container); containerLayout->setContentsMargins(0, 0, 0, 0); containerLayout->setSpacing(3); if (getKnobsCountOnSameLine() > 1) { disableSlider(); } if (!isSliderDisabled()) { layout->parentWidget()->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); } KnobPtr knob = _imp->getKnob(); const int nDims = knob->getDimension(); std::vector<double> increments, displayMins, displayMaxs, mins, maxs; std::vector<int> decimals; boost::shared_ptr<Knob<double> > doubleKnob = _imp->getKnobAsDouble(); boost::shared_ptr<Knob<int> > intKnob = _imp->getKnobAsInt(); if (doubleKnob) { displayMins = doubleKnob->getDisplayMinimums(); displayMaxs = doubleKnob->getDisplayMaximums(); mins = doubleKnob->getMinimums(); maxs = doubleKnob->getMaximums(); } else { const std::vector<int>& intDmins = intKnob->getDisplayMinimums(); const std::vector<int>& intDMaxs = intKnob->getDisplayMaximums(); const std::vector<int>& intMins = intKnob->getMinimums(); const std::vector<int>& intMaxs = intKnob->getMaximums(); assert(intDMaxs.size() == intDmins.size() && intDmins.size() == intMins.size() && intMins.size() == intMaxs.size()); displayMins.resize(intDmins.size()); displayMaxs.resize(intDmins.size()); mins.resize(intDmins.size()); maxs.resize(intDmins.size()); for (std::size_t i = 0; i < intMins.size(); ++i) { displayMins[i] = intDmins[i]; displayMaxs[i] = intDMaxs[i]; mins[i] = intMins[i]; maxs[i] = intMaxs[i]; } } getIncrements(&increments); getDecimals(&decimals); std::vector<std::string> dimensionLabels(nDims); bool isRectangleParam = isRectangleType(); // This is a rectangle parameter if (isRectangleParam) { dimensionLabels[0] = "x"; dimensionLabels[1] = "y"; dimensionLabels[2] = "w"; dimensionLabels[3] = "h"; } else { for (int i = 0; i < nDims; ++i) { dimensionLabels[i] = knob->getDimensionName(i); } } KnobGuiPtr thisShared = shared_from_this(); SpinBox::SpinBoxTypeEnum type; if (doubleKnob) { type = SpinBox::eSpinBoxTypeDouble; } else { type = SpinBox::eSpinBoxTypeInt; } int nItemsPerRow = nDims; if (std::floor(nDims / 3. + 0.5) == nDims / 3.) { nItemsPerRow = 3; } if (std::floor(nDims / 4. + 0.5) == nDims / 4.) { nItemsPerRow = 4; } int nbRows = nDims / nItemsPerRow; assert(nbRows >= 1); QWidget* allSpinBoxesContainer = 0; QGridLayout* spinBoxesGrid = 0; if (nbRows == 1) { allSpinBoxesContainer = _imp->container; } else { allSpinBoxesContainer = new QWidget(_imp->container); spinBoxesGrid = new QGridLayout(allSpinBoxesContainer); spinBoxesGrid->setContentsMargins(0, 0, 0, 0); spinBoxesGrid->setVerticalSpacing(TO_DPIY(1)); spinBoxesGrid->setHorizontalSpacing(TO_DPIX(1)); } _imp->spinBoxes.resize(nDims); int rowIndex = 0; int columnIndex = 0; for (std::size_t i = 0; i < _imp->spinBoxes.size(); ++i) { QWidget *boxContainer = new QWidget(allSpinBoxesContainer); boxContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); QHBoxLayout *boxContainerLayout = 0; boxContainerLayout = new QHBoxLayout(boxContainer); boxContainerLayout->setContentsMargins(0, 0, 0, 0); boxContainerLayout->setSpacing(3); Label *subDesc = 0; if (nDims != 1 && nbRows == 1) { subDesc = new Label(QString::fromUtf8(dimensionLabels[i].c_str()), boxContainer); boxContainerLayout->addWidget(subDesc); } SpinBox *box = new KnobSpinBox(layout->parentWidget(), type, thisShared , i); NumericKnobValidator* validator = new NumericKnobValidator(box,thisShared); box->setValidator(validator); QObject::connect( box, SIGNAL(valueChanged(double)), this, SLOT(onSpinBoxValueChanged()) ); // Set the copy/link actions in the right click menu of the SpinBox enableRightClickMenu(box,i); #ifdef SPINBOX_TAKE_PLUGIN_RANGE_INTO_ACCOUNT double min = mins[i]; double max = maxs[i]; valueAccordingToType(false, i, &min); valueAccordingToType(false, i, &max); box->setMaximum(max); box->setMinimum(min); #endif if (type == SpinBox::eSpinBoxTypeDouble) { // Set the number of digits after the decimal point if (i < decimals.size()) { box->decimals(decimals[i]); } } if (i < increments.size()) { double incr = 1; incr = increments[i]; valueAccordingToType(false, i, &incr); box->setIncrement(incr); } boxContainerLayout->addWidget(box); if (!spinBoxesGrid) { containerLayout->addWidget(boxContainer); } else { spinBoxesGrid->addWidget(boxContainer, rowIndex, columnIndex); } _imp->spinBoxes[i] = std::make_pair(box, subDesc); ++columnIndex; if (columnIndex >= nItemsPerRow) { columnIndex = 0; ++rowIndex; } } if (spinBoxesGrid) { containerLayout->addWidget(allSpinBoxesContainer); } bool sliderVisible = false; if (!isSliderDisabled() && !isRectangleParam) { double dispmin = displayMins[0]; double dispmax = displayMaxs[0]; if (dispmin == -DBL_MAX) { dispmin = mins[0]; } if (dispmax == DBL_MAX) { dispmax = maxs[0]; } // denormalize if necessary double dispminGui = dispmin; double dispmaxGui = dispmax; valueAccordingToType(false, 0, &dispminGui); valueAccordingToType(false, 0, &dispmaxGui); bool spatial = isSpatialType(); Format f; if (spatial) { getKnob()->getHolder()->getApp()->getProject()->getProjectDefaultFormat(&f); } if (dispminGui < -SLIDER_MAX_RANGE) { if (spatial) { dispminGui = -f.width(); } else { dispminGui = -SLIDER_MAX_RANGE; } } if (dispmaxGui > SLIDER_MAX_RANGE) { if (spatial) { dispmaxGui = f.width(); } else { dispmaxGui = SLIDER_MAX_RANGE; } } double value0 = _imp->getKnobValue(0); ScaleSliderQWidget::DataTypeEnum sliderType; if (doubleKnob) { sliderType = ScaleSliderQWidget::eDataTypeDouble; } else { sliderType = ScaleSliderQWidget::eDataTypeInt; } _imp->slider = new ScaleSliderQWidget(dispminGui, dispmaxGui, value0,knob->getEvaluateOnChange(), sliderType,getGui(), eScaleTypeLinear, layout->parentWidget()); _imp->slider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); if (hasToolTip()) { _imp->slider->setToolTip( toolTip() ); } QObject::connect(_imp->slider, SIGNAL(positionChanged(double)), this, SLOT(onSliderValueChanged(double))); QObject::connect(_imp->slider, SIGNAL(editingFinished(bool)), this, SLOT(onSliderEditingFinished(bool))); containerLayout->addWidget(_imp->slider); sliderVisible = shouldSliderBeVisible(dispminGui, dispmaxGui); // onDisplayMinMaxChanged takes original (maybe normalized) values onDisplayMinMaxChanged(dispmin, dispmax); }
void RestoreDefaultsCommand::redo() { std::list<SequenceTime> times; KnobPtr first = _knobs.front().lock(); AppInstance* app = 0; KnobHolder* holder = first->getHolder(); EffectInstance* isEffect = dynamic_cast<EffectInstance*>(holder); if (holder) { app = holder->getApp(); holder->beginChanges(); } /* First reset all knobs values, this will not call instanceChanged action */ for (std::list<KnobWPtr >::iterator it = _knobs.begin(); it != _knobs.end(); ++it) { KnobPtr itKnob = it->lock(); if (!itKnob) { continue; } if ( itKnob->getHolder() && itKnob->getHolder()->getApp() ) { int dim = itKnob->getDimension(); for (int i = 0; i < dim; ++i) { if ( (i == _targetDim) || (_targetDim == -1) ) { boost::shared_ptr<Curve> c = itKnob->getCurve(ViewIdx(0), i); if (c) { KeyFrameSet kfs = c->getKeyFrames_mt_safe(); for (KeyFrameSet::iterator it = kfs.begin(); it != kfs.end(); ++it) { times.push_back( std::floor(it->getTime() + 0.5) ); } } } } } if ( itKnob->getHolder() ) { itKnob->getHolder()->beginChanges(); } itKnob->blockValueChanges(); for (int d = 0; d < itKnob->getDimension(); ++d) { itKnob->resetToDefaultValue(d); } itKnob->unblockValueChanges(); if ( itKnob->getHolder() ) { itKnob->getHolder()->endChanges(true); } } /* Block value changes and call instanceChange on all knobs afterwards to put back the plug-in in a correct state */ double time = 0; if (app) { time = app->getTimeLine()->currentFrame(); } for (std::list<KnobWPtr >::iterator it = _knobs.begin(); it != _knobs.end(); ++it) { KnobPtr itKnob = it->lock(); if (!itKnob) { continue; } if ( itKnob->getHolder() ) { itKnob->getHolder()->onKnobValueChanged_public(itKnob.get(), eValueChangedReasonRestoreDefault, time, ViewIdx(0), true); } } if (app) { app->removeMultipleKeyframeIndicator(times, true); } if ( holder && holder->getApp() ) { holder->endChanges(); } if (_isNodeReset && isEffect) { isEffect->purgeCaches(); } if ( first->getHolder() ) { first->getHolder()->incrHashAndEvaluate(true, true); if ( first->getHolder()->getApp() ) { first->getHolder()->getApp()->redrawAllViewers(); } } setText( tr("Restore default value(s)") ); } // RestoreDefaultsCommand::redo
void PasteUndoCommand::copyFrom(const KnobPtr& serializedKnob, bool isRedo) { KnobPtr internalKnob = _imp->knob.lock()->getKnob(); switch (_imp->type) { case eKnobClipBoardTypeCopyAnim: { internalKnob->beginChanges(); for (int i = 0; i < internalKnob->getDimension(); ++i) { if ( ( _imp->targetDimension == -1) || ( i == _imp->targetDimension) ) { boost::shared_ptr<Curve> fromCurve; if ( ( i == _imp->targetDimension) && ( _imp->fromDimension != -1) ) { fromCurve = serializedKnob->getCurve(ViewIdx(0), _imp->fromDimension); } else { fromCurve = serializedKnob->getCurve(ViewIdx(0), i); } if (!fromCurve) { continue; } internalKnob->cloneCurve(ViewIdx(0), i, *fromCurve); } } internalKnob->endChanges(); break; } case eKnobClipBoardTypeCopyValue: { Knob<int>* isInt = dynamic_cast<Knob<int>*>( internalKnob.get() ); Knob<bool>* isBool = dynamic_cast<Knob<bool>*>( internalKnob.get() ); Knob<double>* isDouble = dynamic_cast<Knob<double>*>( internalKnob.get() ); Knob<std::string>* isString = dynamic_cast<Knob<std::string>*>( internalKnob.get() ); Knob<int>* isFromInt = dynamic_cast<Knob<int>*>( serializedKnob.get() ); Knob<bool>* isFromBool = dynamic_cast<Knob<bool>*>( serializedKnob.get() ); Knob<double>* isFromDouble = dynamic_cast<Knob<double>*>( serializedKnob.get() ); Knob<std::string>* isFromString = dynamic_cast<Knob<std::string>*>( serializedKnob.get() ); internalKnob->beginChanges(); for (int i = 0; i < internalKnob->getDimension(); ++i) { if ( ( _imp->targetDimension == -1) || ( i == _imp->targetDimension) ) { if (isInt && isFromInt) { int f = (i == _imp->targetDimension && _imp->fromDimension != -1) ? isFromInt->getValue(_imp->fromDimension) : isFromInt->getValue(i); isInt->setValue(f, ViewIdx(0), i, eValueChangedReasonNatronInternalEdited, 0); } else if (isBool && isFromBool) { bool f = (i == _imp->targetDimension && _imp->fromDimension != -1) ? isFromBool->getValue(_imp->fromDimension) : isFromBool->getValue(i); isBool->setValue(f, ViewIdx(0), i, eValueChangedReasonNatronInternalEdited, 0); } else if (isDouble && isFromDouble) { double f = (i == _imp->targetDimension && _imp->fromDimension != -1) ? isFromDouble->getValue(_imp->fromDimension) : isFromDouble->getValue(i); isDouble->setValue(f, ViewIdx(0), i, eValueChangedReasonNatronInternalEdited, 0); } else if (isString && isFromString) { std::string f = (i == _imp->targetDimension && _imp->fromDimension != -1) ? isFromString->getValue(_imp->fromDimension) : isFromString->getValue(i); isString->setValue(f, ViewIdx(0), i, eValueChangedReasonNatronInternalEdited, 0); } } } internalKnob->endChanges(); break; } case eKnobClipBoardTypeCopyLink: { //bool useExpression = !KnobI::areTypesCompatibleForSlave(internalKnob.get(), serializedKnob.get()); internalKnob->beginChanges(); for (int i = 0; i < internalKnob->getDimension(); ++i) { if ( ( _imp->targetDimension == -1) || ( i == _imp->targetDimension) ) { if (isRedo) { if (_imp->fromDimension != -1) { internalKnob->slaveTo(i, serializedKnob, _imp->fromDimension); } else { internalKnob->slaveTo(i, serializedKnob, i); } } else { internalKnob->unSlave(i, false); } } } internalKnob->endChanges(); break; } } // switch } // redo
QString KnobGui::toolTip() const { KnobPtr knob = getKnob(); KnobChoice* isChoice = dynamic_cast<KnobChoice*>( knob.get() ); bool isMarkdown = knob.get()->isHintInMarkdown(); QString tt; QString realTt; if (isMarkdown) { tt = QString::fromUtf8( knob.get()->getName().c_str() ); tt.append( QString::fromUtf8("\n==========\n\n") ); } else { tt = getScriptNameHtml(); } if (!isChoice) { realTt.append( QString::fromUtf8( knob->getHintToolTip().c_str() ) ); } else { realTt.append( QString::fromUtf8( isChoice->getHintToolTipFull().c_str() ) ); } std::vector<std::string> expressions; bool exprAllSame = true; for (int i = 0; i < knob->getDimension(); ++i) { expressions.push_back( knob->getExpression(i) ); if ( (i > 0) && (expressions[i] != expressions[0]) ) { exprAllSame = false; } } QString exprTt; if (exprAllSame) { if ( !expressions[0].empty() ) { if (isMarkdown) { exprTt = QString::fromUtf8("ret = **%1**\n\n").arg( QString::fromUtf8( expressions[0].c_str() ) ); } else { exprTt = QString::fromUtf8("ret = <b>%1</b><br />").arg( QString::fromUtf8( expressions[0].c_str() ) ); } } } else { for (int i = 0; i < knob->getDimension(); ++i) { std::string dimName = knob->getDimensionName(i); QString toAppend; if (isMarkdown) { toAppend = QString::fromUtf8("%1 = **%2**\n\n").arg( QString::fromUtf8( dimName.c_str() ) ).arg( QString::fromUtf8( expressions[i].c_str() ) ); } else { toAppend = QString::fromUtf8("%1 = <b>%2</b><br />").arg( QString::fromUtf8( dimName.c_str() ) ).arg( QString::fromUtf8( expressions[i].c_str() ) ); } exprTt.append(toAppend); } } if ( !exprTt.isEmpty() ) { tt.append(exprTt); if (!isMarkdown) { tt += QLatin1String("<br/>"); } } if ( !realTt.isEmpty() ) { if (!isMarkdown) { realTt = GuiUtils::convertFromPlainText(realTt.trimmed(), Qt::WhiteSpaceNormal); } tt.append(realTt); } if (isMarkdown) { tt = Markdown::convert2html(tt); // Shrink H1/H2 (Can't do it in qt stylesheet) tt.replace( QString::fromUtf8("<h1>"), QString::fromUtf8("<h1 style=\"font-size:large;\">") ); tt.replace( QString::fromUtf8("<h2>"), QString::fromUtf8("<h2 style=\"font-size:large;\">") ); } return tt; } // KnobGui::toolTip