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