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; }
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(); } }
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; }
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; }