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