1 #ifndef DALI_INTERNAL_ANIMATION_H
2 #define DALI_INTERNAL_ANIMATION_H
5 * Copyright (c) 2024 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/devel-api/animation/animation-devel.h>
23 #include <dali/devel-api/common/owner-container.h>
24 #include <dali/internal/event/common/event-thread-services.h>
25 #include <dali/public-api/animation/animation.h>
26 #include <dali/public-api/animation/key-frames.h>
27 #include <dali/public-api/common/vector-wrapper.h>
28 #include <dali/public-api/object/base-object.h>
29 #include <dali/public-api/object/ref-object.h>
39 } // namespace SceneGraph
43 class AnimationPlaylist;
44 class AnimatorConnectorBase;
48 using AnimationPtr = IntrusivePtr<Animation>;
49 using AnimationContainer = std::vector<AnimationPtr>;
51 using AnimationIter = AnimationContainer::iterator;
52 using AnimationConstIter = AnimationContainer::const_iterator;
55 * Animation is a proxy for a SceneGraph::Animation object.
56 * The UpdateManager owns the Animation object, but the lifetime of the animation is
57 * indirectly controlled by the Animation.
59 class Animation : public BaseObject
64 TO, ///< Animating TO the given value
65 BY, ///< Animating BY the given value
66 BETWEEN ///< Animating BETWEEN key-frames
69 using EndAction = Dali::Animation::EndAction;
70 using Interpolation = Dali::Animation::Interpolation;
73 * Create a new Animation object.
74 * @param[in] durationSeconds The duration of the animation.
75 * @return A smart-pointer to the newly allocated Animation.
77 static AnimationPtr New(float durationSeconds);
80 * @copydoc Dali::Animation::SetDuration()
82 void SetDuration(float seconds);
85 * @copydoc Dali::DevelAnimation::SetProgressNotification()
87 void SetProgressNotification(float progress);
90 * @copydoc Dali::DevelAnimation::GetProgressNotification()
92 float GetProgressNotification();
95 * @copydoc Dali::Animation::GetDuration()
97 float GetDuration() const;
100 * @copydoc Dali::Animation::SetLooping()
102 void SetLooping(bool on);
105 * @copydoc Dali::Animation::SetLoopCount()
107 void SetLoopCount(int32_t count);
110 * @copydoc Dali::Animation::GetLoopCount()
112 int32_t GetLoopCount();
115 * @copydoc Dali::Animation::GetCurrentLoop()
117 int32_t GetCurrentLoop();
120 * @copydoc Dali::Animation::IsLooping()
122 bool IsLooping() const;
125 * @copydoc Dali::Animation::SetEndAction()
127 void SetEndAction(EndAction action);
130 * @copydoc Dali::Animation::GetEndAction()
132 EndAction GetEndAction() const;
135 * @copydoc Dali::Animation::SetDisconnectAction()
137 void SetDisconnectAction(EndAction action);
140 * @copydoc Dali::Animation::GetDisconnectAction()
142 EndAction GetDisconnectAction() const;
145 * @copydoc Dali::Animation::SetDefaultAlphaFunction()
147 void SetDefaultAlphaFunction(AlphaFunction alpha)
149 mDefaultAlpha = alpha;
153 * @copydoc Dali::Animation::GetDefaultAlphaFunction()
155 AlphaFunction GetDefaultAlphaFunction() const
157 return mDefaultAlpha;
161 * @copydoc Dali::Animation::Play()
166 * @copydoc Dali::Animation::PlayFrom()
168 void PlayFrom(float progress);
171 * @copydoc Dali::Animation::PlayAfter()
173 void PlayAfter(float delaySeconds);
176 * @copydoc Dali::Animation::Pause()
181 * @copydoc Dali::Animation::GetState()
183 Dali::Animation::State GetState() const;
186 * @copydoc Dali::Animation::Stop()
191 * @copydoc Dali::Animation::Clear()
196 * Query whether a Finished signal should be emitted for this animation.
197 * This should only be called by NotificationManager, before signals are emitted.
198 * @post HasFinished() will return false on subsequent calls, until the animation is replayed to completion.
203 * @copydoc Dali::Animation::FinishedSignal()
205 Dali::Animation::AnimationSignalType& FinishedSignal();
208 * @copydoc Dali::DevelAnimation::ProgressHasBeenReachedSignal()
210 Dali::Animation::AnimationSignalType& ProgressReachedSignal();
213 * Emit the Finished signal
215 void EmitSignalFinish();
218 * Emit the ProgressReached signal
220 void EmitSignalProgressReached();
223 * Connects a callback function with the object's signals.
224 * @param[in] object The object providing the signal.
225 * @param[in] tracker Used to disconnect the signal.
226 * @param[in] signalName The signal to connect to.
227 * @param[in] functor A newly allocated FunctorDelegate.
228 * @return True if the signal was connected.
229 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
231 static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
234 * Performs actions as requested using the action name.
235 * @param[in] object The object on which to perform the action.
236 * @param[in] actionName The action to perform.
237 * @param[in] attributes The attributes with which to perfrom this action.
238 * @return true if action was done
240 static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes);
243 * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue)
245 void AnimateBy(Property& target, Property::Value relativeValue);
248 * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha)
250 void AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha);
253 * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, TimePeriod period)
255 void AnimateBy(Property& target, Property::Value relativeValue, TimePeriod period);
258 * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period)
260 void AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period);
263 * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue)
265 void AnimateTo(Property& target, Property::Value destinationValue);
268 * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha)
270 void AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha);
273 * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, TimePeriod period)
275 void AnimateTo(Property& target, Property::Value destinationValue, TimePeriod period);
278 * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period)
280 void AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period);
283 * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames)
285 void AnimateBetween(Property target, Dali::KeyFrames keyFrames);
288 * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, Interpolation interpolation)
290 void AnimateBetween(Property target, Dali::KeyFrames keyFrames, Interpolation interpolation);
293 * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, TimePeriod period)
295 void AnimateBetween(Property target, Dali::KeyFrames keyFrames, TimePeriod period);
298 * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, TimePeriod period, Interpolation interpolation)
300 void AnimateBetween(Property target, Dali::KeyFrames keyFrames, TimePeriod period, Interpolation interpolation);
303 * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha)
305 void AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha);
308 * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, Interpolation interpolation)
310 void AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, Interpolation interpolation);
313 * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, TimePeriod period)
315 void AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, TimePeriod period);
318 * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation )
320 void AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation);
322 // Actor-specific convenience functions
325 * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward )
327 void Animate(Actor& actor, const Path& path, const Vector3& forward);
330 * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha )
332 void Animate(Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha);
335 * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period )
337 void Animate(Actor& actor, const Path& path, const Vector3& forward, TimePeriod period);
340 * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
342 void Animate(Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
345 * @copydoc Dali::Animation::Show()
347 void Show(Actor& actor, float delaySeconds);
350 * @copydoc Dali::Animation::Hide()
352 void Hide(Actor& actor, float delaySeconds);
355 * @copydoc Dali::Animation::SetCurrentProgress()
357 void SetCurrentProgress(float progress);
360 * @copydoc Dali::Animation::GetCurrentProgress()
362 float GetCurrentProgress();
365 * @copydoc Dali::Animation::SetSpeedFactor()
367 void SetSpeedFactor(float factor);
370 * @copydoc Dali::Animation::GetSpeedFactor()
372 float GetSpeedFactor() const;
375 * @copydoc Dali::Animation::SetPlayRange()
377 void SetPlayRange(const Vector2& range);
380 * @copydoc Dali::Animation::GetPlayRange()
382 Vector2 GetPlayRange() const;
385 * @copydoc Dali::Animation::SetBlendPoint()
387 void SetBlendPoint(float blendPoint);
390 * @copydoc Dali::Animation::GetBlendPoint()
392 float GetBlendPoint() const;
395 * @copydoc Dali::Animation::SetLoopingMode()
397 void SetLoopingMode(Dali::Animation::LoopingMode loopingMode);
400 * @copydoc Dali::Animation::GetLoopingMode()
402 Dali::Animation::LoopingMode GetLoopingMode() const;
405 * @copydoc Dali::Animation::GetAnimationId()
407 uint32_t GetAnimationId() const;
409 public: // For connecting animators to animations
411 * Add an animator connector.
412 * @param[in] connector The animator connector.
414 void AddAnimatorConnector(AnimatorConnectorBase* connector);
417 * Retrieve the SceneGraph::Animation object.
418 * @return The animation.
420 const SceneGraph::Animation* GetSceneObject()
426 * Retrieve the event thread services object
427 * @return The interface for sending messages to the scene graph
429 EventThreadServices& GetEventThreadServices()
431 return mEventThreadServices;
436 * Construct a new Animation.
437 * @param[in] eventThreadServices The interface for sending messages to the scene graph
438 * @param[in] playlist The list of currently playing animations.
439 * @param[in] durationSeconds The duration of the animation in seconds.
440 * @param[in] endAction The action to perform when the animation ends.
441 * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
442 * @param[in] defaultAlpha The default alpha function to apply to animators.
444 Animation(EventThreadServices& eventThreadServices,
445 AnimationPlaylist& playlist,
446 float durationSeconds,
448 EndAction disconnectAction,
449 AlphaFunction defaultAlpha);
452 * Second-phase constructor.
457 * Helper to create a scene-graph animation
459 void CreateSceneObject();
462 * Helper to create a scene-graph animation
464 void DestroySceneObject();
467 * A reference counted object may only be deleted by calling Unreference()
469 ~Animation() override;
473 * Extends the duration when an animator is added with TimePeriod that exceeds current duration.
474 * @param[in] timePeriod The time period for an animator.
476 void ExtendDuration(const TimePeriod& timePeriod);
479 Animation(const Animation&);
482 Animation& operator=(const Animation& rhs);
485 struct ConnectorTargetValues
487 ConnectorTargetValues() = default;
489 ConnectorTargetValues(Property::Value value, TimePeriod time, std::size_t index, Animation::Type type)
490 : targetValue(std::move(value)),
492 connectorIndex(index),
498 ConnectorTargetValues(ConnectorTargetValues&& rhs) noexcept
499 : targetValue(std::move(rhs.targetValue)),
500 timePeriod(std::move(rhs.timePeriod)),
501 connectorIndex(rhs.connectorIndex),
502 animatorType(rhs.animatorType)
506 ConnectorTargetValues& operator=(ConnectorTargetValues&& rhs) noexcept
508 targetValue = std::move(rhs.targetValue);
509 timePeriod = std::move(rhs.timePeriod);
510 connectorIndex = rhs.connectorIndex;
511 animatorType = rhs.animatorType;
515 Property::Value targetValue;
516 TimePeriod timePeriod{0.f};
517 std::size_t connectorIndex{0};
518 Animation::Type animatorType{TO};
521 enum class Notify : uint8_t
523 USE_CURRENT_VALUE, ///< Set the current value for the property
524 USE_TARGET_VALUE, ///< Set the animator's target value for the property
525 FORCE_CURRENT_VALUE, ///< Set the current value for the property even if the end action is to discard
530 * Compares the end times of the animators returning true if lhs end time is less than rhs end time.
531 * @param[in] lhs The first comparator
532 * @param[in] rhs The second comparator
533 * @return True if end time of lhs is less, false otherwise.
535 static bool CompareConnectorEndTimes(const ConnectorTargetValues& lhs, const ConnectorTargetValues& rhs);
538 * Notifies all the objects whose properties are being animated.
539 * @param[in] notifyValueType Whether we should set the current or target value
541 void NotifyObjects(Notify notifyValueType);
544 * Sends message to SceneGraph with final progress value
546 void SendFinalProgressNotificationMessage();
549 * @brief Append ConnectorTargetValues into the container.
551 * @param[in] connectorTargetValues moved ConnectorTargetValues that will be append end of container
553 void AppendConnectorTargetValues(ConnectorTargetValues&& connectorTargetValues);
556 using AnimatorConnectorContainer = OwnerContainer<AnimatorConnectorBase*>;
557 using ConnectorTargetValuesContainer = std::vector<ConnectorTargetValues>;
559 const SceneGraph::Animation* mAnimation{nullptr};
561 EventThreadServices& mEventThreadServices;
562 AnimationPlaylist& mPlaylist;
564 Dali::Animation::AnimationSignalType mFinishedSignal{};
565 Dali::Animation::AnimationSignalType mProgressReachedSignal{};
567 AnimatorConnectorContainer mConnectors{}; ///< Owned by the Animation
568 ConnectorTargetValuesContainer mConnectorTargetValues{}; //< Used to store animating property target value information
570 uint32_t mAnimationId{0u};
572 AlphaFunction mDefaultAlpha;
573 Vector2 mPlayRange{0.0f, 1.0f};
574 float mBlendPoint{0.0f};
575 float mDurationSeconds;
576 float mSpeedFactor{1.0f};
577 int32_t mNotificationCount{0}; ///< Keep track of how many Finished signals have been emitted.
578 int32_t mLoopCount{1};
579 float mProgressReachedMarker{0.0f};
580 float mDelaySeconds{0.0f};
581 EndAction mEndAction;
582 EndAction mDisconnectAction;
583 Dali::Animation::State mState{Dali::Animation::STOPPED};
584 bool mAutoReverseEnabled{false}; ///< Flag to identify that the looping mode is auto reverse.
585 bool mConnectorTargetValuesSortRequired{false}; ///< Flag to whether we need to sort mConnectorTargetValues or not
586 bool mPlayCalled{false}; ///< Flag to whether we call Play at least 1 time after create, or clear.
589 } // namespace Internal
591 // Helpers for public-api forwarding methods
593 inline Internal::Animation& GetImplementation(Dali::Animation& animation)
595 DALI_ASSERT_ALWAYS(animation && "Animation handle is empty");
597 BaseObject& handle = animation.GetBaseObject();
599 return static_cast<Internal::Animation&>(handle);
602 inline const Internal::Animation& GetImplementation(const Dali::Animation& animation)
604 DALI_ASSERT_ALWAYS(animation && "Animation handle is empty");
606 const BaseObject& handle = animation.GetBaseObject();
608 return static_cast<const Internal::Animation&>(handle);
613 #endif // DALI_INTERNAL_ANIMATION_H