KeyFrame Curve::setKeyFrameInterpolation(Natron::KeyframeType interp,int index,int* newIndex) { bool evaluateAnimation = false; KeyFrame ret; { QWriteLocker l(&_imp->_lock); KeyFrameSet::iterator it = atIndex(index); assert(it != _imp->keyFrames.end()); ///if the curve is a string_curve or bool_curve the interpolation is bound to be constant. if ((_imp->type == CurvePrivate::STRING_CURVE || _imp->type == CurvePrivate::BOOL_CURVE || _imp->type == CurvePrivate::INT_CURVE_CONSTANT_INTERP) && interp != Natron::KEYFRAME_CONSTANT) { return *it; } if (interp != it->getInterpolation()) { it = setKeyframeInterpolation_internal(it, interp); } if (newIndex) { *newIndex = std::distance(_imp->keyFrames.begin(),it); } ret = *it; } if (evaluateAnimation && _imp->owner) { _imp->owner->evaluateAnimationChange(); } return ret; }
KeyFrame Curve::setKeyFrameValueAndTime(double time,double value,int index,int* newIndex) { bool evaluateAnimation = false; KeyFrame ret; { QWriteLocker l(&_imp->_lock); KeyFrameSet::iterator it = atIndex(index); if (it == _imp->keyFrames.end()) { QString err = QString("No such keyframe at index %1").arg(index); throw std::invalid_argument(err.toStdString()); } bool setTime = (time != it->getTime()); bool setValue = (value != it->getValue()); if (setTime || setValue) { it = setKeyFrameValueAndTimeNoUpdate(value,time, it); it = evaluateCurveChanged(KEYFRAME_CHANGED,it); evaluateAnimation = true; } if (newIndex) { *newIndex = std::distance(_imp->keyFrames.begin(),it); } ret = *it; } if (evaluateAnimation && _imp->owner) { _imp->owner->evaluateAnimationChange(); } return ret; }
KeyFrame Curve::setKeyFrameDerivatives(double left, double right,int index,int* newIndex) { bool evaluateAnimation = false; KeyFrame ret; { QWriteLocker l(&_imp->_lock); KeyFrameSet::iterator it = atIndex(index); assert(it != _imp->keyFrames.end()); if (left != it->getLeftDerivative() || right != it->getRightDerivative()) { KeyFrame newKey(*it); newKey.setLeftDerivative(left); newKey.setRightDerivative(right); it = addKeyFrameNoUpdate(newKey).first; it = evaluateCurveChanged(DERIVATIVES_CHANGED,it); evaluateAnimation = true; } if (newIndex) { *newIndex = std::distance(_imp->keyFrames.begin(),it); } ret = *it; } if (evaluateAnimation && _imp->owner) { _imp->owner->evaluateAnimationChange(); } return ret; }
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); }
std::pair<KeyFrameSet::iterator,bool> Curve::addKeyFrameNoUpdate(const KeyFrame& cp) { // PRIVATE - should not lock if (!_imp->isParametric) { //< if keyframes are clamped to integers std::pair<KeyFrameSet::iterator,bool> newKey = _imp->keyFrames.insert(cp); // keyframe at this time exists, erase and insert again bool addedKey = true; if (!newKey.second) { _imp->keyFrames.erase(newKey.first); newKey = _imp->keyFrames.insert(cp); assert(newKey.second); addedKey = false; } return std::make_pair(newKey.first,addedKey); } else { bool addedKey = true; double paramEps = NATRON_CURVE_X_SPACING_EPSILON * std::abs(_imp->xMax - _imp->xMin); for (KeyFrameSet::iterator it = _imp->keyFrames.begin(); it!= _imp->keyFrames.end(); ++it) { if (std::abs(it->getTime() - cp.getTime()) < paramEps) { _imp->keyFrames.erase(it); addedKey = false; break; } } std::pair<KeyFrameSet::iterator,bool> newKey = _imp->keyFrames.insert(cp); newKey.second = addedKey; return newKey; } }
void Curve::setCurveInterpolation(Natron::KeyframeType interp) { bool evaluateAnimation = false; { QWriteLocker l(&_imp->_lock); ///if the curve is a string_curve or bool_curve the interpolation is bound to be constant. if ((_imp->type == CurvePrivate::STRING_CURVE || _imp->type == CurvePrivate::BOOL_CURVE || _imp->type == CurvePrivate::INT_CURVE_CONSTANT_INTERP) && interp != Natron::KEYFRAME_CONSTANT) { return; } for (int i = 0; i < (int)_imp->keyFrames.size(); ++i) { KeyFrameSet::iterator it = _imp->keyFrames.begin(); std::advance(it, i); if (interp != it->getInterpolation()) { it = setKeyframeInterpolation_internal(it, interp); evaluateAnimation = true; } } } if (evaluateAnimation && _imp->owner) { _imp->owner->evaluateAnimationChange(); } }
void TrackMarker::getCenterKeyframes(std::set<double>* keyframes) const { CurvePtr curve = _imp->center.lock()->getAnimationCurve(ViewIdx(0), DimIdx(0)); assert(curve); KeyFrameSet keys = curve->getKeyFrames_mt_safe(); for (KeyFrameSet::iterator it = keys.begin(); it != keys.end(); ++it) { keyframes->insert( it->getTime() ); } }
KeyFrameSet::iterator Curve::evaluateCurveChanged(CurveChangedReason reason, KeyFrameSet::iterator key) { // PRIVATE - should not lock assert(key!=_imp->keyFrames.end()); if (key->getInterpolation()!= Natron::KEYFRAME_BROKEN && key->getInterpolation() != Natron::KEYFRAME_FREE && reason != DERIVATIVES_CHANGED ) { key = refreshDerivatives(DERIVATIVES_CHANGED,key); } KeyFrameSet::iterator prev = key; if (key != _imp->keyFrames.begin()) { --prev; if(prev->getInterpolation()!= Natron::KEYFRAME_BROKEN && prev->getInterpolation()!= Natron::KEYFRAME_FREE && prev->getInterpolation()!= Natron::KEYFRAME_NONE){ prev = refreshDerivatives(DERIVATIVES_CHANGED,prev); } } KeyFrameSet::iterator next = key; ++next; if (next != _imp->keyFrames.end()) { if(next->getInterpolation()!= Natron::KEYFRAME_BROKEN && next->getInterpolation()!= Natron::KEYFRAME_FREE && next->getInterpolation()!= Natron::KEYFRAME_NONE){ next = refreshDerivatives(DERIVATIVES_CHANGED,next); } } return key; }
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 Curve::clone(const Curve& other, SequenceTime offset, const RangeD* range) { KeyFrameSet otherKeys = other.getKeyFrames_mt_safe(); // The range=[0,0] case is obviously a bug in the spec of paramCopy() from the parameter suite: // it prevents copying the value of frame 0. bool copyRange = range != NULL /*&& (range->min != 0 || range->max != 0)*/; QWriteLocker l(&_imp->_lock); _imp->keyFrames.clear(); for (KeyFrameSet::iterator it = otherKeys.begin(); it!=otherKeys.end(); ++it) { double time = it->getTime(); if (copyRange && (time < range->min || time > range->max)) { continue; } KeyFrame k(*it); if (offset != 0) { k.setTime(time + offset); } _imp->keyFrames.insert(k); } }
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); } } }
static void deleteKnobAnimation(const std::set<double>& userKeyframes, const KnobIPtr& knob, DeleteKnobAnimationEnum type, double currentTime) { for (int i = 0; i < knob->getNDimensions(); ++i) { CurvePtr curve = knob->getAnimationCurve(ViewIdx(0), DimIdx(i)); assert(curve); KeyFrameSet keys = curve->getKeyFrames_mt_safe(); std::list<double> toRemove; switch (type) { case eDeleteKnobAnimationAll: { for (KeyFrameSet::iterator it = keys.begin(); it != keys.end(); ++it) { std::set<double>::iterator found = userKeyframes.find( it->getTime() ); if ( found == userKeyframes.end() ) { toRemove.push_back( it->getTime() ); } } break; } case eDeleteKnobAnimationBeforeTime: { for (KeyFrameSet::iterator it = keys.begin(); it != keys.end(); ++it) { if (it->getTime() >= currentTime) { break; } std::set<double>::iterator found = userKeyframes.find( it->getTime() ); if ( found == userKeyframes.end() ) { toRemove.push_back( it->getTime() ); } } break; } case eDeleteKnobAnimationAfterTime: { for (KeyFrameSet::reverse_iterator it = keys.rbegin(); it != keys.rend(); ++it) { if (it->getTime() <= currentTime) { break; } std::set<double>::iterator found = userKeyframes.find( it->getTime() ); if ( found == userKeyframes.end() ) { toRemove.push_back( it->getTime() ); } } break; } } knob->deleteValuesAtTime(toRemove, ViewSetSpec::all(), DimIdx(i), eValueChangedReasonUserEdited); } }
KeyFrameSet::iterator Curve::refreshDerivatives(Curve::CurveChangedReason reason, KeyFrameSet::iterator key) { // PRIVATE - should not lock double tcur = key->getTime(); double vcur = key->getValue(); double tprev, vprev, tnext, vnext, vprevDerivRight, vnextDerivLeft; Natron::KeyframeType prevType, nextType; if (key == _imp->keyFrames.begin()) { tprev = tcur; vprev = vcur; vprevDerivRight = 0.; prevType = Natron::KEYFRAME_NONE; } else { KeyFrameSet::const_iterator prev = key; --prev; tprev = prev->getTime(); vprev = prev->getValue(); vprevDerivRight = prev->getRightDerivative(); prevType = prev->getInterpolation(); //if prev is the first keyframe, and not edited by the user then interpolate linearly if (prev == _imp->keyFrames.begin() && prevType != Natron::KEYFRAME_FREE && prevType != Natron::KEYFRAME_BROKEN) { prevType = Natron::KEYFRAME_LINEAR; } } KeyFrameSet::const_iterator next = key; ++next; if (next == _imp->keyFrames.end()) { tnext = tcur; vnext = vcur; vnextDerivLeft = 0.; nextType = Natron::KEYFRAME_NONE; } else { tnext = next->getTime(); vnext = next->getValue(); vnextDerivLeft = next->getLeftDerivative(); nextType = next->getInterpolation(); KeyFrameSet::const_iterator nextnext = next; ++nextnext; //if next is thelast keyframe, and not edited by the user then interpolate linearly if (nextnext == _imp->keyFrames.end() && nextType != Natron::KEYFRAME_FREE && nextType != Natron::KEYFRAME_BROKEN) { nextType = Natron::KEYFRAME_LINEAR; } } double vcurDerivLeft,vcurDerivRight; assert(key->getInterpolation() != Natron::KEYFRAME_NONE && key->getInterpolation() != Natron::KEYFRAME_BROKEN && key->getInterpolation() != Natron::KEYFRAME_FREE); Natron::autoComputeDerivatives(prevType, key->getInterpolation(), nextType, tprev, vprev, tcur, vcur, tnext, vnext, vprevDerivRight, vnextDerivLeft, &vcurDerivLeft, &vcurDerivRight); KeyFrame newKey(*key); newKey.setLeftDerivative(vcurDerivLeft); newKey.setRightDerivative(vcurDerivRight); std::pair<KeyFrameSet::iterator,bool> newKeyIt = _imp->keyFrames.insert(newKey); // keyframe at this time exists, erase and insert again if (!newKeyIt.second) { _imp->keyFrames.erase(newKeyIt.first); newKeyIt = _imp->keyFrames.insert(newKey); assert(newKeyIt.second); } key = newKeyIt.first; if (reason != DERIVATIVES_CHANGED) { key = evaluateCurveChanged(DERIVATIVES_CHANGED,key); } return key; }
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