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