2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali/dali.h>
20 #include "generated/animated-shapes-frag.h"
21 #include "generated/animated-shapes-vert.h"
22 #include "shared/view.h"
27 using namespace Dali::Toolkit;
31 const char* APPLICATION_TITLE("Animated Shapes");
33 Shader CreateShader(unsigned int pointCount)
35 std::ostringstream vertexShader;
36 vertexShader << "#define MAX_POINT_COUNT " << pointCount << "\n"
37 << SHADER_ANIMATED_SHAPES_VERT;
39 std::ostringstream fragmentShader;
40 fragmentShader << "#extension GL_OES_standard_derivatives : enable "
42 << SHADER_ANIMATED_SHAPES_FRAG;
44 Shader shader = Shader::New(vertexShader.str(), fragmentShader.str());
45 for(unsigned int i(0); i < pointCount; ++i)
47 std::ostringstream propertyName;
48 propertyName << "uPosition[" << i << "]";
49 shader.RegisterProperty(propertyName.str(), Vector3(0.0f, 0.0f, 0.0f));
57 // This example shows resolution independent rendering and animation of curves using the gpu.
59 class AnimatedShapesExample : public ConnectionTracker
62 AnimatedShapesExample(Application& application)
63 : mApplication(application)
65 // Connect to the Application's Init signal
66 mApplication.InitSignal().Connect(this, &AnimatedShapesExample::Create);
69 ~AnimatedShapesExample() = default;
71 // The Init signal is received once (only) during the Application lifetime
72 void Create(Application& application)
74 Window window = application.GetWindow();
75 const Vector2 windowSize = window.GetSize();
77 // Creates the background gradient
78 Toolkit::Control background = Dali::Toolkit::Control::New();
79 background[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER;
80 background[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER;
81 background.SetResizePolicy(Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS);
83 Dali::Property::Map map;
84 map.Insert(Toolkit::Visual::Property::TYPE, Visual::GRADIENT);
85 Property::Array stopOffsets;
86 stopOffsets.PushBack(0.0f);
87 stopOffsets.PushBack(1.0f);
88 map.Insert(GradientVisual::Property::STOP_OFFSET, stopOffsets);
89 Property::Array stopColors;
90 stopColors.PushBack(Vector4(0.0f, 0.0f, 1.0f, 1.0f));
91 stopColors.PushBack(Vector4(1.0f, 1.0f, 1.0f, 1.0f));
92 map.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
93 Vector2 halfWindowSize = windowSize * 0.5f;
94 map.Insert(GradientVisual::Property::START_POSITION, Vector2(0.0f, -halfWindowSize.y));
95 map.Insert(GradientVisual::Property::END_POSITION, Vector2(0.0f, halfWindowSize.y));
96 map.Insert(GradientVisual::Property::UNITS, GradientVisual::Units::USER_SPACE);
97 background[Dali::Toolkit::Control::Property::BACKGROUND] = map;
98 window.Add(background);
100 // Create a TextLabel for the application title.
101 Toolkit::TextLabel label = Toolkit::TextLabel::New(APPLICATION_TITLE);
102 label[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_CENTER;
103 label[Actor::Property::PARENT_ORIGIN] = Vector3(0.5f, 0.0f, 0.5f);
104 label[Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT] = "CENTER";
105 label[Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT] = "CENTER";
106 label[Toolkit::TextLabel::Property::TEXT_COLOR] = Color::WHITE;
109 CreateTriangleMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.15f, 0.0f), 100.0f);
110 CreateCircleMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.5f, 0.0f), 55.0f);
111 CreateQuadMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.85f, 0.0f), 60.0f);
113 window.KeyEventSignal().Connect(this, &AnimatedShapesExample::OnKeyEvent);
116 void CreateTriangleMorph(Vector3 center, float side)
118 float h = (side * 0.5f) / 0.866f;
120 Vector3 v0 = Vector3(-h, h, 0.0f);
121 Vector3 v1 = Vector3(0.0f, -side * 0.366f, 0.0f);
122 Vector3 v2 = Vector3(h, h, 0.0f);
124 Vector3 v3 = v0 + ((v1 - v0) * 0.5f);
125 Vector3 v4 = v1 + ((v2 - v1) * 0.5f);
126 Vector3 v5 = v2 + ((v0 - v2) * 0.5f);
128 Shader shader = CreateShader(12);
129 shader["uPosition[0]"] = v0;
130 shader["uPosition[1]"] = v3;
131 shader["uPosition[2]"] = v1;
133 shader["uPosition[3]"] = v1;
134 shader["uPosition[4]"] = v4;
135 shader["uPosition[5]"] = v2;
137 shader["uPosition[6]"] = v2;
138 shader["uPosition[7]"] = v5;
139 shader["uPosition[8]"] = v0;
141 shader["uPosition[9]"] = v0;
142 shader["uPosition[10]"] = v1;
143 shader["uPosition[11]"] = v2;
146 static const Vector3 vertexData[] = {Dali::Vector3(0.0f, 0.0f, 0.0f),
147 Dali::Vector3(0.5f, 0.0f, 1.0f),
148 Dali::Vector3(1.0f, 1.0f, 2.0f),
150 Dali::Vector3(0.0f, 0.0f, 3.0f),
151 Dali::Vector3(0.5f, 0.0f, 4.0f),
152 Dali::Vector3(1.0f, 1.0f, 5.0f),
154 Dali::Vector3(0.0f, 0.0f, 6.0f),
155 Dali::Vector3(0.5f, 0.0f, 7.0f),
156 Dali::Vector3(1.0f, 1.0f, 8.0f),
158 Dali::Vector3(0.0f, 1.0f, 9.0f),
159 Dali::Vector3(0.0f, 1.0f, 10.0f),
160 Dali::Vector3(0.0f, 1.0f, 11.0f)};
162 unsigned short indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10};
164 //Create a vertex buffer for vertex positions and texture coordinates
165 Dali::Property::Map vertexFormat;
166 vertexFormat["aCoefficient"] = Dali::Property::VECTOR3;
167 Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
168 vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
170 //Create the geometry
171 Dali::Geometry geometry = Dali::Geometry::New();
172 geometry.AddVertexBuffer(vertexBuffer);
173 geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
175 Renderer renderer = Renderer::New(geometry, shader);
176 renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
178 Actor actor = Actor::New();
179 actor[Actor::Property::SIZE] = Vector2(400.0f, 400.0f);
180 actor[Actor::Property::POSITION] = center;
181 actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
182 actor[Actor::Property::COLOR] = Color::YELLOW;
183 actor.AddRenderer(renderer);
185 Window window = mApplication.GetWindow();
189 Animation animation = Animation::New(5.0f);
190 KeyFrames k0 = KeyFrames::New();
192 k0.Add(0.5f, v3 + Vector3(-150.0f, -150.0f, 0.0f));
194 animation.AnimateBetween(Property(shader, "uPosition[1]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
196 k0 = KeyFrames::New();
198 k0.Add(0.5f, v4 + Vector3(150.0f, -150.0f, 0.0f));
200 animation.AnimateBetween(Property(shader, "uPosition[4]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
202 k0 = KeyFrames::New();
204 k0.Add(0.5f, v5 + Vector3(0.0, 150.0f, 0.0f));
206 animation.AnimateBetween(Property(shader, "uPosition[7]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
207 animation.SetLooping(true);
211 void CreateCircleMorph(Vector3 center, float radius)
213 Shader shader = CreateShader(16);
214 shader["uPosition[0]"] = Vector3(-radius, -radius, 0.0f);
215 shader["uPosition[1]"] = Vector3(0.0f, -radius, 0.0f);
216 shader["uPosition[2]"] = Vector3(radius, -radius, 0.0f);
218 shader["uPosition[3]"] = Vector3(radius, -radius, 0.0f);
219 shader["uPosition[4]"] = Vector3(radius, 0.0f, 0.0f);
220 shader["uPosition[5]"] = Vector3(radius, radius, 0.0f);
222 shader["uPosition[6]"] = Vector3(radius, radius, 0.0f);
223 shader["uPosition[7]"] = Vector3(0.0f, radius, 0.0f);
224 shader["uPosition[8]"] = Vector3(-radius, radius, 0.0f);
226 shader["uPosition[9]"] = Vector3(-radius, radius, 0.0f);
227 shader["uPosition[10]"] = Vector3(-radius, 0.0f, 0.0f);
228 shader["uPosition[11]"] = Vector3(-radius, -radius, 0.0f);
230 shader["uPosition[12]"] = Vector3(-radius, -radius, 0.0f);
231 shader["uPosition[13]"] = Vector3(radius, -radius, 0.0f);
232 shader["uPosition[14]"] = Vector3(radius, radius, 0.0f);
233 shader["uPosition[15]"] = Vector3(-radius, radius, 0.0f);
235 //shader["uLineWidth"), 2.0] ;
237 static const Vector3 vertexData[] = {Vector3(0.0f, 0.0f, 0.0f),
238 Vector3(0.5f, 0.0f, 1.0f),
239 Vector3(1.0f, 1.0f, 2.0f),
240 Vector3(0.0f, 0.0f, 3.0f),
241 Vector3(0.5f, 0.0f, 4.0f),
242 Vector3(1.0f, 1.0f, 5.0f),
243 Vector3(0.0f, 0.0f, 6.0f),
244 Vector3(0.5f, 0.0f, 7.0f),
245 Vector3(1.0f, 1.0f, 8.0f),
246 Vector3(0.0f, 0.0f, 9.0f),
247 Vector3(0.5f, 0.0f, 10.0f),
248 Vector3(1.0f, 1.0f, 11.0f),
249 Vector3(0.0f, 1.0f, 12.0f),
250 Vector3(0.0f, 1.0f, 13.0f),
251 Vector3(0.0f, 1.0f, 14.0f),
252 Vector3(0.0f, 1.0f, 15.0f)};
254 short unsigned int indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 13, 14, 12, 14, 15};
256 //Create a vertex buffer for vertex positions and texture coordinates
257 Dali::Property::Map vertexFormat;
258 vertexFormat["aCoefficient"] = Dali::Property::VECTOR3;
259 Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
260 vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
262 //Create the geometry
263 Dali::Geometry geometry = Dali::Geometry::New();
264 geometry.AddVertexBuffer(vertexBuffer);
265 geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
267 Renderer renderer = Renderer::New(geometry, shader);
268 renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
270 Actor actor = Actor::New();
271 actor[Actor::Property::SIZE] = Vector2(400.0f, 400.0f);
272 actor[Actor::Property::POSITION] = center;
273 actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
274 actor.AddRenderer(renderer);
276 Window window = mApplication.GetWindow();
280 Animation animation = Animation::New(5.0f);
281 KeyFrames k0 = KeyFrames::New();
282 k0.Add(0.0f, Vector3(0.0f, -radius * 1.85, 0.0f));
283 k0.Add(0.5f, Vector3(-radius * 1.85, -radius * 3.0f, 0.0f));
284 k0.Add(1.0f, Vector3(0.0f, -radius * 1.85, 0.0f));
285 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[1]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
287 k0 = KeyFrames::New();
288 k0.Add(0.0f, Vector3(radius * 1.85, 0.0f, 0.0f));
289 k0.Add(0.5f, Vector3(radius * 3.0f, -radius * 1.85, 0.0f));
290 k0.Add(1.0f, Vector3(radius * 1.85, 0.0f, 0.0f));
291 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[4]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
293 k0 = KeyFrames::New();
294 k0.Add(0.0f, Vector3(0.0f, radius * 1.85, 0.0f));
295 k0.Add(0.5f, Vector3(radius * 1.85, radius * 3.0f, 0.0f));
296 k0.Add(1.0f, Vector3(0.0f, radius * 1.85, 0.0f));
297 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[7]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
299 k0 = KeyFrames::New();
300 k0.Add(0.0f, Vector3(-radius * 1.85, 0.0f, 0.0f));
301 k0.Add(0.5f, Vector3(-radius * 3.0f, radius * 1.85, 0.0f));
302 k0.Add(1.0f, Vector3(-radius * 1.85, 0.0f, 0.0f));
303 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[10]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
305 animation.AnimateBy(Property(actor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(-90.0f)), Vector3::ZAXIS));
306 animation.SetLooping(true);
310 void CreateQuadMorph(Vector3 center, float radius)
312 Shader shader = CreateShader(16);
313 shader["uPosition[0]"] = Vector3(-radius, -radius, 0.0f);
314 shader["uPosition[1]"] = Vector3(0.0f, -radius, 0.0f);
315 shader["uPosition[2]"] = Vector3(radius, -radius, 0.0f);
317 shader["uPosition[3]"] = Vector3(radius, -radius, 0.0f);
318 shader["uPosition[4]"] = Vector3(radius, 0.0f, 0.0f);
319 shader["uPosition[5]"] = Vector3(radius, radius, 0.0f);
321 shader["uPosition[6]"] = Vector3(radius, radius, 0.0f);
322 shader["uPosition[7]"] = Vector3(0.0f, radius, 0.0f);
323 shader["uPosition[8]"] = Vector3(-radius, radius, 0.0f);
325 shader["uPosition[9]"] = Vector3(-radius, radius, 0.0f);
326 shader["uPosition[10]"] = Vector3(-radius, 0.0f, 0.0f);
327 shader["uPosition[11]"] = Vector3(-radius, -radius, 0.0f);
329 shader["uPosition[12]"] = Vector3(-radius, -radius, 0.0f);
330 shader["uPosition[13]"] = Vector3(radius, -radius, 0.0f);
331 shader["uPosition[14]"] = Vector3(radius, radius, 0.0f);
332 shader["uPosition[15]"] = Vector3(-radius, radius, 0.0f);
334 static const Vector3 vertexData[] = {Dali::Vector3(0.0f, 0.0f, 0.0f),
335 Dali::Vector3(0.5f, 0.0f, 1.0f),
336 Dali::Vector3(1.0f, 1.0f, 2.0f),
338 Dali::Vector3(0.0f, 0.0f, 3.0f),
339 Dali::Vector3(0.5f, 0.0f, 4.0f),
340 Dali::Vector3(1.0f, 1.0f, 5.0f),
342 Dali::Vector3(0.0f, 0.0f, 6.0f),
343 Dali::Vector3(0.5f, 0.0f, 7.0f),
344 Dali::Vector3(1.0f, 1.0f, 8.0f),
346 Dali::Vector3(0.0f, 0.0f, 9.0f),
347 Dali::Vector3(0.5f, 0.0f, 10.0f),
348 Dali::Vector3(1.0f, 1.0f, 11.0f),
350 Dali::Vector3(0.0f, 1.0f, 12.0f),
351 Dali::Vector3(0.0f, 1.0f, 13.0f),
352 Dali::Vector3(0.0f, 1.0f, 14.0f),
353 Dali::Vector3(0.0f, 1.0f, 15.0f)};
355 short unsigned int indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 15, 14, 12, 14, 13};
357 //Create a vertex buffer for vertex positions and texture coordinates
358 Dali::Property::Map vertexFormat;
359 vertexFormat["aCoefficient"] = Dali::Property::VECTOR3;
360 Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
361 vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
363 //Create the geometry
364 Dali::Geometry geometry = Dali::Geometry::New();
365 geometry.AddVertexBuffer(vertexBuffer);
366 geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
368 Renderer renderer = Renderer::New(geometry, shader);
369 renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
371 Actor actor = Actor::New();
372 actor[Actor::Property::SIZE] = Vector2(400.0f, 400.0f);
373 actor[Actor::Property::POSITION] = center;
374 actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
375 actor[Actor::Property::COLOR] = Color::RED;
376 actor.AddRenderer(renderer);
378 Window window = mApplication.GetWindow();
382 Animation animation = Animation::New(5.0f);
383 KeyFrames k0 = KeyFrames::New();
384 k0.Add(0.0f, Vector3(0.0f, -radius, 0.0f));
385 k0.Add(0.5f, Vector3(0.0f, -radius * 4.0f, 0.0f));
386 k0.Add(1.0f, Vector3(0.0f, -radius, 0.0f));
387 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[1]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
389 k0 = KeyFrames::New();
390 k0.Add(0.0f, Vector3(radius, 0.0f, 0.0f));
391 k0.Add(0.5f, Vector3(radius * 4.0f, 0.0f, 0.0f));
392 k0.Add(1.0f, Vector3(radius, 0.0f, 0.0f));
393 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[4]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
395 k0 = KeyFrames::New();
396 k0.Add(0.0f, Vector3(0.0f, radius, 0.0f));
397 k0.Add(0.5f, Vector3(0.0f, radius * 4.0f, 0.0f));
398 k0.Add(1.0f, Vector3(0.0f, radius, 0.0f));
399 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[7]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
401 k0 = KeyFrames::New();
402 k0.Add(0.0f, Vector3(-radius, 0.0f, 0.0f));
403 k0.Add(0.5f, Vector3(-radius * 4.0f, 0.0f, 0.0f));
404 k0.Add(1.0f, Vector3(-radius, 0.0f, 0.0f));
405 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[10]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
407 animation.AnimateBy(Property(actor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(90.0f)), Vector3::ZAXIS));
408 animation.SetLooping(true);
413 * Main key event handler
415 void OnKeyEvent(const KeyEvent& event)
417 if(event.GetState() == KeyEvent::DOWN && (IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK)))
424 Application& mApplication;
427 int DALI_EXPORT_API main(int argc, char** argv)
429 Application application = Application::New(&argc, &argv);
430 AnimatedShapesExample test(application);
431 application.MainLoop();