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