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