X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fupdate%2Fanimation%2Fscene-graph-animation.cpp;h=4449e7f29cccd2974e8b30ce1a68ceadb7f1c852;hb=af358efba365767f68094c669e12eea7fd0f5059;hp=8b1b925ea5ff9c65a7efdf67defff1bdf1eb95bf;hpb=7c6f8ed43521c52d6cc46a7e3e3e40069514f818;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/update/animation/scene-graph-animation.cpp b/dali/internal/update/animation/scene-graph-animation.cpp index 8b1b925..4449e7f 100644 --- a/dali/internal/update/animation/scene-graph-animation.cpp +++ b/dali/internal/update/animation/scene-graph-animation.cpp @@ -24,8 +24,6 @@ // INTERNAL INCLUDES #include -using namespace std; - namespace Dali { @@ -40,14 +38,16 @@ float DefaultAlphaFunc(float progress) return progress; // linear } -Animation::Animation(float durationSeconds, bool isLooping, Dali::Animation::EndAction endAction, Dali::Animation::EndAction destroyAction) +Animation::Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, Dali::Animation::EndAction endAction, Dali::Animation::EndAction disconnectAction ) : mDurationSeconds(durationSeconds), + mSpeedFactor( speedFactor ), mLooping(isLooping), mEndAction(endAction), - mDestroyAction(destroyAction), + mDisconnectAction(disconnectAction), mState(Stopped), - mElapsedSeconds(0.0f), - mPlayCount(0) + mElapsedSeconds(playRange.x*mDurationSeconds), + mPlayCount(0), + mPlayRange( playRange ) { } @@ -72,14 +72,37 @@ void Animation::SetEndAction(Dali::Animation::EndAction action) mEndAction = action; } -void Animation::SetDestroyAction(Dali::Animation::EndAction action) +void Animation::SetDisconnectAction(Dali::Animation::EndAction action) { - mDestroyAction = action; + if ( mDisconnectAction != action ) + { + mDisconnectAction = action; + + for ( AnimatorIter iter = mAnimators.Begin(), endIter = mAnimators.End(); iter != endIter; ++iter ) + { + (*iter)->SetDisconnectAction( action ); + } + } +} + +void Animation::SetPlayRange( const Vector2& range ) +{ + mPlayRange = range; + + //Make sure mElapsedSeconds is within the new range + mElapsedSeconds = Dali::Clamp(mElapsedSeconds, mPlayRange.x*mDurationSeconds , mPlayRange.y*mDurationSeconds ); } void Animation::Play() { mState = Playing; + + if ( mSpeedFactor < 0.0f && mElapsedSeconds <= mPlayRange.x*mDurationSeconds ) + { + mElapsedSeconds = mPlayRange.y * mDurationSeconds; + } + + SetAnimatorsActive( true ); } void Animation::PlayFrom( float progress ) @@ -89,6 +112,8 @@ void Animation::PlayFrom( float progress ) { mElapsedSeconds = progress * mDurationSeconds; mState = Playing; + + SetAnimatorsActive( true ); } } @@ -100,6 +125,31 @@ void Animation::Pause() } } +void Animation::Bake(BufferIndex bufferIndex, EndAction action) +{ + if( action == Dali::Animation::BakeFinal ) + { + if( mSpeedFactor > 0.0f ) + { + mElapsedSeconds = mPlayRange.y*mDurationSeconds + Math::MACHINE_EPSILON_1; // Force animation to reach it's end + } + else + { + mElapsedSeconds = mPlayRange.x*mDurationSeconds - Math::MACHINE_EPSILON_1; //Force animation to reach it's beginning + } + } + + UpdateAnimators( bufferIndex, true/*bake the final result*/, true /*animation finished*/ ); +} + +void Animation::SetAnimatorsActive( bool active ) +{ + for ( AnimatorIter iter = mAnimators.Begin(), endIter = mAnimators.End(); iter != endIter; ++iter ) + { + (*iter)->SetActive( active ); + } +} + bool Animation::Stop(BufferIndex bufferIndex) { bool animationFinished(false); @@ -110,18 +160,20 @@ bool Animation::Stop(BufferIndex bufferIndex) if( mEndAction != Dali::Animation::Discard ) { - if( mEndAction == Dali::Animation::BakeFinal ) - { - mElapsedSeconds = mDurationSeconds + Math::MACHINE_EPSILON_1; // Force animation to reach it's end - } - UpdateAnimators(bufferIndex, true/*bake the final result*/); + Bake( bufferIndex, mEndAction ); + + // Animators are automatically set to inactive in Bake + } + else + { + SetAnimatorsActive( false ); } // The animation has now been played to completion ++mPlayCount; } - mElapsedSeconds = 0.0f; + mElapsedSeconds = mPlayRange.x*mDurationSeconds; mState = Stopped; return animationFinished; @@ -131,19 +183,24 @@ void Animation::OnDestroy(BufferIndex bufferIndex) { if (mState == Playing || mState == Paused) { - if (mDestroyAction != Dali::Animation::Discard) + if (mEndAction != Dali::Animation::Discard) + { + Bake( bufferIndex, mEndAction ); + + // Animators are automatically set to inactive in Bake + } + else { - UpdateAnimators(bufferIndex, true/*bake the final result*/); + SetAnimatorsActive( false ); } } mState = Destroyed; } -void Animation::AddAnimator( AnimatorBase* animator, PropertyOwner* propertyOwner ) +void Animation::AddAnimator( AnimatorBase* animator ) { - animator->Attach( propertyOwner ); - + animator->SetDisconnectAction( mDisconnectAction ); mAnimators.PushBack( animator ); } @@ -158,68 +215,93 @@ bool Animation::Update(BufferIndex bufferIndex, float elapsedSeconds) // The animation must still be applied when Paused/Stopping if (mState == Playing) { - mElapsedSeconds += elapsedSeconds; + mElapsedSeconds += elapsedSeconds * mSpeedFactor; } + Vector2 playRangeSeconds = mPlayRange * mDurationSeconds; if (mLooping) { - if (mElapsedSeconds > mDurationSeconds) + if (mElapsedSeconds > playRangeSeconds.y ) + { + mElapsedSeconds = playRangeSeconds.x + fmod(mElapsedSeconds, playRangeSeconds.y); + } + else if( mElapsedSeconds < playRangeSeconds.x ) { - mElapsedSeconds = fmod(mElapsedSeconds, mDurationSeconds); + mElapsedSeconds = playRangeSeconds.y - fmod(mElapsedSeconds, playRangeSeconds.y); } } - const bool animationFinished(mState == Playing && mElapsedSeconds > mDurationSeconds); + const bool animationFinished(mState == Playing && + (( mSpeedFactor > 0.0f && mElapsedSeconds > playRangeSeconds.y ) || + ( mSpeedFactor < 0.0f && mElapsedSeconds < playRangeSeconds.x )) + ); - UpdateAnimators(bufferIndex, animationFinished && (mEndAction != Dali::Animation::Discard)); + UpdateAnimators(bufferIndex, animationFinished && (mEndAction != Dali::Animation::Discard), animationFinished); if (animationFinished) { // The animation has now been played to completion ++mPlayCount; - mElapsedSeconds = 0.0f; + mElapsedSeconds = playRangeSeconds.x; mState = Stopped; } return animationFinished; } -void Animation::UpdateAnimators(BufferIndex bufferIndex, bool bake) +void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished ) { + float elapsedSecondsClamped = Clamp( mElapsedSeconds, mPlayRange.x * mDurationSeconds,mPlayRange.y * mDurationSeconds ); + + //Loop through all animators + bool applied(true); for ( AnimatorIter iter = mAnimators.Begin(); iter != mAnimators.End(); ) { - // If an animator is not successfully applied, then it has been orphaned - bool applied(true); - AnimatorBase *animator = *iter; - const float initialDelay(animator->GetInitialDelay()); - - if (mElapsedSeconds >= initialDelay) - { - // Calculate a progress specific to each individual animator - float progress(1.0f); - const float animatorDuration = animator->GetDuration(); - if (animatorDuration > 0.0f) // animators can be "immediate" - { - progress = min(1.0f, (mElapsedSeconds - initialDelay) / animatorDuration); - } - - applied = animator->Update(bufferIndex, progress, bake); - } - // Animators are automatically removed, when orphaned from animatable scene objects. - if (!applied) + if( animator->Orphan() ) { + //Remove animators whose PropertyOwner has been destroyed iter = mAnimators.Erase(iter); } else { - ++iter; + if( animator->IsEnabled() ) + { + const float initialDelay(animator->GetInitialDelay()); + if (elapsedSecondsClamped >= initialDelay || mSpeedFactor < 0.0f ) + { + // Calculate a progress specific to each individual animator + float progress(1.0f); + const float animatorDuration = animator->GetDuration(); + if (animatorDuration > 0.0f) // animators can be "immediate" + { + progress = Clamp((elapsedSecondsClamped - initialDelay) / animatorDuration, 0.0f , 1.0f ); + } + animator->Update(bufferIndex, progress, bake); + } + applied = true; + } + else + { + applied = false; + } - INCREASE_COUNTER(PerformanceMonitor::ANIMATORS_APPLIED); + if ( animationFinished ) + { + animator->SetActive( false ); + } + + if (applied) + { + INCREASE_COUNTER(PerformanceMonitor::ANIMATORS_APPLIED); + } + + ++iter; } } + } } // namespace SceneGraph