2 * Copyright (c) 2014 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/event/effects/shader-effect-impl.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 ),
126 mPlayRange( Vector2(0.0f,1.0f)),
127 mEndAction( endAction ),
128 mDisconnectAction( disconnectAction ),
129 mDefaultAlpha( defaultAlpha )
133 void Animation::Initialize()
135 // Connect to the animation playlist
136 mPlaylist.AnimationCreated( *this );
143 Animation::~Animation()
145 // Guard to allow handle destruction after Core has been destroyed
146 if ( Stage::IsInstalled() )
148 // Disconnect from the animation playlist
149 mPlaylist.AnimationDestroyed( *this );
151 DestroySceneObject();
157 void Animation::CreateSceneObject()
159 DALI_ASSERT_DEBUG( mAnimation == NULL );
161 // Create a new animation, temporarily owned
162 SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mIsLooping, mEndAction, mDisconnectAction );
164 // Keep a const pointer to the animation.
165 mAnimation = animation;
167 // Transfer animation ownership to the update manager through a message
168 AddAnimationMessage( mEventThreadServices.GetUpdateManager(), animation );
171 void Animation::DestroySceneObject()
173 if ( mAnimation != NULL )
175 // Remove animation using a message to the update manager
176 RemoveAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
181 void Animation::SetDuration(float seconds)
185 DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
189 // Cache for public getters
190 mDurationSeconds = seconds;
192 // mAnimation is being used in a separate thread; queue a message to set the value
193 SetDurationMessage( mEventThreadServices, *mAnimation, seconds );
196 float Animation::GetDuration() const
198 // This is not animatable; the cached value is up-to-date.
199 return mDurationSeconds;
202 void Animation::SetLooping(bool looping)
204 // Cache for public getters
205 mIsLooping = looping;
207 // mAnimation is being used in a separate thread; queue a message to set the value
208 SetLoopingMessage( mEventThreadServices, *mAnimation, looping );
211 bool Animation::IsLooping() const
213 // This is not animatable; the cached value is up-to-date.
217 void Animation::SetEndAction(EndAction action)
219 // Cache for public getters
222 // mAnimation is being used in a separate thread; queue a message to set the value
223 SetEndActionMessage( mEventThreadServices, *mAnimation, action );
226 Dali::Animation::EndAction Animation::GetEndAction() const
228 // This is not animatable; the cached value is up-to-date.
232 void Animation::SetDisconnectAction(EndAction action)
234 // Cache for public getters
235 mDisconnectAction = action;
237 // mAnimation is being used in a separate thread; queue a message to set the value
238 SetDisconnectActionMessage( mEventThreadServices, *mAnimation, action );
241 Dali::Animation::EndAction Animation::GetDisconnectAction() const
243 // This is not animatable; the cached value is up-to-date.
244 return mDisconnectAction;
247 void Animation::Play()
249 // Update the current playlist
250 mPlaylist.OnPlay( *this );
252 // mAnimation is being used in a separate thread; queue a Play message
253 PlayAnimationMessage( mEventThreadServices, *mAnimation );
256 void Animation::PlayFrom( float progress )
258 if( progress >= mPlayRange.x && progress <= mPlayRange.y )
260 // Update the current playlist
261 mPlaylist.OnPlay( *this );
263 // mAnimation is being used in a separate thread; queue a Play message
264 PlayAnimationFromMessage( mEventThreadServices, *mAnimation, progress );
268 void Animation::Pause()
270 // mAnimation is being used in a separate thread; queue a Pause message
271 PauseAnimationMessage( mEventThreadServices, *mAnimation );
274 void Animation::Stop()
276 // mAnimation is being used in a separate thread; queue a Stop message
277 StopAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
280 void Animation::Clear()
282 DALI_ASSERT_DEBUG(mAnimation);
284 // Remove all the connectors
287 // Replace the old scene-object with a new one
288 DestroySceneObject();
291 // Reset the notification count, since the new scene-object has never been played
292 mNotificationCount = 0;
294 // Update the current playlist
295 mPlaylist.OnClear( *this );
298 void Animation::AnimateBy(Property& target, Property::Value& relativeValue)
300 AnimateBy(target, relativeValue, mDefaultAlpha, TimePeriod(mDurationSeconds));
303 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha)
305 AnimateBy(target, relativeValue, alpha, TimePeriod(mDurationSeconds));
308 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period)
310 AnimateBy(target, relativeValue, mDefaultAlpha, period);
313 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period)
315 Object& object = dynamic_cast<Object&>( GetImplementation(target.object) );
317 ExtendDuration( period );
319 switch ( relativeValue.GetType() )
321 case Property::BOOLEAN:
323 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
324 target.propertyIndex,
325 target.componentIndex,
326 new AnimateByBoolean(relativeValue.Get<bool>()),
332 case Property::INTEGER:
334 AddAnimatorConnector( AnimatorConnector<int>::New( object,
335 target.propertyIndex,
336 target.componentIndex,
337 new AnimateByInteger(relativeValue.Get<int>()),
343 case Property::UNSIGNED_INTEGER:
345 AddAnimatorConnector( AnimatorConnector<unsigned int>::New( object,
346 target.propertyIndex,
347 target.componentIndex,
348 new AnimateByUnsignedInteger(relativeValue.Get<unsigned int>()),
354 case Property::FLOAT:
356 AddAnimatorConnector( AnimatorConnector<float>::New( object,
357 target.propertyIndex,
358 target.componentIndex,
359 new AnimateByFloat(relativeValue.Get<float>()),
365 case Property::VECTOR2:
367 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
368 target.propertyIndex,
369 target.componentIndex,
370 new AnimateByVector2(relativeValue.Get<Vector2>()),
376 case Property::VECTOR3:
378 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
379 target.propertyIndex,
380 target.componentIndex,
381 new AnimateByVector3(relativeValue.Get<Vector3>()),
387 case Property::VECTOR4:
389 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
390 target.propertyIndex,
391 target.componentIndex,
392 new AnimateByVector4(relativeValue.Get<Vector4>()),
398 case Property::ROTATION:
400 AngleAxis angleAxis = relativeValue.Get<AngleAxis>();
402 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
403 target.propertyIndex,
404 target.componentIndex,
405 new RotateByAngleAxis(angleAxis.angle, angleAxis.axis),
412 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
417 void Animation::AnimateTo(Property& target, Property::Value& destinationValue)
419 AnimateTo(target, destinationValue, mDefaultAlpha, TimePeriod(mDurationSeconds));
422 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha)
424 AnimateTo(target, destinationValue, alpha, TimePeriod(mDurationSeconds));
427 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period)
429 AnimateTo(target, destinationValue, mDefaultAlpha, period);
432 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
434 Object& object = dynamic_cast<Object&>( GetImplementation(target.object) );
436 AnimateTo( object, target.propertyIndex, target.componentIndex, destinationValue, alpha, period );
439 void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
441 Property::Type type = targetObject.GetPropertyType(targetPropertyIndex);
442 if(componentIndex != Property::INVALID_COMPONENT_INDEX)
444 if( type == Property::VECTOR2
445 || type == Property::VECTOR3
446 || type == Property::VECTOR4 )
448 type = Property::FLOAT;
451 DALI_ASSERT_ALWAYS( type == destinationValue.GetType() && "DestinationValue does not match Target Property type" );
453 ExtendDuration( period );
455 switch (destinationValue.GetType())
457 case Property::BOOLEAN:
459 AddAnimatorConnector( AnimatorConnector<bool>::New( targetObject,
462 new AnimateToBoolean( destinationValue.Get<bool>() ),
468 case Property::INTEGER:
470 AddAnimatorConnector( AnimatorConnector<int>::New( targetObject,
473 new AnimateToInteger( destinationValue.Get<int>() ),
479 case Property::UNSIGNED_INTEGER:
481 AddAnimatorConnector( AnimatorConnector<unsigned int>::New( targetObject,
484 new AnimateToUnsignedInteger( destinationValue.Get<unsigned int>() ),
490 case Property::FLOAT:
492 if ( ( Dali::Actor::Property::SIZE_WIDTH == targetPropertyIndex )||
493 ( Dali::Actor::Property::SIZE_HEIGHT == targetPropertyIndex ) )
495 // Test whether this is actually an Actor
496 Actor* maybeActor = dynamic_cast<Actor*>( &targetObject );
499 // Notify the actor that its size is being animated
500 maybeActor->NotifySizeAnimation( *this, destinationValue.Get<float>(), targetPropertyIndex );
503 AddAnimatorConnector( AnimatorConnector<float>::New( targetObject,
506 new AnimateToFloat( destinationValue.Get<float>() ),
512 case Property::VECTOR2:
514 AddAnimatorConnector( AnimatorConnector<Vector2>::New( targetObject,
517 new AnimateToVector2( destinationValue.Get<Vector2>() ),
523 case Property::VECTOR3:
525 if ( Dali::Actor::Property::SIZE == targetPropertyIndex )
527 // Test whether this is actually an Actor
528 Actor* maybeActor = dynamic_cast<Actor*>( &targetObject );
531 // Notify the actor that its size is being animated
532 maybeActor->NotifySizeAnimation( *this, destinationValue.Get<Vector3>() );
536 AddAnimatorConnector( AnimatorConnector<Vector3>::New( targetObject,
539 new AnimateToVector3( destinationValue.Get<Vector3>() ),
545 case Property::VECTOR4:
547 AddAnimatorConnector( AnimatorConnector<Vector4>::New( targetObject,
550 new AnimateToVector4( destinationValue.Get<Vector4>() ),
556 case Property::ROTATION:
558 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( targetObject,
561 new RotateToQuaternion( destinationValue.Get<Quaternion>() ),
568 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
573 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
575 AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION );
578 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation )
580 AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), interpolation );
583 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period)
585 AnimateBetween(target, keyFrames, mDefaultAlpha, period, DEFAULT_INTERPOLATION);
588 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
590 AnimateBetween(target, keyFrames, mDefaultAlpha, period, interpolation);
593 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha)
595 AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION);
598 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
600 AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), interpolation);
603 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
605 AnimateBetween(target, keyFrames, alpha, period, DEFAULT_INTERPOLATION);
608 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation)
610 Object& object = dynamic_cast<Object&>( GetImplementation(target.object) );
612 ExtendDuration( period );
614 switch(keyFrames.GetType())
616 case Dali::Property::BOOLEAN:
618 const KeyFrameBoolean* kf;
619 GetSpecialization(keyFrames, kf);
620 KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf);
621 AddAnimatorConnector( AnimatorConnector<bool>::New( object,
622 target.propertyIndex,
623 target.componentIndex,
624 new KeyFrameBooleanFunctor(kfCopy),
630 case Dali::Property::INTEGER:
632 const KeyFrameInteger* kf;
633 GetSpecialization(keyFrames, kf);
634 KeyFrameIntegerPtr kfCopy = KeyFrameInteger::Clone(*kf);
635 AddAnimatorConnector( AnimatorConnector<int>::New( object,
636 target.propertyIndex,
637 target.componentIndex,
638 new KeyFrameIntegerFunctor(kfCopy,interpolation),
644 case Dali::Property::UNSIGNED_INTEGER:
646 const KeyFrameUnsignedInteger* kf;
647 GetSpecialization(keyFrames, kf);
648 KeyFrameUnsignedIntegerPtr kfCopy = KeyFrameUnsignedInteger::Clone(*kf);
649 AddAnimatorConnector( AnimatorConnector<int>::New( object,
650 target.propertyIndex,
651 target.componentIndex,
652 new KeyFrameUnsignedIntegerFunctor(kfCopy,interpolation),
658 case Dali::Property::FLOAT:
660 const KeyFrameNumber* kf;
661 GetSpecialization(keyFrames, kf);
662 KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf);
663 AddAnimatorConnector( AnimatorConnector<float>::New( object,
664 target.propertyIndex,
665 target.componentIndex,
666 new KeyFrameNumberFunctor(kfCopy,interpolation),
672 case Dali::Property::VECTOR2:
674 const KeyFrameVector2* kf;
675 GetSpecialization(keyFrames, kf);
676 KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf);
677 AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
678 target.propertyIndex,
679 target.componentIndex,
680 new KeyFrameVector2Functor(kfCopy,interpolation),
686 case Dali::Property::VECTOR3:
688 const KeyFrameVector3* kf;
689 GetSpecialization(keyFrames, kf);
690 KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf);
691 AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
692 target.propertyIndex,
693 target.componentIndex,
694 new KeyFrameVector3Functor(kfCopy,interpolation),
700 case Dali::Property::VECTOR4:
702 const KeyFrameVector4* kf;
703 GetSpecialization(keyFrames, kf);
704 KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf);
705 AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
706 target.propertyIndex,
707 target.componentIndex,
708 new KeyFrameVector4Functor(kfCopy,interpolation),
714 case Dali::Property::ROTATION:
716 const KeyFrameQuaternion* kf;
717 GetSpecialization(keyFrames, kf);
718 KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf);
719 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
720 target.propertyIndex,
721 target.componentIndex,
722 new KeyFrameQuaternionFunctor(kfCopy),
728 default: // not all property types are animateable
733 bool Animation::HasFinished()
735 bool hasFinished(false);
736 const int playCount(mAnimation->GetPlayCount());
738 // If the play count has been incremented, then another notification is required
739 if (playCount > mNotificationCount)
741 // Note that only one signal is emitted, if the animation has been played repeatedly
742 mNotificationCount = playCount;
750 Dali::Animation::AnimationSignalType& Animation::FinishedSignal()
752 return mFinishedSignal;
755 void Animation::EmitSignalFinish()
757 if ( !mFinishedSignal.Empty() )
759 Dali::Animation handle( this );
760 mFinishedSignal.Emit( handle );
763 // This callback is used internally, to avoid the overhead of using a signal.
764 if ( mFinishedCallback )
766 mFinishedCallback( mFinishedCallbackObject );
770 bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
772 bool connected( true );
773 Animation* animation = dynamic_cast<Animation*>(object);
775 if( 0 == signalName.compare( SIGNAL_FINISHED ) )
777 animation->FinishedSignal().Connect( tracker, functor );
781 // signalName does not match any signal
788 void Animation::SetFinishedCallback( FinishedCallback callback, Object* object )
790 mFinishedCallback = callback;
791 mFinishedCallbackObject = object;
794 void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector )
796 DALI_ASSERT_DEBUG( NULL != connector );
798 connector->SetParent(*this);
800 mConnectors.PushBack( connector );
803 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward )
805 Animate( actor, path, forward, mDefaultAlpha, TimePeriod(mDurationSeconds) );
808 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha )
810 Animate( actor, path, forward, alpha, TimePeriod(mDurationSeconds) );
813 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period )
815 Animate( actor, path, forward, mDefaultAlpha, period );
818 void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
820 ExtendDuration( period );
822 PathPtr pathCopy = Path::Clone(path);
825 AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
826 Dali::Actor::Property::POSITION,
827 Property::INVALID_COMPONENT_INDEX,
828 new PathPositionFunctor( pathCopy ),
832 //If forward is zero, PathRotationFunctor will always return the unit quaternion
833 if( forward != Vector3::ZERO )
836 AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
837 Dali::Actor::Property::ORIENTATION,
838 Property::INVALID_COMPONENT_INDEX,
839 new PathRotationFunctor( pathCopy, forward ),
845 void Animation::Show(Actor& actor, float delaySeconds)
847 ExtendDuration( TimePeriod(delaySeconds, 0) );
849 AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
850 Dali::Actor::Property::VISIBLE,
851 Property::INVALID_COMPONENT_INDEX,
852 new AnimateToBoolean(SHOW_VALUE),
854 TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
857 void Animation::Hide(Actor& actor, float delaySeconds)
859 ExtendDuration( TimePeriod(delaySeconds, 0) );
861 AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
862 Dali::Actor::Property::VISIBLE,
863 Property::INVALID_COMPONENT_INDEX,
864 new AnimateToBoolean(HIDE_VALUE),
866 TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
869 bool Animation::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
872 Animation* animation = dynamic_cast<Animation*>( object );
876 if( 0 == actionName.compare( ACTION_PLAY ) )
878 if( Property::Value* value = attributes.Find("duration", Property::FLOAT) )
880 animation->SetDuration( value->Get<float>() );
886 else if( 0 == actionName.compare( ACTION_STOP ) )
891 else if( 0 == actionName.compare( ACTION_PAUSE ) )
901 void Animation::SetCurrentProgress(float progress)
903 if( mAnimation && progress >= mPlayRange.x && progress <= mPlayRange.y )
905 // mAnimation is being used in a separate thread; queue a message to set the current progress
906 SetCurrentProgressMessage( mEventThreadServices, *mAnimation, progress );
910 float Animation::GetCurrentProgress()
914 return mAnimation->GetCurrentProgress();
920 void Animation::ExtendDuration( const TimePeriod& timePeriod )
922 float duration = timePeriod.delaySeconds + timePeriod.durationSeconds;
924 if( duration > mDurationSeconds )
926 SetDuration( duration );
930 void Animation::SetSpeedFactor( float factor )
934 mSpeedFactor = factor;
935 SetSpeedFactorMessage( mEventThreadServices, *mAnimation, factor );
939 float Animation::GetSpeedFactor() const
944 void Animation::SetPlayRange( const Vector2& range)
946 //Make sure the range specified is between 0.0 and 1.0
947 if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
949 Vector2 orderedRange( range );
950 //If the range is not in order swap values
951 if( range.x > range.y )
953 orderedRange = Vector2(range.y, range.x);
956 // Cache for public getters
957 mPlayRange = orderedRange;
959 // mAnimation is being used in a separate thread; queue a message to set play range
960 SetPlayRangeMessage( mEventThreadServices, *mAnimation, orderedRange );
964 Vector2 Animation::GetPlayRange() const
970 } // namespace Internal