2 * Copyright (c) 2018 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/animation/alpha-function.h>
26 #include <dali/public-api/animation/time-period.h>
27 #include <dali/public-api/common/dali-common.h>
28 #include <dali/public-api/object/type-registry.h>
29 #include <dali/public-api/math/vector2.h>
30 #include <dali/public-api/math/radian.h>
31 #include <dali/internal/event/animation/animation-playlist.h>
32 #include <dali/internal/event/animation/animator-connector.h>
33 #include <dali/internal/event/animation/path-impl.h>
34 #include <dali/internal/event/common/notification-manager.h>
35 #include <dali/internal/event/common/property-helper.h>
36 #include <dali/internal/event/common/stage-impl.h>
37 #include <dali/internal/event/common/thread-local-storage.h>
38 #include <dali/internal/update/animation/scene-graph-animator.h>
39 #include <dali/internal/update/manager/update-manager.h>
41 using Dali::Internal::SceneGraph::UpdateManager;
42 using Dali::Internal::SceneGraph::AnimatorBase;
43 using Dali::Internal::SceneGraph::Shader;
51 static bool SHOW_VALUE = true;
52 static bool HIDE_VALUE = false;
59 const char* const SIGNAL_FINISHED = "finished";
63 const char* const ACTION_PLAY = "play";
64 const char* const ACTION_STOP = "stop";
65 const char* const ACTION_PAUSE = "pause";
69 return Dali::Animation::New(0.f);
72 TypeRegistration mType( typeid( Dali::Animation ), typeid( Dali::BaseHandle ), Create );
74 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &Animation::DoConnectSignal );
76 TypeAction action1( mType, ACTION_PLAY, &Animation::DoAction );
77 TypeAction action2( mType, ACTION_STOP, &Animation::DoAction );
78 TypeAction action3( mType, ACTION_PAUSE, &Animation::DoAction );
80 const Dali::Animation::EndAction DEFAULT_END_ACTION( Dali::Animation::Bake );
81 const Dali::Animation::EndAction DEFAULT_DISCONNECT_ACTION( Dali::Animation::BakeFinal );
82 const Dali::Animation::Interpolation DEFAULT_INTERPOLATION( Dali::Animation::Linear );
83 const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION( Dali::AlphaFunction::DEFAULT );
86 * Helper to tell if a property is animatable (if we have animators for it)
88 * @param type type to check
89 * @return true if animatable
91 inline bool IsAnimatable( Property::Type type )
93 bool animatable = false;
96 case Property::BOOLEAN :
97 case Property::FLOAT :
98 case Property::INTEGER :
99 case Property::VECTOR2 :
100 case Property::VECTOR3 :
101 case Property::VECTOR4 :
102 case Property::ROTATION :
107 case Property::MATRIX : // matrix is allowed as a scene graph property but there's no animators for it
108 case Property::MATRIX3 : // matrix3 is allowed as a scene graph property but there's no animators for it
109 case Property::NONE :
110 case Property::RECTANGLE :
111 case Property::STRING :
112 case Property::ARRAY :
114 case Property::EXTENTS :
123 * Helper to validate animation input values
125 * @param propertyType type of the property that is being animated
126 * @param destinationType type of the target
127 * @param period time period of the animation
129 void ValidateParameters( Property::Type propertyType, Property::Type destinationType, const TimePeriod& period )
131 // destination value has to be animatable
132 DALI_ASSERT_ALWAYS( IsAnimatable( propertyType ) && "Property type is not animatable" );
133 DALI_ASSERT_ALWAYS( IsAnimatable( destinationType ) && "Target value is not animatable" );
134 DALI_ASSERT_ALWAYS( propertyType == destinationType && "Property and target types don't match" );
135 DALI_ASSERT_ALWAYS( period.durationSeconds >= 0 && "Duration must be >=0" );
138 } // anonymous namespace
141 AnimationPtr Animation::New(float durationSeconds)
143 Stage* stage = Stage::GetCurrent();
147 AnimationPlaylist& playlist = stage->GetAnimationPlaylist();
149 if( durationSeconds < 0.0f )
151 DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
152 durationSeconds = 0.0f;
155 AnimationPtr animation = new Animation( *stage, playlist, durationSeconds, DEFAULT_END_ACTION, DEFAULT_DISCONNECT_ACTION, DEFAULT_ALPHA_FUNCTION );
157 // Second-phase construction
158 animation->Initialize();
168 Animation::Animation( EventThreadServices& eventThreadServices, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha )
169 : mAnimation( NULL ),
170 mEventThreadServices( eventThreadServices ),
171 mPlaylist( playlist ),
174 mConnectorTargetValues(),
175 mPlayRange( Vector2(0.0f,1.0f)),
176 mDurationSeconds( durationSeconds ),
178 mNotificationCount( 0 ),
181 mEndAction( endAction ),
182 mDisconnectAction( disconnectAction ),
183 mDefaultAlpha( defaultAlpha ),
184 mState(Dali::Animation::STOPPED),
185 mProgressReachedMarker( 0.0f ),
186 mDelaySeconds( 0.0f ),
187 mAutoReverseEnabled( false )
191 void Animation::Initialize()
193 // Connect to the animation playlist
194 mPlaylist.AnimationCreated( *this );
201 Animation::~Animation()
203 // Guard to allow handle destruction after Core has been destroyed
204 if ( Stage::IsInstalled() )
206 // Disconnect from the animation playlist
207 mPlaylist.AnimationDestroyed( *this );
209 DestroySceneObject();
215 void Animation::CreateSceneObject()
217 DALI_ASSERT_DEBUG( mAnimation == NULL );
219 // Create a new animation, Keep a const pointer to the animation.
220 mAnimation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mLoopCount, mEndAction, mDisconnectAction );
221 OwnerPointer< SceneGraph::Animation > transferOwnership( const_cast< SceneGraph::Animation* >( mAnimation ) );
222 AddAnimationMessage( mEventThreadServices.GetUpdateManager(), transferOwnership );
225 void Animation::DestroySceneObject()
227 if ( mAnimation != NULL )
229 // Remove animation using a message to the update manager
230 RemoveAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
235 void Animation::SetDuration(float seconds)
239 DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
243 mDurationSeconds = seconds;
245 // mAnimation is being used in a separate thread; queue a message to set the value
246 SetDurationMessage( mEventThreadServices, *mAnimation, seconds );
249 void Animation::SetProgressNotification( float progress )
251 // mAnimation is being used in a separate thread; queue a message to set the value
252 mProgressReachedMarker = progress;
255 float Animation::GetProgressNotification()
257 return mProgressReachedMarker;
260 float Animation::GetDuration() const
262 // This is not animatable; the cached value is up-to-date.
263 return mDurationSeconds;
266 void Animation::SetLooping(bool on)
268 SetLoopCount( on ? 0 : 1 );
271 void Animation::SetLoopCount(int32_t count)
273 // Cache for public getters
276 // mAnimation is being used in a separate thread; queue a message to set the value
277 SetLoopingMessage( mEventThreadServices, *mAnimation, mLoopCount );
280 int32_t Animation::GetLoopCount()
285 int32_t Animation::GetCurrentLoop()
290 bool Animation::IsLooping() const
292 return mLoopCount != 1;
295 void Animation::SetEndAction(EndAction action)
297 // Cache for public getters
300 // mAnimation is being used in a separate thread; queue a message to set the value
301 SetEndActionMessage( mEventThreadServices, *mAnimation, action );
304 Dali::Animation::EndAction Animation::GetEndAction() const
306 // This is not animatable; the cached value is up-to-date.
310 void Animation::SetDisconnectAction(EndAction action)
312 // Cache for public getters
313 mDisconnectAction = action;
315 // mAnimation is being used in a separate thread; queue a message to set the value
316 SetDisconnectActionMessage( mEventThreadServices, *mAnimation, action );
319 Dali::Animation::EndAction Animation::GetDisconnectAction() const
321 // This is not animatable; the cached value is up-to-date.
322 return mDisconnectAction;
325 void Animation::Play()
327 // Update the current playlist
328 mPlaylist.OnPlay( *this );
330 mState = Dali::Animation::PLAYING;
334 SendFinalProgressNotificationMessage();
336 // mAnimation is being used in a separate thread; queue a Play message
337 PlayAnimationMessage( mEventThreadServices, *mAnimation );
340 void Animation::PlayFrom( float progress )
342 if( progress >= mPlayRange.x && progress <= mPlayRange.y )
344 // Update the current playlist
345 mPlaylist.OnPlay( *this );
347 mState = Dali::Animation::PLAYING;
351 SendFinalProgressNotificationMessage();
353 // mAnimation is being used in a separate thread; queue a Play message
354 PlayAnimationFromMessage( mEventThreadServices, *mAnimation, progress );
358 void Animation::PlayAfter( float delaySeconds )
360 // The negative delay means play immediately.
361 delaySeconds = std::max( 0.f, delaySeconds );
363 mDelaySeconds = delaySeconds;
365 // Update the current playlist
366 mPlaylist.OnPlay( *this );
368 mState = Dali::Animation::PLAYING;
372 SendFinalProgressNotificationMessage();
374 // mAnimation is being used in a separate thread; queue a message to set the value
375 PlayAfterMessage( mEventThreadServices, *mAnimation, delaySeconds );
378 void Animation::Pause()
380 mState = Dali::Animation::PAUSED;
382 // mAnimation is being used in a separate thread; queue a Pause message
383 PauseAnimationMessage( mEventThreadServices, *mAnimation );
386 Dali::Animation::State Animation::GetState() const
391 void Animation::Stop()
393 mState = Dali::Animation::STOPPED;
395 // mAnimation is being used in a separate thread; queue a Stop message
396 StopAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
399 void Animation::Clear()
401 DALI_ASSERT_DEBUG(mAnimation);
403 // Remove all the connectors
406 // Reset the connector target values
407 mConnectorTargetValues.clear();
409 // Replace the old scene-object with a new one
410 DestroySceneObject();
413 // Reset the notification count, since the new scene-object has never been played
414 mNotificationCount = 0;
416 // Update the current playlist
417 mPlaylist.OnClear( *this );
420 void Animation::AnimateBy( Property& target, Property::Value& relativeValue )
422 AnimateBy( target, relativeValue, mDefaultAlpha, TimePeriod(mDurationSeconds) );
425 void Animation::AnimateBy( Property& target, Property::Value& relativeValue, AlphaFunction alpha )
427 AnimateBy( target, relativeValue, alpha, TimePeriod(mDurationSeconds) );
430 void Animation::AnimateBy( Property& target, Property::Value& relativeValue, TimePeriod period )
432 AnimateBy( target, relativeValue, mDefaultAlpha, period );
435 void Animation::AnimateBy( Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period )
437 Object& object = GetImplementation(target.object);
438 const Property::Type propertyType = object.GetPropertyType( target.propertyIndex );
439 const Property::Type destinationType = relativeValue.GetType();
441 // validate animation parameters, if component index is set then use float as checked type
442 ValidateParameters( (target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? propertyType : Property::FLOAT,
443 destinationType, period );
445 ExtendDuration(period);
447 // Store data to later notify the object that its property is being animated
448 ConnectorTargetValues connectorPair;
449 connectorPair.targetValue = relativeValue;
450 connectorPair.connectorIndex = mConnectors.Count();
451 connectorPair.timePeriod = period;
452 connectorPair.animatorType = Animation::BY;
453 mConnectorTargetValues.push_back( connectorPair );
455 // using destination type so component animation gets correct type
456 switch ( destinationType )
458 case Property::BOOLEAN:
460 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
461 target.propertyIndex,
462 target.componentIndex,
463 new AnimateByBoolean(relativeValue.Get<bool>()),
469 case Property::INTEGER:
471 AddAnimatorConnector( AnimatorConnector<int32_t>::New( object,
472 target.propertyIndex,
473 target.componentIndex,
474 new AnimateByInteger(relativeValue.Get<int32_t>()),
480 case Property::FLOAT:
482 AddAnimatorConnector( AnimatorConnector<float>::New( object,
483 target.propertyIndex,
484 target.componentIndex,
485 new AnimateByFloat(relativeValue.Get<float>()),
491 case Property::VECTOR2:
493 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
494 target.propertyIndex,
495 target.componentIndex,
496 new AnimateByVector2(relativeValue.Get<Vector2>()),
502 case Property::VECTOR3:
504 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
505 target.propertyIndex,
506 target.componentIndex,
507 new AnimateByVector3(relativeValue.Get<Vector3>()),
513 case Property::VECTOR4:
515 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
516 target.propertyIndex,
517 target.componentIndex,
518 new AnimateByVector4(relativeValue.Get<Vector4>()),
524 case Property::ROTATION:
526 AngleAxis angleAxis = relativeValue.Get<AngleAxis>();
528 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
529 target.propertyIndex,
530 target.componentIndex,
531 new RotateByAngleAxis(angleAxis.angle, angleAxis.axis),
539 // non animatable types handled already
544 void Animation::AnimateTo( Property& target, Property::Value& destinationValue )
546 AnimateTo( target, destinationValue, mDefaultAlpha, TimePeriod(mDurationSeconds) );
549 void Animation::AnimateTo( Property& target, Property::Value& destinationValue, AlphaFunction alpha )
551 AnimateTo( target, destinationValue, alpha, TimePeriod(mDurationSeconds));
554 void Animation::AnimateTo( Property& target, Property::Value& destinationValue, TimePeriod period )
556 AnimateTo( target, destinationValue, mDefaultAlpha, period );
559 void Animation::AnimateTo( Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period )
561 Object& object = GetImplementation( target.object );
562 const Property::Type propertyType = object.GetPropertyType( target.propertyIndex );
563 const Property::Type destinationType = destinationValue.GetType();
565 // validate animation parameters, if component index is set then use float as checked type
566 ValidateParameters( (target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? propertyType : Property::FLOAT,
567 destinationType, period );
569 ExtendDuration( period );
571 // Store data to later notify the object that its property is being animated
572 ConnectorTargetValues connectorPair;
573 connectorPair.targetValue = destinationValue;
574 connectorPair.connectorIndex = mConnectors.Count();
575 connectorPair.timePeriod = period;
576 connectorPair.animatorType = Animation::TO;
577 mConnectorTargetValues.push_back( connectorPair );
579 // using destination type so component animation gets correct type
580 switch ( destinationType )
582 case Property::BOOLEAN:
584 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
585 target.propertyIndex,
586 target.componentIndex,
587 new AnimateToBoolean( destinationValue.Get<bool>() ),
593 case Property::INTEGER:
595 AddAnimatorConnector( AnimatorConnector<int32_t>::New( object,
596 target.propertyIndex,
597 target.componentIndex,
598 new AnimateToInteger( destinationValue.Get<int32_t>() ),
604 case Property::FLOAT:
606 AddAnimatorConnector( AnimatorConnector<float>::New( object,
607 target.propertyIndex,
608 target.componentIndex,
609 new AnimateToFloat( destinationValue.Get<float>() ),
615 case Property::VECTOR2:
617 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
618 target.propertyIndex,
619 target.componentIndex,
620 new AnimateToVector2( destinationValue.Get<Vector2>() ),
626 case Property::VECTOR3:
628 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
629 target.propertyIndex,
630 target.componentIndex,
631 new AnimateToVector3( destinationValue.Get<Vector3>() ),
637 case Property::VECTOR4:
639 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
640 target.propertyIndex,
641 target.componentIndex,
642 new AnimateToVector4( destinationValue.Get<Vector4>() ),
648 case Property::ROTATION:
650 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
651 target.propertyIndex,
652 target.componentIndex,
653 new RotateToQuaternion( destinationValue.Get<Quaternion>() ),
661 // non animatable types handled already
666 void Animation::AnimateBetween( Property target, const KeyFrames& keyFrames )
668 AnimateBetween( target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION );
671 void Animation::AnimateBetween( Property target, const KeyFrames& keyFrames, Interpolation interpolation )
673 AnimateBetween( target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), interpolation );
676 void Animation::AnimateBetween( Property target, const KeyFrames& keyFrames, TimePeriod period )
678 AnimateBetween( target, keyFrames, mDefaultAlpha, period, DEFAULT_INTERPOLATION );
681 void Animation::AnimateBetween( Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation )
683 AnimateBetween( target, keyFrames, mDefaultAlpha, period, interpolation );
686 void Animation::AnimateBetween( Property target, const KeyFrames& keyFrames, AlphaFunction alpha )
688 AnimateBetween( target, keyFrames, alpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION );
691 void Animation::AnimateBetween( Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation )
693 AnimateBetween( target, keyFrames, alpha, TimePeriod(mDurationSeconds), interpolation );
696 void Animation::AnimateBetween( Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period )
698 AnimateBetween( target, keyFrames, alpha, period, DEFAULT_INTERPOLATION );
701 void Animation::AnimateBetween( Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation )
703 Object& object = GetImplementation( target.object );
704 const Property::Type propertyType = object.GetPropertyType( target.propertyIndex );
705 const Property::Type destinationType = keyFrames.GetType();
707 // validate animation parameters, if component index is set then use float as checked type
708 ValidateParameters( (target.componentIndex == Property::INVALID_COMPONENT_INDEX) ? propertyType : Property::FLOAT,
709 destinationType, period );
711 ExtendDuration( period );
713 // Store data to later notify the object that its property is being animated
714 ConnectorTargetValues connectorPair;
715 connectorPair.targetValue = keyFrames.GetLastKeyFrameValue();
716 connectorPair.connectorIndex = mConnectors.Count();
717 connectorPair.timePeriod = period;
718 connectorPair.animatorType = BETWEEN;
719 mConnectorTargetValues.push_back( connectorPair );
721 // using destination type so component animation gets correct type
722 switch( destinationType )
724 case Dali::Property::BOOLEAN:
726 const KeyFrameBoolean* kf;
727 GetSpecialization(keyFrames, kf);
728 KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf);
729 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
730 target.propertyIndex,
731 target.componentIndex,
732 new KeyFrameBooleanFunctor(kfCopy),
738 case Dali::Property::INTEGER:
740 const KeyFrameInteger* kf;
741 GetSpecialization(keyFrames, kf);
742 KeyFrameIntegerPtr kfCopy = KeyFrameInteger::Clone(*kf);
743 AddAnimatorConnector( AnimatorConnector<int32_t>::New( object,
744 target.propertyIndex,
745 target.componentIndex,
746 new KeyFrameIntegerFunctor(kfCopy,interpolation),
752 case Dali::Property::FLOAT:
754 const KeyFrameNumber* kf;
755 GetSpecialization(keyFrames, kf);
756 KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf);
757 AddAnimatorConnector( AnimatorConnector<float>::New( object,
758 target.propertyIndex,
759 target.componentIndex,
760 new KeyFrameNumberFunctor(kfCopy,interpolation),
766 case Dali::Property::VECTOR2:
768 const KeyFrameVector2* kf;
769 GetSpecialization(keyFrames, kf);
770 KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf);
771 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
772 target.propertyIndex,
773 target.componentIndex,
774 new KeyFrameVector2Functor(kfCopy,interpolation),
780 case Dali::Property::VECTOR3:
782 const KeyFrameVector3* kf;
783 GetSpecialization(keyFrames, kf);
784 KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf);
785 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
786 target.propertyIndex,
787 target.componentIndex,
788 new KeyFrameVector3Functor(kfCopy,interpolation),
794 case Dali::Property::VECTOR4:
796 const KeyFrameVector4* kf;
797 GetSpecialization(keyFrames, kf);
798 KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf);
799 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
800 target.propertyIndex,
801 target.componentIndex,
802 new KeyFrameVector4Functor(kfCopy,interpolation),
808 case Dali::Property::ROTATION:
810 const KeyFrameQuaternion* kf;
811 GetSpecialization(keyFrames, kf);
812 KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf);
813 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
814 target.propertyIndex,
815 target.componentIndex,
816 new KeyFrameQuaternionFunctor(kfCopy),
824 // non animatable types handled by keyframes
829 bool Animation::HasFinished()
831 bool hasFinished(false);
832 const int32_t playedCount(mAnimation->GetPlayedCount());
834 // If the play count has been incremented, then another notification is required
835 mCurrentLoop = mAnimation->GetCurrentLoop();
837 if (playedCount > mNotificationCount)
839 // Note that only one signal is emitted, if the animation has been played repeatedly
840 mNotificationCount = playedCount;
844 mState = Dali::Animation::STOPPED;
850 Dali::Animation::AnimationSignalType& Animation::FinishedSignal()
852 return mFinishedSignal;
855 Dali::Animation::AnimationSignalType& Animation::ProgressReachedSignal()
857 return mProgressReachedSignal;
860 void Animation::EmitSignalFinish()
862 if ( !mFinishedSignal.Empty() )
864 Dali::Animation handle( this );
865 mFinishedSignal.Emit( handle );
869 void Animation::EmitSignalProgressReached()
871 if ( !mProgressReachedSignal.Empty() )
873 Dali::Animation handle( this );
874 mProgressReachedSignal.Emit( handle );
878 bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
880 bool connected( true );
881 Animation* animation = static_cast< Animation* >(object); // TypeRegistry guarantees that this is the correct type.
883 if( 0 == signalName.compare( SIGNAL_FINISHED ) )
885 animation->FinishedSignal().Connect( tracker, functor );
889 // signalName does not match any signal
896 void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector )
898 DALI_ASSERT_DEBUG( NULL != connector );
900 connector->SetParent(*this);
902 mConnectors.PushBack( connector );
905 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward )
907 Animate( actor, path, forward, mDefaultAlpha, TimePeriod(mDurationSeconds) );
910 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha )
912 Animate( actor, path, forward, alpha, TimePeriod(mDurationSeconds) );
915 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period )
917 Animate( actor, path, forward, mDefaultAlpha, period );
920 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
922 ExtendDuration( period );
924 PathPtr pathCopy = Path::Clone(path);
927 AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
928 Dali::Actor::Property::POSITION,
929 Property::INVALID_COMPONENT_INDEX,
930 new PathPositionFunctor( pathCopy ),
934 //If forward is zero, PathRotationFunctor will always return the unit quaternion
935 if( forward != Vector3::ZERO )
938 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
939 Dali::Actor::Property::ORIENTATION,
940 Property::INVALID_COMPONENT_INDEX,
941 new PathRotationFunctor( pathCopy, forward ),
947 void Animation::Show(Actor& actor, float delaySeconds)
949 ExtendDuration( TimePeriod(delaySeconds, 0) );
951 AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
952 Dali::Actor::Property::VISIBLE,
953 Property::INVALID_COMPONENT_INDEX,
954 new AnimateToBoolean(SHOW_VALUE),
956 TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
959 void Animation::Hide(Actor& actor, float delaySeconds)
961 ExtendDuration( TimePeriod(delaySeconds, 0) );
963 AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
964 Dali::Actor::Property::VISIBLE,
965 Property::INVALID_COMPONENT_INDEX,
966 new AnimateToBoolean(HIDE_VALUE),
968 TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
971 bool Animation::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
974 Animation* animation = dynamic_cast<Animation*>( object );
978 if( 0 == actionName.compare( ACTION_PLAY ) )
980 if( Property::Value* value = attributes.Find("duration", Property::FLOAT) )
982 animation->SetDuration( value->Get<float>() );
988 else if( 0 == actionName.compare( ACTION_STOP ) )
993 else if( 0 == actionName.compare( ACTION_PAUSE ) )
1003 void Animation::SetCurrentProgress(float progress)
1005 if( mAnimation && progress >= mPlayRange.x && progress <= mPlayRange.y )
1007 // mAnimation is being used in a separate thread; queue a message to set the current progress
1008 SetCurrentProgressMessage( mEventThreadServices, *mAnimation, progress );
1012 float Animation::GetCurrentProgress()
1016 return mAnimation->GetCurrentProgress();
1022 void Animation::ExtendDuration( const TimePeriod& timePeriod )
1024 float duration = timePeriod.delaySeconds + timePeriod.durationSeconds;
1026 if( duration > mDurationSeconds )
1028 SetDuration( duration );
1032 void Animation::SetSpeedFactor( float factor )
1036 mSpeedFactor = factor;
1037 SetSpeedFactorMessage( mEventThreadServices, *mAnimation, factor );
1041 float Animation::GetSpeedFactor() const
1043 return mSpeedFactor;
1046 void Animation::SetPlayRange( const Vector2& range)
1048 //Make sure the range specified is between 0.0 and 1.0
1049 if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
1051 Vector2 orderedRange( range );
1052 //If the range is not in order swap values
1053 if( range.x > range.y )
1055 orderedRange = Vector2(range.y, range.x);
1058 // Cache for public getters
1059 mPlayRange = orderedRange;
1061 // mAnimation is being used in a separate thread; queue a message to set play range
1062 SetPlayRangeMessage( mEventThreadServices, *mAnimation, orderedRange );
1066 Vector2 Animation::GetPlayRange() const
1071 void Animation::SetLoopingMode( Dali::Animation::LoopingMode loopingMode )
1073 mAutoReverseEnabled = ( loopingMode == Dali::Animation::LoopingMode::AUTO_REVERSE );
1075 // mAnimation is being used in a separate thread; queue a message to set play range
1076 SetLoopingModeMessage( mEventThreadServices, *mAnimation, mAutoReverseEnabled );
1079 Dali::Animation::LoopingMode Animation::GetLoopingMode() const
1081 return mAutoReverseEnabled ? Dali::Animation::AUTO_REVERSE : Dali::Animation::RESTART;
1084 bool Animation::CompareConnectorEndTimes( const Animation::ConnectorTargetValues& lhs, const Animation::ConnectorTargetValues& rhs )
1086 return ( ( lhs.timePeriod.delaySeconds + lhs.timePeriod.durationSeconds ) < ( rhs.timePeriod.delaySeconds + rhs.timePeriod.durationSeconds ) );
1089 void Animation::NotifyObjects()
1091 if( mEndAction != EndAction::Discard ) // If the animation is discarded, then we do not want to change the target values
1093 // Sort according to end time with earlier end times coming first, if the end time is the same, then the connectors are not moved
1094 std::stable_sort( mConnectorTargetValues.begin(), mConnectorTargetValues.end(), CompareConnectorEndTimes );
1096 // Loop through all connector target values sorted by increasing end time
1097 ConnectorTargetValuesContainer::const_iterator iter = mConnectorTargetValues.begin();
1098 const ConnectorTargetValuesContainer::const_iterator endIter = mConnectorTargetValues.end();
1099 for( ; iter != endIter; ++iter )
1101 AnimatorConnectorBase* connector = mConnectors[ iter->connectorIndex ];
1103 Object* object = connector->GetObject();
1106 object->NotifyPropertyAnimation( *this, connector->GetPropertyIndex(), iter->targetValue, iter->animatorType );
1113 void Animation::SendFinalProgressNotificationMessage()
1115 if ( mProgressReachedMarker > 0.0f )
1117 float progressMarkerSeconds = mDurationSeconds * mProgressReachedMarker;
1118 SetProgressNotificationMessage( mEventThreadServices, *mAnimation, progressMarkerSeconds );
1122 } // namespace Internal