Refactoring Gestures Class
[platform/core/uifw/dali-demo.git] / examples / primitive-shapes / primitive-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-toolkit/devel-api/controls/table-view/table-view.h>
20
21 using namespace Dali;
22 using namespace Dali::Toolkit;
23
24 namespace
25 {
26   //Button image urls
27   const char* BUTTON_IMAGE_URL[] =
28   {
29     DEMO_IMAGE_DIR "sphere-button.png",
30     DEMO_IMAGE_DIR "cone-button.png",
31     DEMO_IMAGE_DIR "conical-frustum-button.png",
32     DEMO_IMAGE_DIR "cylinder-button.png",
33     DEMO_IMAGE_DIR "cube-button.png",
34     DEMO_IMAGE_DIR "bevelled-cube-button.png",
35     DEMO_IMAGE_DIR "octahedron-button.png"
36   };
37
38   //Prefix of all shape titles.
39   const std::string SHAPE_TITLE_PREFIX = "Current Shape: ";
40
41   //Shape property defaults
42   const int DEFAULT_SLICES = 32;
43   const int DEFAULT_STACKS = 32;
44   const float DEFAULT_SCALE_HEIGHT = 16.0f;
45   const float DEFAULT_SCALE_BOTTOM_RADIUS = 8.0f;
46   const float DEFAULT_SCALE_TOP_RADIUS = 4.0f;
47   const float DEFAULT_SCALE_RADIUS = 8.0f;
48   const float DEFAULT_BEVEL_PERCENTAGE = 0.3f;
49   const float DEFAULT_BEVEL_SMOOTHNESS = 0.0f;
50
51   //Shape property limits
52   const int SLICES_LOWER_BOUND = 3;
53   const int SLICES_UPPER_BOUND = 16;
54   const int STACKS_LOWER_BOUND = 2;
55   const int STACKS_UPPER_BOUND = 16;
56
57   //Used to the control rate of rotation when panning an object.
58   const float X_ROTATION_DISPLACEMENT_FACTOR = 60.0f;
59   const float Y_ROTATION_DISPLACEMENT_FACTOR = 60.0f;
60
61   const int NUM_MODELS = 7; //Total number of possible base shapes.
62   const int MAX_PROPERTIES = 3; //Maximum number of properties a shape may require. (For displaying sliders.)
63
64 } //End namespace
65
66 class PrimitiveShapesController : public ConnectionTracker
67 {
68 public:
69
70   PrimitiveShapesController( Application& application )
71   : mApplication( application ),
72     mColor( Vector4( 0.3f, 0.7f, 1.0f, 1.0f ) ),
73     mRotation( Vector2::ZERO )
74   {
75     // Connect to the Application's Init signal
76     mApplication.InitSignal().Connect( this, &PrimitiveShapesController::Create );
77   }
78
79   ~PrimitiveShapesController()
80   {
81   }
82
83   // The Init signal is received once (only) during the Application lifetime
84   void Create( Application& application )
85   {
86     // Get a handle to the window
87     Window window = application.GetWindow();
88     window.SetBackgroundColor( Color::WHITE );
89
90     //Set up layer to place UI on.
91     Layer layer = Layer::New();
92     layer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
93     layer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
94     layer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
95     layer.SetProperty( Layer::Property::BEHAVIOR, Layer::LAYER_UI ); //We use a 2D layer as this is closer to UI work than full 3D scene creation.
96     layer.SetProperty( Layer::Property::DEPTH_TEST, true ); //Enable depth testing, as otherwise the 2D layer would not do so.
97     window.Add( layer );
98
99     //Set up model selection buttons.
100     SetupButtons( layer );
101
102     //Set up model parameter sliders.
103     SetupSliders( layer );
104
105     //Set up 3D model.
106     SetupModel( layer );
107
108     //Allow for exiting of the application via key presses.
109     window.KeyEventSignal().Connect( this, &PrimitiveShapesController::OnKeyEvent );
110   }
111
112   //Place buttons on the top of the screen, which allow for selection of the shape to be displayed.
113   //A title above indicates the currently selected shape.
114   //The buttons are laid out like so:
115   //
116   //      ^    +--------------------------------+
117   //      |    | Current Shape: ~~~~~           |
118   //      |    |                                |
119   //      |    | +----+ +----+ +----+ +----+    |
120   //      |    | |    | |    | |    | |    |    |
121   //  30% |    | +----+ +----+ +----+ +----+    |
122   //      |    |                                |
123   //      |    | +----+ +----+ +----+           |
124   //      |    | |    | |    | |    |           |
125   //      v    | +----+ +----+ +----+           |
126   //           |                                |
127   //           |                                |
128   //           |                                |
129   //           |                                |
130   //           |                                |
131   //           |                                |
132   //           |                                |
133   //           |                                |
134   //           |                                |
135   //           |                                |
136   //           |                                |
137   //           |                                |
138   //           |                                |
139   //           |                                |
140   //           |                                |
141   //           |                                |
142   //           |                                |
143   //           |                                |
144   //           +--------------------------------+
145   //
146   void SetupButtons( Layer layer )
147   {
148     float containerPadding = 10.0f;
149     float elementPadding = 5.0f;
150
151     //Used to layout the title and the buttons below it.
152     Control topAlignment = Control::New();
153     topAlignment.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
154     topAlignment.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER );
155     topAlignment.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
156     topAlignment.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::HEIGHT );
157     layer.Add( topAlignment );
158
159     //Add a title to indicate the currently selected shape.
160     mShapeTitle = TextLabel::New( "DEFAULT" );
161     mShapeTitle.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
162     mShapeTitle.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
163     mShapeTitle.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
164     mShapeTitle.SetProperty( Actor::Property::PADDING, Padding( elementPadding, elementPadding, elementPadding, elementPadding ) );
165     topAlignment.Add( mShapeTitle );
166
167     //Create a variable-length container that can wrap buttons around as more are added.
168     FlexContainer buttonContainer = FlexContainer::New();
169     buttonContainer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
170     buttonContainer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER );
171     buttonContainer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
172     buttonContainer.SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
173     buttonContainer.SetProperty( Actor::Property::PADDING, Padding( containerPadding, containerPadding, containerPadding, containerPadding ) );
174     buttonContainer.SetProperty( FlexContainer::Property::FLEX_DIRECTION, FlexContainer::ROW );
175     buttonContainer.SetProperty( FlexContainer::Property::FLEX_WRAP, FlexContainer::WRAP );
176     topAlignment.Add( buttonContainer );
177
178     //Create buttons and place them in the container.
179     for( int modelNumber = 0; modelNumber < NUM_MODELS; modelNumber++ )
180     {
181       PushButton button = Toolkit::PushButton::New();
182       button.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
183       button.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
184       button.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
185       button.SetProperty( Actor::Property::PADDING, Padding( elementPadding, elementPadding, elementPadding, elementPadding ) );
186       button.SetProperty( Button::Property::UNSELECTED_BACKGROUND_VISUAL, BUTTON_IMAGE_URL[modelNumber] );
187       button.SetProperty( Button::Property::SELECTED_BACKGROUND_VISUAL,  BUTTON_IMAGE_URL[modelNumber] );
188       button.RegisterProperty( "modelNumber", Property::Value( modelNumber ) );
189       button.ClickedSignal().Connect( this, &PrimitiveShapesController::OnChangeShapeClicked );
190
191       buttonContainer.Add( button );
192     }
193   }
194
195   //Add sliders to the bottom of the screen, which allow for control of shape properties such as radius.
196   //Each slider is placed next to a label that states the property it affects.
197   //The sliders are laid out like so:
198   //
199   //           +--------------------------------+
200   //           |                                |
201   //           |                                |
202   //           |                                |
203   //           |                                |
204   //           |                                |
205   //           |                                |
206   //           |                                |
207   //           |                                |
208   //           |                                |
209   //           |                                |
210   //           |                                |
211   //           |                                |
212   //           |                                |
213   //           |                                |
214   //           |                                |
215   //           |                                |
216   //           |                                |
217   //           |                                |
218   //           |                                |
219   //      ^    | Label +----------O-----------+ |
220   //      |    |                                |
221   //      |    |                                |
222   //      |    | Label +--O-------------------+ |
223   //  30% |    |                                |
224   //      |    |                                |
225   //      |    | Label +----------------------O |
226   //      |    |                                |
227   //      v    +--------------------------------+
228   //
229   void SetupSliders( Layer layer )
230   {
231     //Create table to hold sliders and their corresponding labels.
232     mSliderTable = Toolkit::TableView::New( MAX_PROPERTIES, 2 );
233     mSliderTable.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
234     mSliderTable.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
235     mSliderTable.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
236     mSliderTable.SetProperty( Actor::Property::SIZE_MODE_FACTOR, Vector3( 0.9, 0.3, 0.0 ) );  //90% of width, 30% of height.
237     mSliderTable.SetFitWidth( 0 );  //Label column should fit to natural size of label.
238     mSliderTable.SetRelativeWidth( 1, 1.0f );  //Slider column should fill remaining space.
239     mSliderTable.SetCellPadding( Vector2( 10.0f, 0.0f ) ); //Leave a gap between the slider and its label.
240     layer.Add( mSliderTable );
241
242     //Set up sliders, and place labels next to them.
243     for( int i = 0; i < MAX_PROPERTIES; i++ )
244     {
245       //Create slider
246       Slider slider = Slider::New();
247       slider.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
248       slider.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
249       slider.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
250       slider.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
251       slider.ValueChangedSignal().Connect( this, &PrimitiveShapesController::OnSliderValueChanged );
252       mSliders.push_back( slider );
253
254       //Setup slider cell properties
255       mSliderTable.AddChild( slider, TableView::CellPosition( i, 1 ) );
256       mSliderTable.SetCellAlignment( TableView::CellPosition( i, 1 ), HorizontalAlignment::CENTER, VerticalAlignment::CENTER );
257
258       //Create slider label
259       TextLabel sliderLabel = TextLabel::New();
260       sliderLabel.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
261       sliderLabel.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
262       sliderLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
263       mSliderLabels.push_back( sliderLabel );
264
265       //Setup slider-label cell properties
266       mSliderTable.AddChild( sliderLabel, TableView::CellPosition( i, 0 ) );
267       mSliderTable.SetCellAlignment( TableView::CellPosition( i, 0 ), HorizontalAlignment::LEFT, VerticalAlignment::CENTER );
268     }
269   }
270
271   //Adds a control to the centre of the window to display the 3D shapes.
272   //The model is placed in the center of the screen, like so:
273   //
274   //           +--------------------------------+
275   //           |                                |
276   //           |                                |
277   //           |                                |
278   //           |                                |
279   //           |                                |
280   //           |                                |
281   //           |                                |
282   //           |                                |
283   //           |                                |
284   //       ^   |           ----------           |
285   //       |   |          /          \          |
286   //       |   |         /            \         |
287   //       |   |        |              |        |
288   //   30% |   |        |              |        |
289   //       |   |        |              |        |
290   //       |   |         \            /         |
291   //       |   |          \          /          |
292   //       v   |           ----------           |
293   //           |                                |
294   //           |                                |
295   //           |                                |
296   //           |                                |
297   //           |                                |
298   //           |                                |
299   //           |                                |
300   //           |                                |
301   //           |                                |
302   //           +--------------------------------+
303   //
304   void SetupModel( Layer layer )
305   {
306     //Create a container to house the visual-holding actor, to provide a constant hitbox.
307     Actor container = Actor::New();
308     container.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
309     container.SetProperty( Actor::Property::SIZE_MODE_FACTOR, Vector3( 0.9, 0.3, 0.0 ) );  //90% of width, 30% of height.
310     container.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
311     container.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
312     layer.Add( container );
313
314     //Create control to display the 3D primitive.
315     mModel = Control::New();
316     mModel.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
317     mModel.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
318     mModel.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
319     container.Add( mModel );
320
321     //Load default shape.
322     LoadCube();
323
324     //Make model spin to demonstrate 3D.
325     mRotationAnimation = Animation::New(15.0f);
326     mRotationAnimation.AnimateBy( Property( mModel, Actor::Property::ORIENTATION ),
327                                  Quaternion( Degree( 0.0f ), Degree( 360.0f ), Degree( 0.0f ) ) );
328     mRotationAnimation.SetLooping(true);
329     mRotationAnimation.Play();
330
331     //Attach gesture detector to pan models when rotated.
332     mPanGestureDetector = PanGestureDetector::New();
333     mPanGestureDetector.Attach( container );
334     mPanGestureDetector.DetectedSignal().Connect( this, &PrimitiveShapesController::OnPan );
335   }
336
337   //Clears all sliders and resets the primitive visual property map.
338   void InitialiseSlidersAndModel()
339   {
340     //Sliders
341     for( unsigned i = 0; i < mSliders.size(); i++ )
342     {
343       mSliders.at( i ).SetProperty( Slider::Property::MARKS, Property::Value( 0 ) ); //Remove marks
344       mSliders.at( i ).SetProperty( Actor::Property::VISIBLE, false );
345       mSliderLabels.at( i ).SetProperty( TextLabel::Property::TEXT, Property::Value( "Default" ) );
346       mSliderLabels.at( i ).SetProperty( Actor::Property::VISIBLE, false );
347     }
348
349     //Visual map for model
350     mVisualMap.Clear();
351     mVisualMap[ Toolkit::Visual::Property::TYPE           ] = Visual::PRIMITIVE;
352     mVisualMap[ PrimitiveVisual::Property::MIX_COLOR ] = mColor;
353     mVisualMap[ Visual::Property::TRANSFORM ] =
354         Property::Map().Add( Visual::Transform::Property::ORIGIN, Align::CENTER )
355                        .Add( Visual::Transform::Property::ANCHOR_POINT, Align::CENTER );
356   }
357
358   //Sets the 3D model to a sphere and modifies the sliders appropriately.
359   void LoadSphere()
360   {
361     InitialiseSlidersAndModel();
362
363     //Set up specific visual properties.
364     mVisualMap[ PrimitiveVisual::Property::SHAPE  ] = PrimitiveVisual::Shape::SPHERE;
365     mVisualMap[ PrimitiveVisual::Property::SLICES ] = DEFAULT_SLICES;
366     mVisualMap[ PrimitiveVisual::Property::STACKS ] = DEFAULT_STACKS;
367
368     //Set up sliders.
369     SetupSlider( 0, SLICES_LOWER_BOUND, SLICES_UPPER_BOUND, DEFAULT_STACKS, PrimitiveVisual::Property::SLICES, "slices" );
370     SetupMarks( 0, SLICES_LOWER_BOUND, SLICES_UPPER_BOUND );
371     mSliders.at( 0 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 0 ) );
372
373     SetupSlider( 1, STACKS_LOWER_BOUND, STACKS_UPPER_BOUND, DEFAULT_STACKS, PrimitiveVisual::Property::STACKS, "stacks" );
374     SetupMarks( 1, STACKS_LOWER_BOUND, STACKS_UPPER_BOUND );
375     mSliders.at( 1 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 0 ) );
376
377     //Set model in control.
378     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
379
380     //Update title.
381     mShapeTitle.SetProperty( TextLabel::Property::TEXT, SHAPE_TITLE_PREFIX + "Sphere" );
382   }
383
384   //Sets the 3D model to a cone and modifies the sliders appropriately.
385   void LoadCone()
386   {
387     InitialiseSlidersAndModel();
388
389     //Set up specific visual properties.
390     mVisualMap[ PrimitiveVisual::Property::SHAPE               ] = PrimitiveVisual::Shape::CONE;
391     mVisualMap[ PrimitiveVisual::Property::SCALE_HEIGHT        ] = DEFAULT_SCALE_HEIGHT;
392     mVisualMap[ PrimitiveVisual::Property::SCALE_BOTTOM_RADIUS ] = DEFAULT_SCALE_BOTTOM_RADIUS;
393     mVisualMap[ PrimitiveVisual::Property::SLICES              ] = DEFAULT_SLICES;
394
395     //Set up sliders.
396     SetupSlider( 0, 1.0f, 32.0f, DEFAULT_SCALE_HEIGHT, PrimitiveVisual::Property::SCALE_HEIGHT, "scaleHeight" );
397     mSliders.at( 0 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 1 ) );
398
399     SetupSlider( 1, 1.0f, 32.0f, DEFAULT_SCALE_BOTTOM_RADIUS, PrimitiveVisual::Property::SCALE_BOTTOM_RADIUS, "scaleBottomRadius" );
400     mSliders.at( 1 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 1 ) );
401
402     SetupSlider( 2, SLICES_LOWER_BOUND, SLICES_UPPER_BOUND, DEFAULT_STACKS, PrimitiveVisual::Property::SLICES, "slices" );
403     SetupMarks( 2, SLICES_LOWER_BOUND, SLICES_UPPER_BOUND );
404     mSliders.at( 2 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 0 ) );
405
406     //Set model in control.
407     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
408
409     //Update title.
410     mShapeTitle.SetProperty( TextLabel::Property::TEXT, SHAPE_TITLE_PREFIX + "Cone" );
411   }
412
413   //Sets the 3D model to a conical frustum and modifies the sliders appropriately.
414   void LoadConicalFrustum()
415   {
416     InitialiseSlidersAndModel();
417
418     //Set up specific visual properties.
419     mVisualMap[ PrimitiveVisual::Property::SHAPE               ] = PrimitiveVisual::Shape::CONICAL_FRUSTUM;
420     mVisualMap[ PrimitiveVisual::Property::SCALE_TOP_RADIUS    ] = DEFAULT_SCALE_TOP_RADIUS;
421     mVisualMap[ PrimitiveVisual::Property::SCALE_BOTTOM_RADIUS ] = DEFAULT_SCALE_BOTTOM_RADIUS;
422     mVisualMap[ PrimitiveVisual::Property::SCALE_HEIGHT        ] = DEFAULT_SCALE_HEIGHT;
423     mVisualMap[ PrimitiveVisual::Property::SLICES              ] = DEFAULT_SLICES;
424
425     //Set up used sliders.
426     SetupSlider( 0, 1.0f, 32.0f, DEFAULT_SCALE_HEIGHT, PrimitiveVisual::Property::SCALE_HEIGHT, "scaleHeight" );
427     mSliders.at( 0 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 1 ) );
428
429     SetupSlider( 1, 0.0f, 32.0f, DEFAULT_SCALE_BOTTOM_RADIUS, PrimitiveVisual::Property::SCALE_BOTTOM_RADIUS, "scaleBottomRadius" );
430     mSliders.at( 1 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 1 ) );
431
432     SetupSlider( 2, 0.0f, 32.0f, DEFAULT_SCALE_TOP_RADIUS, PrimitiveVisual::Property::SCALE_TOP_RADIUS, "scaleTopRadius" );
433     mSliders.at( 2 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 1 ) );
434
435     //Set model in control.
436     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
437
438     //Update title.
439     mShapeTitle.SetProperty( TextLabel::Property::TEXT, SHAPE_TITLE_PREFIX + "Conical Frustum" );
440   }
441
442   //Sets the 3D model to a cylinder and modifies the sliders appropriately.
443   void LoadCylinder()
444   {
445     InitialiseSlidersAndModel();
446
447     //Set up specific visual properties.
448     mVisualMap[ PrimitiveVisual::Property::SHAPE        ] = PrimitiveVisual::Shape::CYLINDER;
449     mVisualMap[ PrimitiveVisual::Property::SCALE_HEIGHT ] = DEFAULT_SCALE_HEIGHT;
450     mVisualMap[ PrimitiveVisual::Property::SCALE_RADIUS ] = DEFAULT_SCALE_RADIUS;
451     mVisualMap[ PrimitiveVisual::Property::SLICES       ] = DEFAULT_SLICES;
452
453     //Set up used sliders.
454     SetupSlider( 0, 1.0f, 32.0f, DEFAULT_SCALE_HEIGHT, PrimitiveVisual::Property::SCALE_HEIGHT, "scaleHeight" );
455     mSliders.at( 0 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 1 ) );
456
457     SetupSlider( 1, 1.0f, 32.0f, DEFAULT_SCALE_RADIUS, PrimitiveVisual::Property::SCALE_RADIUS, "scaleRadius" );
458     mSliders.at( 1 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 1 ) );
459
460     SetupSlider( 2, SLICES_LOWER_BOUND, SLICES_UPPER_BOUND, DEFAULT_STACKS, PrimitiveVisual::Property::SLICES, "slices" );
461     SetupMarks( 2 , SLICES_LOWER_BOUND, SLICES_UPPER_BOUND );
462     mSliders.at( 2 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 0 ) );
463
464     //Set model in control.
465     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
466
467     //Update title.
468     mShapeTitle.SetProperty( TextLabel::Property::TEXT, SHAPE_TITLE_PREFIX + "Cylinder" );
469   }
470
471   //Sets the 3D model to a cube and modifies the sliders appropriately.
472   void LoadCube()
473   {
474     InitialiseSlidersAndModel();
475
476     //Set up specific visual properties.
477     mVisualMap[ PrimitiveVisual::Property::SHAPE ] = PrimitiveVisual::Shape::CUBE;
478
479     //Set model in control.
480     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
481
482     //Update title.
483     mShapeTitle.SetProperty( TextLabel::Property::TEXT, SHAPE_TITLE_PREFIX + "Cube" );
484   }
485
486   //Sets the 3D model to a bevelled cube and modifies the sliders appropriately.
487   void LoadBevelledCube()
488   {
489     InitialiseSlidersAndModel();
490
491     //Set up specific visual properties.
492     mVisualMap[ PrimitiveVisual::Property::SHAPE            ] = PrimitiveVisual::Shape::BEVELLED_CUBE;
493     mVisualMap[ PrimitiveVisual::Property::BEVEL_PERCENTAGE ] = DEFAULT_BEVEL_PERCENTAGE;
494     mVisualMap[ PrimitiveVisual::Property::BEVEL_SMOOTHNESS ] = DEFAULT_BEVEL_SMOOTHNESS;
495
496     //Set up used sliders.
497     SetupSlider( 0, 0.0f, 1.0f, DEFAULT_BEVEL_PERCENTAGE, PrimitiveVisual::Property::BEVEL_PERCENTAGE, "bevelPercentage" );
498     mSliders.at( 0 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 2 ) );
499
500     SetupSlider( 1, 0.0f, 1.0f, DEFAULT_BEVEL_SMOOTHNESS, PrimitiveVisual::Property::BEVEL_SMOOTHNESS, "bevelSmoothness" );
501     mSliders.at( 1 ).SetProperty( Slider::Property::VALUE_PRECISION, Property::Value( 2 ) );
502
503     //Set model in control.
504     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
505
506     //Update title.
507     mShapeTitle.SetProperty( TextLabel::Property::TEXT, SHAPE_TITLE_PREFIX + "Bevelled Cube" );
508   }
509
510   //Sets the 3D model to an octahedron and modifies the sliders appropriately.
511   void LoadOctahedron()
512   {
513     InitialiseSlidersAndModel();
514
515     //Set up specific visual properties.
516     mVisualMap[ PrimitiveVisual::Property::SHAPE ] = PrimitiveVisual::Shape::OCTAHEDRON;
517
518     //Set model in control.
519     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
520
521     //Update title.
522     mShapeTitle.SetProperty( TextLabel::Property::TEXT, SHAPE_TITLE_PREFIX + "Octahedron" );
523   }
524
525   //Sets up the slider at the given index for the supplied property, and labels it appropriately.
526   // visualProperty is the property that will be set by this slider.
527   void SetupSlider( int sliderIndex, float lowerBound, float upperBound, float startPoint,
528                     Property::Index visualProperty, std::string visualPropertyLabel )
529   {
530     //Set up the slider itself.
531     mSliders.at( sliderIndex ).RegisterProperty( "visualProperty", Property::Value( visualProperty ), Property::READ_WRITE );
532     mSliders.at( sliderIndex ).SetProperty( Slider::Property::LOWER_BOUND, Property::Value( lowerBound ) );
533     mSliders.at( sliderIndex ).SetProperty( Slider::Property::UPPER_BOUND, Property::Value( upperBound ) );
534     mSliders.at( sliderIndex ).SetProperty( Slider::Property::VALUE, Property::Value( startPoint ) );
535     mSliders.at( sliderIndex ).SetProperty( Actor::Property::VISIBLE, true );
536
537     //Label the slider with the property.
538     //We reset the TextLabel to force a relayout of the table.
539     mSliderTable.RemoveChildAt( TableView::CellPosition(sliderIndex, 0) );
540
541     TextLabel sliderLabel = TextLabel::New( visualPropertyLabel );
542     sliderLabel.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
543     sliderLabel.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
544     sliderLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
545
546     mSliderTable.AddChild( sliderLabel, TableView::CellPosition( sliderIndex, 0 ) );
547     mSliderTable.SetCellAlignment( TableView::CellPosition( sliderIndex, 0 ), HorizontalAlignment::LEFT, VerticalAlignment::CENTER );
548
549     mSliderLabels.at( sliderIndex ).SetProperty( Actor::Property::VISIBLE, true );
550     mSliderLabels.at( sliderIndex) = sliderLabel;
551   }
552
553   //Setup snapping to integer values between the two given values.
554   void SetupMarks( int sliderIndex, int lower, int upper )
555   {
556     Property::Array marks;
557
558     for( int mark = lower; mark <= upper; mark++ )
559     {
560       marks.PushBack( Property::Value( mark ) );
561     }
562
563     mSliders.at( sliderIndex ).SetProperty( Slider::Property::MARKS, Property::Value( marks ) );
564     mSliders.at( sliderIndex ).SetProperty( Slider::Property::SNAP_TO_MARKS, Property::Value( true ) );
565   }
566
567   //When a shape button is tapped, switch to the corresponding shape.
568   bool OnChangeShapeClicked( Button button )
569   {
570     //Get the model number from the button.
571     int modelNumber;
572     button.GetProperty( button.GetPropertyIndex( "modelNumber" ) ).Get( modelNumber );
573
574     //Switch to the shape that corresponds to the model number.
575     switch( modelNumber )
576     {
577       case 0:
578       {
579         LoadSphere();
580         break;
581       }
582       case 1:
583       {
584         LoadCone();
585         break;
586       }
587       case 2:
588       {
589         LoadConicalFrustum();
590         break;
591       }
592       case 3:
593       {
594         LoadCylinder();
595         break;
596       }
597       case 4:
598       {
599         LoadCube();
600         break;
601       }
602       case 5:
603       {
604         LoadBevelledCube();
605         break;
606       }
607       case 6:
608       {
609         LoadOctahedron();
610         break;
611       }
612     }
613
614     return true;
615   }
616
617   //When the slider is adjusted, change the corresponding shape property accordingly.
618   bool OnSliderValueChanged( Slider slider, float value )
619   {
620     //Update property map to reflect the change to the specific visual property.
621     int visualProperty;
622     slider.GetProperty( slider.GetPropertyIndex( "visualProperty" ) ).Get( visualProperty );
623     mVisualMap[ visualProperty ] = value;
624
625     //Reload the model to display the change.
626     mModel.SetProperty( Control::Property::BACKGROUND, Property::Value( mVisualMap ) );
627
628     return true;
629   }
630
631   //Panning around the shape rotates it.
632   void OnPan( Actor actor, const PanGesture& gesture )
633   {
634     switch( gesture.GetState() )
635     {
636       case Gesture::Started:
637       {
638         //Pause animation, as the gesture will be used to manually rotate the model
639         mRotationAnimation.Pause();
640
641         break;
642       }
643       case Gesture::Continuing:
644       {
645         //Rotate based off the gesture.
646         const Vector2& displacement = gesture.GetDisplacement();
647         mRotation.x -= displacement.y / X_ROTATION_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis
648         mRotation.y += displacement.x / Y_ROTATION_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis
649         Quaternion rotation = Quaternion( Radian( mRotation.x ), Vector3::XAXIS) *
650                               Quaternion( Radian( mRotation.y ), Vector3::YAXIS);
651
652         mModel.SetProperty( Actor::Property::ORIENTATION, rotation );
653
654         break;
655       }
656       case Gesture::Finished:
657       {
658         //Return to automatic animation
659         mRotationAnimation.Play();
660
661         break;
662       }
663       case Gesture::Cancelled:
664       {
665         //Return to automatic animation
666         mRotationAnimation.Play();
667
668         break;
669       }
670       default:
671       {
672         break;
673       }
674     }
675   }
676
677   //If escape or the back button is pressed, quit the application (and return to the launcher)
678   void OnKeyEvent( const KeyEvent& event )
679   {
680     if( event.GetState() == KeyEvent::DOWN )
681     {
682       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
683       {
684         mApplication.Quit();
685       }
686     }
687   }
688
689 private:
690   Application& mApplication;
691
692   std::vector<Slider>       mSliders;               ///< Holds the sliders on screen that each shape accesses.
693   std::vector<TextLabel>    mSliderLabels;          ///< Holds the labels to each slider.
694   TableView                 mSliderTable;           ///< A table to layout the sliders next to their labels.
695
696   Property::Map             mVisualMap;             ///< Property map to create a primitive visual.
697   Control                   mModel;                 ///< Control to house the primitive visual.
698   TextLabel                 mShapeTitle;            ///< Indicates what the currently selected shape is.
699
700   PanGestureDetector        mPanGestureDetector;    ///< Detects pan gestures for rotation of the model.
701   Animation                 mRotationAnimation;     ///< Automatically rotates the model, unless it is being panned.
702
703   Vector4                   mColor;                 ///< Color to set all shapes.
704   Vector2                   mRotation;              ///< Keeps track of model rotation.
705 };
706
707 int DALI_EXPORT_API main( int argc, char **argv )
708 {
709   Application application = Application::New( &argc, &argv );
710   PrimitiveShapesController test( application );
711   application.MainLoop();
712   return 0;
713 }