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