1 /* 2 * Copyright (c) 2021-2022 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 "base/memory/ace_type.h" 20 #include "base/utils/macros.h" 21 #include "base/utils/utils.h" 22 #ifdef LINUX_PLATFORM 23 #include <functional> 24 #endif 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_EXPORT_WITH_PREVIEW 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 }; 55 56 // The reverse curve is used to convert the direction of motion. 57 // It uses the 1.0->0.0 motion of the child curve to achieve the reverse purpose. 58 class ReverseCurve final : public Curve { 59 DECLARE_ACE_TYPE(ReverseCurve, Curve); 60 61 public: ReverseCurve(const RefPtr<Curve> & curve)62 explicit ReverseCurve(const RefPtr<Curve>& curve) : curve_(curve) {} 63 ~ReverseCurve() override = default; 64 MoveInternal(float time)65 float MoveInternal(float time) final 66 { 67 if (!curve_) { 68 return 0.0f; 69 } 70 71 if (time > 1.0f || time < 0.0f) { 72 return curve_->MoveInternal(0.0f); 73 } 74 return curve_->MoveInternal(1.0f - time); 75 } 76 77 private: 78 const RefPtr<Curve> curve_; 79 }; 80 81 class ComplementaryCurve final : public Curve { 82 DECLARE_ACE_TYPE(ComplementaryCurve, Curve); 83 84 public: ComplementaryCurve(const RefPtr<Curve> & curve)85 explicit ComplementaryCurve(const RefPtr<Curve>& curve) : curve_(curve) {} 86 ~ComplementaryCurve() override = default; 87 MoveInternal(float time)88 float MoveInternal(float time) final 89 { 90 if (!curve_) { 91 return 0.0f; 92 } 93 94 if (time > 1.0f || time < 0.0f) { 95 return curve_->MoveInternal(0.0f); 96 } 97 return 1.0f - curve_->MoveInternal(time); 98 } 99 100 private: 101 const RefPtr<Curve> curve_; 102 }; 103 104 class DecelerationCurve final : public Curve { 105 DECLARE_ACE_TYPE(DecelerationCurve, Curve); 106 107 public: MoveInternal(float time)108 float MoveInternal(float time) override 109 { 110 return 1.0f - std::pow(1.0f - time, SQUARE); 111 } 112 }; 113 114 class LinearCurve final : public Curve { 115 DECLARE_ACE_TYPE(LinearCurve, Curve); 116 117 public: MoveInternal(float time)118 float MoveInternal(float time) override 119 { 120 if (time < fractionMin || time > fractionMax) { 121 LOGE("LinearCurve MoveInternal: time is less than 0 or larger than 1, return 1"); 122 return fractionMax; 123 } 124 return time; 125 } 126 private: 127 float fractionMin = 0.0f; 128 float fractionMax = 1.0f; 129 }; 130 131 class SineCurve final : public Curve { 132 DECLARE_ACE_TYPE(SineCurve, Curve); 133 134 public: MoveInternal(float time)135 float MoveInternal(float time) override 136 { 137 static constexpr float PI = 3.14f; 138 return std::sin(PI * time / 2.0f); // half period 139 } 140 }; 141 142 class ElasticsCurve final : public Curve { 143 DECLARE_ACE_TYPE(ElasticsCurve, Curve); 144 145 public: ElasticsCurve(float tension)146 explicit ElasticsCurve(float tension) : tension_(tension) {} 147 ~ElasticsCurve() override = default; MoveInternal(float time)148 float MoveInternal(float time) override 149 { 150 float para = time - 1.0f; 151 return para * para * ((tension_ + 1.0f) * para + tension_) + 1.0f; 152 } 153 154 private: 155 float tension_ = 2.0f; // Default Elastics tension. 156 }; 157 158 enum class StepsCurvePosition { 159 START, 160 END, 161 }; 162 163 class StepsCurve : public Curve { 164 DECLARE_ACE_TYPE(StepsCurve, Curve); 165 166 public: 167 explicit StepsCurve(int32_t steps, StepsCurvePosition position = StepsCurvePosition::START) 168 : steps_(steps <= 0 ? 1 : steps), position_(position) {} 169 ~StepsCurve() override = default; 170 MoveInternal(float time)171 float MoveInternal(float time) override 172 { 173 if (time < fractionMin || time > fractionMax) { 174 LOGE("StepsCurve MoveInternal: time is less than 0 or larger than 1, return 1"); 175 return fractionMax; 176 } 177 auto currentStep = static_cast<int32_t>(time * steps_); 178 if (position_ == StepsCurvePosition::START) { 179 currentStep++; 180 } 181 return static_cast<float>(currentStep) / steps_; 182 } ToString()183 const std::string ToString() override 184 { 185 std::string curveString("steps"); 186 std::string comma(","); 187 curveString.append(std::string("(") + std::to_string(steps_) + comma); 188 if (position_ == StepsCurvePosition::START) { 189 curveString.append(std::string("start")); 190 } else { 191 curveString.append(std::string("end")); 192 } 193 curveString.append(std::string(")")); 194 return curveString; 195 } 196 private: 197 int32_t steps_; 198 const StepsCurvePosition position_; 199 float fractionMin = 0.0f; 200 float fractionMax = 1.0f; 201 202 friend class NativeCurveHelper; 203 }; 204 205 class CustomCurve final : public Curve { 206 DECLARE_ACE_TYPE(CustomCurve, Curve); 207 208 public: CustomCurve(const std::function<float (float)> & func)209 explicit CustomCurve(const std::function<float(float)>& func) : interpolateFunc_(func) {} 210 ~CustomCurve() override = default; MoveInternal(float time)211 float MoveInternal(float time) override 212 { 213 float value = interpolateFunc_(time); 214 return std::clamp(value, 0.f, 1.f); 215 } 216 217 private: 218 std::function<float(float)> interpolateFunc_; 219 220 friend class NativeCurveHelper; 221 }; 222 223 class ResponsiveSpringMotion final : public Curve { 224 DECLARE_ACE_TYPE(ResponsiveSpringMotion, Curve); 225 226 public: 227 ResponsiveSpringMotion(float response, float dampingRatio, float blendDuration = 0.0f) response_(response)228 : response_(response), dampingRatio_(dampingRatio), blendDuration_(blendDuration) {} 229 ~ResponsiveSpringMotion() override = default; 230 // this MoveInterval function is not the real implementation of the function. 231 // The curve should use the curve in rosen. MoveInternal(float time)232 float MoveInternal(float time) override 233 { 234 return 0.0f; 235 } ToString()236 const std::string ToString() override 237 { 238 std::string curveString("responsive-spring-motion"); 239 std::string comma(","); 240 curveString.append(std::string("(") + std::to_string(response_) + comma + std::to_string(dampingRatio_) + 241 comma + std::to_string(blendDuration_) + std::string(")")); 242 return curveString; 243 } GetResponse()244 float GetResponse() const 245 { 246 return response_; 247 } GetDampingRatio()248 float GetDampingRatio() const 249 { 250 return dampingRatio_; 251 } GetBlendDuration()252 float GetBlendDuration() const 253 { 254 return blendDuration_; 255 } 256 static constexpr float DEFAULT_SPRING_MOTION_RESPONSE = 0.55f; 257 static constexpr float DEFAULT_SPRING_MOTION_DAMPING_RATIO = 0.825f; 258 static constexpr float DEFAULT_SPRING_MOTION_BLEND_DURATION = 0.0f; 259 static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE = 0.15f; 260 static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO = 0.86f; 261 static constexpr float DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION = 0.25f; 262 private: 263 float response_; 264 float dampingRatio_; 265 float blendDuration_; 266 }; 267 268 } // namespace OHOS::Ace 269 270 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_CURVE_H 271