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