1 #ifndef DALI_INTERNAL_ANIMATION_H
2 #define DALI_INTERNAL_ANIMATION_H
5 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 #include <dali/public-api/common/vector-wrapper.h>
23 #include <dali/public-api/object/ref-object.h>
24 #include <dali/public-api/animation/animation.h>
25 #include <dali/public-api/object/base-object.h>
26 #include <dali/devel-api/animation/animation-devel.h>
27 #include <dali/devel-api/common/owner-container.h>
28 #include <dali/internal/event/animation/key-frames-impl.h>
29 #include <dali/internal/event/common/event-thread-services.h>
45 class AnimationPlaylist;
46 class AnimatorConnectorBase;
50 using AnimationPtr = IntrusivePtr<Animation>;
51 using AnimationContainer = std::vector<AnimationPtr>;
53 using AnimationIter = AnimationContainer::iterator;
54 using AnimationConstIter = AnimationContainer::const_iterator;
57 * Animation is a proxy for a SceneGraph::Animation object.
58 * The UpdateManager owns the Animation object, but the lifetime of the animation is
59 * indirectly controlled by the Animation.
61 class Animation : public BaseObject
66 TO, ///< Animating TO the given value
67 BY, ///< Animating BY the given value
68 BETWEEN ///< Animating BETWEEN key-frames
71 using EndAction = Dali::Animation::EndAction;
72 using Interpolation = Dali::Animation::Interpolation;
75 * Create a new Animation object.
76 * @param[in] durationSeconds The duration of the animation.
77 * @return A smart-pointer to the newly allocated Animation.
79 static AnimationPtr New(float durationSeconds);
82 * @copydoc Dali::Animation::SetDuration()
84 void SetDuration(float seconds);
87 * @copydoc Dali::DevelAnimation::SetProgressNotification()
89 void SetProgressNotification( float progress );
92 * @copydoc Dali::DevelAnimation::GetProgressNotification()
94 float GetProgressNotification();
97 * @copydoc Dali::Animation::GetDuration()
99 float GetDuration() const;
102 * @copydoc Dali::Animation::SetLooping()
104 void SetLooping(bool on);
107 * @copydoc Dali::Animation::SetLoopCount()
109 void SetLoopCount(int32_t count);
112 * @copydoc Dali::Animation::GetLoopCount()
114 int32_t GetLoopCount();
117 * @copydoc Dali::Animation::GetCurrentLoop()
119 int32_t GetCurrentLoop();
122 * @copydoc Dali::Animation::IsLooping()
124 bool IsLooping() const;
127 * @copydoc Dali::Animation::SetEndAction()
129 void SetEndAction(EndAction action);
132 * @copydoc Dali::Animation::GetEndAction()
134 EndAction GetEndAction() const;
137 * @copydoc Dali::Animation::SetDisconnectAction()
139 void SetDisconnectAction(EndAction action);
142 * @copydoc Dali::Animation::GetDisconnectAction()
144 EndAction GetDisconnectAction() const;
147 * @copydoc Dali::Animation::SetDefaultAlphaFunction()
149 void SetDefaultAlphaFunction(AlphaFunction alpha)
151 mDefaultAlpha = alpha;
155 * @copydoc Dali::Animation::GetDefaultAlphaFunction()
157 AlphaFunction GetDefaultAlphaFunction() const
159 return mDefaultAlpha;
163 * @copydoc Dali::Animation::Play()
168 * @copydoc Dali::Animation::PlayFrom()
170 void PlayFrom( float progress );
173 * @copydoc Dali::Animation::PlayAfter()
175 void PlayAfter( float delaySeconds );
178 * @copydoc Dali::Animation::Pause()
183 * @copydoc Dali::Animation::GetState()
185 Dali::Animation::State GetState() const;
188 * @copydoc Dali::Animation::Stop()
193 * @copydoc Dali::Animation::Clear()
198 * Query whether a Finished signal should be emitted for this animation.
199 * This should only be called by NotificationManager, before signals are emitted.
200 * @post HasFinished() will return false on subsequent calls, until the animation is replayed to completion.
205 * @copydoc Dali::Animation::FinishedSignal()
207 Dali::Animation::AnimationSignalType& FinishedSignal();
210 * @copydoc Dali::DevelAnimation::ProgressHasBeenReachedSignal()
212 Dali::Animation::AnimationSignalType& ProgressReachedSignal();
215 * Emit the Finished signal
217 void EmitSignalFinish();
220 * Emit the ProgressReached signal
222 void EmitSignalProgressReached();
225 * Connects a callback function with the object's signals.
226 * @param[in] object The object providing the signal.
227 * @param[in] tracker Used to disconnect the signal.
228 * @param[in] signalName The signal to connect to.
229 * @param[in] functor A newly allocated FunctorDelegate.
230 * @return True if the signal was connected.
231 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
233 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
236 * Performs actions as requested using the action name.
237 * @param[in] object The object on which to perform the action.
238 * @param[in] actionName The action to perform.
239 * @param[in] attributes The attributes with which to perfrom this action.
240 * @return true if action was done
242 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes);
245 * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue)
247 void AnimateBy(Property& target, Property::Value relativeValue);
250 * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha)
252 void AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha);
255 * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, TimePeriod period)
257 void AnimateBy(Property& target, Property::Value relativeValue, TimePeriod period);
260 * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period)
262 void AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period);
265 * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue)
267 void AnimateTo(Property& target, Property::Value destinationValue);
270 * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha)
272 void AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha);
275 * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, TimePeriod period)
277 void AnimateTo(Property& target, Property::Value destinationValue, TimePeriod period);
280 * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period)
282 void AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period);
285 * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames)
287 void AnimateBetween(Property target, const KeyFrames& keyFrames);
290 * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation)
292 void AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation );
295 * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period)
297 void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period);
300 * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
302 void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation);
305 * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha)
307 void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha);
310 * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
312 void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation);
315 * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
317 void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period);
320 * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation )
322 void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation );
324 // Actor-specific convenience functions
327 * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward )
329 void Animate( Actor& actor, const Path& path, const Vector3& forward );
332 * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha )
334 void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha );
337 * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period )
339 void Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period );
342 * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
344 void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
347 * @copydoc Dali::Animation::Show()
349 void Show(Actor& actor, float delaySeconds);
352 * @copydoc Dali::Animation::Hide()
354 void Hide(Actor& actor, float delaySeconds);
357 * @copydoc Dali::Animation::SetCurrentProgress()
359 void SetCurrentProgress(float progress);
362 * @copydoc Dali::Animation::GetCurrentProgress()
364 float GetCurrentProgress();
367 * @copydoc Dali::Animation::SetSpeedFactor()
369 void SetSpeedFactor( float factor );
372 * @copydoc Dali::Animation::GetSpeedFactor()
374 float GetSpeedFactor() const;
377 * @copydoc Dali::Animation::SetPlayRange()
379 void SetPlayRange( const Vector2& range );
382 * @copydoc Dali::Animation::GetPlayRange()
384 Vector2 GetPlayRange() const;
387 * @copydoc Dali::Animation::SetLoopingMode()
389 void SetLoopingMode( Dali::Animation::LoopingMode loopingMode );
392 * @copydoc Dali::Animation::GetLoopingMode()
394 Dali::Animation::LoopingMode GetLoopingMode() const;
396 public: // For connecting animators to animations
399 * Add an animator connector.
400 * @param[in] connector The animator connector.
402 void AddAnimatorConnector( AnimatorConnectorBase* connector );
405 * Retrieve the SceneGraph::Animation object.
406 * @return The animation.
408 const SceneGraph::Animation* GetSceneObject()
414 * Retrieve the event thread services object
415 * @return The interface for sending messages to the scene graph
417 EventThreadServices& GetEventThreadServices()
419 return mEventThreadServices;
425 * Construct a new Animation.
426 * @param[in] eventThreadServices The interface for sending messages to the scene graph
427 * @param[in] playlist The list of currently playing animations.
428 * @param[in] durationSeconds The duration of the animation in seconds.
429 * @param[in] endAction The action to perform when the animation ends.
430 * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
431 * @param[in] defaultAlpha The default alpha function to apply to animators.
433 Animation( EventThreadServices& eventThreadServices,
434 AnimationPlaylist& playlist,
435 float durationSeconds,
437 EndAction disconnectAction,
438 AlphaFunction defaultAlpha);
441 * Second-phase constructor.
446 * Helper to create a scene-graph animation
448 void CreateSceneObject();
451 * Helper to create a scene-graph animation
453 void DestroySceneObject();
456 * A reference counted object may only be deleted by calling Unreference()
458 ~Animation() override;
463 * Extends the duration when an animator is added with TimePeriod that exceeds current duration.
464 * @param[in] timePeriod The time period for an animator.
466 void ExtendDuration( const TimePeriod& timePeriod );
469 Animation(const Animation&);
472 Animation& operator=(const Animation& rhs);
476 struct ConnectorTargetValues
478 ConnectorTargetValues() = default;
480 ConnectorTargetValues(Property::Value value, TimePeriod time, std::size_t index, Animation::Type type)
481 : targetValue(std::move(value)),
483 connectorIndex(index),
488 Property::Value targetValue;
489 TimePeriod timePeriod{0.f};
490 std::size_t connectorIndex{0};
491 Animation::Type animatorType{TO};
494 enum class Notify : uint8_t
496 USE_CURRENT_VALUE, ///< Set the current value for the property
497 USE_TARGET_VALUE, ///< Set the animator's target value for the property
498 FORCE_CURRENT_VALUE, ///< Set the current value for the property even if the end action is to discard
504 * Compares the end times of the animators returning true if lhs end time is less than rhs end time.
505 * @param[in] lhs The first comparator
506 * @param[in] rhs The second comparator
507 * @return True if end time of lhs is less, false otherwise.
509 static bool CompareConnectorEndTimes( const ConnectorTargetValues& lhs, const ConnectorTargetValues& rhs );
512 * Notifies all the objects whose properties are being animated.
513 * @param[in] notifyValueType Whether we should set the current or target value
515 void NotifyObjects( Notify notifyValueType );
518 * Sends message to SceneGraph with final progress value
520 void SendFinalProgressNotificationMessage();
523 using AnimatorConnectorContainer = OwnerContainer<AnimatorConnectorBase*>;
524 using ConnectorTargetValuesContainer = std::vector<ConnectorTargetValues>;
526 const SceneGraph::Animation* mAnimation{ nullptr };
528 EventThreadServices& mEventThreadServices;
529 AnimationPlaylist& mPlaylist;
531 Dali::Animation::AnimationSignalType mFinishedSignal{};
532 Dali::Animation::AnimationSignalType mProgressReachedSignal{};
534 AnimatorConnectorContainer mConnectors{}; ///< Owned by the Animation
535 ConnectorTargetValuesContainer mConnectorTargetValues{}; //< Used to store animating property target value information
537 AlphaFunction mDefaultAlpha;
538 Vector2 mPlayRange{0.0f, 1.0f};
539 float mDurationSeconds;
540 float mSpeedFactor{1.0f};
541 int32_t mNotificationCount{0}; ///< Keep track of how many Finished signals have been emitted.
542 int32_t mLoopCount{1};
543 int32_t mCurrentLoop{0};
544 float mProgressReachedMarker{0.0f};
545 float mDelaySeconds{0.0f};
546 EndAction mEndAction;
547 EndAction mDisconnectAction;
548 Dali::Animation::State mState{Dali::Animation::STOPPED};
549 bool mAutoReverseEnabled{false}; ///< Flag to identify that the looping mode is auto reverse.
552 } // namespace Internal
554 // Helpers for public-api forwarding methods
556 inline Internal::Animation& GetImplementation(Dali::Animation& animation)
558 DALI_ASSERT_ALWAYS( animation && "Animation handle is empty" );
560 BaseObject& handle = animation.GetBaseObject();
562 return static_cast<Internal::Animation&>(handle);
565 inline const Internal::Animation& GetImplementation(const Dali::Animation& animation)
567 DALI_ASSERT_ALWAYS( animation && "Animation handle is empty" );
569 const BaseObject& handle = animation.GetBaseObject();
571 return static_cast<const Internal::Animation&>(handle);
576 #endif // DALI_INTERNAL_ANIMATION_H