1 /*
2 * Copyright (c) 2021-2023 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 <event_handler.h>
17 #include <iostream>
18 #include <surface.h>
19
20 #include "include/core/SkCanvas.h"
21 #include "include/core/SkColor.h"
22 #include "window.h"
23
24 #include "render/rs_border.h"
25 #include "transaction/rs_transaction.h"
26 #include "ui/rs_display_node.h"
27 #include "ui/rs_root_node.h"
28 #include "ui/rs_surface_extractor.h"
29 #include "ui/rs_surface_node.h"
30 #include "ui/rs_ui_director.h"
31
32 using namespace OHOS;
33 using namespace OHOS::Rosen;
34 using namespace std;
35
36 std::shared_ptr<RSNode> rootNode;
37 std::vector<std::shared_ptr<RSCanvasNode>> nodes;
38
Init(std::shared_ptr<RSUIDirector> rsUiDirector,int width,int height)39 void Init(std::shared_ptr<RSUIDirector> rsUiDirector, int width, int height)
40 {
41 std::cout << "rs app demo Init Rosen Backend!" << std::endl;
42
43 rootNode = RSRootNode::Create();
44 rootNode->SetBounds(0, 0, width, height);
45 rootNode->SetFrame(0, 0, width, height);
46 rootNode->SetBackgroundColor(SK_ColorYELLOW);
47
48 nodes.emplace_back(RSCanvasNode::Create());
49 nodes[0]->SetBounds(10, 10, 100, 100);
50 nodes[0]->SetFrame(10, 10, 100, 100);
51 nodes[0]->SetBackgroundColor(SK_ColorBLUE);
52
53 rootNode->AddChild(nodes[0], -1);
54
55 rootNode->AddChild(nodes[0], -1);
56 rsUiDirector->SetRSRootNode(rootNode->ReinterpretCastTo<RSRootNode>());
57 }
58
59 class NodeModifier : public RSNodeModifier {
60 public:
61 NodeModifier() = default;
62 virtual ~NodeModifier() = default;
63
Modify(RSNode & target) const64 void Modify(RSNode& target) const override
65 {
66 target.SetTranslate(translate_->Get());
67 }
68
SetTranslate(Vector2f translate)69 void SetTranslate(Vector2f translate)
70 {
71 if (translate_ == nullptr) {
72 translate_ = std::make_shared<RSAnimatableProperty<Vector2f>>(translate);
73 AttachProperty(translate_);
74 } else {
75 translate_->Set(translate);
76 }
77 }
78
GetTranslate() const79 Vector2f GetTranslate() const
80 {
81 return currentTranslateValue_;
82 }
83
SetTranslateCallBack()84 bool SetTranslateCallBack()
85 {
86 if (!translate_) {
87 return false;
88 }
89
90 // add callback for each frame
91 translate_->SetUpdateCallback([&](Vector2f vec) { currentTranslateValue_ = vec; });
92 return true;
93 }
94
95 Vector2f currentTranslateValue_ = Vector2f(0.0f, 0.0f);
96
97 private:
98 std::shared_ptr<RSAnimatableProperty<Vector2f>> translate_;
99 };
100
main()101 int main()
102 {
103 int cnt = 0;
104
105 // Init demo env
106 std::cout << "rs app demo start!" << std::endl;
107 sptr<WindowOption> option = new WindowOption();
108 option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
109 option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
110 option->SetWindowRect({ 0, 0, 720, 1280 });
111 auto window = Window::Create("app_demo", option);
112 window->Show();
113 auto rect = window->GetRect();
114 while (rect.width_ == 0 && rect.height_ == 0) {
115 std::cout << "rs app demo create window failed: " << rect.width_ << " " << rect.height_ << std::endl;
116 window->Hide();
117 window->Destroy();
118 window = Window::Create("app_demo", option);
119 window->Show();
120 rect = window->GetRect();
121 }
122 std::cout << "rs app demo create window " << rect.width_ << " " << rect.height_ << std::endl;
123 auto surfaceNode = window->GetSurfaceNode();
124
125 // Build rosen renderThread & create nodes
126 std::cout << "rs app demo stage " << cnt++ << std::endl;
127 auto rsUiDirector = RSUIDirector::Create();
128 rsUiDirector->Init();
129 auto runner = OHOS::AppExecFwk::EventRunner::Create(true);
130 auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
131 rsUiDirector->SetUITaskRunner(
132 [handler](const std::function<void()>& task, uint32_t delay) { handler->PostTask(task); });
133 runner->Run();
134 RSTransaction::FlushImplicitTransaction();
135 rsUiDirector->SetRSSurfaceNode(surfaceNode);
136 Init(rsUiDirector, rect.width_, rect.height_);
137
138 std::cout << "rs app demo stage " << cnt++ << std::endl;
139
140 // simulate sliding trajecity
141 int pointsNum = 30;
142 vector<Vector2f> handPoint(pointsNum);
143 for (int i = 0; i < handPoint.size(); i++) {
144 handPoint[i].data_[0] = 0.0f;
145 handPoint[i].data_[1] = 0.5f * i * i;
146 }
147
148 // simulate sliding stage
149 for (auto vec : handPoint) {
150 nodes[0]->SetTranslate(vec);
151 rsUiDirector->SendMessages();
152 usleep(30000);
153 }
154
155 // calculate sliding velocity
156 auto velocity = (handPoint[pointsNum - 1] - handPoint[pointsNum - 2]) * (1.0f / (30000.0f * 1e-6));
157
158 // calculate final points
159 Vector2f finalTrans = handPoint[pointsNum - 1] + velocity * 0.5;
160
161 std::cout << "rs app demo stage " << cnt++ << std::endl;
162
163 auto nodeModifier = std::make_shared<NodeModifier>();
164 nodes[0]->AddModifier(nodeModifier);
165
166 // init property
167 nodes[0]->SetTranslate(handPoint[pointsNum - 1]);
168
169 RSAnimationTimingProtocol protocol;
170 // duration is not effective when the curve is interpolatingSpring
171 protocol.SetDuration(3000);
172
173 auto timingCurve = RSAnimationTimingCurve::CreateInterpolatingSpring(1.0f, 225.0f, 30.0f, 2.0f);
174
175 // create property animation
176 RSNode::Animate(
177 protocol, timingCurve,
178 [&]() {
179 std::cout << "the end tranlate of sliding animation is " << finalTrans.data_[0] << ", "
180 << finalTrans.data_[1] << std::endl;
181 nodeModifier->SetTranslate(finalTrans);
182 },
183 []() { std::cout << "sliding animation finish callback" << std::endl; });
184
185 int64_t startNum = 80825861106;
186 int64_t interruptNum = 80825861106 * 15;
187
188 bool hasRunningAnimation = true;
189 bool stopSignal = true;
190
191 while (hasRunningAnimation) {
192 hasRunningAnimation = rsUiDirector->FlushAnimation(startNum);
193 rsUiDirector->FlushModifier();
194 rsUiDirector->SendMessages();
195 std::cout << "the current translate is " << nodeModifier->GetTranslate().data_[0] << ", "
196 << nodeModifier->GetTranslate().data_[1] << endl;
197
198 // simulate to stop animation by gesture
199 if ((startNum >= interruptNum) && stopSignal) {
200 std::cout << "stop sliding animation in current translate " << nodeModifier->GetTranslate().data_[0] << ", "
201 << nodeModifier->GetTranslate().data_[1] << endl;
202
203 // set duration to 0
204 protocol.SetDuration(0);
205
206 // create interrupt animation
207 RSNode::Animate(
208 protocol, RSAnimationTimingCurve::EASE_IN_OUT,
209 [&]() { nodeModifier->SetTranslate(nodeModifier->GetTranslate()); },
210 [&]() {
211 std::cout << "interrupt animation finish callback, the end translate is "
212 << nodeModifier->GetTranslate().data_[0] << ", " << nodeModifier->GetTranslate().data_[1]
213 << std::endl;
214 });
215
216 stopSignal = false;
217 }
218 startNum += 100000000;
219 usleep(100000);
220 }
221
222 // dump property via modifiers
223 std::cout << "rs app demo stage " << cnt++ << std::endl;
224 std::cout << nodes[0]->GetStagingProperties().Dump() << std::endl;
225 std::cout << "rs app demo end!" << std::endl;
226 sleep(3);
227
228 window->Hide();
229 window->Destroy();
230 return 0;
231 }