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