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#include "node/animate_impl.h"
17
18#include "node/node_model.h"
19
20#include "base/error/error_code.h"
21
22namespace OHOS::Ace::AnimateModel {
23
24int32_t AnimateTo(ArkUI_ContextHandle context, ArkUI_AnimateOption* option, ArkUI_ContextCallback* update,
25    ArkUI_AnimateCompleteCallback* complete)
26{
27    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
28    if (!impl || !context || !option || !update || !update->callback) {
29        return ERROR_CODE_PARAM_INVALID;
30    }
31
32    ArkUIAnimateOption animateOption {};
33    animateOption.duration = option->duration;
34    animateOption.tempo = option->tempo;
35    animateOption.curve = static_cast<ArkUI_Int32>(option->curve);
36    animateOption.delay = option->delay;
37    animateOption.iterations = option->iterations;
38    if (option->iCurve) {
39        animateOption.iCurve = option->iCurve->curve;
40        animateOption.curveType = option->iCurve->baseCurveType;
41    }
42    animateOption.playMode = static_cast<ArkUI_Int32>(option->playMode);
43    if (option->expectedFrameRateRange) {
44        animateOption.expectedFrameRateRange =
45            reinterpret_cast<ArkUIExpectedFrameRateRange*>(option->expectedFrameRateRange);
46    }
47
48    if (complete && complete->callback) {
49        animateOption.onFinishCallback = reinterpret_cast<void*>(complete->callback);
50    }
51
52    if (complete && complete->userData) {
53        animateOption.user = complete->userData;
54    }
55    auto finishCallbackType = static_cast<ArkUI_Int32>(ARKUI_FINISH_CALLBACK_REMOVED);
56    if (complete && complete->type == ARKUI_FINISH_CALLBACK_LOGICALLY) {
57        finishCallbackType = static_cast<ArkUI_Int32>(ARKUI_FINISH_CALLBACK_LOGICALLY);
58    }
59    animateOption.finishCallbackType = finishCallbackType;
60
61    impl->getAnimation()->animateTo(reinterpret_cast<ArkUIContext*>(context), animateOption,
62        reinterpret_cast<void*>(update->callback), update->userData);
63    return ERROR_CODE_NO_ERROR;
64}
65
66int32_t KeyframeAnimateTo(ArkUI_ContextHandle context, ArkUI_KeyframeAnimateOption* option)
67{
68    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
69    if (!impl || !context || !option || option->keyframes.size() == 0) {
70        return ERROR_CODE_PARAM_INVALID;
71    }
72
73    ArkUIKeyframeAnimateOption animateOption {};
74    animateOption.delay = option->delay;
75    animateOption.iterations = option->iterations;
76    animateOption.onFinish = option->onFinish;
77    animateOption.userData = option->userData;
78    ArkUIKeyframeState keyframes[option->keyframes.size()];
79    for (size_t i = 0; i < option->keyframes.size(); i++) {
80        keyframes[i].duration = option->keyframes[i].duration;
81        keyframes[i].event = option->keyframes[i].event;
82        keyframes[i].userData = option->keyframes[i].userData;
83
84        auto curve = option->keyframes[i].curve;
85        if (!curve) {
86            continue;
87        }
88        //不支持当前curve
89        if (curve->type == ARKUI_CURVE_TYPE_SPRING_MOTION || curve->type == ARKUI_CURVE_TYPE_RESPONSIVE_SPRING_MOTION ||
90            curve->type == ARKUI_CURVE_TYPE_INTERPOLATING_SPRING) {
91            continue;
92        }
93        keyframes[i].curve = curve->curve;
94        keyframes[i].curveType = curve->type;
95    }
96    animateOption.keyframes = keyframes;
97    animateOption.keyframeSize = static_cast<int32_t>(option->keyframes.size());
98
99    impl->getAnimation()->keyframeAnimateTo(reinterpret_cast<ArkUIContext*>(context), &animateOption);
100    return ERROR_CODE_NO_ERROR;
101}
102
103ArkUIAnimatorOption* ConvertAnimatorOption(ArkUI_AnimatorOption* option)
104{
105    ArkUIAnimatorOption* animatorOption = new ArkUIAnimatorOption;
106    animatorOption->duration = option->duration;
107    animatorOption->delay = option->delay;
108    animatorOption->iterations = option->iterations;
109    animatorOption->begin = option->begin;
110    animatorOption->end = option->end;
111    animatorOption->fill = option->fill;
112    animatorOption->direction = option->direction;
113    if (option->easing) {
114        animatorOption->easing = option->easing->curve;
115        animatorOption->curveType = option->easing->type;
116    } else {
117        animatorOption->easing = nullptr;
118    }
119
120    if (option->expectedFrameRateRange) {
121        animatorOption->isHasExpectedFrameRateRange = 1;
122        animatorOption->expectedFrameRateRange = { option->expectedFrameRateRange->min,
123            option->expectedFrameRateRange->max, option->expectedFrameRateRange->expected };
124    } else {
125        animatorOption->isHasExpectedFrameRateRange = 0;
126    }
127
128    int32_t keyframeSize = static_cast<int32_t>(option->keyframes.size());
129    if (keyframeSize > 0) {
130        animatorOption->keyframes = new ArkUIKeyframe[keyframeSize];
131        for (int32_t i = 0; i < keyframeSize; ++i) {
132            animatorOption->keyframes[i].keyTime = option->keyframes[i].keyTime;
133            animatorOption->keyframes[i].keyValue = option->keyframes[i].keyValue;
134            if (option->keyframes[i].curve) {
135                animatorOption->keyframes[i].curve = option->keyframes[i].curve->curve;
136                animatorOption->keyframes[i].curveType = option->keyframes[i].curve->type;
137            } else {
138                animatorOption->keyframes[i].curve = nullptr;
139                animatorOption->keyframes[i].curveType = 0; // 默认或无效的曲线类型
140            }
141        }
142    } else {
143        animatorOption->keyframes = nullptr;
144    }
145    animatorOption->keyframeSize = keyframeSize;
146
147    animatorOption->onFrame = option->onFrame;
148    animatorOption->onFinish = option->onFinish;
149    animatorOption->onCancel = option->onCancel;
150    animatorOption->onRepeat = option->onRepeat;
151
152    animatorOption->frameUserData = option->frameUserData;
153    animatorOption->finishUserData = option->finishUserData;
154    animatorOption->cancelUserData = option->cancelUserData;
155    animatorOption->repeatUserData = option->repeatUserData;
156    return animatorOption;
157}
158
159ArkUI_AnimatorHandle CreateAnimator(ArkUI_ContextHandle context, ArkUI_AnimatorOption* option)
160{
161    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
162    if (!impl || !context || !option) {
163        return nullptr;
164    }
165
166    auto animatorOption = ConvertAnimatorOption(option);
167    auto animator = impl->getAnimation()->createAnimator(reinterpret_cast<ArkUIContext*>(context), animatorOption);
168    ArkUI_Animator* animatorHandle = new ArkUI_Animator { animator, option, animatorOption };
169    return animatorHandle;
170}
171
172void DisposeAnimator(ArkUI_AnimatorHandle animatorHandle)
173{
174    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
175    if (!animatorHandle || !animatorHandle->animator) {
176        return;
177    }
178    impl->getAnimation()->disposeAnimator(animatorHandle->animator);
179    if (animatorHandle->animatorOption) {
180        auto* animatorOption = reinterpret_cast<ArkUIAnimatorOption*>(animatorHandle->animatorOption);
181        if (animatorOption->keyframes) {
182            delete[] animatorOption->keyframes;
183            animatorOption->keyframes = nullptr;
184        }
185        delete animatorOption;
186        animatorHandle->animatorOption = nullptr;
187    }
188    delete animatorHandle;
189}
190
191int32_t AnimatorReset(ArkUI_AnimatorHandle animatorHandle, ArkUI_AnimatorOption* option)
192{
193    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
194    if (!impl || !animatorHandle || !animatorHandle->animator || !option) {
195        return ERROR_CODE_PARAM_INVALID;
196    }
197
198    auto animatorOption = ConvertAnimatorOption(option);
199    impl->getAnimation()->animatorReset(animatorHandle->animator, animatorOption);
200    if (animatorHandle->animatorOption) {
201        auto* animatorOption = reinterpret_cast<ArkUIAnimatorOption*>(animatorHandle->animatorOption);
202        if (animatorOption->keyframes) {
203            delete[] animatorOption->keyframes;
204            animatorOption->keyframes = nullptr;
205        }
206        delete animatorOption;
207        animatorHandle->animatorOption = nullptr;
208    }
209    animatorHandle->animatorOption = animatorOption;
210    return ERROR_CODE_NO_ERROR;
211}
212
213int32_t AnimatorPlay(ArkUI_AnimatorHandle animatorHandle)
214{
215    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
216    if (!impl || !animatorHandle || !animatorHandle->animator) {
217        return ERROR_CODE_PARAM_INVALID;
218    }
219    impl->getAnimation()->animatorPlay(animatorHandle->animator);
220    return ERROR_CODE_NO_ERROR;
221}
222
223int32_t AnimatorFinish(ArkUI_AnimatorHandle animatorHandle)
224{
225    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
226    if (!impl || !animatorHandle || !animatorHandle->animator) {
227        return ERROR_CODE_PARAM_INVALID;
228    }
229    impl->getAnimation()->animatorFinish(animatorHandle->animator);
230    return ERROR_CODE_NO_ERROR;
231}
232
233int32_t AnimatorPause(ArkUI_AnimatorHandle animatorHandle)
234{
235    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
236    if (!impl || !animatorHandle || !animatorHandle->animator) {
237        return ERROR_CODE_PARAM_INVALID;
238    }
239    impl->getAnimation()->animatorPause(animatorHandle->animator);
240    return ERROR_CODE_NO_ERROR;
241}
242
243int32_t AnimatorCancel(ArkUI_AnimatorHandle animatorHandle)
244{
245    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
246    if (!impl || !animatorHandle || !animatorHandle->animator) {
247        return ERROR_CODE_PARAM_INVALID;
248    }
249    impl->getAnimation()->animatorCancel(animatorHandle->animator);
250    return ERROR_CODE_NO_ERROR;
251}
252
253int32_t AnimatorReverse(ArkUI_AnimatorHandle animatorHandle)
254{
255    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
256    if (!impl || !animatorHandle || !animatorHandle->animator) {
257        return ERROR_CODE_PARAM_INVALID;
258    }
259    impl->getAnimation()->animatorReverse(animatorHandle->animator);
260    return ERROR_CODE_NO_ERROR;
261}
262
263ArkUI_CurveHandle InitCurve(ArkUI_AnimationCurve animationCurve)
264{
265    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
266    if (!impl) {
267        return nullptr;
268    }
269    auto curve = impl->getAnimation()->initCurve(animationCurve);
270    ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_BASE, curve, animationCurve });
271    return iCurve;
272}
273
274ArkUI_CurveHandle StepsCurve(int32_t count, bool end)
275{
276    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
277    if (!impl || count < 1) {
278        return nullptr;
279    }
280    auto curve = impl->getAnimation()->stepsCurve(count, end);
281    ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_STEPS, curve });
282    return iCurve;
283}
284
285ArkUI_CurveHandle CubicBezierCurve(float x1, float y1, float x2, float y2)
286{
287    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
288    if (!impl) {
289        return nullptr;
290    }
291    x1 = std::clamp(x1, 0.0f, 1.0f);
292    x2 = std::clamp(x2, 0.0f, 1.0f);
293    auto curve = impl->getAnimation()->cubicBezierCurve(x1, y1, x2, y2);
294    ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_CUBIC_BEZIER, curve });
295    return iCurve;
296}
297
298ArkUI_CurveHandle SpringCurve(float velocity, float mass, float stiffness, float damping)
299{
300    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
301    if (!impl) {
302        return nullptr;
303    }
304    if (mass <= 0) {
305        mass = 1;
306    }
307    if (stiffness <= 0) {
308        stiffness = 1;
309    }
310    if (damping <= 0) {
311        damping = 1;
312    }
313    auto curve = impl->getAnimation()->springCurve(velocity, mass, stiffness, damping);
314    ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_SPRING, curve });
315    return iCurve;
316}
317
318ArkUI_CurveHandle SpringMotion(float response, float dampingFraction, float overlapDuration)
319{
320    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
321    if (!impl) {
322        return nullptr;
323    }
324    //default
325    if (response <= 0) {
326        response = 0.55f;
327    }
328    //default
329    if (dampingFraction <= 0) {
330        dampingFraction = 0.825f;
331    }
332    //default
333    if (overlapDuration < 0) {
334        overlapDuration = 0;
335    }
336    auto curve = impl->getAnimation()->springMotion(response, dampingFraction, overlapDuration);
337    ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_SPRING_MOTION, curve });
338    return iCurve;
339}
340
341ArkUI_CurveHandle ResponsiveSpringMotion(float response, float dampingFraction, float overlapDuration)
342{
343    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
344    if (!impl) {
345        return nullptr;
346    }
347    //default
348    if (response <= 0) {
349        response = 0.15f;
350    }
351    //default
352    if (dampingFraction < 0) {
353        dampingFraction = 0.86f;
354    }
355    //default
356    if (overlapDuration < 0) {
357        overlapDuration = 0.25f;
358    }
359    auto curve = impl->getAnimation()->responsiveSpringMotion(response, dampingFraction, overlapDuration);
360    ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_RESPONSIVE_SPRING_MOTION, curve });
361    return iCurve;
362}
363
364ArkUI_CurveHandle InterpolatingSpring(float velocity, float mass, float stiffness, float damping)
365{
366    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
367    if (!impl) {
368        return nullptr;
369    }
370    if (mass <= 0) {
371        mass = 1;
372    }
373    if (stiffness <= 0) {
374        stiffness = 1;
375    }
376    if (damping <= 0) {
377        damping = 1;
378    }
379    auto curve = impl->getAnimation()->interpolatingSpring(velocity, mass, stiffness, damping);
380    ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_INTERPOLATING_SPRING, curve });
381    return iCurve;
382}
383
384ArkUI_CurveHandle CustomCurve(void* userData, float (*interpolate)(float fraction, void* userdata))
385{
386    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
387    if (!impl) {
388        return nullptr;
389    }
390    auto curve = impl->getAnimation()->customCurve(interpolate, userData);
391    ArkUI_Curve* iCurve = new ArkUI_Curve({ ARKUI_CURVE_TYPE_CUSTOM, curve });
392    return iCurve;
393}
394
395void DisposeCurve(ArkUI_CurveHandle curveHandle)
396{
397    auto* impl = OHOS::Ace::NodeModel::GetFullImpl();
398    if (!impl || !curveHandle) {
399        return;
400    }
401    impl->getAnimation()->disposeCurve(curveHandle->curve);
402    delete curveHandle;
403}
404} // namespace OHOS::Ace::AnimateModel