Merge "DALi Version 1.2.42" into devel/master
[platform/core/uifw/dali-demo.git] / examples / mesh-visual / mesh-visual-example.cpp
1 #include <dali-toolkit/dali-toolkit.h>
2 #include <dali/public-api/object/property-map.h>
3
4 using namespace Dali;
5 using namespace Dali::Toolkit;
6
7 namespace
8 {
9 // Keeps information about each model for access.
10 struct Model
11 {
12   Control control; // Control housing the mesh visual of the model.
13   Vector2 rotation; // Keeps track of rotation about x and y axis for manual rotation.
14   Animation rotationAnimation; // Automatically rotates when left alone.
15 };
16
17 // Files for meshes
18 const char * const MODEL_FILE_TABLE[] =
19 {
20     DEMO_MODEL_DIR "Dino.obj",
21     DEMO_MODEL_DIR "ToyRobot-Metal.obj",
22     DEMO_MODEL_DIR "Toyrobot-Plastic.obj"
23 };
24
25 const char * const MATERIAL_FILE_TABLE[] =
26 {
27     DEMO_MODEL_DIR "Dino.mtl",
28     DEMO_MODEL_DIR "ToyRobot-Metal.mtl",
29     DEMO_MODEL_DIR "Toyrobot-Plastic.mtl"
30 };
31
32 const char * const TEXTURES_PATH( DEMO_IMAGE_DIR "" );
33
34 // Possible shading modes.
35 MeshVisual::ShadingMode::Value SHADING_MODE_TABLE[] =
36 {
37   MeshVisual::ShadingMode::TEXTURED_WITH_DETAILED_SPECULAR_LIGHTING,
38   MeshVisual::ShadingMode::TEXTURED_WITH_SPECULAR_LIGHTING,
39   MeshVisual::ShadingMode::TEXTURELESS_WITH_DIFFUSE_LIGHTING
40 };
41
42 // Button labels.
43 const char * const PAUSE =  "  ||  ";
44 const char * const PLAY =   "  >  ";
45 const char * const FIXED =  "FIXED";
46 const char * const MANUAL = "MANUAL";
47 const char * const FRONT =  "FRONT";
48 const char * const BACK =   "BACK";
49
50 // Image urls for the light.
51 const char * const LIGHT_URL_FRONT = DEMO_IMAGE_DIR "light-icon-front.png";
52 const char * const LIGHT_URL_BACK =  DEMO_IMAGE_DIR "light-icon-back.png";
53
54 const float X_ROTATION_DISPLACEMENT_FACTOR = 60.0f;
55 const float Y_ROTATION_DISPLACEMENT_FACTOR = 60.0f;
56 const float MODEL_SCALE =                    0.75f;
57 const float LIGHT_SCALE =                    0.15f;
58 const float BUTTONS_OFFSET_BOTTOM =          0.08f;
59 const float BUTTONS_OFFSET_SIDE =            0.2f;
60 const int   NUM_MESHES =                     2;
61
62 // Used to identify actors.
63 const int MODEL_TAG = 0;
64 const int LIGHT_TAG = 1;
65 const int LAYER_TAG = 2;
66
67 const Vector4 STAGE_COLOR( 211.0f / 255.0f, 211.0f / 255.0f, 211.0f / 255.0f, 1.0f ); ///< The color of the stage
68
69 } // unnamed namespace
70
71 class MeshVisualController : public ConnectionTracker
72 {
73 public:
74
75   MeshVisualController( Application& application )
76   : mApplication( application ),   //Store handle to the application.
77     mModelIndex( 1 ),              //Start with metal robot.
78     mShadingModeIndex( 0 ),        //Start with texture and detailed specular lighting.
79     mTag( -1 ),                    //Non-valid default, which will get set to a correct value when used.
80     mSelectedModelIndex( -1 ),     //Non-valid default, which will get set to a correct value when used.
81     mPaused( false ),              //Animations play by default.
82     mLightFixed( true ),           //The light is fixed by default.
83     mLightFront( true )            //The light is in front by default.
84   {
85     // Connect to the Application's Init signal
86     mApplication.InitSignal().Connect( this, &MeshVisualController::Create );
87   }
88
89   ~MeshVisualController()
90   {
91   }
92
93   // The Init signal is received once (only) during the Application lifetime
94   void Create( Application& application )
95   {
96     // Get a handle to the stage
97     Stage stage = Stage::GetCurrent();
98     stage.SetBackgroundColor( STAGE_COLOR );
99
100     //Set up root layer to receive touch gestures.
101     Layer rootLayer = stage.GetRootLayer();
102     rootLayer.RegisterProperty( "Tag", LAYER_TAG ); //Used to differentiate between different kinds of actor.
103     rootLayer.TouchSignal().Connect( this, &MeshVisualController::OnTouch );
104
105     //Place models on the scene.
106     SetupModels( rootLayer );
107
108     //Place buttons on the scene.
109     SetupButtons( rootLayer );
110
111     //Add a light to the scene.
112     SetupLight( rootLayer );
113
114     //Allow for exiting of the application via key presses.
115     stage.KeyEventSignal().Connect( this, &MeshVisualController::OnKeyEvent );
116   }
117
118   //Loads and adds the models to the scene, inside containers for hit detection.
119   void SetupModels( Layer layer )
120   {
121     //Add containers to house each renderer-holding-actor.
122     for( int i = 0; i < NUM_MESHES; i++ )
123     {
124       mContainers[i] = Actor::New();
125       mContainers[i].SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
126       mContainers[i].RegisterProperty( "Tag", MODEL_TAG ); //Used to differentiate between different kinds of actor.
127       mContainers[i].RegisterProperty( "Model", Property::Value( i ) ); //Used to index into the model.
128       mContainers[i].TouchSignal().Connect( this, &MeshVisualController::OnTouch );
129       layer.Add( mContainers[i] );
130     }
131
132     //Position each container individually on screen
133
134     //Main, central model
135     mContainers[0].SetSizeModeFactor( Vector3( MODEL_SCALE, MODEL_SCALE, 0.0f ) );
136     mContainers[0].SetParentOrigin( ParentOrigin::CENTER );
137     mContainers[0].SetAnchorPoint( AnchorPoint::CENTER );
138
139     //Top left model
140     mContainers[1].SetSizeModeFactor( Vector3( MODEL_SCALE / 3.0f, MODEL_SCALE / 3.0f, 0.0f ) );
141     mContainers[1].SetParentOrigin( Vector3( 0.05, 0.03, 0.5 ) ); //Offset from top left
142     mContainers[1].SetAnchorPoint( AnchorPoint::TOP_LEFT );
143
144     //Set up models
145     for( int i = 0; i < NUM_MESHES; i++ )
146     {
147       //Create control to display model
148       Control control = Control::New();
149       control.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
150       control.SetParentOrigin( ParentOrigin::CENTER );
151       control.SetAnchorPoint( AnchorPoint::CENTER );
152       mContainers[i].Add( control );
153
154       //Make model spin to demonstrate 3D
155       Animation rotationAnimation = Animation::New( 15.0f );
156       float spin = i % 2 == 0 ? 1.0f : -1.0f; //Make actors spin in different directions to better show independence.
157       rotationAnimation.AnimateBy( Property( control, Actor::Property::ORIENTATION ),
158                                    Quaternion( Degree( 0.0f ), Degree( spin * 360.0f ), Degree( 0.0f ) ) );
159       rotationAnimation.SetLooping( true );
160       rotationAnimation.Play();
161
162       //Store model information in corresponding structs.
163       mModels[i].control = control;
164       mModels[i].rotation.x = 0.0f;
165       mModels[i].rotation.y = 0.0f;
166       mModels[i].rotationAnimation = rotationAnimation;
167     }
168
169     //Calling this sets the model in the controls.
170     ReloadModel();
171   }
172
173   //Place the various buttons on the bottom of the screen, with title labels where necessary.
174   void SetupButtons( Layer layer )
175   {
176     //Actor for positioning model and shading mode buttons.
177     Actor positionActorModel = Actor::New();
178     positionActorModel.SetParentOrigin( Vector3( BUTTONS_OFFSET_SIDE, 1.0 - BUTTONS_OFFSET_BOTTOM, 0.5 ) );
179     positionActorModel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
180     layer.Add( positionActorModel );
181
182     //Create button for model changing.
183     PushButton modelButton = Toolkit::PushButton::New();
184     modelButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
185     modelButton.ClickedSignal().Connect( this, &MeshVisualController::OnChangeModelClicked );
186     modelButton.SetParentOrigin( ParentOrigin::TOP_CENTER );
187     modelButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
188     modelButton.SetProperty( Toolkit::Button::Property::LABEL, "Model" );
189     positionActorModel.Add( modelButton );
190
191     //Create button for shading mode changing.
192     PushButton shadingModeButton = Toolkit::PushButton::New();
193     shadingModeButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
194     shadingModeButton.ClickedSignal().Connect( this, &MeshVisualController::OnChangeShadingModeClicked );
195     shadingModeButton.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
196     shadingModeButton.SetAnchorPoint( AnchorPoint::TOP_CENTER );
197     shadingModeButton.SetProperty( Toolkit::Button::Property::LABEL, "Shading Mode" );
198     positionActorModel.Add( shadingModeButton );
199
200     //Text label title for changing model or shading mode.
201     TextLabel changeTitleLabel = TextLabel::New( "Change" );
202     changeTitleLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
203     changeTitleLabel.SetProperty( TextLabel::Property::UNDERLINE, "{\"thickness\":\"2.0\"}" );
204     changeTitleLabel.SetParentOrigin( ParentOrigin::TOP_CENTER );
205     changeTitleLabel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
206     modelButton.Add( changeTitleLabel );
207
208     //Create button for pausing animations.
209     PushButton pauseButton = Toolkit::PushButton::New();
210     pauseButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
211     pauseButton.ClickedSignal().Connect( this, &MeshVisualController::OnPauseClicked );
212     pauseButton.SetParentOrigin( Vector3( 0.5, 1.0 - BUTTONS_OFFSET_BOTTOM, 0.5 ) );
213     pauseButton.SetAnchorPoint( AnchorPoint::CENTER );
214     pauseButton.SetProperty( Toolkit::Button::Property::LABEL, PAUSE );
215     layer.Add( pauseButton );
216
217     //Actor for positioning light position buttons.
218     Actor positionActorLight = Actor::New();
219     positionActorLight.SetParentOrigin( Vector3( 1.0 - BUTTONS_OFFSET_SIDE, 1.0 - BUTTONS_OFFSET_BOTTOM, 0.5 ) );
220     positionActorLight.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
221     layer.Add( positionActorLight );
222
223     //Create button for switching between manual and fixed light position.
224     PushButton lightModeButton = Toolkit::PushButton::New();
225     lightModeButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
226     lightModeButton.ClickedSignal().Connect( this, &MeshVisualController::OnChangeLightModeClicked );
227     lightModeButton.SetParentOrigin( ParentOrigin::TOP_CENTER );
228     lightModeButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
229     lightModeButton.SetProperty( Toolkit::Button::Property::LABEL, FIXED );
230     positionActorLight.Add( lightModeButton );
231
232     //Create button for switching between front and back light position.
233     PushButton lightSideButton = Toolkit::PushButton::New();
234     lightSideButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
235     lightSideButton.ClickedSignal().Connect( this, &MeshVisualController::OnChangeLightSideClicked );
236     lightSideButton.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
237     lightSideButton.SetAnchorPoint( AnchorPoint::TOP_CENTER );
238     lightSideButton.SetProperty( Toolkit::Button::Property::LABEL, FRONT );
239     positionActorLight.Add( lightSideButton );
240
241     //Text label title for light position mode.
242     TextLabel lightTitleLabel = TextLabel::New( "Light Position" );
243     lightTitleLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
244     lightTitleLabel.SetProperty( TextLabel::Property::UNDERLINE, "{\"thickness\":\"2.0\"}" );
245     lightTitleLabel.SetParentOrigin( ParentOrigin::TOP_CENTER );
246     lightTitleLabel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
247     lightModeButton.Add( lightTitleLabel );
248   }
249
250   //Add a point light source the the scene, on a layer above the first.
251   void SetupLight( Layer baseLayer )
252   {
253     //Create control to act as light source of scene.
254     mLightSource = Control::New();
255     mLightSource.RegisterProperty( "Tag", LIGHT_TAG );
256
257     //Set size of control based on screen dimensions.
258     Stage stage = Stage::GetCurrent();
259     if( stage.GetSize().width < stage.GetSize().height )
260     {
261       //Scale to width.
262       mLightSource.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
263       mLightSource.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
264       mLightSource.SetSizeModeFactor( Vector3( LIGHT_SCALE, 0.0f, 0.0f ) );
265     }
266     else
267     {
268       //Scale to height.
269       mLightSource.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::HEIGHT );
270       mLightSource.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
271       mLightSource.SetSizeModeFactor( Vector3( 0.0f, LIGHT_SCALE, 0.0f ) );
272     }
273
274     //Set position relative to top left, as the light source property is also relative to the top left.
275     mLightSource.SetParentOrigin( ParentOrigin::TOP_LEFT );
276     mLightSource.SetAnchorPoint( AnchorPoint::CENTER );
277     mLightSource.SetPosition( Stage::GetCurrent().GetSize().x * 0.85f, Stage::GetCurrent().GetSize().y * 0.125 );
278
279     //Supply an image to represent the light.
280     SetLightImage();
281
282     //Connect to touch signal for dragging.
283     mLightSource.TouchSignal().Connect( this, &MeshVisualController::OnTouch );
284
285     //Place the light source on a layer above the base, so that it is rendered above everything else.
286     Layer upperLayer = Layer::New();
287     upperLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
288     upperLayer.SetParentOrigin( ParentOrigin::CENTER );
289     upperLayer.SetAnchorPoint( AnchorPoint::CENTER );
290
291     baseLayer.Add( upperLayer );
292     upperLayer.Add( mLightSource );
293
294     //Decide which light to use to begin with.
295     SetLightMode();
296   }
297
298   //Sets the image to use for the light source depending on whether the light is in front or behind.
299   void SetLightImage()
300   {
301     std::string imageUrl;
302
303     if( mLightFront )
304     {
305       imageUrl = LIGHT_URL_FRONT;
306     }
307     else
308     {
309       imageUrl = LIGHT_URL_BACK;
310     }
311
312     Property::Map lightMap;
313     lightMap.Insert( Visual::Property::TYPE, Visual::IMAGE );
314     lightMap.Insert( ImageVisual::Property::URL, imageUrl );
315     mLightSource.SetProperty( Control::Property::BACKGROUND, Property::Value( lightMap ) );
316   }
317
318   //Updates the displayed models to account for parameter changes.
319   void ReloadModel()
320   {
321     //Create mesh property map
322     Property::Map map;
323     map.Insert( Visual::Property::TYPE,  Visual::MESH );
324     map.Insert( MeshVisual::Property::OBJECT_URL, MODEL_FILE_TABLE[mModelIndex] );
325     map.Insert( MeshVisual::Property::MATERIAL_URL, MATERIAL_FILE_TABLE[mModelIndex] );
326     map.Insert( MeshVisual::Property::TEXTURES_PATH, TEXTURES_PATH );
327     map.Insert( MeshVisual::Property::SHADING_MODE, SHADING_MODE_TABLE[mShadingModeIndex] );
328
329     //Set the two controls to use the mesh
330     for( int i = 0; i < NUM_MESHES; i++ )
331     {
332       mModels[i].control.SetProperty( Control::Property::BACKGROUND, Property::Value( map ) );
333     }
334   }
335
336   //Set the mode used to light the models.
337   void SetLightMode()
338   {
339     if( mLightFixed )
340     {
341       UseFixedLight();
342     }
343     else
344     {
345       UseManualLight();
346     }
347   }
348
349   //Make the models use a fixed, invisible light above the center of the stage.
350   void UseFixedLight()
351   {
352     //Hide draggable source
353     mLightSource.SetVisible( false );
354
355     //Use stage dimensions to place light at center, offset in z axis.
356     Stage stage = Stage::GetCurrent();
357     float width = stage.GetSize().width;
358     float height = stage.GetSize().height;
359     Vector3 lightPosition = Vector3( width / 2.0f, height / 2.0f,
360                                      ( mLightFront ? 1 : -1 ) * std::max( width, height ) * 5.0f );
361
362     //Set global light position
363     for( int i = 0; i < NUM_MESHES; ++i )
364     {
365       mModels[i].control.RegisterProperty( "lightPosition", lightPosition, Property::ANIMATABLE );
366     }
367   }
368
369   //Make the models use a light source that the user can drag around.
370   void UseManualLight()
371   {
372     //Show draggable source
373     mLightSource.SetVisible( true );
374
375     //Update to switch light position of models to that of the source.
376     UpdateLight();
377   }
378
379   //Updates the light position for each model to account for changes in the source on screen.
380   void UpdateLight()
381   {
382     //Set light position to the x and y of the light control, offset into/out of the screen.
383     Vector3 controlPosition = mLightSource.GetCurrentPosition();
384     Vector3 lightPosition = Vector3( controlPosition.x, controlPosition.y,
385                                      ( mLightFront ? 1 : -1 ) * Stage::GetCurrent().GetSize().x / 2.0f );
386
387     for( int i = 0; i < NUM_MESHES; ++i )
388     {
389       mModels[i].control.RegisterProperty( "lightPosition", lightPosition, Property::ANIMATABLE );
390     }
391   }
392
393   //If the light source is touched, move it by dragging it.
394   //If a model is touched, rotate it by panning around.
395   bool OnTouch( Actor actor, const TouchData& touch )
396   {
397     switch( touch.GetState( 0 ) )
398     {
399       case PointState::DOWN:
400       {
401         //Determine what was touched.
402         actor.GetProperty( actor.GetPropertyIndex( "Tag" ) ).Get( mTag );
403
404         if( mTag == MODEL_TAG )
405         {
406           //Find out which model has been selected
407           actor.GetProperty( actor.GetPropertyIndex( "Model" ) ).Get( mSelectedModelIndex );
408
409           //Pause current animation, as the touch gesture will be used to manually rotate the model
410           mModels[mSelectedModelIndex].rotationAnimation.Pause();
411
412           //Store start points.
413           mPanStart = touch.GetScreenPosition( 0 );
414           mRotationStart = mModels[mSelectedModelIndex].rotation;
415         }
416
417         break;
418       }
419       case PointState::MOTION:
420       {
421         //Switch on the kind of actor we're interacting with.
422         switch( mTag )
423         {
424           case MODEL_TAG: //Rotate model
425           {
426             //Calculate displacement and corresponding rotation.
427             Vector2 displacement = touch.GetScreenPosition( 0 ) - mPanStart;
428             mModels[mSelectedModelIndex].rotation = Vector2( mRotationStart.x - displacement.y / Y_ROTATION_DISPLACEMENT_FACTOR,   // Y displacement rotates around X axis
429                                                              mRotationStart.y + displacement.x / X_ROTATION_DISPLACEMENT_FACTOR ); // X displacement rotates around Y axis
430             Quaternion rotation = Quaternion( Radian( mModels[mSelectedModelIndex].rotation.x ), Vector3::XAXIS) *
431                                   Quaternion( Radian( mModels[mSelectedModelIndex].rotation.y ), Vector3::YAXIS);
432
433             //Apply rotation.
434             mModels[mSelectedModelIndex].control.SetOrientation( rotation );
435
436             break;
437           }
438           case LIGHT_TAG: //Drag light
439           {
440             //Set light source to new position and update the models accordingly.
441             mLightSource.SetPosition( Vector3( touch.GetScreenPosition( 0 ) ) );
442             UpdateLight();
443
444             break;
445           }
446         }
447
448         break;
449       }
450       case PointState::INTERRUPTED: //Same as finished.
451       case PointState::FINISHED:
452       {
453         if( mTag == MODEL_TAG )
454         {
455           //Return to automatic animation
456           if( !mPaused )
457           {
458             mModels[mSelectedModelIndex].rotationAnimation.Play();
459           }
460         }
461
462         break;
463       }
464       default:
465       {
466         //Other touch states do nothing.
467         break;
468       }
469     }
470
471     return true;
472   }
473
474   //Cycle through the list of models.
475   bool OnChangeModelClicked( Toolkit::Button button )
476   {
477     ++mModelIndex %= 3;
478
479     ReloadModel();
480
481     return true;
482   }
483
484   //Cycle through the list of shading modes.
485   bool OnChangeShadingModeClicked( Toolkit::Button button )
486   {
487     ++mShadingModeIndex %= 3;
488
489     ReloadModel();
490
491     return true;
492   }
493
494   //Pause all animations, and keep them paused even after user panning.
495   //This button is a toggle, so pressing again will start the animations again.
496   bool OnPauseClicked( Toolkit::Button button )
497   {
498     //Toggle pause state.
499     mPaused = !mPaused;
500
501     //If we wish to pause animations, do so and keep them paused.
502     if( mPaused )
503     {
504       for( int i = 0; i < NUM_MESHES ; ++i )
505       {
506         mModels[i].rotationAnimation.Pause();
507       }
508
509       button.SetProperty( Toolkit::Button::Property::LABEL, PLAY );
510     }
511     else //Unpause all animations again.
512     {
513       for( int i = 0; i < NUM_MESHES ; ++i )
514       {
515         mModels[i].rotationAnimation.Play();
516       }
517
518       button.SetProperty( Toolkit::Button::Property::LABEL, PAUSE );
519     }
520
521     return true;
522   }
523
524
525   //Switch between a fixed light source above/behind the screen, and a light source the user can drag around.
526   bool OnChangeLightModeClicked( Toolkit::Button button )
527   {
528     //Toggle state.
529     mLightFixed = !mLightFixed;
530
531     if( mLightFixed )
532     {
533       button.SetProperty( Toolkit::Button::Property::LABEL, FIXED );
534     }
535     else
536     {
537       button.SetProperty( Toolkit::Button::Property::LABEL, MANUAL );
538     }
539
540     SetLightMode();
541
542     return true;
543   }
544
545   //Switch between the light being in front of and behind the models.
546   bool OnChangeLightSideClicked( Toolkit::Button button )
547   {
548     //Toggle state.
549     mLightFront = !mLightFront;
550
551     if( mLightFront )
552     {
553       button.SetProperty( Toolkit::Button::Property::LABEL, FRONT );
554     }
555     else
556     {
557       button.SetProperty( Toolkit::Button::Property::LABEL, BACK );
558     }
559
560     //Change light image.
561     SetLightImage();
562
563     //Update light to account for the change.
564     SetLightMode();
565
566     return true;
567   }
568
569   //If escape or the back button is pressed, quit the application (and return to the launcher)
570   void OnKeyEvent( const KeyEvent& event )
571   {
572     if( event.state == KeyEvent::Down )
573     {
574       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
575       {
576         mApplication.Quit();
577       }
578     }
579   }
580
581 private:
582   Application&  mApplication;
583
584   //The models displayed on screen, including information about rotation.
585   Model mModels[NUM_MESHES];
586   Actor mContainers[NUM_MESHES];
587
588   //Acts as a global light source, which can be dragged around.
589   Control mLightSource;
590
591   //Used to detect panning to rotate the selected model.
592   Vector2 mPanStart;
593   Vector2 mRotationStart;
594
595   int mModelIndex; //Index of model to load.
596   int mShadingModeIndex; //Index of shading mode to use.
597   int mTag; //Identifies what kind of actor has been selected in OnTouch.
598   int mSelectedModelIndex; //Index of model selected on screen.
599   bool mPaused; //If true, all animations are paused and should stay so.
600   bool mLightFixed; //If false, the light is in manual.
601   bool mLightFront; //Bool for light being in front or behind the models.
602 };
603
604 // Entry point for Linux & Tizen applications
605 //
606 int main( int argc, char **argv )
607 {
608   Application application = Application::New( &argc, &argv );
609   MeshVisualController test( application );
610   application.MainLoop();
611   return 0;
612 }