Updated demos to use DALi clang-format
[platform/core/uifw/dali-demo.git] / examples / animated-shapes / animated-shapes-example.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali/dali.h>
20 #include "shared/view.h"
21
22 #include <sstream>
23
24 using namespace Dali;
25 using namespace Dali::Toolkit;
26
27 namespace
28 {
29 const char* APPLICATION_TITLE("Animated Shapes");
30
31 // clang-format off
32 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER
33 (
34   attribute mediump vec3 aCoefficient;
35   uniform mediump mat4 uMvpMatrix;
36   uniform mediump vec3 uPosition[MAX_POINT_COUNT];
37   varying lowp vec2 vCoefficient;
38   void main()
39   {
40     int vertexId = int(aCoefficient.z);
41     gl_Position = uMvpMatrix * vec4(uPosition[vertexId], 1.0);
42
43     vCoefficient = aCoefficient.xy;
44   }
45 );
46
47 // Fragment shader.
48 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER
49 (
50   uniform lowp vec4 uColor;
51   varying lowp vec2 vCoefficient;
52   void main()
53   {
54     lowp float C = (vCoefficient.x*vCoefficient.x-vCoefficient.y);
55     lowp float Cdx = dFdx(C);
56     lowp float Cdy = dFdy(C);
57
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 );
61   }
62 );
63 // clang-format on
64
65 Shader CreateShader(unsigned int pointCount)
66 {
67   std::ostringstream vertexShader;
68   vertexShader << "#define MAX_POINT_COUNT " << pointCount << "\n"
69                << VERTEX_SHADER;
70
71   std::ostringstream fragmentShader;
72   fragmentShader << "#extension GL_OES_standard_derivatives : enable "
73                  << "\n"
74                  << FRAGMENT_SHADER;
75
76   Shader shader = Shader::New(vertexShader.str(), fragmentShader.str());
77   for(unsigned int i(0); i < pointCount; ++i)
78   {
79     std::ostringstream propertyName;
80     propertyName << "uPosition[" << i << "]";
81     shader.RegisterProperty(propertyName.str(), Vector3(0.0f, 0.0f, 0.0f));
82   }
83
84   return shader;
85 }
86
87 } //unnamed namespace
88
89 // This example shows resolution independent rendering and animation of curves using the gpu.
90 //
91 class AnimatedShapesExample : public ConnectionTracker
92 {
93 public:
94   AnimatedShapesExample(Application& application)
95   : mApplication(application)
96   {
97     // Connect to the Application's Init signal
98     mApplication.InitSignal().Connect(this, &AnimatedShapesExample::Create);
99   }
100
101   ~AnimatedShapesExample() = default;
102
103   // The Init signal is received once (only) during the Application lifetime
104   void Create(Application& application)
105   {
106     Window        window     = application.GetWindow();
107     const Vector2 windowSize = window.GetSize();
108
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);
114
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);
131
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;
139     window.Add(label);
140
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);
144
145     window.KeyEventSignal().Connect(this, &AnimatedShapesExample::OnKeyEvent);
146   }
147
148   void CreateTriangleMorph(Vector3 center, float side)
149   {
150     float h = (side * 0.5f) / 0.866f;
151
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);
155
156     Vector3 v3 = v0 + ((v1 - v0) * 0.5f);
157     Vector3 v4 = v1 + ((v2 - v1) * 0.5f);
158     Vector3 v5 = v2 + ((v0 - v2) * 0.5f);
159
160     Shader shader          = CreateShader(12);
161     shader["uPosition[0]"] = v0;
162     shader["uPosition[1]"] = v3;
163     shader["uPosition[2]"] = v1;
164
165     shader["uPosition[3]"] = v1;
166     shader["uPosition[4]"] = v4;
167     shader["uPosition[5]"] = v2;
168
169     shader["uPosition[6]"] = v2;
170     shader["uPosition[7]"] = v5;
171     shader["uPosition[8]"] = v0;
172
173     shader["uPosition[9]"]  = v0;
174     shader["uPosition[10]"] = v1;
175     shader["uPosition[11]"] = v2;
176
177     //Create geometry
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),
181
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),
185
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),
189
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)};
193
194     unsigned short indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10};
195
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]));
201
202     //Create the geometry
203     Dali::Geometry geometry = Dali::Geometry::New();
204     geometry.AddVertexBuffer(vertexBuffer);
205     geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
206
207     Renderer renderer                        = Renderer::New(geometry, shader);
208     renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
209
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);
216
217     Window window = mApplication.GetWindow();
218     window.Add(actor);
219
220     //Animation
221     Animation animation = Animation::New(5.0f);
222     KeyFrames k0        = KeyFrames::New();
223     k0.Add(0.0f, v3);
224     k0.Add(0.5f, v3 + Vector3(-150.0f, -150.0f, 0.0f));
225     k0.Add(1.0f, v3);
226     animation.AnimateBetween(Property(shader, "uPosition[1]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
227
228     k0 = KeyFrames::New();
229     k0.Add(0.0f, v4);
230     k0.Add(0.5f, v4 + Vector3(150.0f, -150.0f, 0.0f));
231     k0.Add(1.0f, v4);
232     animation.AnimateBetween(Property(shader, "uPosition[4]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
233
234     k0 = KeyFrames::New();
235     k0.Add(0.0f, v5);
236     k0.Add(0.5f, v5 + Vector3(0.0, 150.0f, 0.0f));
237     k0.Add(1.0f, v5);
238     animation.AnimateBetween(Property(shader, "uPosition[7]"), k0, AlphaFunction::EASE_IN_OUT_SINE);
239     animation.SetLooping(true);
240     animation.Play();
241   }
242
243   void CreateCircleMorph(Vector3 center, float radius)
244   {
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);
249
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);
253
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);
257
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);
261
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);
266
267     //shader["uLineWidth"), 2.0] ;
268
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)};
285
286     short unsigned int indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 13, 14, 12, 14, 15};
287
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]));
293
294     //Create the geometry
295     Dali::Geometry geometry = Dali::Geometry::New();
296     geometry.AddVertexBuffer(vertexBuffer);
297     geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
298
299     Renderer renderer                        = Renderer::New(geometry, shader);
300     renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
301
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);
307
308     Window window = mApplication.GetWindow();
309     window.Add(actor);
310
311     //Animation
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);
318
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);
324
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);
330
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);
336
337     animation.AnimateBy(Property(actor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(-90.0f)), Vector3::ZAXIS));
338     animation.SetLooping(true);
339     animation.Play();
340   }
341
342   void CreateQuadMorph(Vector3 center, float radius)
343   {
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);
348
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);
352
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);
356
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);
360
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);
365
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),
369
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),
373
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),
377
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),
381
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)};
386
387     short unsigned int indexData[] = {0, 2, 1, 3, 5, 4, 6, 8, 7, 9, 11, 10, 12, 15, 14, 12, 14, 13};
388
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]));
394
395     //Create the geometry
396     Dali::Geometry geometry = Dali::Geometry::New();
397     geometry.AddVertexBuffer(vertexBuffer);
398     geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
399
400     Renderer renderer                        = Renderer::New(geometry, shader);
401     renderer[Renderer::Property::BLEND_MODE] = BlendMode::ON;
402
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);
409
410     Window window = mApplication.GetWindow();
411     window.Add(actor);
412
413     //Animation
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);
420
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);
426
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);
432
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);
438
439     animation.AnimateBy(Property(actor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(90.0f)), Vector3::ZAXIS));
440     animation.SetLooping(true);
441     animation.Play();
442   }
443
444   /**
445    * Main key event handler
446    */
447   void OnKeyEvent(const KeyEvent& event)
448   {
449     if(event.GetState() == KeyEvent::DOWN && (IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK)))
450     {
451       mApplication.Quit();
452     }
453   }
454
455 private:
456   Application& mApplication;
457 };
458
459 int DALI_EXPORT_API main(int argc, char** argv)
460 {
461   Application           application = Application::New(&argc, &argv);
462   AnimatedShapesExample test(application);
463   application.MainLoop();
464   return 0;
465 }