1 /*
2  * Copyright (c) 2021 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_ANIMATABLE_TRANSFORM_OPERATION_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_ANIMATABLE_TRANSFORM_OPERATION_H
18 
19 #include <list>
20 #include <vector>
21 
22 #include "base/geometry/transform_util.h"
23 #include "core/animation/animatable_base.h"
24 
25 namespace OHOS::Ace {
26 
27 class ACE_EXPORT AnimatableTransformOperation final : public AnimatableBase<TransformOperation> {
28 public:
29     explicit AnimatableTransformOperation(const AnimationOption& animationOption = AnimationOption())
30     {
31         animationOption_ = animationOption;
32     }
33     explicit AnimatableTransformOperation(
34         const TransformOperation& operation, const AnimationOption& animationOption = AnimationOption())
35     {
36         animationOption_ = animationOption;
37         SetCurrentValue(operation);
38     }
39     ~AnimatableTransformOperation() override = default;
40 
MoveTo(const TransformOperation & value)41     void MoveTo(const TransformOperation& value) override
42     {
43         SetCurrentValue(value);
44     }
45 
46 private:
OnAnimationCallback(const TransformOperation & value)47     void OnAnimationCallback(const TransformOperation& value) override
48     {
49         SetCurrentValue(value);
50         AnimatableBase<TransformOperation>::OnAnimationCallback(value);
51     }
52 
SetCurrentValue(const TransformOperation & other)53     void SetCurrentValue(const TransformOperation& other)
54     {
55         auto pipelineContext = context_.Upgrade();
56         if (pipelineContext && pipelineContext->GetIsDeclarative() && type_ != TransformOperationType::UNDEFINED &&
57             type_ != other.type_) {
58             LOGE("SetCurrentValue failed, not same type");
59             return;
60         }
61         TransformOperation& self = *this;
62         self = other;
63     }
64 };
65 
66 class AnimatableTransformOperations final {
67 public:
68     AnimatableTransformOperations() = default;
69     AnimatableTransformOperations(const AnimatableTransformOperations& other) = default;
70     ~AnimatableTransformOperations() = default;
71 
SetContextAndCallback(const WeakPtr<PipelineContext> & context,const RenderNodeAnimationCallback & callback)72     void SetContextAndCallback(const WeakPtr<PipelineContext>& context, const RenderNodeAnimationCallback& callback)
73     {
74         context_ = context;
75         animationCallback_ = callback;
76     }
77 
GetOperations()78     const std::vector<AnimatableTransformOperation>& GetOperations() const
79     {
80         return operations_;
81     }
82 
83     void AddTransformOperation(
84         const TransformOperation& operation, const AnimationOption& animationOption = AnimationOption())
85     {
86         operations_.emplace_back(operation, animationOption);
87     }
88 
Clear()89     void Clear()
90     {
91         operations_.clear();
92     }
93 
94     AnimatableTransformOperations& operator=(const AnimatableTransformOperations& other)
95     {
96         if (isFirstAssign_) {
97             operations_ = other.operations_;
98             isFirstAssign_ = false;
99         } else {
100             auto pipelineContext = context_.Upgrade();
101             if (!pipelineContext) {
102                 LOGE("AnimatableTransformOperations pipelineContext is null!");
103                 operations_ = other.operations_;
104                 return *this;
105             }
106             const auto& explicitOption = pipelineContext->GetExplicitAnimationOption();
107             if (other.operations_.size() == operations_.size()) {
108                 for (std::size_t i = 0; i < operations_.size(); i++) {
109                     if (explicitOption.IsValid()) {
110                         operations_[i].SetAnimationOption(explicitOption);
111                     } else {
112                         operations_[i].SetAnimationOption(other.operations_[i].GetAnimationOption());
113                     }
114                     operations_[i].SetContextAndCallback(context_, animationCallback_);
115                     operations_[i].AnimateTo(operations_[i], other.operations_[i]);
116                 }
117             } else {
118                 LOGE("AddTransformOperation %{public}d != %{public}d", static_cast<int32_t>(operations_.size()),
119                     static_cast<int32_t>(other.operations_.size()));
120                 operations_ = other.operations_;
121             }
122         }
123         return *this;
124     }
125 
126 private:
127     std::vector<AnimatableTransformOperation> operations_;
128     RenderNodeAnimationCallback animationCallback_;
129     WeakPtr<PipelineContext> context_;
130     bool isFirstAssign_ = true;
131 };
132 
133 class TransformAnimation final : public AnimatableBase<TransformOperations> {
134 public:
ComputerBlendedMatrix4()135     Matrix4 ComputerBlendedMatrix4()
136     {
137         TransformOperations::ParseOperationsToMatrix(blended.GetOperations());
138         return blended.ComputerRemaining(0);
139     }
140 
SetTransformOperations(const std::vector<TransformOperation> & other)141     void SetTransformOperations(const std::vector<TransformOperation>& other)
142     {
143         operations_ = other;
144         blended = TransformOperations(operations_);
145         endValue_ = blended;
146     }
147 
148     void PlayTransformAnimation(
149         const AnimationOption& option, const std::vector<TransformOperation>& other, bool alwaysRotate = false)
150     {
151         SetAnimationOption(option);
152         auto target = TransformOperations(other);
153         TransformOperations::ParseOperationsToMatrix(operations_);
154         TransformOperations::ParseOperationsToMatrix(target.GetOperations());
155         target.SetAlwaysRotate(alwaysRotate);
156         AnimateTo(blended, target);
157         // just move to target, renderNode should use blended to computer matrix
158         MoveTo(target);
159     }
160 
MoveTo(const TransformOperations & value)161     void MoveTo(const TransformOperations& value) override
162     {
163         operations_ = value.GetOperations();
164     }
165 
166 private:
OnAnimationCallback(const TransformOperations & value)167     void OnAnimationCallback(const TransformOperations& value) override
168     {
169         blended = value;
170         AnimatableBase<TransformOperations>::OnAnimationCallback(value);
171     }
172 
173 private:
174     TransformOperations blended;
175 };
176 
177 } // namespace OHOS::Ace
178 
179 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_ANIMATION_ANIMATABLE_TRANSFORM_OPERATION_H
180