예제 #1
0
파일: Curve.cpp 프로젝트: sanfx/Natron
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;
}
예제 #2
0
파일: Curve.cpp 프로젝트: sanfx/Natron
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;

}
예제 #3
0
파일: Curve.cpp 프로젝트: sanfx/Natron
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;
    
}
예제 #4
0
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);
}
예제 #5
0
파일: Curve.cpp 프로젝트: sanfx/Natron
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;
    }
}
예제 #6
0
파일: Curve.cpp 프로젝트: sanfx/Natron
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();
    }
}
예제 #7
0
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() );
    }
}
예제 #8
0
파일: Curve.cpp 프로젝트: sanfx/Natron
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;
}
예제 #9
0
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)") );
}
예제 #10
0
파일: Curve.cpp 프로젝트: sanfx/Natron
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);
    }
}
예제 #11
0
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);
        }
    }
}
예제 #12
0
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);
    }
}
예제 #13
0
파일: Curve.cpp 프로젝트: sanfx/Natron
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;
}
예제 #14
0
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