2 * Copyright (c) 2017 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 );
88 AnimationPtr Animation::New(float durationSeconds)
90 Stage* stage = Stage::GetCurrent();
94 AnimationPlaylist& playlist = stage->GetAnimationPlaylist();
96 if( durationSeconds < 0.0f )
98 DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
99 durationSeconds = 0.0f;
102 AnimationPtr animation = new Animation( *stage, playlist, durationSeconds, DEFAULT_END_ACTION, DEFAULT_DISCONNECT_ACTION, DEFAULT_ALPHA_FUNCTION );
104 // Second-phase construction
105 animation->Initialize();
115 Animation::Animation( EventThreadServices& eventThreadServices, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha )
116 : mAnimation( NULL ),
117 mEventThreadServices( eventThreadServices ),
118 mPlaylist( playlist ),
121 mConnectorTargetValues(),
122 mPlayRange( Vector2(0.0f,1.0f)),
123 mDurationSeconds( durationSeconds ),
125 mNotificationCount( 0 ),
128 mEndAction( endAction ),
129 mDisconnectAction( disconnectAction ),
130 mDefaultAlpha( defaultAlpha ),
131 mState(Dali::Animation::STOPPED),
132 mProgressReachedMarker( 0.0f ),
133 mDelaySeconds( 0.0f ),
134 mAutoReverseEnabled( false )
138 void Animation::Initialize()
140 // Connect to the animation playlist
141 mPlaylist.AnimationCreated( *this );
148 Animation::~Animation()
150 // Guard to allow handle destruction after Core has been destroyed
151 if ( Stage::IsInstalled() )
153 // Disconnect from the animation playlist
154 mPlaylist.AnimationDestroyed( *this );
156 DestroySceneObject();
162 void Animation::CreateSceneObject()
164 DALI_ASSERT_DEBUG( mAnimation == NULL );
166 // Create a new animation, Keep a const pointer to the animation.
167 mAnimation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mLoopCount, mEndAction, mDisconnectAction );
168 OwnerPointer< SceneGraph::Animation > transferOwnership( const_cast< SceneGraph::Animation* >( mAnimation ) );
169 AddAnimationMessage( mEventThreadServices.GetUpdateManager(), transferOwnership );
172 void Animation::DestroySceneObject()
174 if ( mAnimation != NULL )
176 // Remove animation using a message to the update manager
177 RemoveAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
182 void Animation::SetDuration(float seconds)
186 DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
190 // Cache for public getters
191 mDurationSeconds = seconds;
193 // mAnimation is being used in a separate thread; queue a message to set the value
194 SetDurationMessage( mEventThreadServices, *mAnimation, seconds );
197 void Animation::SetProgressNotification( float progress )
199 // mAnimation is being used in a separate thread; queue a message to set the value
200 mProgressReachedMarker = progress;
203 float Animation::GetProgressNotification()
205 return mProgressReachedMarker;
208 float Animation::GetDuration() const
210 // This is not animatable; the cached value is up-to-date.
211 return mDurationSeconds;
214 void Animation::SetLooping(bool on)
216 SetLoopCount( on ? 0 : 1 );
219 void Animation::SetLoopCount(int count)
221 // Cache for public getters
224 // mAnimation is being used in a separate thread; queue a message to set the value
225 SetLoopingMessage( mEventThreadServices, *mAnimation, mLoopCount );
228 int Animation::GetLoopCount()
233 int Animation::GetCurrentLoop()
238 bool Animation::IsLooping() const
240 return mLoopCount != 1;
243 void Animation::SetEndAction(EndAction action)
245 // Cache for public getters
248 // mAnimation is being used in a separate thread; queue a message to set the value
249 SetEndActionMessage( mEventThreadServices, *mAnimation, action );
252 Dali::Animation::EndAction Animation::GetEndAction() const
254 // This is not animatable; the cached value is up-to-date.
258 void Animation::SetDisconnectAction(EndAction action)
260 // Cache for public getters
261 mDisconnectAction = action;
263 // mAnimation is being used in a separate thread; queue a message to set the value
264 SetDisconnectActionMessage( mEventThreadServices, *mAnimation, action );
267 Dali::Animation::EndAction Animation::GetDisconnectAction() const
269 // This is not animatable; the cached value is up-to-date.
270 return mDisconnectAction;
273 void Animation::Play()
275 // Update the current playlist
276 mPlaylist.OnPlay( *this );
278 mState = Dali::Animation::PLAYING;
282 SendFinalProgressNotificationMessage();
284 // mAnimation is being used in a separate thread; queue a Play message
285 PlayAnimationMessage( mEventThreadServices, *mAnimation );
288 void Animation::PlayFrom( float progress )
290 if( progress >= mPlayRange.x && progress <= mPlayRange.y )
292 // Update the current playlist
293 mPlaylist.OnPlay( *this );
295 mState = Dali::Animation::PLAYING;
299 SendFinalProgressNotificationMessage();
301 // mAnimation is being used in a separate thread; queue a Play message
302 PlayAnimationFromMessage( mEventThreadServices, *mAnimation, progress );
306 void Animation::PlayAfter( float delaySeconds )
308 // The negative delay means play immediately.
309 delaySeconds = std::max( 0.f, delaySeconds );
311 mDelaySeconds = delaySeconds;
313 // Update the current playlist
314 mPlaylist.OnPlay( *this );
316 mState = Dali::Animation::PLAYING;
320 SendFinalProgressNotificationMessage();
322 // mAnimation is being used in a separate thread; queue a message to set the value
323 PlayAfterMessage( mEventThreadServices, *mAnimation, delaySeconds );
326 void Animation::Pause()
328 mState = Dali::Animation::PAUSED;
330 // mAnimation is being used in a separate thread; queue a Pause message
331 PauseAnimationMessage( mEventThreadServices, *mAnimation );
334 Dali::Animation::State Animation::GetState() const
339 void Animation::Stop()
341 mState = Dali::Animation::STOPPED;
343 // mAnimation is being used in a separate thread; queue a Stop message
344 StopAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
347 void Animation::Clear()
349 DALI_ASSERT_DEBUG(mAnimation);
351 // Remove all the connectors
354 // Reset the connector target values
355 mConnectorTargetValues.clear();
357 // Replace the old scene-object with a new one
358 DestroySceneObject();
361 // Reset the notification count, since the new scene-object has never been played
362 mNotificationCount = 0;
364 // Update the current playlist
365 mPlaylist.OnClear( *this );
368 void Animation::AnimateBy(Property& target, Property::Value& relativeValue)
370 AnimateBy(target, relativeValue, mDefaultAlpha, TimePeriod(mDurationSeconds));
373 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha)
375 AnimateBy(target, relativeValue, alpha, TimePeriod(mDurationSeconds));
378 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period)
380 AnimateBy(target, relativeValue, mDefaultAlpha, period);
383 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period)
385 Object& object = GetImplementation(target.object);
386 const Property::Type targetType = object.GetPropertyType(target.propertyIndex);
387 const Property::Type destinationType = relativeValue.GetType();
389 if ( object.GetPropertyComponentIndex( target.propertyIndex ) != Property::INVALID_COMPONENT_INDEX )
391 DALI_ASSERT_ALWAYS(Property::FLOAT == destinationType && "Animated value and Property type don't match");
395 DALI_ASSERT_ALWAYS(targetType == destinationType && "Animated value and Property type don't match");
398 ExtendDuration(period);
400 // Store data to later notify the object that its property is being animated
401 ConnectorTargetValues connectorPair;
402 connectorPair.targetValue = relativeValue;
403 connectorPair.connectorIndex = mConnectors.Count();
404 connectorPair.timePeriod = period;
405 connectorPair.animatorType = Animation::BY;
406 mConnectorTargetValues.push_back( connectorPair );
408 switch ( targetType )
410 case Property::BOOLEAN:
412 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
413 target.propertyIndex,
414 target.componentIndex,
415 new AnimateByBoolean(relativeValue.Get<bool>()),
421 case Property::INTEGER:
423 AddAnimatorConnector( AnimatorConnector<int>::New( object,
424 target.propertyIndex,
425 target.componentIndex,
426 new AnimateByInteger(relativeValue.Get<int>()),
432 case Property::FLOAT:
434 AddAnimatorConnector( AnimatorConnector<float>::New( object,
435 target.propertyIndex,
436 target.componentIndex,
437 new AnimateByFloat(relativeValue.Get<float>()),
443 case Property::VECTOR2:
445 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
446 target.propertyIndex,
447 target.componentIndex,
448 new AnimateByVector2(relativeValue.Get<Vector2>()),
454 case Property::VECTOR3:
456 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
457 target.propertyIndex,
458 target.componentIndex,
459 new AnimateByVector3(relativeValue.Get<Vector3>()),
465 case Property::VECTOR4:
467 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
468 target.propertyIndex,
469 target.componentIndex,
470 new AnimateByVector4(relativeValue.Get<Vector4>()),
476 case Property::ROTATION:
478 AngleAxis angleAxis = relativeValue.Get<AngleAxis>();
480 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
481 target.propertyIndex,
482 target.componentIndex,
483 new RotateByAngleAxis(angleAxis.angle, angleAxis.axis),
491 // non animatable types handled already
496 void Animation::AnimateTo(Property& target, Property::Value& destinationValue)
498 AnimateTo(target, destinationValue, mDefaultAlpha, TimePeriod(mDurationSeconds));
501 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha)
503 AnimateTo(target, destinationValue, alpha, TimePeriod(mDurationSeconds));
506 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period)
508 AnimateTo(target, destinationValue, mDefaultAlpha, period);
511 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
513 Object& object = GetImplementation(target.object);
515 AnimateTo( object, target.propertyIndex, target.componentIndex, destinationValue, alpha, period );
518 void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
520 Property::Type targetType = targetObject.GetPropertyType(targetPropertyIndex);
521 if( componentIndex != Property::INVALID_COMPONENT_INDEX )
523 if( ( targetType == Property::VECTOR2 ) ||
524 ( targetType == Property::VECTOR3 ) ||
525 ( targetType == Property::VECTOR4 ) )
527 targetType = Property::FLOAT;
530 const Property::Type destinationType = destinationValue.GetType();
531 DALI_ASSERT_ALWAYS( targetType == destinationType && "Animated value and Property type don't match" );
533 ExtendDuration( period );
535 // Store data to later notify the object that its property is being animated
536 ConnectorTargetValues connectorPair;
537 connectorPair.targetValue = destinationValue;
538 connectorPair.connectorIndex = mConnectors.Count();
539 connectorPair.timePeriod = period;
540 connectorPair.animatorType = Animation::TO;
541 mConnectorTargetValues.push_back( connectorPair );
543 switch ( destinationType )
545 case Property::BOOLEAN:
547 AddAnimatorConnector( AnimatorConnector<bool>::New( targetObject,
550 new AnimateToBoolean( destinationValue.Get<bool>() ),
556 case Property::INTEGER:
558 AddAnimatorConnector( AnimatorConnector<int>::New( targetObject,
561 new AnimateToInteger( destinationValue.Get<int>() ),
567 case Property::FLOAT:
569 AddAnimatorConnector( AnimatorConnector<float>::New( targetObject,
572 new AnimateToFloat( destinationValue.Get<float>() ),
578 case Property::VECTOR2:
580 AddAnimatorConnector( AnimatorConnector<Vector2>::New( targetObject,
583 new AnimateToVector2( destinationValue.Get<Vector2>() ),
589 case Property::VECTOR3:
591 AddAnimatorConnector( AnimatorConnector<Vector3>::New( targetObject,
594 new AnimateToVector3( destinationValue.Get<Vector3>() ),
600 case Property::VECTOR4:
602 AddAnimatorConnector( AnimatorConnector<Vector4>::New( targetObject,
605 new AnimateToVector4( destinationValue.Get<Vector4>() ),
611 case Property::ROTATION:
613 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( targetObject,
616 new RotateToQuaternion( destinationValue.Get<Quaternion>() ),
624 // non animatable types handled already
629 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
631 AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION );
634 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation )
636 AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), interpolation );
639 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period)
641 AnimateBetween(target, keyFrames, mDefaultAlpha, period, DEFAULT_INTERPOLATION);
644 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
646 AnimateBetween(target, keyFrames, mDefaultAlpha, period, interpolation);
649 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha)
651 AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION);
654 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
656 AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), interpolation);
659 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
661 AnimateBetween(target, keyFrames, alpha, period, DEFAULT_INTERPOLATION);
664 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation)
666 Object& object = GetImplementation( target.object );
668 ExtendDuration( period );
670 // Store data to later notify the object that its property is being animated
671 ConnectorTargetValues connectorPair;
672 connectorPair.targetValue = keyFrames.GetLastKeyFrameValue();
673 connectorPair.connectorIndex = mConnectors.Count();
674 connectorPair.timePeriod = period;
675 connectorPair.animatorType = BETWEEN;
676 mConnectorTargetValues.push_back( connectorPair );
678 switch(keyFrames.GetType())
680 case Dali::Property::BOOLEAN:
682 const KeyFrameBoolean* kf;
683 GetSpecialization(keyFrames, kf);
684 KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf);
685 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
686 target.propertyIndex,
687 target.componentIndex,
688 new KeyFrameBooleanFunctor(kfCopy),
694 case Dali::Property::INTEGER:
696 const KeyFrameInteger* kf;
697 GetSpecialization(keyFrames, kf);
698 KeyFrameIntegerPtr kfCopy = KeyFrameInteger::Clone(*kf);
699 AddAnimatorConnector( AnimatorConnector<int>::New( object,
700 target.propertyIndex,
701 target.componentIndex,
702 new KeyFrameIntegerFunctor(kfCopy,interpolation),
708 case Dali::Property::FLOAT:
710 const KeyFrameNumber* kf;
711 GetSpecialization(keyFrames, kf);
712 KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf);
713 AddAnimatorConnector( AnimatorConnector<float>::New( object,
714 target.propertyIndex,
715 target.componentIndex,
716 new KeyFrameNumberFunctor(kfCopy,interpolation),
722 case Dali::Property::VECTOR2:
724 const KeyFrameVector2* kf;
725 GetSpecialization(keyFrames, kf);
726 KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf);
727 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
728 target.propertyIndex,
729 target.componentIndex,
730 new KeyFrameVector2Functor(kfCopy,interpolation),
736 case Dali::Property::VECTOR3:
738 const KeyFrameVector3* kf;
739 GetSpecialization(keyFrames, kf);
740 KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf);
741 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
742 target.propertyIndex,
743 target.componentIndex,
744 new KeyFrameVector3Functor(kfCopy,interpolation),
750 case Dali::Property::VECTOR4:
752 const KeyFrameVector4* kf;
753 GetSpecialization(keyFrames, kf);
754 KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf);
755 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
756 target.propertyIndex,
757 target.componentIndex,
758 new KeyFrameVector4Functor(kfCopy,interpolation),
764 case Dali::Property::ROTATION:
766 const KeyFrameQuaternion* kf;
767 GetSpecialization(keyFrames, kf);
768 KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf);
769 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
770 target.propertyIndex,
771 target.componentIndex,
772 new KeyFrameQuaternionFunctor(kfCopy),
780 // non animatable types handled by keyframes
785 bool Animation::HasFinished()
787 bool hasFinished(false);
788 const int playedCount(mAnimation->GetPlayedCount());
790 // If the play count has been incremented, then another notification is required
791 mCurrentLoop = mAnimation->GetCurrentLoop();
793 if (playedCount > mNotificationCount)
795 // Note that only one signal is emitted, if the animation has been played repeatedly
796 mNotificationCount = playedCount;
800 mState = Dali::Animation::STOPPED;
806 Dali::Animation::AnimationSignalType& Animation::FinishedSignal()
808 return mFinishedSignal;
811 Dali::Animation::AnimationSignalType& Animation::ProgressReachedSignal()
813 return mProgressReachedSignal;
816 void Animation::EmitSignalFinish()
818 if ( !mFinishedSignal.Empty() )
820 Dali::Animation handle( this );
821 mFinishedSignal.Emit( handle );
825 void Animation::EmitSignalProgressReached()
827 if ( !mProgressReachedSignal.Empty() )
829 Dali::Animation handle( this );
830 mProgressReachedSignal.Emit( handle );
834 bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
836 bool connected( true );
837 Animation* animation = static_cast< Animation* >(object); // TypeRegistry guarantees that this is the correct type.
839 if( 0 == signalName.compare( SIGNAL_FINISHED ) )
841 animation->FinishedSignal().Connect( tracker, functor );
845 // signalName does not match any signal
852 void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector )
854 DALI_ASSERT_DEBUG( NULL != connector );
856 connector->SetParent(*this);
858 mConnectors.PushBack( connector );
861 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward )
863 Animate( actor, path, forward, mDefaultAlpha, TimePeriod(mDurationSeconds) );
866 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha )
868 Animate( actor, path, forward, alpha, TimePeriod(mDurationSeconds) );
871 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period )
873 Animate( actor, path, forward, mDefaultAlpha, period );
876 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
878 ExtendDuration( period );
880 PathPtr pathCopy = Path::Clone(path);
883 AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
884 Dali::Actor::Property::POSITION,
885 Property::INVALID_COMPONENT_INDEX,
886 new PathPositionFunctor( pathCopy ),
890 //If forward is zero, PathRotationFunctor will always return the unit quaternion
891 if( forward != Vector3::ZERO )
894 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
895 Dali::Actor::Property::ORIENTATION,
896 Property::INVALID_COMPONENT_INDEX,
897 new PathRotationFunctor( pathCopy, forward ),
903 void Animation::Show(Actor& actor, float delaySeconds)
905 ExtendDuration( TimePeriod(delaySeconds, 0) );
907 AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
908 Dali::Actor::Property::VISIBLE,
909 Property::INVALID_COMPONENT_INDEX,
910 new AnimateToBoolean(SHOW_VALUE),
912 TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
915 void Animation::Hide(Actor& actor, float delaySeconds)
917 ExtendDuration( TimePeriod(delaySeconds, 0) );
919 AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
920 Dali::Actor::Property::VISIBLE,
921 Property::INVALID_COMPONENT_INDEX,
922 new AnimateToBoolean(HIDE_VALUE),
924 TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
927 bool Animation::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
930 Animation* animation = dynamic_cast<Animation*>( object );
934 if( 0 == actionName.compare( ACTION_PLAY ) )
936 if( Property::Value* value = attributes.Find("duration", Property::FLOAT) )
938 animation->SetDuration( value->Get<float>() );
944 else if( 0 == actionName.compare( ACTION_STOP ) )
949 else if( 0 == actionName.compare( ACTION_PAUSE ) )
959 void Animation::SetCurrentProgress(float progress)
961 if( mAnimation && progress >= mPlayRange.x && progress <= mPlayRange.y )
963 // mAnimation is being used in a separate thread; queue a message to set the current progress
964 SetCurrentProgressMessage( mEventThreadServices, *mAnimation, progress );
968 float Animation::GetCurrentProgress()
972 return mAnimation->GetCurrentProgress();
978 void Animation::ExtendDuration( const TimePeriod& timePeriod )
980 float duration = timePeriod.delaySeconds + timePeriod.durationSeconds;
982 if( duration > mDurationSeconds )
984 SetDuration( duration );
988 void Animation::SetSpeedFactor( float factor )
992 mSpeedFactor = factor;
993 SetSpeedFactorMessage( mEventThreadServices, *mAnimation, factor );
997 float Animation::GetSpeedFactor() const
1002 void Animation::SetPlayRange( const Vector2& range)
1004 //Make sure the range specified is between 0.0 and 1.0
1005 if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
1007 Vector2 orderedRange( range );
1008 //If the range is not in order swap values
1009 if( range.x > range.y )
1011 orderedRange = Vector2(range.y, range.x);
1014 // Cache for public getters
1015 mPlayRange = orderedRange;
1017 // mAnimation is being used in a separate thread; queue a message to set play range
1018 SetPlayRangeMessage( mEventThreadServices, *mAnimation, orderedRange );
1022 Vector2 Animation::GetPlayRange() const
1027 void Animation::SetLoopingMode( Dali::Animation::LoopingMode loopingMode )
1029 mAutoReverseEnabled = ( loopingMode == Dali::Animation::LoopingMode::AUTO_REVERSE );
1031 // mAnimation is being used in a separate thread; queue a message to set play range
1032 SetLoopingModeMessage( mEventThreadServices, *mAnimation, mAutoReverseEnabled );
1035 Dali::Animation::LoopingMode Animation::GetLoopingMode() const
1037 return mAutoReverseEnabled ? Dali::Animation::AUTO_REVERSE : Dali::Animation::RESTART;
1040 bool Animation::CompareConnectorEndTimes( const Animation::ConnectorTargetValues& lhs, const Animation::ConnectorTargetValues& rhs )
1042 return ( ( lhs.timePeriod.delaySeconds + lhs.timePeriod.durationSeconds ) < ( rhs.timePeriod.delaySeconds + rhs.timePeriod.durationSeconds ) );
1045 void Animation::NotifyObjects()
1047 if( mEndAction != EndAction::Discard ) // If the animation is discarded, then we do not want to change the target values
1049 // Sort according to end time with earlier end times coming first, if the end time is the same, then the connectors are not moved
1050 std::stable_sort( mConnectorTargetValues.begin(), mConnectorTargetValues.end(), CompareConnectorEndTimes );
1052 // Loop through all connector target values sorted by increasing end time
1053 ConnectorTargetValuesContainer::const_iterator iter = mConnectorTargetValues.begin();
1054 const ConnectorTargetValuesContainer::const_iterator endIter = mConnectorTargetValues.end();
1055 for( ; iter != endIter; ++iter )
1057 AnimatorConnectorBase* connector = mConnectors[ iter->connectorIndex ];
1059 Object* object = connector->GetObject();
1062 object->NotifyPropertyAnimation( *this, connector->GetPropertyIndex(), iter->targetValue, iter->animatorType );
1069 void Animation::SendFinalProgressNotificationMessage()
1071 if ( mProgressReachedMarker > 0.0f )
1073 float progressMarkerSeconds = mDurationSeconds * mProgressReachedMarker;
1074 SetProgressNotificationMessage( mEventThreadServices, *mAnimation, progressMarkerSeconds );
1078 } // namespace Internal