1 /* 2 * Copyright (c) 2025 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 FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_ANIMATION_CURVE_H 17 #define FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_ANIMATION_CURVE_H 18 19 #include <functional> 20 #include <math.h> 21 22 #include "ui/base/ace_type.h" 23 #include "ui/base/macros.h" 24 #include "ui/base/utils/utils.h" 25 26 namespace OHOS::Ace { 27 class NativeCurveHelper; 28 29 constexpr double SQUARE = 2.0; 30 31 // The running time of the curve needs to be normalized to the interval of 0.0 to 1.0; 32 // Relatively, the corresponding value of the curve also needs to be normalized to the interval of 0.0 to 1.0; 33 class ACE_FORCE_EXPORT Curve : public AceType { 34 DECLARE_ACE_TYPE(Curve, AceType); 35 36 public: 37 Curve() = default; 38 ~Curve() override = default; 39 40 // Returns the value at specific time. 41 // Notice: The value of time must be between 0.0 and 1.0 since the curve uses normalized timestamp. Move(float time)42 float Move(float time) 43 { 44 // time always between 0.0 and 1.0 45 return MoveInternal(time); 46 } 47 48 // Each subclass needs to override this method to implement motion in the 0.0 to 1.0 time range. 49 virtual float MoveInternal(float time) = 0; ToString()50 virtual const std::string ToString() 51 { 52 return ""; 53 } 54 IsEqual(const RefPtr<Curve> & curve)55 virtual bool IsEqual(const RefPtr<Curve>& curve) const 56 { 57 return false; 58 } 59 }; 60 61 // The reverse curve is used to convert the direction of motion. 62 // It uses the 1.0->0.0 motion of the child curve to achieve the reverse purpose. 63 class ReverseCurve final : public Curve { 64 DECLARE_ACE_TYPE(ReverseCurve, Curve); 65 66 public: ReverseCurve(const RefPtr<Curve> & curve)67 explicit ReverseCurve(const RefPtr<Curve>& curve) : curve_(curve) {} 68 ~ReverseCurve() override = default; 69 MoveInternal(float time)70 float MoveInternal(float time) final 71 { 72 if (!curve_) { 73 return 0.0f; 74 } 75 76 if (time > 1.0f || time < 0.0f) { 77 return curve_->MoveInternal(0.0f); 78 } 79 return curve_->MoveInternal(1.0f - time); 80 } 81 private: 82 const RefPtr<Curve> curve_; 83 }; 84 85 class ComplementaryCurve final : public Curve { 86 DECLARE_ACE_TYPE(ComplementaryCurve, Curve); 87 88 public: ComplementaryCurve(const RefPtr<Curve> & curve)89 explicit ComplementaryCurve(const RefPtr<Curve>& curve) : curve_(curve) {} 90 ~ComplementaryCurve() override = default; 91 MoveInternal(float time)92 float MoveInternal(float time) final 93 { 94 if (!curve_) { 95 return 0.0f; 96 } 97 98 if (time > 1.0f || time < 0.0f) { 99 return curve_->MoveInternal(0.0f); 100 } 101 return 1.0f - curve_->MoveInternal(time); 102 } 103 private: 104 const RefPtr<Curve> curve_; 105 }; 106 107 class DecelerationCurve final : public Curve { 108 DECLARE_ACE_TYPE(DecelerationCurve, Curve); 109 110 public: MoveInternal(float time)111 float MoveInternal(float time) override 112 { 113 return 1.0f - std::pow(1.0f - time, SQUARE); 114 } 115 IsEqual(const RefPtr<Curve> & curve)116 bool IsEqual(const RefPtr<Curve>& curve) const override 117 { 118 return AceType::InstanceOf<DecelerationCurve>(curve); 119 } 120 }; 121 122 class LinearCurve final : public Curve { 123 DECLARE_ACE_TYPE(LinearCurve, Curve); 124 125 public: MoveInternal(float time)126 float MoveInternal(float time) override 127 { 128 if (time < fractionMin || time > fractionMax) { 129 return fractionMax; 130 } 131 return time; 132 } 133 ToString()134 const std::string ToString() override 135 { 136 std::string curveString("linear"); 137 return curveString; 138 } 139 IsEqual(const RefPtr<Curve> & curve)140 bool IsEqual(const RefPtr<Curve>& curve) const override 141 { 142 return AceType::InstanceOf<LinearCurve>(curve); 143 } 144 145 private: 146 float fractionMin = 0.0f; 147 float fractionMax = 1.0f; 148 }; 149 150 class SineCurve final : public Curve { 151 DECLARE_ACE_TYPE(SineCurve, Curve); 152 153 public: MoveInternal(float time)154 float MoveInternal(float time) override 155 { 156 static constexpr float PI = 3.14f; 157 return std::sin(PI * time / 2.0f); // half period 158 } 159 IsEqual(const RefPtr<Curve> & curve)160 bool IsEqual(const RefPtr<Curve>& curve) const override 161 { 162 return AceType::InstanceOf<SineCurve>(curve); 163 } 164 }; 165 166 class ElasticsCurve final : public Curve { 167 DECLARE_ACE_TYPE(ElasticsCurve, Curve); 168 169 public: ElasticsCurve(float tension)170 explicit ElasticsCurve(float tension) : tension_(tension) {} 171 ~ElasticsCurve() override = default; MoveInternal(float time)172 float MoveInternal(float time) override 173 { 174 float para = time - 1.0f; 175 return para * para * ((tension_ + 1.0f) * para + tension_) + 1.0f; 176 } 177 GetTension()178 float GetTension() const 179 { 180 return tension_; 181 } 182 IsEqual(const RefPtr<Curve> & curve)183 bool IsEqual(const RefPtr<Curve>& curve) const override 184 { 185 auto other = AceType::DynamicCast<ElasticsCurve>(curve); 186 if (!other) { 187 return false; 188 } 189 return NearEqual(other->GetTension(), tension_); 190 } 191 private: 192 float tension_ = 2.0f; // Default Elastics tension. 193 }; 194 195 enum class StepsCurvePosition { 196 START, 197 END, 198 }; 199 200 class StepsCurve : public Curve { 201 DECLARE_ACE_TYPE(StepsCurve, Curve); 202 203 public: 204 explicit StepsCurve(int32_t steps, StepsCurvePosition position = StepsCurvePosition::START) 205 : steps_(steps <= 0 ? 1 : steps), position_(position) 206 {} 207 ~StepsCurve() override = default; 208 MoveInternal(float time)209 float MoveInternal(float time) override 210 { 211 if (time < fractionMin || time > fractionMax) { 212 return fractionMax; 213 } 214 auto currentStep = static_cast<int32_t>(time * steps_); 215 if (position_ == StepsCurvePosition::START && currentStep < steps_) { 216 currentStep++; 217 } 218 return static_cast<float>(currentStep) / steps_; 219 } ToString()220 const std::string ToString() override 221 { 222 std::string curveString("steps"); 223 std::string comma(","); 224 curveString.append(std::string("(") + std::to_string(steps_) + comma); 225 if (position_ == StepsCurvePosition::START) { 226 curveString.append(std::string("start")); 227 } else { 228 curveString.append(std::string("end")); 229 } 230 curveString.append(std::string(")")); 231 return curveString; 232 } 233 IsEqual(const RefPtr<Curve> & curve)234 bool IsEqual(const RefPtr<Curve>& curve) const override 235 { 236 auto other = AceType::DynamicCast<StepsCurve>(curve); 237 if (!other) { 238 return false; 239 } 240 return other->GetSteps() == steps_ && other->GetStepsCurvePosition() == position_; 241 } 242 GetSteps()243 int32_t GetSteps() const 244 { 245 return steps_; 246 } 247 GetStepsCurvePosition()248 StepsCurvePosition GetStepsCurvePosition() const 249 { 250 return position_; 251 } 252 253 private: 254 int32_t steps_; 255 const StepsCurvePosition position_; 256 float fractionMin = 0.0f; 257 float fractionMax = 1.0f; 258 259 friend class NativeCurveHelper; 260 }; 261 262 class CustomCurve final : public Curve { 263 DECLARE_ACE_TYPE(CustomCurve, Curve); 264 265 public: CustomCurve(const std::function<float (float)> & func)266 explicit CustomCurve(const std::function<float(float)>& func) : interpolateFunc_(func) {} 267 ~CustomCurve() override = default; MoveInternal(float time)268 float MoveInternal(float time) override 269 { 270 return interpolateFunc_ ? interpolateFunc_(time) : 1.0f; 271 } ToString()272 const std::string ToString() override 273 { 274 return "customCallback"; 275 } 276 private: 277 std::function<float(float)> interpolateFunc_; 278 279 friend class NativeCurveHelper; 280 }; 281 282 class ResponsiveSpringMotion final : public Curve { 283 DECLARE_ACE_TYPE(ResponsiveSpringMotion, Curve); 284 285 public: 286 ResponsiveSpringMotion(float response, float dampingRatio, float blendDuration = 0.0f) response_(response)287 : response_(response), dampingRatio_(dampingRatio), blendDuration_(blendDuration) 288 {} 289 ~ResponsiveSpringMotion() override = default; 290 // this MoveInterval function is not the real implementation of the function. 291 // The curve should use the curve in rosen. MoveInternal(float time)292 float MoveInternal(float time) override 293 { 294 return 0.0f; 295 } ToString()296 const std::string ToString() override 297 { 298 std::string curveString("responsive-spring-motion"); 299 std::string comma(","); 300 curveString.append(std::string("(") + std::to_string(response_) + comma + std::to_string(dampingRatio_) + 301 comma + std::to_string(blendDuration_) + std::string(")")); 302 return curveString; 303 } IsEqual(const RefPtr<Curve> & curve)304 bool IsEqual(const RefPtr<Curve>& curve) const override 305 { 306 auto other = AceType::DynamicCast<ResponsiveSpringMotion>(curve); 307 if (!other) { 308 return false; 309 } 310 return NearEqual(other->GetResponse(), response_) && NearEqual(other->GetDampingRatio(), dampingRatio_) && 311 NearEqual(other->GetBlendDuration(), blendDuration_); 312 } GetResponse()313 float GetResponse() const 314 { 315 return response_; 316 } GetDampingRatio()317 float GetDampingRatio() const 318 { 319 return dampingRatio_; 320 } GetBlendDuration()321 float GetBlendDuration() const 322 { 323 return blendDuration_; 324 } GetMinimumAmplitudeRatio()325 float GetMinimumAmplitudeRatio() const 326 { 327 return minimumAmplitudeRatio_; 328 } UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio)329 void UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio) 330 { 331 minimumAmplitudeRatio_ = minimumAmplitudeRatio; 332 } 333 static constexpr float DEFAULT_SPRING_MOTION_RESPONSE = 0.55f; 334 static constexpr float DEFAULT_SPRING_MOTION_DAMPING_RATIO = 0.825f; 335 static constexpr float DEFAULT_SPRING_MOTION_BLEND_DURATION = 0.0f; 336 static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE = 0.15f; 337 static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO = 0.86f; 338 static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION = 0.25f; 339 static constexpr float DEFAULT_RESPONSIVE_SPRING_AMPLITUDE_RATIO = 0.001f; 340 341 private: 342 float response_; 343 float dampingRatio_; 344 float blendDuration_; 345 float minimumAmplitudeRatio_ = DEFAULT_RESPONSIVE_SPRING_AMPLITUDE_RATIO; 346 }; 347 348 class InterpolatingSpring final : public Curve { 349 DECLARE_ACE_TYPE(InterpolatingSpring, Curve); 350 351 public: InterpolatingSpring(float velocity,float mass,float stiffness,float damping)352 InterpolatingSpring(float velocity, float mass, float stiffness, float damping) 353 : velocity_(velocity), mass_(mass), stiffness_(stiffness), damping_(damping) 354 {} 355 ~InterpolatingSpring() override = default; 356 // this MoveInterval function is not the real implementation of the function. 357 // The curve should use the curve in rosen. MoveInternal(float time)358 float MoveInternal(float time) override 359 { 360 return 0.0f; 361 } ToString()362 const std::string ToString() override 363 { 364 std::string curveString("interpolating-spring"); 365 std::string comma(","); 366 curveString.append(std::string("(") + std::to_string(velocity_) + comma + std::to_string(mass_) + comma + 367 std::to_string(stiffness_) + comma + std::to_string(damping_) + std::string(")")); 368 return curveString; 369 } 370 IsEqual(const RefPtr<Curve> & curve)371 bool IsEqual(const RefPtr<Curve>& curve) const override 372 { 373 auto other = AceType::DynamicCast<InterpolatingSpring>(curve); 374 if (!other) { 375 return false; 376 } 377 return NearEqual(other->GetVelocity(), velocity_) && NearEqual(other->GetMass(), mass_) && 378 NearEqual(other->GetStiffness(), stiffness_) && NearEqual(other->GetDamping(), damping_); 379 } 380 GetVelocity()381 float GetVelocity() const 382 { 383 return velocity_; 384 } 385 UpdateVelocity(float velocity)386 void UpdateVelocity(float velocity) 387 { 388 velocity_ = velocity; 389 } 390 GetMass()391 float GetMass() const 392 { 393 return mass_; 394 } 395 GetStiffness()396 float GetStiffness() const 397 { 398 return stiffness_; 399 } 400 GetDamping()401 float GetDamping() const 402 { 403 return damping_; 404 } 405 GetMinimumAmplitudeRatio()406 float GetMinimumAmplitudeRatio() const 407 { 408 return minimumAmplitudeRatio_; 409 } 410 UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio)411 void UpdateMinimumAmplitudeRatio(float minimumAmplitudeRatio) 412 { 413 minimumAmplitudeRatio_ = minimumAmplitudeRatio; 414 } 415 416 static constexpr float DEFAULT_INTERPOLATING_SPRING_MASS = 1.0f; 417 static constexpr float DEFAULT_INTERPOLATING_SPRING_VELOCITY = 0.0f; 418 static constexpr float DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO = 0.00025f; 419 420 private: 421 float velocity_ = 0.0f; 422 float mass_ = 0.0f; 423 float stiffness_ = 0.0f; 424 float damping_ = 0.0f; 425 float minimumAmplitudeRatio_ = DEFAULT_INTERPOLATING_SPRING_AMPLITUDE_RATIO; 426 }; 427 } // namespace OHOS::Ace 428 429 #endif // FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_ANIMATION_CURVE_H 430