END_TEST;
}
+int UtcDaliAnimationMultipleProgressSignalsP2(void)
+{
+ tet_infoline( "Multiple animations with different progress markers and big step time" );
+
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ Animation animationAlpha = Animation::New(0.0f);
+ Animation animationBeta = Animation::New(0.0f);
+
+ //Set duration
+ const float durationSeconds(1.0f);
+ animationAlpha.SetDuration(durationSeconds);
+ animationBeta.SetDuration(durationSeconds);
+
+ bool progressSignalReceivedAlpha(false);
+ bool progressSignalReceivedBeta(false);
+
+ AnimationProgressCheck progressCheckAlpha(progressSignalReceivedAlpha, "animation:Alpha");
+ AnimationProgressCheck progressCheckBeta(progressSignalReceivedBeta, "animation:Beta" );
+
+ DevelAnimation::ProgressReachedSignal( animationAlpha ).Connect( &application, progressCheckAlpha );
+ DevelAnimation::ProgressReachedSignal( animationBeta ).Connect( &application, progressCheckBeta);
+ application.SendNotification();
+
+ Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+ animationAlpha.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+ animationBeta.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+ tet_infoline( "AnimationAlpha Progress notification set to 1%" );
+ DevelAnimation::SetProgressNotification( animationAlpha, 0.01f );
+
+ tet_infoline( "AnimationBeta Progress notification set to 99%" );
+ DevelAnimation::SetProgressNotification( animationBeta, 0.99f );
+
+ application.SendNotification();
+ application.Render( );
+
+ progressCheckAlpha.CheckSignalNotReceived();
+ progressCheckBeta.CheckSignalNotReceived();
+
+ // Start the animations unlimited looping
+ animationAlpha.SetLooping( true );
+ animationBeta.SetLooping( true );
+ animationAlpha.Play();
+ animationBeta.Play();
+
+ application.SendNotification();
+ application.Render(0); // start animation
+ application.Render(durationSeconds*20.0f ); // 2% progress
+ application.SendNotification();
+ DALI_TEST_EQUALS( 0.02f, animationAlpha.GetCurrentProgress(), TEST_LOCATION );
+
+ tet_infoline( "Animation at 2% - Alpha signals should be received, Beta should not." );
+
+ progressCheckAlpha.CheckSignalReceived();
+ progressCheckBeta.CheckSignalNotReceived();
+
+ tet_infoline( "Progress check reset" );
+ progressCheckAlpha.Reset();
+ progressCheckBeta.Reset();
+
+ application.SendNotification();
+ application.Render(durationSeconds*960.0f ); // 98% progress
+ application.SendNotification();
+ tet_infoline( "Animation at 98% - No signal received" );
+ DALI_TEST_EQUALS( 0.98f, animationAlpha.GetCurrentProgress(), TEST_LOCATION );
+
+ progressCheckAlpha.CheckSignalNotReceived();
+ progressCheckBeta.CheckSignalNotReceived();
+
+ application.SendNotification();
+ application.Render(durationSeconds*40.0f ); // 2% progress
+ application.SendNotification();
+ tet_infoline( "Animation loop once and now 2% - Alpha and Beta should receive signal" );
+ application.SendNotification();
+
+ DALI_TEST_EQUALS( 0.02f, animationBeta.GetCurrentProgress(), TEST_LOCATION );
+
+ progressCheckAlpha.CheckSignalReceived();
+ progressCheckBeta.CheckSignalReceived();
+
+ tet_infoline( "Progress check reset" );
+ progressCheckAlpha.Reset();
+ progressCheckBeta.Reset();
+
+ application.SendNotification();
+ application.Render(durationSeconds*980.0f ); // 100% progress
+ application.SendNotification();
+ tet_infoline( "Animation loop one more time. and now 100% - Beta should receive signal, Alhpa sholud not" );
+ application.SendNotification();
+
+ progressCheckAlpha.CheckSignalNotReceived();
+ progressCheckBeta.CheckSignalReceived();
+
+ tet_infoline( "Progress check reset" );
+ progressCheckAlpha.Reset();
+ progressCheckBeta.Reset();
+
+ animationAlpha.SetLooping( false );
+ animationBeta.SetLooping( false );
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*2000.0f) + 1u/*just beyond the animation duration*/);
+ application.SendNotification();
+
+ // We did expect the animation to finish
+ tet_infoline( "Animation finished" );
+
+ END_TEST;
+}
+
int UtcDaliAnimationProgressSignalWithPlayAfterP(void)
{
tet_infoline( "Multiple animations with different progress markers" );
Animation animation = Animation::New(0.0f);
//Set duration
- float durationSeconds(1.0f);
+ const float durationSeconds(1.0f);
animation.SetDuration(durationSeconds);
// Set Looping Count
- int loopCount( 4 );
+ const int loopCount( 4 );
animation.SetLoopCount( loopCount );
bool finishedSignalReceived(false);
Animation animation = Animation::New(0.0f);
//Set duration
- float durationSeconds(1.0f);
+ const float durationSeconds(1.0f);
animation.SetDuration(durationSeconds);
// Set Looping Unlmited
END_TEST;
}
+int UtcDaliAnimationProgressCallbackNegativeSpeed(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ Animation animation = Animation::New(0.0f);
+
+ //Set duration
+ const float durationSeconds(1.0f);
+ animation.SetDuration(durationSeconds);
+
+ //Set speed negative
+ animation.SetSpeedFactor( -1.0f );
+
+ // Set Looping Unlmited
+ animation.SetLooping( true );
+
+ bool finishedSignalReceived(false);
+ bool progressSignalReceived(false);
+
+ AnimationFinishCheck finishCheck(finishedSignalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ AnimationProgressCheck progressCheck(progressSignalReceived);
+ DevelAnimation::ProgressReachedSignal( animation ).Connect( &application, progressCheck);
+ application.SendNotification();
+
+ Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+ animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+ tet_infoline( "Animation Progress notification set to 50%" );
+ DevelAnimation::SetProgressNotification( animation, 0.5f );
+
+ application.SendNotification();
+ application.Render( );
+
+ progressCheck.CheckSignalNotReceived();
+
+ animation.Play();
+
+ for(int count = 0; count < 4; count++)
+ {
+ application.SendNotification();
+ application.Render(0); // start animation
+ progressCheck.CheckSignalNotReceived();
+
+ application.SendNotification();
+ application.Render(durationSeconds*0.25*1000.0f ); // 25% progress
+ DALI_TEST_EQUALS( 0.75f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ tet_infoline( "Animation at 25%" );
+
+ progressCheck.CheckSignalNotReceived();
+
+ application.SendNotification();
+ application.Render(durationSeconds*0.25*1000.0f ); // 50% progress
+ application.SendNotification();
+ tet_infoline( "Animation at 50%" );
+ DALI_TEST_EQUALS( 0.5f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ progressCheck.CheckSignalReceived();
+
+ tet_infoline( "Progress check reset" );
+ progressCheck.Reset();
+
+ application.Render(durationSeconds*0.25*1000.0f ); // 75% progress
+ tet_infoline( "Animation at 75%" );
+ application.SendNotification();
+
+ DALI_TEST_EQUALS( 0.25f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ progressCheck.CheckSignalNotReceived();
+
+ application.Render(durationSeconds*0.25*1000.0f ); // 100% progress
+ tet_infoline( "Animation at 100%" );
+ application.SendNotification();
+
+ //Nothing check at 100% progress. cause It can be both 100% and 0%.
+ finishCheck.CheckSignalNotReceived();
+ application.SendNotification();
+ }
+ finishCheck.CheckSignalNotReceived();
+
+ animation.Stop();
+ animation.SetLooping( false );
+ animation.SetLoopCount( 4 );
+ animation.Play();
+ application.Render(0u);
+ application.SendNotification();
+
+ for(int count = 0; count < 4; count++)
+ {
+ application.SendNotification();
+ application.Render(0); // start animation
+ progressCheck.CheckSignalNotReceived();
+
+ application.SendNotification();
+ application.Render(durationSeconds*0.25*1000.0f ); // 25% progress
+ DALI_TEST_EQUALS( 0.75f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ tet_infoline( "Animation at 25%" );
+
+ progressCheck.CheckSignalNotReceived();
+
+ application.SendNotification();
+ application.Render(durationSeconds*0.25*1000.0f ); // 50% progress
+ application.SendNotification();
+ tet_infoline( "Animation at 50%" );
+ DALI_TEST_EQUALS( 0.5f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ progressCheck.CheckSignalReceived();
+
+ tet_infoline( "Progress check reset" );
+ progressCheck.Reset();
+
+ application.Render(durationSeconds*0.25*1000.0f ); // 75% progress
+ tet_infoline( "Animation at 75%" );
+ application.SendNotification();
+
+ DALI_TEST_EQUALS( 0.25f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ progressCheck.CheckSignalNotReceived();
+
+ application.Render(durationSeconds*0.25*1000.0f ); // 100% progress
+ tet_infoline( "Animation at 100%" );
+ application.SendNotification();
+
+ //Nothing check at 100% progress. cause It can be both 100% and 0%.
+ application.SendNotification();
+ }
+ application.Render(10u);
+ application.SendNotification();
+ application.Render(0u);
+ application.SendNotification();
+
+ finishCheck.CheckSignalReceived();
+
+ END_TEST;
+}
+
+int UtcDaliAnimationProgressCallbackInvalidSignalN(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ Stage::GetCurrent().Add(actor);
+
+ // Build the animation
+ Animation animation = Animation::New(0.0f);
+
+ //Set duration
+ const float durationSeconds(1.0f);
+ animation.SetDuration(durationSeconds);
+
+ bool finishedSignalReceived(false);
+ bool progressSignalReceived(false);
+
+ AnimationFinishCheck finishCheck(finishedSignalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ AnimationProgressCheck progressCheck(progressSignalReceived);
+ DevelAnimation::ProgressReachedSignal( animation ).Connect( &application, progressCheck);
+ application.SendNotification();
+
+ Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+ animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+ tet_infoline( "Animation Progress PlayRange as 10% ~ 90%" );
+ animation.SetPlayRange( Vector2( 0.1f, 0.9f ) );
+
+ tet_infoline( "Animation Progress notification set to >90% that never can notificated" );
+ DevelAnimation::SetProgressNotification( animation, 0.9f + Math::MACHINE_EPSILON_1 );
+
+ application.SendNotification();
+ application.Render( );
+
+ progressCheck.CheckSignalNotReceived();
+
+ animation.Play();
+
+ application.SendNotification();
+ application.Render(0); // start animation
+ application.Render(durationSeconds*0.25*1000.0f ); // 35% progress
+ DALI_TEST_EQUALS( 0.35f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ tet_infoline( "Animation at 35%" );
+
+ progressCheck.CheckSignalNotReceived();
+
+ application.SendNotification();
+ application.Render(durationSeconds*0.25*1000.0f ); // 60% progress
+ application.SendNotification();
+ DALI_TEST_EQUALS( 0.6f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ tet_infoline( "Animation at 60%" );
+
+ progressCheck.CheckSignalNotReceived();
+
+ application.Render(durationSeconds*0.25*1000.0f ); // 85% progress
+ tet_infoline( "Animation at 85%" );
+ application.SendNotification();
+ DALI_TEST_EQUALS( 0.85f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+ progressCheck.CheckSignalNotReceived();
+
+ application.Render(durationSeconds*0.25*1000.0f ); // 90% progress
+ tet_infoline( "Animation over 90%" );
+ application.SendNotification();
+
+ // progress never signaled because playrange is 90%
+ progressCheck.CheckSignalNotReceived();
+
+ END_TEST;
+}
+
int UtcDaliAnimationProgressCallbackLongDurationP(void)
{
TestApplication application;
//Memory pool used to allocate new animations. Memory used by this pool will be released when shutting down DALi
Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Animation> gAnimationMemoryPool;
-inline void WrapInPlayRange( float& elapsed, const Dali::Vector2& playRangeSeconds)
+inline void WrapInPlayRange( float& elapsed, const float& playRangeStartSeconds, const float& playRangeEndSeconds)
{
- if( elapsed > playRangeSeconds.y )
+ if( elapsed > playRangeEndSeconds )
{
- elapsed = playRangeSeconds.x + fmodf((elapsed-playRangeSeconds.x), (playRangeSeconds.y-playRangeSeconds.x));
+ elapsed = playRangeStartSeconds + fmodf( ( elapsed - playRangeStartSeconds ), ( playRangeEndSeconds - playRangeStartSeconds ) );
}
- else if( elapsed < playRangeSeconds.x )
+ else if( elapsed < playRangeStartSeconds )
{
- elapsed = playRangeSeconds.y - fmodf( (playRangeSeconds.x - elapsed), (playRangeSeconds.y-playRangeSeconds.x) );
+ elapsed = playRangeEndSeconds - fmodf( ( playRangeStartSeconds - elapsed ), ( playRangeEndSeconds - playRangeStartSeconds ) );
}
}
// The animation must still be applied when Paused/Stopping
if (mState == Playing)
{
+ // Sign value of speed factor. It can optimize many arithmetic comparision
+ int signSpeedFactor = ( mSpeedFactor < 0.0f ) ? -1 : 1;
+
// If there is delay time before Animation starts, wait the Animation until mDelaySeconds.
if( mDelaySeconds > 0.0f )
{
float reduceSeconds = fabsf( elapsedSeconds * mSpeedFactor );
if( reduceSeconds > mDelaySeconds )
{
- if( mSpeedFactor < 0.0f )
- {
- mElapsedSeconds -= reduceSeconds - mDelaySeconds;
- }
- else
- {
- mElapsedSeconds += reduceSeconds - mDelaySeconds;
- }
+ // add overflowed time to mElapsedSecond.
+ // If speed factor > 0, add it. if speed factor < 0, subtract it.
+ float overflowSeconds = reduceSeconds - mDelaySeconds;
+ mElapsedSeconds += signSpeedFactor * overflowSeconds;
mDelaySeconds = 0.0f;
}
else
mElapsedSeconds += ( elapsedSeconds * mSpeedFactor );
}
- if ( mProgressReachedSignalRequired && ( mElapsedSeconds >= mProgressMarker ) )
- {
- // The application should be notified by NotificationManager, in another thread
- progressReached = true;
- mProgressReachedSignalRequired = false;
- }
- }
+ const float playRangeStartSeconds = mPlayRange.x * mDurationSeconds;
+ const float playRangeEndSeconds = mPlayRange.y * mDurationSeconds;
+ // Final reached seconds. It can optimize many arithmetic comparision
+ float edgeRangeSeconds = ( mSpeedFactor < 0.0f ) ? playRangeStartSeconds : playRangeEndSeconds;
- Vector2 playRangeSeconds = mPlayRange * mDurationSeconds;
+ // Optimized Factors.
+ // elapsed > edge --> check if looped
+ // elapsed >= marker --> check if elapsed reached to marker in normal case
+ // edge >= marker --> check if elapsed reached to marker in looped case
+ float elapsedFactor = signSpeedFactor * mElapsedSeconds;
+ float edgeFactor = signSpeedFactor * edgeRangeSeconds;
+ float markerFactor = signSpeedFactor * mProgressMarker;
- if( 0 == mLoopCount || mCurrentLoop < mLoopCount - 1) // '-1' here so last loop iteration uses play once below
- {
- // looping
- looped = (mState == Playing &&
- (( mSpeedFactor > 0.0f && mElapsedSeconds > playRangeSeconds.y ) ||
- ( mSpeedFactor < 0.0f && mElapsedSeconds < playRangeSeconds.x )) );
+ // check it is looped
+ looped = ( elapsedFactor > edgeFactor );
- WrapInPlayRange( mElapsedSeconds, playRangeSeconds );
+ if( looped )
+ {
+ WrapInPlayRange( mElapsedSeconds, playRangeStartSeconds, playRangeEndSeconds );
- UpdateAnimators(bufferIndex, false, false );
+ // Recalculate elapsedFactor here
+ elapsedFactor = signSpeedFactor * mElapsedSeconds;
- if(looped)
- {
if( mLoopCount != 0 )
{
+ // Check If this animation is finished
++mCurrentLoop;
- }
- mProgressReachedSignalRequired = mProgressMarker > 0.0f;
- // don't increment mPlayedCount until the finished final loop
- }
- }
- else
- {
- // playing once (and last mCurrentLoop)
- finished = (mState == Playing &&
- (( mSpeedFactor > 0.0f && mElapsedSeconds > playRangeSeconds.y ) ||
- ( mSpeedFactor < 0.0f && mElapsedSeconds < playRangeSeconds.x )) );
+ if( mCurrentLoop >= mLoopCount )
+ {
+ DALI_ASSERT_DEBUG( mCurrentLoop == mLoopCount );
+ finished = true;
- // update with bake if finished
- UpdateAnimators(bufferIndex, finished && (mEndAction != Dali::Animation::Discard), finished );
+ // The animation has now been played to completion
+ ++mPlayedCount;
- if(finished)
- {
- // The animation has now been played to completion
- ++mPlayedCount;
+ // Make elapsed second as edge of range forcely.
+ mElapsedSeconds = edgeRangeSeconds + signSpeedFactor * Math::MACHINE_EPSILON_10;
+ UpdateAnimators(bufferIndex, finished && (mEndAction != Dali::Animation::Discard), finished );
- // loop iterations come to this else branch for their final iterations
- if( mCurrentLoop < mLoopCount)
- {
- ++mCurrentLoop;
- DALI_ASSERT_DEBUG(mCurrentLoop == mLoopCount);
+ // After update animation, mElapsedSeconds must be begin of value
+ mElapsedSeconds = playRangeStartSeconds + playRangeEndSeconds - edgeRangeSeconds;
+ mState = Stopped;
+ }
}
- mProgressReachedSignalRequired = mProgressMarker > 0.0f;
- mElapsedSeconds = playRangeSeconds.x;
- mState = Stopped;
+ // when it is on looped state, 2 case to send progress signal.
+ // (require && range_value >= marker) || << Signal at previous loop
+ // (marker > 0 && !finished && elaped >= marker) << Signal at current loop
+ if( ( mProgressMarker > 0.0f ) && !finished && ( elapsedFactor >= markerFactor ) )
+ {
+ // The application should be notified by NotificationManager, in another thread
+ progressReached = true;
+ mProgressReachedSignalRequired = false;
+ }
+ else
+ {
+ if( mProgressReachedSignalRequired && ( edgeFactor >= markerFactor ) )
+ {
+ progressReached = true;
+ }
+ mProgressReachedSignalRequired = mProgressMarker > 0.0f;
+ }
}
+ else
+ {
+ // when it is not on looped state, only 1 case to send progress signal.
+ // (require && elaped >= marker)
+ if( mProgressReachedSignalRequired && ( elapsedFactor >= markerFactor ) )
+ {
+ // The application should be notified by NotificationManager, in another thread
+ progressReached = true;
+ mProgressReachedSignalRequired = false;
+ }
+ }
+ }
+
+ // Already updated when finished. So skip.
+ if( !finished )
+ {
+ UpdateAnimators(bufferIndex, false, false );
}
}