1 /*
2 * Copyright (c) 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 #include <iostream>
17 #include <vector>
18
19 #include "include/core/SkBitmap.h"
20 #include "include/core/SkCanvas.h"
21 #include "include/core/SkColor.h"
22 #include "include/core/SkImage.h"
23 #include "include/core/SkImageInfo.h"
24 #include "include/core/SkPaint.h"
25 #include "include/core/SkRect.h"
26 #include "wm/window.h"
27
28 #include "animation/rs_transition.h"
29 #include "animation/rs_transition_effect.h"
30 #include "modifier/rs_extended_modifier.h"
31 #include "modifier/rs_property_modifier.h"
32 #include "transaction/rs_transaction.h"
33 #include "ui/rs_display_node.h"
34 #include "ui/rs_root_node.h"
35 #include "ui/rs_surface_node.h"
36 #include "ui/rs_ui_director.h"
37
38 using namespace std;
39 using namespace OHOS;
40 using namespace OHOS::Rosen;
41
42 constexpr int64_t START_NUMBER = 181154000809;
43 constexpr int64_t INCREASE_NUMBER = 10000000;
44 constexpr int64_t SLEEP_TIME = 10000;
45 constexpr int NUMBER_HALF = 2;
46 constexpr int NUMBER_TWO = 2;
47 constexpr int CLIP_NUMBER = 10;
48 constexpr int COLOR_VALUE_MAX = 255;
49 constexpr int WINDOW_WIDTH = 720;
50 constexpr int WINDOW_HEIGHT = 1280;
51 constexpr int ANIMATION_DURATION = 2000;
52 constexpr int ANIMATION_DELAY_TIME = 500;
53 std::shared_ptr<RSNode> rootNode;
54 std::vector<std::shared_ptr<RSCanvasNode>> nodes;
55 std::shared_ptr<RSUIDirector> rsUiDirector;
56
57 class TransitionModifier1 : public RSTransitionModifier {
58 public:
Draw(RSDrawingContext & context) const59 void Draw(RSDrawingContext& context) const override
60 {
61 if (!radius_ || !backgroundColor_ || !alpha_) {
62 SkRect rect = SkRect::MakeXYWH(0, 0, 0, 0);
63 SkPaint p;
64 context.canvas->drawRect(rect, p);
65 return;
66 }
67 context.canvas->save();
68 SkPath path;
69 path.addCircle(context.width / NUMBER_HALF, context.height / NUMBER_HALF,
70 radius_->Get() * sqrt(pow(context.width / NUMBER_HALF, NUMBER_TWO) +
71 pow(context.height / NUMBER_HALF, NUMBER_TWO)));
72 context.canvas->clipPath(path);
73 SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
74 SkPaint p;
75 p.setColor(backgroundColor_->Get().AsArgbInt());
76 p.setAlphaf(alpha_->Get());
77 context.canvas->drawRect(rect, p);
78 context.canvas->restore();
79 }
80
SetRadius(float radius)81 void SetRadius(float radius)
82 {
83 if (radius_ == nullptr) {
84 radius_ = std::make_shared<RSAnimatableProperty<float>>(radius);
85 AttachProperty(radius_);
86 } else {
87 radius_->Set(radius);
88 }
89 }
90
SetBackgroundColor(Color backgroundColor)91 void SetBackgroundColor(Color backgroundColor)
92 {
93 if (backgroundColor_ == nullptr) {
94 backgroundColor_ = std::make_shared<RSAnimatableProperty<Color>>(backgroundColor);
95 AttachProperty(backgroundColor_);
96 } else {
97 backgroundColor_->Set(backgroundColor);
98 }
99 }
100
SetAlpha(float alpha)101 void SetAlpha(float alpha)
102 {
103 if (alpha_ == nullptr) {
104 alpha_ = std::make_shared<RSAnimatableProperty<float>>(alpha);
105 AttachProperty(alpha_);
106 } else {
107 alpha_->Set(alpha);
108 }
109 }
110
Active()111 void Active() override
112 {
113 // should set property of before transition-in
114 SetRadius(0);
115 SetBackgroundColor(Color(COLOR_VALUE_MAX, 0, 0));
116 SetAlpha(0);
117 }
118
Identity()119 void Identity() override
120 {
121 // should set property of after transition-in
122 SetRadius(1);
123 SetBackgroundColor(Color(0, 0, COLOR_VALUE_MAX));
124 SetAlpha(1);
125 }
126
127 private:
128 std::shared_ptr<RSAnimatableProperty<float>> radius_;
129 std::shared_ptr<RSAnimatableProperty<Color>> backgroundColor_;
130 std::shared_ptr<RSAnimatableProperty<float>> alpha_;
131 };
132
133 class TransitionModifier2 : public RSTransitionModifier {
134 public:
Draw(RSDrawingContext & context) const135 void Draw(RSDrawingContext& context) const override
136 {
137 float radius = 0;
138 if (radius_) {
139 radius = radius_->Get();
140 }
141 context.canvas->save();
142 SkPath path;
143 path.addCircle(0, 0, radius * sqrt(pow(context.width, NUMBER_TWO) + pow(context.height, NUMBER_TWO)));
144 context.canvas->clipPath(path);
145 SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
146 SkPaint p;
147 p.setColor(backgroundColor_.AsArgbInt());
148 context.canvas->drawRect(rect, p);
149 context.canvas->restore();
150 }
151
SetRadius(float radius)152 void SetRadius(float radius)
153 {
154 if (radius_ == nullptr) {
155 radius_ = std::make_shared<RSAnimatableProperty<float>>(radius);
156 AttachProperty(radius_);
157 } else {
158 radius_->Set(radius);
159 }
160 }
161
SetBackgroundColor(Color backgroundColor)162 void SetBackgroundColor(Color backgroundColor)
163 {
164 backgroundColor_ = backgroundColor;
165 }
166
Active()167 void Active() override
168 {
169 // should set property of before transition-in
170 SetRadius(0);
171 }
172
Identity()173 void Identity() override
174 {
175 // should set property of after transition-in
176 SetRadius(1);
177 }
178
179 private:
180 std::shared_ptr<RSAnimatableProperty<float>> radius_;
181 Color backgroundColor_ = Color(COLOR_VALUE_MAX, 0, 0);
182 };
183
184 class TransitionModifier3 : public RSTransitionModifier {
185 public:
Draw(RSDrawingContext & context) const186 void Draw(RSDrawingContext& context) const override
187 {
188 float clipWidth = 0;
189 if (clipWidth_) {
190 clipWidth = clipWidth_->Get();
191 }
192 for (int i = 0; i < clipPieces_; i++) {
193 context.canvas->save();
194 SkRect clipRect = SkRect::MakeXYWH(context.width / clipPieces_ * i, 0,
195 clipWidth * context.width / clipPieces_, context.height);
196 context.canvas->clipRect(clipRect);
197 SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
198 SkPaint p;
199 p.setColor(backgroundColor_.AsArgbInt());
200 context.canvas->drawRect(rect, p);
201 context.canvas->restore();
202 }
203 }
204
SetClipWidth(float clipWidth)205 void SetClipWidth(float clipWidth)
206 {
207 if (clipWidth_ == nullptr) {
208 clipWidth_ = std::make_shared<RSAnimatableProperty<float>>(clipWidth);
209 AttachProperty(clipWidth_);
210 } else {
211 clipWidth_->Set(clipWidth);
212 }
213 }
214
SetBackgroundColor(Color backgroundColor)215 void SetBackgroundColor(Color backgroundColor)
216 {
217 backgroundColor_ = backgroundColor;
218 }
219
Active()220 void Active() override
221 {
222 // should set property of before transition-in
223 SetClipWidth(0);
224 }
225
Identity()226 void Identity() override
227 {
228 // should set property of after transition-in
229 SetClipWidth(1);
230 }
231
232 private:
233 std::shared_ptr<RSAnimatableProperty<float>> clipWidth_;
234 Color backgroundColor_ = Color(COLOR_VALUE_MAX, 0, 0);
235 int clipPieces_ = CLIP_NUMBER;
236 };
237
238 class TransitionModifier4 : public RSTransitionModifier {
239 public:
Draw(RSDrawingContext & context) const240 void Draw(RSDrawingContext& context) const override
241 {
242 float clipWidth = 0;
243 if (clipWidth_) {
244 clipWidth = clipWidth_->Get();
245 }
246 for (int i = 0; i < clipPieces_; i++) {
247 context.canvas->save();
248 SkRect clipRect = SkRect::MakeXYWH(
249 context.width / clipPieces_ * (i + 1) - clipWidth * context.width / clipPieces_, 0,
250 clipWidth * context.width / clipPieces_, context.height);
251 context.canvas->clipRect(clipRect);
252 SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
253 SkPaint p;
254 p.setColor(backgroundColor_.AsArgbInt());
255 context.canvas->drawRect(rect, p);
256 context.canvas->restore();
257 }
258 }
259
SetClipWidth(float clipWidth)260 void SetClipWidth(float clipWidth)
261 {
262 if (clipWidth_ == nullptr) {
263 clipWidth_ = std::make_shared<RSAnimatableProperty<float>>(clipWidth);
264 AttachProperty(clipWidth_);
265 } else {
266 clipWidth_->Set(clipWidth);
267 }
268 }
269
SetBackgroundColor(Color backgroundColor)270 void SetBackgroundColor(Color backgroundColor)
271 {
272 backgroundColor_ = backgroundColor;
273 }
274
Active()275 void Active() override
276 {
277 // should set property of before transition-in
278 SetClipWidth(0);
279 }
280
Identity()281 void Identity() override
282 {
283 // should set property of after transition-in
284 SetClipWidth(1);
285 }
286
287 private:
288 std::shared_ptr<RSAnimatableProperty<float>> clipWidth_;
289 Color backgroundColor_ = Color(COLOR_VALUE_MAX, 0, 0);
290 int clipPieces_ = CLIP_NUMBER;
291 };
292
293 class TransitionModifier5 : public RSTransitionModifier {
294 public:
Draw(RSDrawingContext & context) const295 void Draw(RSDrawingContext& context) const override
296 {
297 float clipHeight = 0;
298 if (clipHeight_) {
299 clipHeight = clipHeight_->Get();
300 }
301 for (int i = 0; i < clipPieces_; i++) {
302 context.canvas->save();
303 SkRect clipRect = SkRect::MakeXYWH(0, context.height / clipPieces_ * i,
304 context.width, clipHeight * context.height / clipPieces_);
305 context.canvas->clipRect(clipRect);
306 SkRect rect = SkRect::MakeXYWH(0, 0, context.width, context.height);
307 SkPaint p;
308 p.setColor(backgroundColor_.AsArgbInt());
309 context.canvas->drawRect(rect, p);
310 context.canvas->restore();
311 }
312 }
313
SetClipHeight(float clipHeight)314 void SetClipHeight(float clipHeight)
315 {
316 if (clipHeight_ == nullptr) {
317 clipHeight_ = std::make_shared<RSAnimatableProperty<float>>(clipHeight);
318 AttachProperty(clipHeight_);
319 } else {
320 clipHeight_->Set(clipHeight);
321 }
322 }
323
SetBackgroundColor(Color backgroundColor)324 void SetBackgroundColor(Color backgroundColor)
325 {
326 backgroundColor_ = backgroundColor;
327 }
328
Active()329 void Active() override
330 {
331 // should set property of before transition-in
332 SetClipHeight(0);
333 }
334
Identity()335 void Identity() override
336 {
337 // should set property of after transition-in
338 SetClipHeight(1);
339 }
340
341 private:
342 std::shared_ptr<RSAnimatableProperty<float>> clipHeight_;
343 Color backgroundColor_ = Color(COLOR_VALUE_MAX, 0, 0);
344 int clipPieces_ = CLIP_NUMBER;
345 };
346
Transition1()347 void Transition1()
348 {
349 nodes.emplace_back(RSCanvasNode::Create());
350 nodes[0]->SetBounds({ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT});
351 // define custom modifier for transition
352 auto transitionModifier1 = std::make_shared<TransitionModifier1>();
353 auto transitionModifier2 = std::make_shared<TransitionModifier2>();
354 transitionModifier2->SetBackgroundColor(Color(0, 0, COLOR_VALUE_MAX));
355 // add the modifier to node
356 nodes[0]->AddModifier(transitionModifier1);
357 nodes[0]->AddModifier(transitionModifier2);
358 // create transition effect
359 auto transitionInEffect = RSTransitionEffect::Create()->Custom(transitionModifier1);
360 auto transitionOutEffect = RSTransitionEffect::Create()->Custom(transitionModifier2);
361 nodes[0]->SetTransitionEffect(RSTransitionEffect::Asymmetric(transitionInEffect, transitionOutEffect));
362 // define animation protocol
363 RSAnimationTimingProtocol protocol;
364 // set duration as 2000 millisecond
365 protocol.SetDuration(ANIMATION_DURATION);
366 // create transition-in animation
367 RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
368 rootNode->AddChild(nodes[0]);
369 }, []() {
370 std::cout << "nodes0 appears" << std::endl;
371 });
372 uint64_t timeStamp = START_NUMBER;
373 bool hasRunningAnimation = true;
374 while (hasRunningAnimation) {
375 hasRunningAnimation = rsUiDirector->FlushAnimation(timeStamp);
376 rsUiDirector->FlushModifier();
377 rsUiDirector->SendMessages();
378 timeStamp += INCREASE_NUMBER;
379 usleep(SLEEP_TIME);
380 }
381 nodes[0]->RemoveModifier(transitionModifier1);
382 }
383
Transition2()384 void Transition2()
385 {
386 nodes.emplace_back(RSCanvasNode::Create());
387 nodes[1]->SetBounds({ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT});
388 // define custom modifier for transition
389 auto transitionModifier2 = std::make_shared<TransitionModifier2>();
390 auto transitionModifier3 = std::make_shared<TransitionModifier3>();
391 transitionModifier2->SetBackgroundColor(Color(0, COLOR_VALUE_MAX, 0));
392 transitionModifier3->SetBackgroundColor(Color(0, COLOR_VALUE_MAX, 0));
393 // add the modifier to node
394 nodes[1]->AddModifier(transitionModifier2);
395 nodes[1]->AddModifier(transitionModifier3);
396 // create transition effect
397 auto transitionInEffect = RSTransitionEffect::Create()->Custom(transitionModifier2);
398 auto transitionOutEffect = RSTransitionEffect::Create()->Custom(transitionModifier3);
399 nodes[1]->SetTransitionEffect(RSTransitionEffect::Asymmetric(transitionInEffect, transitionOutEffect));
400 // define animation protocol
401 RSAnimationTimingProtocol protocol;
402 // set duration as 2000 millisecond
403 protocol.SetDuration(ANIMATION_DURATION);
404 // create transition-out animation
405 RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
406 rootNode->RemoveChild(nodes[0]);
407 }, []() {
408 std::cout << "nodes0 disappears" << std::endl;
409 });
410 protocol.SetStartDelay(ANIMATION_DELAY_TIME);
411 // create transition-in animation
412 RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
413 rootNode->AddChild(nodes[1]);
414 }, []() {
415 std::cout << "nodes1 appears" << std::endl;
416 });
417 uint64_t timeStamp = START_NUMBER;
418 bool hasRunningAnimation = true;
419 while (hasRunningAnimation) {
420 hasRunningAnimation = rsUiDirector->FlushAnimation(timeStamp);
421 rsUiDirector->FlushModifier();
422 rsUiDirector->SendMessages();
423 timeStamp += INCREASE_NUMBER;
424 usleep(SLEEP_TIME);
425 }
426 nodes[1]->RemoveModifier(transitionModifier2);
427 }
428
Transition3()429 void Transition3()
430 {
431 nodes.emplace_back(RSCanvasNode::Create());
432 nodes[NUMBER_TWO]->SetBounds({ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT});
433 // define custom modifier for transition
434 auto transitionModifier4 = std::make_shared<TransitionModifier4>();
435 auto transitionModifier5 = std::make_shared<TransitionModifier5>();
436 transitionModifier4->SetBackgroundColor(Color(0, COLOR_VALUE_MAX, COLOR_VALUE_MAX));
437 transitionModifier5->SetBackgroundColor(Color(0, COLOR_VALUE_MAX, COLOR_VALUE_MAX));
438 // add the modifier to node
439 nodes[NUMBER_TWO]->AddModifier(transitionModifier4);
440 nodes[NUMBER_TWO]->AddModifier(transitionModifier5);
441 // create transition effect
442 auto transitionInEffect = RSTransitionEffect::Create()->Custom(transitionModifier4);
443 auto transitionOutEffect = RSTransitionEffect::Create()->Custom(transitionModifier5);
444 nodes[NUMBER_TWO]->SetTransitionEffect(RSTransitionEffect::Asymmetric(transitionInEffect, transitionOutEffect));
445 // define animation protocol
446 RSAnimationTimingProtocol protocol;
447 // set duration as 2000 millisecond
448 protocol.SetDuration(ANIMATION_DURATION);
449 // create transition-out animation
450 RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
451 rootNode->RemoveChild(nodes[1]);
452 }, []() {
453 std::cout << "nodes1 disappears" << std::endl;
454 });
455 // create transition-in animation
456 RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
457 rootNode->AddChild(nodes[NUMBER_TWO]);
458 }, []() {
459 std::cout << "nodes2 appears" << std::endl;
460 });
461 uint64_t timeStamp = START_NUMBER;
462 bool hasRunningAnimation = true;
463 while (hasRunningAnimation) {
464 hasRunningAnimation = rsUiDirector->FlushAnimation(timeStamp);
465 rsUiDirector->FlushModifier();
466 rsUiDirector->SendMessages();
467 timeStamp += INCREASE_NUMBER;
468 usleep(SLEEP_TIME);
469 }
470 nodes[NUMBER_TWO]->RemoveModifier(transitionModifier4);
471 }
472
Transition4()473 void Transition4()
474 {
475 // define animation protocol
476 RSAnimationTimingProtocol protocol;
477 // set duration as 2000 millisecond
478 protocol.SetDuration(ANIMATION_DURATION);
479 // create transition-out animation
480 RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_IN_OUT, [&]() {
481 rootNode->RemoveChild(nodes[NUMBER_TWO]);
482 }, []() {
483 std::cout << "nodes2 disappears" << std::endl;
484 });
485 uint64_t timeStamp = START_NUMBER;
486 bool hasRunningAnimation = true;
487 while (hasRunningAnimation) {
488 hasRunningAnimation = rsUiDirector->FlushAnimation(timeStamp);
489 rsUiDirector->FlushModifier();
490 rsUiDirector->SendMessages();
491 timeStamp += INCREASE_NUMBER;
492 usleep(SLEEP_TIME);
493 }
494 }
495
main()496 int main()
497 {
498 std::cout << "transition demo start!" << std::endl;
499
500 // create window
501 sptr<WindowOption> option = new WindowOption();
502 option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
503 option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
504 option->SetWindowRect({ 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT });
505 auto window = Window::Create("transition", option);
506 window->Show();
507 auto rect = window->GetRect();
508 while (rect.width_ == 0 && rect.height_ == 0) {
509 std::cout << "create window failed: " << rect.width_ << " " << rect.height_ << std::endl;
510 window->Hide();
511 window->Destroy();
512 window = Window::Create("transition_demo", option);
513 window->Show();
514 rect = window->GetRect();
515 }
516 std::cout << "create window " << rect.width_ << " " << rect.height_ << std::endl;
517 auto surfaceNode = window->GetSurfaceNode();
518
519 std::cout << "init rosen backend!" << std::endl;
520
521 // init rosen backend
522 rsUiDirector = RSUIDirector::Create();
523 rsUiDirector->Init();
524 RSTransaction::FlushImplicitTransaction();
525 rsUiDirector->SetRSSurfaceNode(surfaceNode);
526
527 rootNode = RSRootNode::Create();
528 rootNode->SetBounds(0, 0, rect.width_, rect.height_);
529 rootNode->SetFrame(0, 0, rect.width_, rect.height_);
530 rootNode->SetBackgroundColor(SK_ColorWHITE);
531 rsUiDirector->SetRoot(rootNode->GetId());
532
533 std::cout << "nodes[0] appearing." << std::endl;
534 Transition1();
535 sleep(NUMBER_TWO);
536 std::cout << "nodes[0] disappearing and nodes[1] appearing." << std::endl;
537 Transition2();
538 sleep(NUMBER_TWO);
539 std::cout << "nodes[1] disappearing and nodes[2] appearing." << std::endl;
540 Transition3();
541 sleep(NUMBER_TWO);
542 std::cout << "nodes[2] disappearing." << std::endl;
543 Transition4();
544 sleep(NUMBER_TWO);
545
546 std::cout << "transition demo end!" << std::endl;
547 window->Hide();
548 window->Destroy();
549 return 0;
550 }
551