DALi Version 2.0.11
[platform/core/uifw/dali-demo.git] / examples / line-mesh / line-mesh-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 // EXTERNAL INCLUDES
19 #include <dali-toolkit/dali-toolkit.h>
20 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
21 #include <dali/devel-api/actors/actor-devel.h>
22
23 // INTERNAL INCLUDES
24 #include "shared/view.h"
25 #include "generated/line-mesh-vert.h"
26 #include "generated/line-mesh-frag.h"
27
28 #include <sstream>
29
30 using namespace Dali;
31
32 namespace
33 {
34
35 const unsigned short  INDEX_LINES[]   = {0, 1, 1, 2, 2, 3, 3, 4, 4, 0};
36 const unsigned short  INDEX_LOOP[]    = {0, 1, 2, 3, 4};
37 const unsigned short  INDEX_STRIP[]   = {0, 1, 2, 3, 4, 0};
38 const unsigned short* INDICES[3]      = {&INDEX_LINES[0], &INDEX_LOOP[0], &INDEX_STRIP[0]};
39 const unsigned int    INDICES_SIZE[3] = {sizeof(INDEX_LINES) / sizeof(INDEX_LINES[0]), sizeof(INDEX_LOOP) / sizeof(INDEX_LOOP[0]), sizeof(INDEX_STRIP) / sizeof(INDEX_STRIP[0])};
40
41 Geometry CreateGeometry()
42 {
43   // Create vertices
44   struct Vertex
45   {
46     Vector2 position1;
47     Vector2 position2;
48     Vector3 color;
49   };
50
51   // Create new geometry object
52   Vertex pentagonVertexData[5] =
53     {
54       {Vector2(0.0f, 1.00f), Vector2(0.0f, -1.00f), Vector3(1.0f, 1.0f, 1.0f)},      // 0
55       {Vector2(-0.95f, 0.31f), Vector2(0.59f, 0.81f), Vector3(1.0f, 0.0f, 0.0f)},    // 1
56       {Vector2(-0.59f, -0.81f), Vector2(-0.95f, -0.31f), Vector3(0.0f, 1.0f, 0.0f)}, // 2
57       {Vector2(0.59f, -0.81f), Vector2(0.95f, -0.31f), Vector3(0.0f, 0.0f, 1.0f)},   // 3
58       {Vector2(0.95f, 0.31f), Vector2(-0.59f, 0.81f), Vector3(1.0f, 1.0f, 0.0f)},    // 4
59     };
60
61   Property::Map pentagonVertexFormat;
62   pentagonVertexFormat["aPosition1"] = Property::VECTOR2;
63   pentagonVertexFormat["aPosition2"] = Property::VECTOR2;
64   pentagonVertexFormat["aColor"]     = Property::VECTOR3;
65   VertexBuffer pentagonVertices      = VertexBuffer::New(pentagonVertexFormat);
66   pentagonVertices.SetData(pentagonVertexData, 5);
67
68   // Create the geometry object
69   Geometry pentagonGeometry = Geometry::New();
70   pentagonGeometry.AddVertexBuffer(pentagonVertices);
71   pentagonGeometry.SetIndexBuffer(INDICES[0], INDICES_SIZE[0]);
72   pentagonGeometry.SetType(Geometry::LINES);
73   return pentagonGeometry;
74 }
75
76 } // anonymous namespace
77
78 // This example shows how to morph between 2 meshes with the same number of
79 // vertices.
80 class ExampleController : public ConnectionTracker
81 {
82 public:
83   /**
84    * The example controller constructor.
85    * @param[in] application The application instance
86    */
87   ExampleController(Application& application)
88   : mApplication(application),
89     mWindowSize(),
90     mShader(),
91     mGeometry(),
92     mRenderer(),
93     mMeshActor(),
94     mButtons(),
95     mMinusButton(),
96     mPlusButton(),
97     mIndicesCountLabel(),
98     mPrimitiveType(Geometry::LINES),
99     mCurrentIndexCount(0),
100     mMaxIndexCount(0)
101   {
102     // Connect to the Application's Init signal
103     mApplication.InitSignal().Connect(this, &ExampleController::Create);
104   }
105
106   /**
107    * The example controller destructor
108    */
109   ~ExampleController()
110   {
111     // Nothing to do here;
112   }
113
114   /**
115    * Invoked upon creation of application
116    * @param[in] application The application instance
117    */
118   void Create(Application& application)
119   {
120     Window window = application.GetWindow();
121
122     // initial settings
123     mPrimitiveType     = Geometry::LINES;
124     mCurrentIndexCount = 10;
125     mMaxIndexCount     = 10;
126
127     CreateRadioButtons();
128
129     window.KeyEventSignal().Connect(this, &ExampleController::OnKeyEvent);
130
131     mWindowSize = window.GetSize();
132
133     Initialise();
134
135     window.SetBackgroundColor(Vector4(0.0f, 0.2f, 0.2f, 1.0f));
136   }
137
138   /**
139    * Invoked whenever application changes the type of geometry drawn
140    */
141   void Initialise()
142   {
143     Window window = mApplication.GetWindow();
144
145     // destroy mesh actor and its resources if already exists
146     if(mMeshActor)
147     {
148       window.Remove(mMeshActor);
149       mMeshActor.Reset();
150     }
151
152     mShader   = Shader::New(SHADER_LINE_MESH_VERT, SHADER_LINE_MESH_FRAG);
153     mGeometry = CreateGeometry();
154     mRenderer = Renderer::New(mGeometry, mShader);
155
156     mRenderer.SetIndexRange(0, 10); // lines
157     mPrimitiveType = Geometry::LINES;
158
159     mMeshActor = Actor::New();
160     mMeshActor.AddRenderer(mRenderer);
161     mMeshActor.SetProperty(Actor::Property::SIZE, Vector2(200, 200));
162     mMeshActor.SetProperty(DevelActor::Property::UPDATE_SIZE_HINT, Vector2(400, 400));
163
164     Property::Index morphAmountIndex = mMeshActor.RegisterProperty("uMorphAmount", 0.0f);
165
166     mRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, 0);
167
168     mMeshActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
169     mMeshActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
170     window.Add(mMeshActor);
171
172     Animation animation = Animation::New(5);
173     KeyFrames keyFrames = KeyFrames::New();
174     keyFrames.Add(0.0f, 0.0f);
175     keyFrames.Add(1.0f, 1.0f);
176
177     animation.AnimateBetween(Property(mMeshActor, morphAmountIndex), keyFrames, AlphaFunction(AlphaFunction::SIN));
178     animation.SetLooping(true);
179     animation.Play();
180   }
181
182   /**
183    * Invoked on create
184    */
185   void CreateRadioButtons()
186   {
187     Window window = mApplication.GetWindow();
188
189     Toolkit::TableView modeSelectTableView = Toolkit::TableView::New(4, 1);
190     modeSelectTableView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
191     modeSelectTableView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
192     modeSelectTableView.SetFitHeight(0);
193     modeSelectTableView.SetFitHeight(1);
194     modeSelectTableView.SetFitHeight(2);
195     modeSelectTableView.SetCellPadding(Vector2(6.0f, 0.0f));
196     modeSelectTableView.SetProperty(Actor::Property::SCALE, Vector3(0.8f, 0.8f, 0.8f));
197
198     const char* labels[] =
199       {
200         "LINES",
201         "LINE_LOOP",
202         "LINE_STRIP"};
203
204     for(int i = 0; i < 3; ++i)
205     {
206       Dali::Toolkit::RadioButton radio = Dali::Toolkit::RadioButton::New();
207
208       radio.SetProperty(Toolkit::Button::Property::LABEL,
209                         Property::Map()
210                           .Add(Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT)
211                           .Add(Toolkit::TextVisual::Property::TEXT, labels[i])
212                           .Add(Toolkit::TextVisual::Property::TEXT_COLOR, Vector4(0.8f, 0.8f, 0.8f, 1.0f)));
213
214       radio.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
215       radio.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
216       radio.SetProperty(Toolkit::Button::Property::SELECTED, i == 0);
217       radio.PressedSignal().Connect(this, &ExampleController::OnButtonPressed);
218       mButtons[i] = radio;
219       modeSelectTableView.AddChild(radio, Toolkit::TableView::CellPosition(i, 0));
220     }
221
222     Toolkit::TableView elementCountTableView = Toolkit::TableView::New(1, 3);
223     elementCountTableView.SetCellPadding(Vector2(6.0f, 0.0f));
224     elementCountTableView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT);
225     elementCountTableView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_LEFT);
226     elementCountTableView.SetFitHeight(0);
227     elementCountTableView.SetFitWidth(0);
228     elementCountTableView.SetFitWidth(1);
229     elementCountTableView.SetFitWidth(2);
230     mMinusButton = Toolkit::PushButton::New();
231     mMinusButton.SetProperty(Toolkit::Button::Property::LABEL, "<<");
232     mMinusButton.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
233     mMinusButton.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_LEFT);
234
235     Toolkit::PushButton mPlusButton = Toolkit::PushButton::New();
236     mPlusButton.SetProperty(Toolkit::Button::Property::LABEL, ">>");
237     mPlusButton.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
238     mPlusButton.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_RIGHT);
239
240     mMinusButton.ClickedSignal().Connect(this, &ExampleController::OnButtonClicked);
241     mPlusButton.ClickedSignal().Connect(this, &ExampleController::OnButtonClicked);
242
243     mIndicesCountLabel = Toolkit::TextLabel::New();
244     mIndicesCountLabel.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
245     mIndicesCountLabel.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
246
247     std::stringstream str;
248     str << mCurrentIndexCount;
249     mIndicesCountLabel.SetProperty(Toolkit::TextLabel::Property::TEXT, str.str());
250     mIndicesCountLabel.SetProperty(Toolkit::TextLabel::Property::TEXT_COLOR, Vector4(1.0, 1.0, 1.0, 1.0));
251     mIndicesCountLabel.SetProperty(Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "BOTTOM");
252     mIndicesCountLabel.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH);
253     mIndicesCountLabel.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT);
254
255     elementCountTableView.AddChild(mMinusButton, Toolkit::TableView::CellPosition(0, 0));
256     elementCountTableView.AddChild(mIndicesCountLabel, Toolkit::TableView::CellPosition(0, 1));
257     elementCountTableView.AddChild(mPlusButton, Toolkit::TableView::CellPosition(0, 2));
258
259     window.Add(modeSelectTableView);
260     window.Add(elementCountTableView);
261   }
262
263   /**
264    * Invoked whenever the quit button is clicked
265    * @param[in] button the quit button
266    */
267   bool OnQuitButtonClicked(Toolkit::Button button)
268   {
269     // quit the application
270     mApplication.Quit();
271     return true;
272   }
273
274   void OnKeyEvent(const KeyEvent& event)
275   {
276     if(event.GetState() == KeyEvent::DOWN)
277     {
278       if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
279       {
280         mApplication.Quit();
281       }
282     }
283   }
284
285   bool OnButtonPressed(Toolkit::Button button)
286   {
287     int indicesArray;
288     if(button == mButtons[0])
289     {
290       mCurrentIndexCount = 10;
291       mMaxIndexCount     = 10;
292       mPrimitiveType     = Geometry::LINES;
293       indicesArray       = 0;
294     }
295     else if(button == mButtons[1])
296     {
297       mCurrentIndexCount = 5;
298       mMaxIndexCount     = 5;
299       mPrimitiveType     = Geometry::LINE_LOOP;
300       indicesArray       = 1;
301     }
302     else
303     {
304       mCurrentIndexCount = 6;
305       mMaxIndexCount     = 6;
306       mPrimitiveType     = Geometry::LINE_STRIP;
307       indicesArray       = 2;
308     }
309
310     std::stringstream str;
311     str << mCurrentIndexCount;
312     mIndicesCountLabel.SetProperty(Toolkit::TextLabel::Property::TEXT, str.str());
313     mGeometry.SetType(mPrimitiveType);
314     mGeometry.SetIndexBuffer(INDICES[indicesArray], INDICES_SIZE[indicesArray]);
315     mRenderer.SetIndexRange(0, mCurrentIndexCount);
316     return true;
317   }
318
319   bool OnButtonClicked(Toolkit::Button button)
320   {
321     if(button == mMinusButton)
322     {
323       if(--mCurrentIndexCount < 2)
324         mCurrentIndexCount = 2;
325     }
326     else
327     {
328       if(++mCurrentIndexCount > mMaxIndexCount)
329         mCurrentIndexCount = mMaxIndexCount;
330     }
331
332     std::stringstream str;
333     str << mCurrentIndexCount;
334     mIndicesCountLabel.SetProperty(Toolkit::TextLabel::Property::TEXT, str.str());
335     mRenderer.SetIndexRange(0, mCurrentIndexCount);
336     return true;
337   }
338
339 private:
340   Application& mApplication; ///< Application instance
341   Vector3      mWindowSize;  ///< The size of the window
342
343   Shader               mShader;
344   Geometry             mGeometry;
345   Renderer             mRenderer;
346   Actor                mMeshActor;
347   Toolkit::RadioButton mButtons[3];
348   Toolkit::PushButton  mMinusButton;
349   Toolkit::PushButton  mPlusButton;
350   Toolkit::TextLabel   mIndicesCountLabel;
351   Geometry::Type       mPrimitiveType;
352   int                  mCurrentIndexCount;
353   int                  mMaxIndexCount;
354 };
355
356 int DALI_EXPORT_API main(int argc, char** argv)
357 {
358   Application       application = Application::New(&argc, &argv);
359   ExampleController test(application);
360   application.MainLoop();
361   return 0;
362 }