• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "core/components/transition/transition_element.h"
17 
18 #include "core/components/box/render_box_base.h"
19 #include "core/components/transform/transform_element.h"
20 #include "core/components/transition/transition_component.h"
21 #include "core/components/tween/tween_component.h"
22 #include "core/components/tween/tween_element.h"
23 
24 namespace OHOS::Ace {
25 
Update()26 void TransitionElement::Update()
27 {
28     ComposedElement::Update();
29     if (!component_) {
30         LOGE("Update failed. component is null");
31         return;
32     }
33     const auto transitionComponent = AceType::DynamicCast<TransitionComponent>(component_);
34     if (!transitionComponent) {
35         LOGE("transition element update failed. transition component is null.");
36         return;
37     }
38     optionMap_[TransitionOptionType::TRANSITION_IN] = transitionComponent->GetTransitionInOption();
39     optionMap_[TransitionOptionType::TRANSITION_OUT] = transitionComponent->GetTransitionOutOption();
40 
41     if (transitionComponent->IsOptionChanged()) {
42         transitionOption_ = transitionComponent->GetTransitionOption();
43         transitionComponent->MarkOptionChanged(false);
44     }
45 
46     auto pipelineContext = context_.Upgrade();
47     if (pipelineContext) {
48         if (!controller_) {
49             controller_ = AceType::MakeRefPtr<Animator>(context_);
50             LOGD("set simulation controller to transition component when update.");
51         } else {
52             controller_->Stop();
53             controller_->ClearInterpolators();
54         }
55     }
56 }
57 
PerformBuild()58 void TransitionElement::PerformBuild()
59 {
60     bool build = true;
61     if (!hasBuildChild_) {
62         ComposedElement::PerformBuild();
63         hasBuildChild_ = true;
64         build = false;
65     }
66 
67     if (transitionOption_.IsValid()) {
68         ReplaceAnimation(transitionOption_);
69     } else {
70         transitionOption_ = TweenOption();
71         if (build) {
72             ComposedElement::PerformBuild();
73         }
74         return;
75     }
76 
77     if (controller_) {
78         SetController(controller_);
79         ApplyAnimation(transitionOption_);
80         controller_->Play();
81     }
82     transitionOption_ = TweenOption();
83     if (build) {
84         ComposedElement::PerformBuild();
85     }
86 }
87 
ReplaceAnimation(TweenOption & transitionOption)88 void TransitionElement::ReplaceAnimation(TweenOption& transitionOption)
89 {
90     auto& propertyAnimationMap = transitionOption.GetFloatPropertyAnimation();
91     auto& colorAniamtion = transitionOption.GetColorAnimation();
92     auto& opacityAniamtion = transitionOption.GetOpacityAnimation();
93     auto elementBox = GetChildBox();
94     if (!elementBox) {
95         LOGE("box element get failed.");
96         return;
97     }
98     auto renderBox = AceType::DynamicCast<RenderBoxBase>(elementBox->GetRenderNode());
99     if (!renderBox) {
100         LOGE("box render get failed.");
101         return;
102     }
103     for (auto&& [propertyAnimatableType, propertyAnimation] : propertyAnimationMap) {
104         if (propertyAnimatableType == PropertyAnimatableType::PROPERTY_WIDTH) {
105             renderBox->UpdateStyleFromRenderNode(propertyAnimatableType);
106             float width = renderBox->GetWidth();
107             auto keyframeWidthBegin = AceType::MakeRefPtr<Keyframe<float>>(0.0f, width);
108             AceType::DynamicCast<KeyframeAnimation<float>>
109                 (propertyAnimationMap[PropertyAnimatableType::PROPERTY_WIDTH])->ReplaceKeyframe(keyframeWidthBegin);
110         }
111         if (propertyAnimatableType == PropertyAnimatableType::PROPERTY_HEIGHT) {
112             renderBox->UpdateStyleFromRenderNode(propertyAnimatableType);
113             float height = renderBox->GetHeight();
114             auto keyframeHeightBegin = AceType::MakeRefPtr<Keyframe<float>>(0.0f, height);
115             AceType::DynamicCast<KeyframeAnimation<float>>
116                 (propertyAnimationMap[PropertyAnimatableType::PROPERTY_HEIGHT])->ReplaceKeyframe(keyframeHeightBegin);
117         }
118     }
119     if (colorAniamtion) {
120         renderBox->UpdateStyleFromRenderNode(PropertyAnimatableType::PROPERTY_BACK_DECORATION_COLOR);
121         Color color = renderBox->GetColor();
122         auto keyframeColorBegin = AceType::MakeRefPtr<Keyframe<Color>>(0.0f, color);
123         AceType::DynamicCast<KeyframeAnimation<Color>>(colorAniamtion)->ReplaceKeyframe(keyframeColorBegin);
124     }
125 
126     auto display = GetChildDisplay();
127     if (display && opacityAniamtion) {
128         auto renderDisplay = AceType::DynamicCast<RenderDisplay>(display->GetRenderNode());
129         if (renderDisplay) {
130             renderDisplay->UpdateOpacity();
131             auto opacity = renderDisplay->GetOpacity() * (1.0 / UINT8_MAX);
132             auto keyframeOpacityBegin = AceType::MakeRefPtr<Keyframe<float>>(0.0f, opacity);
133             AceType::DynamicCast<KeyframeAnimation<float>>(opacityAniamtion)->ReplaceKeyframe(keyframeOpacityBegin);
134         }
135     }
136 }
137 
GetChildDisplay() const138 RefPtr<DisplayElement> TransitionElement::GetChildDisplay() const
139 {
140     auto tween = GetChildTween();
141     if (!tween) {
142         LOGE("transition option get failed. no tween found.");
143         return nullptr;
144     }
145     return AceType::DynamicCast<DisplayElement>(tween->GetFirstChild());
146 }
147 
GetChildTransform() const148 RefPtr<TransformElement> TransitionElement::GetChildTransform() const
149 {
150     auto display = GetChildDisplay();
151     if (!display) {
152         LOGE("transition option get failed. no display found.");
153         return nullptr;
154     }
155     return AceType::DynamicCast<TransformElement>(display->GetFirstChild());
156 }
157 
GetChildBox() const158 RefPtr<BoxBaseElement> TransitionElement::GetChildBox() const
159 {
160     auto elementDisplay = GetChildDisplay();
161     if (!elementDisplay) {
162         LOGE("display element get failed.");
163         return nullptr;
164     }
165     auto elementTransform = AceType::DynamicCast<TransformElement>(elementDisplay->GetFirstChild());
166     if (!elementTransform) {
167         LOGE("transform element get failed.");
168         return nullptr;
169     }
170     return AceType::DynamicCast<BoxBaseElement>(elementTransform->GetFirstChild());
171 }
172 
ApplyAnimation(TweenOption & transitionOption)173 void TransitionElement::ApplyAnimation(TweenOption& transitionOption)
174 {
175     auto tween = GetChildTween();
176     if (!tween) {
177         LOGE("transition option get failed. no tween found.");
178         return;
179     }
180 
181     tween->SetOption(transitionOption);
182     if (!tween->ApplyKeyframes()) {
183         LOGW("Apply transition option failed. tween apply option fail.");
184     }
185     tween->ApplyOptions();
186 }
187 
SetController(const RefPtr<Animator> & controller)188 void TransitionElement::SetController(const RefPtr<Animator>& controller)
189 {
190     auto tween = GetChildTween();
191     if (!tween) {
192         LOGE("set controller failed. no tween found.");
193         return;
194     }
195     tween->SetController(controller);
196 }
197 
GetController() const198 RefPtr<Animator> TransitionElement::GetController() const
199 {
200     auto tween = GetChildTween();
201     if (!tween) {
202         LOGE("get controller failed. no tween found.");
203         return nullptr;
204     }
205     return tween->GetController();
206 }
207 
SetTouchable(bool enable)208 void TransitionElement::SetTouchable(bool enable)
209 {
210     auto tween = GetChildTween();
211     if (!tween) {
212         LOGE("set touchable failed. no tween found. enable: %{public}d", enable);
213         return;
214     }
215     tween->SetTouchable(enable);
216 }
217 
SwitchTransitionOption(TransitionOptionType type,bool needApplyOption)218 void TransitionElement::SwitchTransitionOption(TransitionOptionType type, bool needApplyOption)
219 {
220     auto tween = GetChildTween();
221     if (!tween) {
222         LOGE("Switch transition option failed. no tween found. direction: %{public}d", type);
223         return;
224     }
225     optionMap_[type].ClearListeners();
226     // If never set before, use empty option instead.
227     tween->SetOption(optionMap_[type]);
228     if (!tween->ApplyKeyframes()) {
229         LOGW("Apply transition option failed. tween apply option fail.");
230     }
231     if (needApplyOption) {
232         tween->ApplyOptions();
233     }
234 }
235 
BuildChild()236 RefPtr<Component> TransitionElement::BuildChild()
237 {
238     RefPtr<TransitionComponent> transition = AceType::DynamicCast<TransitionComponent>(component_);
239     if (transition) {
240         RefPtr<TweenComponent> tweenComponent =
241             AceType::MakeRefPtr<TweenComponent>(TweenComponent::AllocTweenComponentId(), transition->GetName());
242         tweenComponent->SetChild(ComposedElement::BuildChild());
243         tweenComponent->SetIsFirstFrameShow(transition->IsFirstFrameShow());
244         return tweenComponent;
245     } else {
246         LOGE("no transition component found. return empty child.");
247         return nullptr;
248     }
249 }
250 
SetWrapHidden(bool hidden)251 void TransitionElement::SetWrapHidden(bool hidden)
252 {
253     auto tween = GetChildTween();
254     if (!tween) {
255         LOGE("set wrap hidden failed. no tween found. hidden: %{public}d", hidden);
256         return;
257     }
258     tween->SetWrapHidden(hidden);
259 }
260 
AddPreFlush()261 void TransitionElement::AddPreFlush()
262 {
263     auto tween = GetChildTween();
264     if (!tween) {
265         LOGE("Add pre flush failed. no tween found.");
266         return;
267     }
268     tween->AddPreFlush();
269 }
270 
SkipPostFlush()271 void TransitionElement::SkipPostFlush()
272 {
273     auto tween = GetChildTween();
274     if (!tween) {
275         LOGE("Skip post flush failed. no tween found.");
276         return;
277     }
278     tween->SkipPostFlush();
279 }
280 
GetChildTween() const281 RefPtr<TweenElement> TransitionElement::GetChildTween() const
282 {
283     if (children_.empty()) {
284         LOGW("get child tween failed. no child yet.");
285         return nullptr;
286     }
287     const auto& child = children_.front();
288     if (!child) {
289         LOGW("get child tween failed. null child.");
290         return nullptr;
291     }
292     auto tween = AceType::DynamicCast<TweenElement>(child);
293     if (!tween) {
294         LOGW("get child tween failed. null tween.");
295         return nullptr;
296     }
297     return tween;
298 }
299 
SetTransition(const TweenOption & inOption,const TweenOption & outOption)300 void TransitionElement::SetTransition(const TweenOption& inOption, const TweenOption& outOption)
301 {
302     optionMap_[TransitionOptionType::TRANSITION_IN] = inOption;
303     optionMap_[TransitionOptionType::TRANSITION_OUT] = outOption;
304 }
305 
SetSharedTransition(const TweenOption & inOption,const TweenOption & outOption)306 void TransitionElement::SetSharedTransition(const TweenOption& inOption, const TweenOption& outOption)
307 {
308     optionMap_[TransitionOptionType::TRANSITION_SHARED_IN] = inOption;
309     optionMap_[TransitionOptionType::TRANSITION_SHARED_OUT] = outOption;
310 }
311 
GetContentElement() const312 RefPtr<Element> TransitionElement::GetContentElement() const
313 {
314     auto tween = GetChildTween();
315     if (!tween) {
316         LOGE("get content element failed. no tween found.");
317         return nullptr;
318     }
319     return tween->GetContentElement();
320 }
321 
ResetPageTransitionAnimation() const322 void TransitionElement::ResetPageTransitionAnimation() const
323 {
324     // reset opacity
325     auto display = GetChildDisplay();
326     if (display) {
327         auto renderDisplay = AceType::DynamicCast<RenderDisplay>(display->GetRenderNode());
328         if (renderDisplay) {
329             renderDisplay->UpdateOpacity(UINT8_MAX);
330         }
331     }
332     // reset transform
333     auto transform = GetChildTransform();
334     if (transform) {
335         auto renderTransform = AceType::DynamicCast<RenderTransform>(transform->GetRenderNode());
336         if (renderTransform) {
337             renderTransform->ResetTransform();
338         }
339     }
340 }
341 
342 } // namespace OHOS::Ace
343