2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/animation/animation-impl.h>
20 #include <dali/public-api/object/property-map.h>
25 #include <dali/public-api/actors/actor.h>
26 #include <dali/public-api/animation/alpha-function.h>
27 #include <dali/public-api/animation/time-period.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/object/type-registry.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/radian.h>
32 #include <dali/internal/event/actors/actor-impl.h>
33 #include <dali/internal/event/animation/animation-playlist.h>
34 #include <dali/internal/event/animation/animator-connector.h>
35 #include <dali/internal/event/common/notification-manager.h>
36 #include <dali/internal/event/common/property-helper.h>
37 #include <dali/internal/event/common/stage-impl.h>
38 #include <dali/internal/event/common/thread-local-storage.h>
39 #include <dali/internal/update/animation/scene-graph-animator.h>
40 #include <dali/internal/update/manager/update-manager.h>
42 using Dali::Internal::SceneGraph::UpdateManager;
43 using Dali::Internal::SceneGraph::AnimatorBase;
44 using Dali::Internal::SceneGraph::Shader;
52 static bool SHOW_VALUE = true;
53 static bool HIDE_VALUE = false;
60 const char* const SIGNAL_FINISHED = "finished";
64 const char* const ACTION_PLAY = "play";
65 const char* const ACTION_STOP = "stop";
66 const char* const ACTION_PAUSE = "pause";
70 return Dali::Animation::New(0.f);
73 TypeRegistration mType( typeid( Dali::Animation ), typeid( Dali::BaseHandle ), Create );
75 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &Animation::DoConnectSignal );
77 TypeAction action1( mType, ACTION_PLAY, &Animation::DoAction );
78 TypeAction action2( mType, ACTION_STOP, &Animation::DoAction );
79 TypeAction action3( mType, ACTION_PAUSE, &Animation::DoAction );
81 const Dali::Animation::EndAction DEFAULT_END_ACTION( Dali::Animation::Bake );
82 const Dali::Animation::EndAction DEFAULT_DISCONNECT_ACTION( Dali::Animation::BakeFinal );
83 const Dali::Animation::Interpolation DEFAULT_INTERPOLATION( Dali::Animation::Linear );
84 const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION( Dali::AlphaFunction::DEFAULT );
89 AnimationPtr Animation::New(float durationSeconds)
91 Stage* stage = Stage::GetCurrent();
95 AnimationPlaylist& playlist = stage->GetAnimationPlaylist();
97 if( durationSeconds < 0.0f )
99 DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
100 durationSeconds = 0.0f;
103 AnimationPtr animation = new Animation( *stage, playlist, durationSeconds, DEFAULT_END_ACTION, DEFAULT_DISCONNECT_ACTION, DEFAULT_ALPHA_FUNCTION );
105 // Second-phase construction
106 animation->Initialize();
116 Animation::Animation( EventThreadServices& eventThreadServices, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha )
117 : mEventThreadServices( eventThreadServices ),
118 mPlaylist( playlist ),
120 mNotificationCount( 0 ),
121 mFinishedCallback( NULL ),
122 mFinishedCallbackObject( NULL ),
123 mDurationSeconds( durationSeconds ),
127 mPlayRange( Vector2(0.0f,1.0f)),
128 mEndAction( endAction ),
129 mDisconnectAction( disconnectAction ),
130 mDefaultAlpha( defaultAlpha ),
131 mState(Dali::Animation::STOPPED)
135 void Animation::Initialize()
137 // Connect to the animation playlist
138 mPlaylist.AnimationCreated( *this );
145 Animation::~Animation()
147 // Guard to allow handle destruction after Core has been destroyed
148 if ( Stage::IsInstalled() )
150 // Disconnect from the animation playlist
151 mPlaylist.AnimationDestroyed( *this );
153 DestroySceneObject();
159 void Animation::CreateSceneObject()
161 DALI_ASSERT_DEBUG( mAnimation == NULL );
163 // Create a new animation, temporarily owned
164 SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mLoopCount, mEndAction, mDisconnectAction );
166 // Keep a const pointer to the animation.
167 mAnimation = animation;
169 // Transfer animation ownership to the update manager through a message
170 AddAnimationMessage( mEventThreadServices.GetUpdateManager(), animation );
173 void Animation::DestroySceneObject()
175 if ( mAnimation != NULL )
177 // Remove animation using a message to the update manager
178 RemoveAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
183 void Animation::SetDuration(float seconds)
187 DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
191 // Cache for public getters
192 mDurationSeconds = seconds;
194 // mAnimation is being used in a separate thread; queue a message to set the value
195 SetDurationMessage( mEventThreadServices, *mAnimation, seconds );
198 float Animation::GetDuration() const
200 // This is not animatable; the cached value is up-to-date.
201 return mDurationSeconds;
204 void Animation::SetLooping(bool on)
206 SetLoopCount( on ? 0 : 1 );
209 void Animation::SetLoopCount(int count)
211 // Cache for public getters
214 // mAnimation is being used in a separate thread; queue a message to set the value
215 SetLoopingMessage( mEventThreadServices, *mAnimation, mLoopCount );
218 int Animation::GetLoopCount()
223 int Animation::GetCurrentLoop()
228 bool Animation::IsLooping() const
230 return mLoopCount != 1;
233 void Animation::SetEndAction(EndAction action)
235 // Cache for public getters
238 // mAnimation is being used in a separate thread; queue a message to set the value
239 SetEndActionMessage( mEventThreadServices, *mAnimation, action );
242 Dali::Animation::EndAction Animation::GetEndAction() const
244 // This is not animatable; the cached value is up-to-date.
248 void Animation::SetDisconnectAction(EndAction action)
250 // Cache for public getters
251 mDisconnectAction = action;
253 // mAnimation is being used in a separate thread; queue a message to set the value
254 SetDisconnectActionMessage( mEventThreadServices, *mAnimation, action );
257 Dali::Animation::EndAction Animation::GetDisconnectAction() const
259 // This is not animatable; the cached value is up-to-date.
260 return mDisconnectAction;
263 void Animation::Play()
265 // Update the current playlist
266 mPlaylist.OnPlay( *this );
268 mState = Dali::Animation::PLAYING;
270 unsigned int connectorTargetValuesIndex( 0 );
271 unsigned int numberOfConnectorTargetValues = mConnectorActorTargetValues.size();
274 * Loop through all Animator connectors, if connector index matches the current index stored in mConnectorActorTargetValues container then
275 * should apply target values for this index to the Actor.
276 * Confirm object is an actor and it is a POSITION or SIZE Property Index before sending Notify message to Actor.
278 for ( unsigned int connectorIndex = 0; connectorIndex < mConnectors.Count(); connectorIndex ++)
280 // Use index to check if the current connector is next in the mConnectorActorTargetValues container, meaning targetValues have been pushed in AnimateXXFunction
281 if ( connectorTargetValuesIndex < numberOfConnectorTargetValues )
283 ConnectorTargetValues& connectorPair = mConnectorActorTargetValues[ connectorTargetValuesIndex ];
285 if ( connectorPair.connectorIndex == connectorIndex )
287 // Current connector index matches next in the stored connectors with target values so apply target value.
288 connectorTargetValuesIndex++; // Found a match for connector so increment index to next one
290 AnimatorConnectorBase* connector = mConnectors[ connectorIndex ];
292 Actor* maybeActor = static_cast<Actor*>( connector->GetObject() ); // Only Actors would be in mConnectorActorTargetValues container
296 // Get Stored Target Value and corresponding connector index
297 const Property::Type valueType = connectorPair.targetValue.GetType();
298 Property::Index propertyIndex = connector->GetPropertyIndex();
300 if ( valueType == Property::VECTOR3 )
302 Vector3 targetVector3 = connectorPair.targetValue.Get<Vector3>();
304 if ( propertyIndex == Dali::Actor::Property::POSITION )
306 maybeActor->NotifyPositionAnimation( *this, targetVector3 );
308 else if ( propertyIndex == Dali::Actor::Property::SIZE )
310 maybeActor->NotifySizeAnimation( *this, targetVector3 );
313 else if ( valueType == Property::FLOAT )
315 float targetFloat = connectorPair.targetValue.Get<float>();
317 if ( ( Dali::Actor::Property::POSITION_X == propertyIndex ) ||
318 ( Dali::Actor::Property::POSITION_Y == propertyIndex ) ||
319 ( Dali::Actor::Property::POSITION_Z == propertyIndex ) )
321 maybeActor->NotifyPositionAnimation( *this, targetFloat, propertyIndex );
323 else if ( ( Dali::Actor::Property::SIZE_WIDTH == propertyIndex ) ||
324 ( Dali::Actor::Property::SIZE_HEIGHT == propertyIndex ) ||
325 ( Dali::Actor::Property::SIZE_DEPTH == propertyIndex ) )
328 maybeActor->NotifySizeAnimation( *this, targetFloat, propertyIndex );
333 // Currently only FLOAT and VECTOR3 is supported for Target values in AnimateXXFunctions
334 DALI_LOG_WARNING("Animation::Play Unsupported Value Type provided as TargetValue\n");
341 // mAnimation is being used in a separate thread; queue a Play message
342 PlayAnimationMessage( mEventThreadServices, *mAnimation );
345 void Animation::PlayFrom( float progress )
347 if( progress >= mPlayRange.x && progress <= mPlayRange.y )
349 // Update the current playlist
350 mPlaylist.OnPlay( *this );
352 mState = Dali::Animation::PLAYING;
354 // mAnimation is being used in a separate thread; queue a Play message
355 PlayAnimationFromMessage( mEventThreadServices, *mAnimation, progress );
359 void Animation::Pause()
361 mState = Dali::Animation::PAUSED;
363 // mAnimation is being used in a separate thread; queue a Pause message
364 PauseAnimationMessage( mEventThreadServices, *mAnimation );
367 Dali::Animation::State Animation::GetState() const
372 void Animation::Stop()
374 mState = Dali::Animation::STOPPED;
376 // mAnimation is being used in a separate thread; queue a Stop message
377 StopAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
380 void Animation::Clear()
382 DALI_ASSERT_DEBUG(mAnimation);
384 // Remove all the connectors
387 // Replace the old scene-object with a new one
388 DestroySceneObject();
391 // Reset the notification count, since the new scene-object has never been played
392 mNotificationCount = 0;
394 // Update the current playlist
395 mPlaylist.OnClear( *this );
398 void Animation::AnimateBy(Property& target, Property::Value& relativeValue)
400 AnimateBy(target, relativeValue, mDefaultAlpha, TimePeriod(mDurationSeconds));
403 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha)
405 AnimateBy(target, relativeValue, alpha, TimePeriod(mDurationSeconds));
408 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period)
410 AnimateBy(target, relativeValue, mDefaultAlpha, period);
413 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period)
415 Object& object = GetImplementation( target.object );
416 const Property::Type targetType = object.GetPropertyType( target.propertyIndex );
417 const Property::Type destinationType = relativeValue.GetType();
418 DALI_ASSERT_ALWAYS( targetType == destinationType && "Animated value and Property type don't match" );
420 ExtendDuration( period );
422 switch ( targetType )
424 case Property::BOOLEAN:
426 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
427 target.propertyIndex,
428 target.componentIndex,
429 new AnimateByBoolean(relativeValue.Get<bool>()),
435 case Property::INTEGER:
437 AddAnimatorConnector( AnimatorConnector<int>::New( object,
438 target.propertyIndex,
439 target.componentIndex,
440 new AnimateByInteger(relativeValue.Get<int>()),
446 case Property::FLOAT:
448 AddAnimatorConnector( AnimatorConnector<float>::New( object,
449 target.propertyIndex,
450 target.componentIndex,
451 new AnimateByFloat(relativeValue.Get<float>()),
457 case Property::VECTOR2:
459 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
460 target.propertyIndex,
461 target.componentIndex,
462 new AnimateByVector2(relativeValue.Get<Vector2>()),
468 case Property::VECTOR3:
470 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
471 target.propertyIndex,
472 target.componentIndex,
473 new AnimateByVector3(relativeValue.Get<Vector3>()),
479 case Property::VECTOR4:
481 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
482 target.propertyIndex,
483 target.componentIndex,
484 new AnimateByVector4(relativeValue.Get<Vector4>()),
490 case Property::ROTATION:
492 AngleAxis angleAxis = relativeValue.Get<AngleAxis>();
494 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
495 target.propertyIndex,
496 target.componentIndex,
497 new RotateByAngleAxis(angleAxis.angle, angleAxis.axis),
505 // non animatable types handled already
510 void Animation::AnimateTo(Property& target, Property::Value& destinationValue)
512 AnimateTo(target, destinationValue, mDefaultAlpha, TimePeriod(mDurationSeconds));
515 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha)
517 AnimateTo(target, destinationValue, alpha, TimePeriod(mDurationSeconds));
520 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period)
522 AnimateTo(target, destinationValue, mDefaultAlpha, period);
525 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
527 Object& object = GetImplementation(target.object);
529 AnimateTo( object, target.propertyIndex, target.componentIndex, destinationValue, alpha, period );
532 void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
534 Property::Type targetType = targetObject.GetPropertyType(targetPropertyIndex);
535 if( componentIndex != Property::INVALID_COMPONENT_INDEX )
537 if( ( targetType == Property::VECTOR2 ) ||
538 ( targetType == Property::VECTOR3 ) ||
539 ( targetType == Property::VECTOR4 ) )
541 targetType = Property::FLOAT;
544 const Property::Type destinationType = destinationValue.GetType();
545 DALI_ASSERT_ALWAYS( targetType == destinationType && "Animated value and Property type don't match" );
547 ExtendDuration( period );
549 switch ( destinationType )
551 case Property::BOOLEAN:
553 AddAnimatorConnector( AnimatorConnector<bool>::New( targetObject,
556 new AnimateToBoolean( destinationValue.Get<bool>() ),
562 case Property::INTEGER:
564 AddAnimatorConnector( AnimatorConnector<int>::New( targetObject,
567 new AnimateToInteger( destinationValue.Get<int>() ),
573 case Property::FLOAT:
575 if ( ( Dali::Actor::Property::SIZE_WIDTH == targetPropertyIndex ) ||
576 ( Dali::Actor::Property::SIZE_HEIGHT == targetPropertyIndex ) ||
577 ( Dali::Actor::Property::SIZE_DEPTH == targetPropertyIndex ) ||
578 ( Dali::Actor::Property::POSITION_X == targetPropertyIndex ) ||
579 ( Dali::Actor::Property::POSITION_Y == targetPropertyIndex ) ||
580 ( Dali::Actor::Property::POSITION_Z == targetPropertyIndex ) )
583 Actor* maybeActor = dynamic_cast<Actor*>( &targetObject );
586 // Store data to later notify the actor that its size or position is being animated
587 ConnectorTargetValues connectorPair;
588 connectorPair.targetValue = destinationValue;
589 connectorPair.connectorIndex = mConnectors.Count();
591 mConnectorActorTargetValues.push_back( connectorPair );
595 AddAnimatorConnector( AnimatorConnector<float>::New( targetObject,
598 new AnimateToFloat( destinationValue.Get<float>() ),
604 case Property::VECTOR2:
606 AddAnimatorConnector( AnimatorConnector<Vector2>::New( targetObject,
609 new AnimateToVector2( destinationValue.Get<Vector2>() ),
615 case Property::VECTOR3:
617 if ( Dali::Actor::Property::SIZE == targetPropertyIndex || Dali::Actor::Property::POSITION == targetPropertyIndex )
619 // Test whether this is actually an Actor
620 Actor* maybeActor = dynamic_cast<Actor*>( &targetObject );
623 // Store data to later notify the actor that its size or position is being animated
624 ConnectorTargetValues connectorPair;
625 connectorPair.targetValue = destinationValue;
626 connectorPair.connectorIndex = mConnectors.Count();
628 mConnectorActorTargetValues.push_back( connectorPair );
632 AddAnimatorConnector( AnimatorConnector<Vector3>::New( targetObject,
635 new AnimateToVector3( destinationValue.Get<Vector3>() ),
641 case Property::VECTOR4:
643 AddAnimatorConnector( AnimatorConnector<Vector4>::New( targetObject,
646 new AnimateToVector4( destinationValue.Get<Vector4>() ),
652 case Property::ROTATION:
654 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( targetObject,
657 new RotateToQuaternion( destinationValue.Get<Quaternion>() ),
665 // non animatable types handled already
670 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
672 AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION );
675 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation )
677 AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), interpolation );
680 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period)
682 AnimateBetween(target, keyFrames, mDefaultAlpha, period, DEFAULT_INTERPOLATION);
685 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
687 AnimateBetween(target, keyFrames, mDefaultAlpha, period, interpolation);
690 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha)
692 AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION);
695 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
697 AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), interpolation);
700 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
702 AnimateBetween(target, keyFrames, alpha, period, DEFAULT_INTERPOLATION);
705 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation)
707 Object& object = GetImplementation( target.object );
709 ExtendDuration( period );
711 switch(keyFrames.GetType())
713 case Dali::Property::BOOLEAN:
715 const KeyFrameBoolean* kf;
716 GetSpecialization(keyFrames, kf);
717 KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf);
718 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
719 target.propertyIndex,
720 target.componentIndex,
721 new KeyFrameBooleanFunctor(kfCopy),
727 case Dali::Property::INTEGER:
729 const KeyFrameInteger* kf;
730 GetSpecialization(keyFrames, kf);
731 KeyFrameIntegerPtr kfCopy = KeyFrameInteger::Clone(*kf);
732 AddAnimatorConnector( AnimatorConnector<int>::New( object,
733 target.propertyIndex,
734 target.componentIndex,
735 new KeyFrameIntegerFunctor(kfCopy,interpolation),
741 case Dali::Property::FLOAT:
743 const KeyFrameNumber* kf;
744 GetSpecialization(keyFrames, kf);
745 KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf);
746 AddAnimatorConnector( AnimatorConnector<float>::New( object,
747 target.propertyIndex,
748 target.componentIndex,
749 new KeyFrameNumberFunctor(kfCopy,interpolation),
755 case Dali::Property::VECTOR2:
757 const KeyFrameVector2* kf;
758 GetSpecialization(keyFrames, kf);
759 KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf);
760 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
761 target.propertyIndex,
762 target.componentIndex,
763 new KeyFrameVector2Functor(kfCopy,interpolation),
769 case Dali::Property::VECTOR3:
771 const KeyFrameVector3* kf;
772 GetSpecialization(keyFrames, kf);
773 KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf);
774 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
775 target.propertyIndex,
776 target.componentIndex,
777 new KeyFrameVector3Functor(kfCopy,interpolation),
783 case Dali::Property::VECTOR4:
785 const KeyFrameVector4* kf;
786 GetSpecialization(keyFrames, kf);
787 KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf);
788 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
789 target.propertyIndex,
790 target.componentIndex,
791 new KeyFrameVector4Functor(kfCopy,interpolation),
797 case Dali::Property::ROTATION:
799 const KeyFrameQuaternion* kf;
800 GetSpecialization(keyFrames, kf);
801 KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf);
802 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
803 target.propertyIndex,
804 target.componentIndex,
805 new KeyFrameQuaternionFunctor(kfCopy),
813 // non animatable types handled by keyframes
818 bool Animation::HasFinished()
820 bool hasFinished(false);
821 const int playedCount(mAnimation->GetPlayedCount());
823 // If the play count has been incremented, then another notification is required
824 mCurrentLoop = mAnimation->GetCurrentLoop();
826 if (playedCount > mNotificationCount)
828 // Note that only one signal is emitted, if the animation has been played repeatedly
829 mNotificationCount = playedCount;
833 mState = Dali::Animation::STOPPED;
839 Dali::Animation::AnimationSignalType& Animation::FinishedSignal()
841 return mFinishedSignal;
844 void Animation::EmitSignalFinish()
846 if ( !mFinishedSignal.Empty() )
848 Dali::Animation handle( this );
849 mFinishedSignal.Emit( handle );
852 // This callback is used internally, to avoid the overhead of using a signal.
853 if ( mFinishedCallback )
855 mFinishedCallback( mFinishedCallbackObject );
859 bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
861 bool connected( true );
862 Animation* animation = static_cast< Animation* >(object); // TypeRegistry guarantees that this is the correct type.
864 if( 0 == signalName.compare( SIGNAL_FINISHED ) )
866 animation->FinishedSignal().Connect( tracker, functor );
870 // signalName does not match any signal
877 void Animation::SetFinishedCallback( FinishedCallback callback, Object* object )
879 mFinishedCallback = callback;
880 mFinishedCallbackObject = object;
883 void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector )
885 DALI_ASSERT_DEBUG( NULL != connector );
887 connector->SetParent(*this);
889 mConnectors.PushBack( connector );
892 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward )
894 Animate( actor, path, forward, mDefaultAlpha, TimePeriod(mDurationSeconds) );
897 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha )
899 Animate( actor, path, forward, alpha, TimePeriod(mDurationSeconds) );
902 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period )
904 Animate( actor, path, forward, mDefaultAlpha, period );
907 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
909 ExtendDuration( period );
911 PathPtr pathCopy = Path::Clone(path);
914 AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
915 Dali::Actor::Property::POSITION,
916 Property::INVALID_COMPONENT_INDEX,
917 new PathPositionFunctor( pathCopy ),
921 //If forward is zero, PathRotationFunctor will always return the unit quaternion
922 if( forward != Vector3::ZERO )
925 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
926 Dali::Actor::Property::ORIENTATION,
927 Property::INVALID_COMPONENT_INDEX,
928 new PathRotationFunctor( pathCopy, forward ),
934 void Animation::Show(Actor& actor, float delaySeconds)
936 ExtendDuration( TimePeriod(delaySeconds, 0) );
938 AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
939 Dali::Actor::Property::VISIBLE,
940 Property::INVALID_COMPONENT_INDEX,
941 new AnimateToBoolean(SHOW_VALUE),
943 TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
946 void Animation::Hide(Actor& actor, float delaySeconds)
948 ExtendDuration( TimePeriod(delaySeconds, 0) );
950 AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
951 Dali::Actor::Property::VISIBLE,
952 Property::INVALID_COMPONENT_INDEX,
953 new AnimateToBoolean(HIDE_VALUE),
955 TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
958 bool Animation::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
961 Animation* animation = dynamic_cast<Animation*>( object );
965 if( 0 == actionName.compare( ACTION_PLAY ) )
967 if( Property::Value* value = attributes.Find("duration", Property::FLOAT) )
969 animation->SetDuration( value->Get<float>() );
975 else if( 0 == actionName.compare( ACTION_STOP ) )
980 else if( 0 == actionName.compare( ACTION_PAUSE ) )
990 void Animation::SetCurrentProgress(float progress)
992 if( mAnimation && progress >= mPlayRange.x && progress <= mPlayRange.y )
994 // mAnimation is being used in a separate thread; queue a message to set the current progress
995 SetCurrentProgressMessage( mEventThreadServices, *mAnimation, progress );
999 float Animation::GetCurrentProgress()
1003 return mAnimation->GetCurrentProgress();
1009 void Animation::ExtendDuration( const TimePeriod& timePeriod )
1011 float duration = timePeriod.delaySeconds + timePeriod.durationSeconds;
1013 if( duration > mDurationSeconds )
1015 SetDuration( duration );
1019 void Animation::SetSpeedFactor( float factor )
1023 mSpeedFactor = factor;
1024 SetSpeedFactorMessage( mEventThreadServices, *mAnimation, factor );
1028 float Animation::GetSpeedFactor() const
1030 return mSpeedFactor;
1033 void Animation::SetPlayRange( const Vector2& range)
1035 //Make sure the range specified is between 0.0 and 1.0
1036 if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
1038 Vector2 orderedRange( range );
1039 //If the range is not in order swap values
1040 if( range.x > range.y )
1042 orderedRange = Vector2(range.y, range.x);
1045 // Cache for public getters
1046 mPlayRange = orderedRange;
1048 // mAnimation is being used in a separate thread; queue a message to set play range
1049 SetPlayRangeMessage( mEventThreadServices, *mAnimation, orderedRange );
1053 Vector2 Animation::GetPlayRange() const
1059 } // namespace Internal