2 * Copyright (c) 2020 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 "shared/view.h"
25 using namespace Dali::Toolkit;
29 const char* APPLICATION_TITLE("Animated Shapes");
32 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER
34 attribute mediump vec3 aCoefficient;
35 uniform mediump mat4 uMvpMatrix;
36 uniform mediump vec3 uPosition[MAX_POINT_COUNT];
37 varying lowp vec2 vCoefficient;
40 int vertexId = int(aCoefficient.z);
41 gl_Position = uMvpMatrix * vec4(uPosition[vertexId], 1.0);
43 vCoefficient = aCoefficient.xy;
48 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER
50 uniform lowp vec4 uColor;
51 varying lowp vec2 vCoefficient;
54 lowp float C = (vCoefficient.x*vCoefficient.x-vCoefficient.y);
55 lowp float Cdx = dFdx(C);
56 lowp float Cdy = dFdy(C);
58 lowp float distance = float(C / sqrt(Cdx*Cdx + Cdy*Cdy));
59 lowp float alpha = 0.5 - distance;
60 gl_FragColor = vec4( uColor.rgb, uColor.a * alpha );
65 Shader CreateShader(unsigned int pointCount)
67 std::ostringstream vertexShader;
68 vertexShader << "#define MAX_POINT_COUNT " << pointCount << "\n"
71 std::ostringstream fragmentShader;
72 fragmentShader << "#extension GL_OES_standard_derivatives : enable "
76 Shader shader = Shader::New(vertexShader.str(), fragmentShader.str());
77 for(unsigned int i(0); i < pointCount; ++i)
79 std::ostringstream propertyName;
80 propertyName << "uPosition[" << i << "]";
81 shader.RegisterProperty(propertyName.str(), Vector3(0.0f, 0.0f, 0.0f));
89 // This example shows resolution independent rendering and animation of curves using the gpu.
91 class AnimatedShapesExample : public ConnectionTracker
94 AnimatedShapesExample(Application& application)
95 : mApplication(application)
97 // Connect to the Application's Init signal
98 mApplication.InitSignal().Connect(this, &AnimatedShapesExample::Create);
101 ~AnimatedShapesExample() = default;
103 // The Init signal is received once (only) during the Application lifetime
104 void Create(Application& application)
106 Window window = application.GetWindow();
107 const Vector2 windowSize = window.GetSize();
109 // Creates the background gradient
110 Toolkit::Control background = Dali::Toolkit::Control::New();
111 background[Actor::Property::ANCHOR_POINT] = Dali::AnchorPoint::CENTER;
112 background[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER;
113 background.SetResizePolicy(Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS);
115 Dali::Property::Map map;
116 map.Insert(Toolkit::Visual::Property::TYPE, Visual::GRADIENT);
117 Property::Array stopOffsets;
118 stopOffsets.PushBack(0.0f);
119 stopOffsets.PushBack(1.0f);
120 map.Insert(GradientVisual::Property::STOP_OFFSET, stopOffsets);
121 Property::Array stopColors;
122 stopColors.PushBack(Vector4(0.0f, 0.0f, 1.0f, 1.0f));
123 stopColors.PushBack(Vector4(1.0f, 1.0f, 1.0f, 1.0f));
124 map.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
125 Vector2 halfWindowSize = windowSize * 0.5f;
126 map.Insert(GradientVisual::Property::START_POSITION, Vector2(0.0f, -halfWindowSize.y));
127 map.Insert(GradientVisual::Property::END_POSITION, Vector2(0.0f, halfWindowSize.y));
128 map.Insert(GradientVisual::Property::UNITS, GradientVisual::Units::USER_SPACE);
129 background[Dali::Toolkit::Control::Property::BACKGROUND] = map;
130 window.Add(background);
132 // Create a TextLabel for the application title.
133 Toolkit::TextLabel label = Toolkit::TextLabel::New(APPLICATION_TITLE);
134 label[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_CENTER;
135 label[Actor::Property::PARENT_ORIGIN] = Vector3(0.5f, 0.0f, 0.5f);
136 label[Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT] = "CENTER";
137 label[Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT] = "CENTER";
138 label[Toolkit::TextLabel::Property::TEXT_COLOR] = Color::WHITE;
141 CreateTriangleMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.15f, 0.0f), 100.0f);
142 CreateCircleMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.5f, 0.0f), 55.0f);
143 CreateQuadMorph(Vector3(windowSize.x * 0.5f, windowSize.y * 0.85f, 0.0f), 60.0f);
145 window.KeyEventSignal().Connect(this, &AnimatedShapesExample::OnKeyEvent);
148 void CreateTriangleMorph(Vector3 center, float side)
150 float h = (side * 0.5f) / 0.866f;
152 Vector3 v0 = Vector3(-h, h, 0.0f);
153 Vector3 v1 = Vector3(0.0f, -side * 0.366f, 0.0f);
154 Vector3 v2 = Vector3(h, h, 0.0f);
156 Vector3 v3 = v0 + ((v1 - v0) * 0.5f);
157 Vector3 v4 = v1 + ((v2 - v1) * 0.5f);
158 Vector3 v5 = v2 + ((v0 - v2) * 0.5f);
160 Shader shader = CreateShader(12);
161 shader["uPosition[0]"] = v0;
162 shader["uPosition[1]"] = v3;
163 shader["uPosition[2]"] = v1;
165 shader["uPosition[3]"] = v1;
166 shader["uPosition[4]"] = v4;
167 shader["uPosition[5]"] = v2;
169 shader["uPosition[6]"] = v2;
170 shader["uPosition[7]"] = v5;
171 shader["uPosition[8]"] = v0;
173 shader["uPosition[9]"] = v0;
174 shader["uPosition[10]"] = v1;
175 shader["uPosition[11]"] = v2;
178 static const Vector3 vertexData[] = {Dali::Vector3(0.0f, 0.0f, 0.0f),
179 Dali::Vector3(0.5f, 0.0f, 1.0f),
180 Dali::Vector3(1.0f, 1.0f, 2.0f),
182 Dali::Vector3(0.0f, 0.0f, 3.0f),
183 Dali::Vector3(0.5f, 0.0f, 4.0f),
184 Dali::Vector3(1.0f, 1.0f, 5.0f),
186 Dali::Vector3(0.0f, 0.0f, 6.0f),
187 Dali::Vector3(0.5f, 0.0f, 7.0f),
188 Dali::Vector3(1.0f, 1.0f, 8.0f),
190 Dali::Vector3(0.0f, 1.0f, 9.0f),
191 Dali::Vector3(0.0f, 1.0f, 10.0f),
192 Dali::Vector3(0.0f, 1.0f, 11.0f)};
194 unsigned short indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10};
196 //Create a vertex buffer for vertex positions and texture coordinates
197 Dali::Property::Map vertexFormat;
198 vertexFormat["aCoefficient"] = Dali::Property::VECTOR3;
199 Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
200 vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
202 //Create the geometry
203 Dali::Geometry geometry = Dali::Geometry::New();
204 geometry.AddVertexBuffer(vertexBuffer);
205 geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
207 Renderer renderer = Renderer::New(geometry, shader);
208 renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
210 Actor actor = Actor::New();
211 actor[Actor::Property::SIZE] = Vector2(400.0f, 400.0f);
212 actor[Actor::Property::POSITION] = center;
213 actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
214 actor[Actor::Property::COLOR] = Color::YELLOW;
215 actor.AddRenderer(renderer);
217 Window window = mApplication.GetWindow();
221 Animation animation = Animation::New(5.0f);
222 KeyFrames k0 = KeyFrames::New();
224 k0.Add(0.5f, v3 + Vector3(-150.0f, -150.0f, 0.0f));
226 animation.AnimateBetween(Property(shader, "uPosition[1]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
228 k0 = KeyFrames::New();
230 k0.Add(0.5f, v4 + Vector3(150.0f, -150.0f, 0.0f));
232 animation.AnimateBetween(Property(shader, "uPosition[4]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
234 k0 = KeyFrames::New();
236 k0.Add(0.5f, v5 + Vector3(0.0, 150.0f, 0.0f));
238 animation.AnimateBetween(Property(shader, "uPosition[7]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
239 animation.SetLooping(true);
243 void CreateCircleMorph(Vector3 center, float radius)
245 Shader shader = CreateShader(16);
246 shader["uPosition[0]"] = Vector3(-radius, -radius, 0.0f);
247 shader["uPosition[1]"] = Vector3(0.0f, -radius, 0.0f);
248 shader["uPosition[2]"] = Vector3(radius, -radius, 0.0f);
250 shader["uPosition[3]"] = Vector3(radius, -radius, 0.0f);
251 shader["uPosition[4]"] = Vector3(radius, 0.0f, 0.0f);
252 shader["uPosition[5]"] = Vector3(radius, radius, 0.0f);
254 shader["uPosition[6]"] = Vector3(radius, radius, 0.0f);
255 shader["uPosition[7]"] = Vector3(0.0f, radius, 0.0f);
256 shader["uPosition[8]"] = Vector3(-radius, radius, 0.0f);
258 shader["uPosition[9]"] = Vector3(-radius, radius, 0.0f);
259 shader["uPosition[10]"] = Vector3(-radius, 0.0f, 0.0f);
260 shader["uPosition[11]"] = Vector3(-radius, -radius, 0.0f);
262 shader["uPosition[12]"] = Vector3(-radius, -radius, 0.0f);
263 shader["uPosition[13]"] = Vector3(radius, -radius, 0.0f);
264 shader["uPosition[14]"] = Vector3(radius, radius, 0.0f);
265 shader["uPosition[15]"] = Vector3(-radius, radius, 0.0f);
267 //shader["uLineWidth"), 2.0] ;
269 static const Vector3 vertexData[] = {Vector3(0.0f, 0.0f, 0.0f),
270 Vector3(0.5f, 0.0f, 1.0f),
271 Vector3(1.0f, 1.0f, 2.0f),
272 Vector3(0.0f, 0.0f, 3.0f),
273 Vector3(0.5f, 0.0f, 4.0f),
274 Vector3(1.0f, 1.0f, 5.0f),
275 Vector3(0.0f, 0.0f, 6.0f),
276 Vector3(0.5f, 0.0f, 7.0f),
277 Vector3(1.0f, 1.0f, 8.0f),
278 Vector3(0.0f, 0.0f, 9.0f),
279 Vector3(0.5f, 0.0f, 10.0f),
280 Vector3(1.0f, 1.0f, 11.0f),
281 Vector3(0.0f, 1.0f, 12.0f),
282 Vector3(0.0f, 1.0f, 13.0f),
283 Vector3(0.0f, 1.0f, 14.0f),
284 Vector3(0.0f, 1.0f, 15.0f)};
286 short unsigned int indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 13, 14, 12, 14, 15};
288 //Create a vertex buffer for vertex positions and texture coordinates
289 Dali::Property::Map vertexFormat;
290 vertexFormat["aCoefficient"] = Dali::Property::VECTOR3;
291 Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
292 vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
294 //Create the geometry
295 Dali::Geometry geometry = Dali::Geometry::New();
296 geometry.AddVertexBuffer(vertexBuffer);
297 geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
299 Renderer renderer = Renderer::New(geometry, shader);
300 renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
302 Actor actor = Actor::New();
303 actor[Actor::Property::SIZE] = Vector2(400.0f, 400.0f);
304 actor[Actor::Property::POSITION] = center;
305 actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
306 actor.AddRenderer(renderer);
308 Window window = mApplication.GetWindow();
312 Animation animation = Animation::New(5.0f);
313 KeyFrames k0 = KeyFrames::New();
314 k0.Add(0.0f, Vector3(0.0f, -radius * 1.85, 0.0f));
315 k0.Add(0.5f, Vector3(-radius * 1.85, -radius * 3.0f, 0.0f));
316 k0.Add(1.0f, Vector3(0.0f, -radius * 1.85, 0.0f));
317 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[1]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
319 k0 = KeyFrames::New();
320 k0.Add(0.0f, Vector3(radius * 1.85, 0.0f, 0.0f));
321 k0.Add(0.5f, Vector3(radius * 3.0f, -radius * 1.85, 0.0f));
322 k0.Add(1.0f, Vector3(radius * 1.85, 0.0f, 0.0f));
323 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[4]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
325 k0 = KeyFrames::New();
326 k0.Add(0.0f, Vector3(0.0f, radius * 1.85, 0.0f));
327 k0.Add(0.5f, Vector3(radius * 1.85, radius * 3.0f, 0.0f));
328 k0.Add(1.0f, Vector3(0.0f, radius * 1.85, 0.0f));
329 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[7]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
331 k0 = KeyFrames::New();
332 k0.Add(0.0f, Vector3(-radius * 1.85, 0.0f, 0.0f));
333 k0.Add(0.5f, Vector3(-radius * 3.0f, radius * 1.85, 0.0f));
334 k0.Add(1.0f, Vector3(-radius * 1.85, 0.0f, 0.0f));
335 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[10]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
337 animation.AnimateBy(Property(actor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(-90.0f)), Vector3::ZAXIS));
338 animation.SetLooping(true);
342 void CreateQuadMorph(Vector3 center, float radius)
344 Shader shader = CreateShader(16);
345 shader["uPosition[0]"] = Vector3(-radius, -radius, 0.0f);
346 shader["uPosition[1]"] = Vector3(0.0f, -radius, 0.0f);
347 shader["uPosition[2]"] = Vector3(radius, -radius, 0.0f);
349 shader["uPosition[3]"] = Vector3(radius, -radius, 0.0f);
350 shader["uPosition[4]"] = Vector3(radius, 0.0f, 0.0f);
351 shader["uPosition[5]"] = Vector3(radius, radius, 0.0f);
353 shader["uPosition[6]"] = Vector3(radius, radius, 0.0f);
354 shader["uPosition[7]"] = Vector3(0.0f, radius, 0.0f);
355 shader["uPosition[8]"] = Vector3(-radius, radius, 0.0f);
357 shader["uPosition[9]"] = Vector3(-radius, radius, 0.0f);
358 shader["uPosition[10]"] = Vector3(-radius, 0.0f, 0.0f);
359 shader["uPosition[11]"] = Vector3(-radius, -radius, 0.0f);
361 shader["uPosition[12]"] = Vector3(-radius, -radius, 0.0f);
362 shader["uPosition[13]"] = Vector3(radius, -radius, 0.0f);
363 shader["uPosition[14]"] = Vector3(radius, radius, 0.0f);
364 shader["uPosition[15]"] = Vector3(-radius, radius, 0.0f);
366 static const Vector3 vertexData[] = {Dali::Vector3(0.0f, 0.0f, 0.0f),
367 Dali::Vector3(0.5f, 0.0f, 1.0f),
368 Dali::Vector3(1.0f, 1.0f, 2.0f),
370 Dali::Vector3(0.0f, 0.0f, 3.0f),
371 Dali::Vector3(0.5f, 0.0f, 4.0f),
372 Dali::Vector3(1.0f, 1.0f, 5.0f),
374 Dali::Vector3(0.0f, 0.0f, 6.0f),
375 Dali::Vector3(0.5f, 0.0f, 7.0f),
376 Dali::Vector3(1.0f, 1.0f, 8.0f),
378 Dali::Vector3(0.0f, 0.0f, 9.0f),
379 Dali::Vector3(0.5f, 0.0f, 10.0f),
380 Dali::Vector3(1.0f, 1.0f, 11.0f),
382 Dali::Vector3(0.0f, 1.0f, 12.0f),
383 Dali::Vector3(0.0f, 1.0f, 13.0f),
384 Dali::Vector3(0.0f, 1.0f, 14.0f),
385 Dali::Vector3(0.0f, 1.0f, 15.0f)};
387 short unsigned int indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 15, 14, 12, 14, 13};
389 //Create a vertex buffer for vertex positions and texture coordinates
390 Dali::Property::Map vertexFormat;
391 vertexFormat["aCoefficient"] = Dali::Property::VECTOR3;
392 Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(vertexFormat);
393 vertexBuffer.SetData(vertexData, sizeof(vertexData) / sizeof(vertexData[0]));
395 //Create the geometry
396 Dali::Geometry geometry = Dali::Geometry::New();
397 geometry.AddVertexBuffer(vertexBuffer);
398 geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
400 Renderer renderer = Renderer::New(geometry, shader);
401 renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
403 Actor actor = Actor::New();
404 actor[Actor::Property::SIZE] = Vector2(400.0f, 400.0f);
405 actor[Actor::Property::POSITION] = center;
406 actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
407 actor[Actor::Property::COLOR] = Color::RED;
408 actor.AddRenderer(renderer);
410 Window window = mApplication.GetWindow();
414 Animation animation = Animation::New(5.0f);
415 KeyFrames k0 = KeyFrames::New();
416 k0.Add(0.0f, Vector3(0.0f, -radius, 0.0f));
417 k0.Add(0.5f, Vector3(0.0f, -radius * 4.0f, 0.0f));
418 k0.Add(1.0f, Vector3(0.0f, -radius, 0.0f));
419 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[1]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
421 k0 = KeyFrames::New();
422 k0.Add(0.0f, Vector3(radius, 0.0f, 0.0f));
423 k0.Add(0.5f, Vector3(radius * 4.0f, 0.0f, 0.0f));
424 k0.Add(1.0f, Vector3(radius, 0.0f, 0.0f));
425 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[4]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
427 k0 = KeyFrames::New();
428 k0.Add(0.0f, Vector3(0.0f, radius, 0.0f));
429 k0.Add(0.5f, Vector3(0.0f, radius * 4.0f, 0.0f));
430 k0.Add(1.0f, Vector3(0.0f, radius, 0.0f));
431 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[7]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
433 k0 = KeyFrames::New();
434 k0.Add(0.0f, Vector3(-radius, 0.0f, 0.0f));
435 k0.Add(0.5f, Vector3(-radius * 4.0f, 0.0f, 0.0f));
436 k0.Add(1.0f, Vector3(-radius, 0.0f, 0.0f));
437 animation.AnimateBetween(Property(shader, shader.GetPropertyIndex("uPosition[10]")), k0, AlphaFunction::EASE_IN_OUT_SINE);
439 animation.AnimateBy(Property(actor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(90.0f)), Vector3::ZAXIS));
440 animation.SetLooping(true);
445 * Main key event handler
447 void OnKeyEvent(const KeyEvent& event)
449 if(event.GetState() == KeyEvent::DOWN && (IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK)))
456 Application& mApplication;
459 int DALI_EXPORT_API main(int argc, char** argv)
461 Application application = Application::New(&argc, &argv);
462 AnimatedShapesExample test(application);
463 application.MainLoop();