1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef META_SRC_ANIMATION_STATE_H
17 #define META_SRC_ANIMATION_STATE_H
18 
19 #include <optional>
20 
21 #include <meta/api/container/find_cache.h>
22 #include <meta/ext/implementation_macros.h>
23 #include <meta/interface/animation/intf_animation.h>
24 #include <meta/interface/animation/intf_animation_modifier.h>
25 #include <meta/interface/intf_any.h>
26 #include <meta/interface/intf_attachment.h>
27 #include <meta/interface/intf_container.h>
28 #include <meta/interface/intf_manual_clock.h>
29 #include <meta/interface/property/property_events.h>
30 
31 #include "intf_animation_internal.h"
32 
META_BEGIN_NAMESPACE()33 META_BEGIN_NAMESPACE()
34 
35 namespace Internal {
36 
37 /**
38  * @brief Base animation state implementation, handles animation state, evaluation.
39  */
40 class AnimationState {
41 public:
42     AnimationState() = default;
43     ~AnimationState() = default;
44     META_NO_COPY_MOVE(AnimationState)
45 
46 public:
47     struct AnimationStateParams {
48         /** Owning animation */
49         IAnimation::WeakPtr owner;
50         /** Writeable IAnimation::Running property */
51         Property<bool> runningProperty;
52         /** Writeable IAnimation::Progress property */
53         Property<float> progressProperty;
54         /** Writeable IAnimation::TotalDuration property */
55         Property<TimeSpan> totalDuration;
56     };
57 
58     /**
59      * @brief Initialize AnimationState.
60      * @param owner Owning animation for AnimationState.
61      */
62     virtual bool Initialize(AnimationStateParams&& params);
63     /**
64      * @brief Uninitializes the state object.
65      */
66     virtual void Uninitialize();
67     /** Result of a step operation */
68     struct StepStatus {
69         IAnimationInternal::AnimationTargetState state { IAnimationInternal::AnimationTargetState::UNDEFINED };
70         float progress {};
71         bool changed {};
72 
73         constexpr bool StatusChanged() const noexcept
74         {
75             return changed;
76         }
77     };
78     /**
79      * @brief Step the state based on clock.
80      * @param clock Clock containing the step time.
81      */
82     virtual StepStatus Step(const IClock::ConstPtr& clock);
83     /**
84      * @brief Seeks the animation state to given position [0,1]
85      */
86     virtual void Seek(float position);
87     /**
88      * @brief Pauses the animation. Returns true if state changed.
89      */
90     virtual bool Pause();
91     /**
92      * @brief Starts the animation. Returns true if state changed.
93      */
94     virtual bool Start();
95     /**
96      * @brief Stops the animation. Returns true if state changed.
97      */
98     virtual bool Stop();
99     /**
100      * @brief Restarts the animation. Returns true if state changed.
101      */
102     virtual bool Restart();
103     /**
104      * @brief Finishes the animation. Returns true if state changed.
105      */
106     virtual bool Finish();
107     /**
108      * @brief Returns true if the animation is running.
109      */
110     bool IsRunning() const noexcept;
111     /**
112      * @brief REturns true if the animation is paused.
113      */
114     bool IsPaused() const noexcept;
115     /**
116      * @brief Returns the current progress of the animation.
117      */
118     float GetProgress() const noexcept;
119     /**
120      * @brief Move the animation to a requested step position
121      * @param step
122      * @param state
123      * @return
124      */
125     StepStatus Move(const IAnimationInternal::MoveParams& move);
126     /**
127      * @brief Resets to the animation clock to initial state, even if the animation is running.
128      */
129     void ResetClock();
130 
131 public:
132     BASE_NS::vector<IAnimationModifier::Ptr> GetModifiers() const;
133     bool Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext);
134     bool Detach(const IObject::Ptr& attachment);
135 
136     virtual void UpdateTotalDuration();
137 
138 protected:
139     virtual TimeSpan GetAnimationBaseDuration() const;
140 
141 protected:
142     AnimationStateParams& GetParams()
143     {
144         return params_;
145     }
146 
147     constexpr IAnimationInternal::AnimationTargetState GetAnimationTargetState() const noexcept
148     {
149         return state_.animationState_;
150     }
151 
152     /** Return the owning animation of this state object */
153     IAnimation::Ptr GetOwner() const noexcept;
154     /** Returns a duration with all modifiers applied */
155     IAnimationModifier::DurationData ApplyDurationModifiers(TimeSpan duration) const;
156     /** Returns step data with all modifiers applied */
157     IAnimationModifier::StepData ApplyStepModifiers(float progress) const;
158 
159 private:
160     void NotifyEvaluationNeeded() const;
161     void NotifyStateChanged(const IAnimationInternal::AnimationStateChangedInfo& info) const;
162     void UpdateController();
163     bool SetState(IAnimationInternal::AnimationTargetState state);
164     void SetRunning(bool running) noexcept;
165     void SetProgress(float progress) noexcept;
166 
167 private:
168     IAnimationController::WeakPtr controller_;         // Animation's controller
169     IOnChanged::InterfaceTypePtr updateTotalDuration_; // Callback function for total duration update
170     AnimationStateParams params_;                      // Animation parameters
171     struct StateData {
172         int32_t loops { 1 };
173         TimeSpan totalDuration;
174         IAnimationModifier::DurationData duration;
175         bool shouldInit_ { false };
176         IManualClock::Ptr clock_;
177         std::optional<META_NS::TimeSpan> lastTick_;
178         IAnimationInternal::AnimationTargetState animationState_ { IAnimationInternal::AnimationTargetState::STOPPED };
179 
180         void ResetLastTick() noexcept
181         {
182             lastTick_.reset();
183         }
184         void SetTime(const TimeSpan& time)
185         {
186             clock_->SetTime(time);
187         }
188         TimeSpan Tick(const TimeSpan& time)
189         {
190             clock_->IncrementTime(GetElapsed(time));
191             lastTick_ = time;
192             return clock_->GetTime();
193         }
194         TimeSpan GetCurrentTime() const
195         {
196             return clock_->GetTime();
197         }
198         constexpr TimeSpan GetElapsed(const TimeSpan& time) const noexcept
199         {
200             return lastTick_ ? time - *lastTick_ : TimeSpan::Zero();
201         }
202         constexpr TimeSpan GetBaseDuration() const noexcept
203         {
204             return duration.duration;
205         }
206 
207     } state_;                                             // State data
208     mutable FindCache<IAnimationModifier> modifierCache_; // Cached modifier query
209 };
210 
211 /**
212  * @brief State class implementation for animation targeting a single property.
213  */
214 class PropertyAnimationState : public AnimationState {
215     using Super = AnimationState;
216 
217 public:
218     PropertyAnimationState() = default;
219     ~PropertyAnimationState() = default;
220 
221     /**
222      * @brief Data needed for evaluating an animation state.
223      */
224     struct EvaluationData {
225         /** Target value */
226         const IAny::Ptr target;
227         /** Start of interpolation range */
228         const IAny::Ptr from;
229         /** End of interpolation range */
230         const IAny::Ptr to;
231         /** Linear animation progress [0,1] */
232         float progress;
233         /** The (optional) curve to use for transforming the progress value */
234         const ICurve1D::Ptr curve;
235         /** Returns true if the data is valid */
236         inline bool IsValid() const noexcept
237         {
238             return target && from && to;
239         }
240     };
241     /**
242      * @brief Initialize state object's internal interpolator to support given type id.
243      */
244     bool SetInterpolator(const TypeId& id);
245     /**
246      * @brief Return the interpolator initialized with SetInterpolator.
247      */
248     IInterpolator::Ptr GetInterpolator() const;
249     /**
250      * @brief Evaluates target value between [from,to] based on state.
251      * @param data Evaluation data.
252      */
253     AnyReturnValue EvaluateValue(const EvaluationData& data) const;
254 
255 private:
256     IInterpolator::Ptr interpolator_;
257 };
258 
259 } // namespace Internal
260 
261 META_END_NAMESPACE()
262 
263 #endif // META_SRC_ANIMATION_STATE_H
264