522d7e9dd3fcc97d4e6f82875139805aaea0ac83
[platform/core/uifw/dali-demo.git] / examples / model3d-view / model3d-view-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
20 using namespace Dali;
21 using Dali::Toolkit::Model3dView;
22
23 namespace
24 {
25 const int MODEL_NUMBER(3);
26
27 const char * const MODEL_FILE[] = {
28     DEMO_MODEL_DIR "Dino.obj",
29     DEMO_MODEL_DIR "ToyRobot-Metal.obj",
30     DEMO_MODEL_DIR "Toyrobot-Plastic.obj"
31 };
32
33 const char * const MATERIAL_FILE[] = {
34     DEMO_MODEL_DIR "Dino.mtl",
35     DEMO_MODEL_DIR "ToyRobot-Metal.mtl",
36     DEMO_MODEL_DIR "Toyrobot-Plastic.mtl"
37 };
38
39 const char * const IMAGE_PATH( DEMO_IMAGE_DIR "" );
40
41 const char * BACKGROUND_IMAGE( DEMO_IMAGE_DIR "background-1.jpg");
42
43 }
44
45 /*
46  * This example shows how to create and display a model3d-view control.
47  * The application can cycle between 3 different models, and 3 different shaders.
48  * There are two animations running, one is a rotation for the model, one is a light that
49  * goes from one side of the model to the other.
50  * There are dedicated buttons for changing the models, the shaders and pausing the animations.
51  * The animations can also be paused, resumed with the space key
52  * A double tap in the model3d-view will make zoom-in/out of the zone clicked
53  */
54
55 class Model3dViewController : public ConnectionTracker
56 {
57 public:
58
59   Model3dViewController( Application& application )
60   : mApplication( application ),
61     mModelCounter( 0 ),
62     mModel3dView(),
63     mButtonLayer(),
64     mTapDetector(),
65     mIlluminationShader( Model3dView::DIFFUSE ),
66     mRotationAnimation(),
67     mLightAnimation(),
68     mPlaying( false ),
69     mScaled( false )
70   {
71     // Connect to the Application's Init signal
72     mApplication.InitSignal().Connect( this, &Model3dViewController::Create );
73   }
74
75   ~Model3dViewController()
76   {
77     // Nothing to do here;
78   }
79
80   // The Init signal is received once (only) during the Application lifetime
81   void Create( Application& application )
82   {
83     // Get a handle to the stage
84     Stage stage = Stage::GetCurrent();
85     Vector2 screenSize = stage.GetSize();
86
87     //Add background
88     Toolkit::ImageView backView = Toolkit::ImageView::New( BACKGROUND_IMAGE );
89     backView.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
90     backView.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
91     stage.Add( backView );
92
93     mModelCounter = 0;
94
95     mModel3dView = Model3dView::New( MODEL_FILE[0], MATERIAL_FILE[0], IMAGE_PATH );
96     mModel3dView.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
97     mModel3dView.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
98     mModel3dView.SetProperty( Dali::Actor::Property::NAME, "model3dViewControl" );
99     mModel3dView.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
100     mModel3dView.SetSize(screenSize);
101
102     mModel3dView.SetProperty(Model3dView::Property::LIGHT_POSITION, Vector3(5,10.,0));
103
104     backView.Add( mModel3dView );
105
106     mIlluminationShader = Model3dView::IlluminationType(mModel3dView.GetProperty<int>(Model3dView::Property::ILLUMINATION_TYPE));
107
108     mButtonLayer = Layer::New();
109     mButtonLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
110     mButtonLayer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
111     mButtonLayer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
112     stage.Add(mButtonLayer);
113
114     // Create button for model changing
115     Toolkit::PushButton editButton = Toolkit::PushButton::New();
116     editButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
117     editButton.ClickedSignal().Connect( this, &Model3dViewController::OnChangeModelClicked);
118     editButton.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
119     editButton.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
120     editButton.SetProperty( Toolkit::Button::Property::LABEL, "Change Model" );
121     mButtonLayer.Add( editButton  );
122
123     // Create button for shader changing
124     editButton = Toolkit::PushButton::New();
125     editButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
126     editButton.ClickedSignal().Connect( this, &Model3dViewController::OnChangeLightingClicked);
127     editButton.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_RIGHT );
128     editButton.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_RIGHT );
129     editButton.SetProperty( Toolkit::Button::Property::LABEL, "Change Shader" );
130     mButtonLayer.Add( editButton  );
131
132     // Create button for pause/resume animation
133     editButton = Toolkit::PushButton::New();
134     editButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
135     editButton.ClickedSignal().Connect( this, &Model3dViewController::OnPauseAnimationsClicked);
136     editButton.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
137     editButton.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
138     editButton.SetProperty( Toolkit::Button::Property::LABEL, "Pause Animations" );
139     mButtonLayer.Add( editButton  );
140
141     //Create animations
142     mLightAnimation = Animation::New(6.f);
143     mLightAnimation.AnimateTo(Property(mModel3dView, Model3dView::Property::LIGHT_POSITION), Vector3(-5,10.0,0), TimePeriod( 0.0f, 3.0f ));
144     mLightAnimation.AnimateTo(Property(mModel3dView, Model3dView::Property::LIGHT_POSITION), Vector3(5,10.0,0), TimePeriod( 3.0f, 3.0f ));
145     mLightAnimation.SetLooping(true);
146     mLightAnimation.Play();
147
148     mRotationAnimation = Animation::New(15.f);
149     mRotationAnimation.AnimateBy(Property(mModel3dView, Actor::Property::ORIENTATION), Quaternion(Degree(0.f), Degree(360.f), Degree(0.f)) );
150     mRotationAnimation.SetLooping(true);
151     mRotationAnimation.Play();
152
153     mPlaying = true;
154     mScaled = false;
155
156     // Respond to a click anywhere on the stage
157     stage.KeyEventSignal().Connect(this, &Model3dViewController::OnKeyEvent);
158
159     //Create a tap gesture detector for zoom
160     mTapDetector = TapGestureDetector::New( 2 );
161     mTapDetector.DetectedSignal().Connect(this, &Model3dViewController::OnTap);
162
163     mTapDetector.Attach( backView );
164   }
165
166   /**
167    * Main Tap event handler
168    */
169   void OnTap( Actor actor, const TapGesture& tap )
170   {
171     if (mScaled)
172     {
173       mModel3dView.SetScale(1.0);
174       mModel3dView.SetPosition(0,0,0);
175       mScaled = false;
176     }
177     else
178     {
179       Stage stage = Stage::GetCurrent();
180       Vector2 screenSize = stage.GetSize();
181
182       Vector2 position;
183       position.x = tap.screenPoint.x - screenSize.x * 0.5;
184       position.y = tap.screenPoint.y - screenSize.y * 0.5;
185
186       float size = 2.5;
187
188       mModel3dView.SetScale(size);
189       mModel3dView.SetPosition(-position.x * size,-position.y * size, 0);
190       mScaled = true;
191     }
192   }
193
194   /**
195    * Change models button signal function
196    */
197   bool OnChangeModelClicked(Toolkit::Button button)
198   {
199     mModelCounter = (mModelCounter + 1) % MODEL_NUMBER;
200     mModel3dView.SetProperty(Model3dView::Property::GEOMETRY_URL, MODEL_FILE[mModelCounter]);
201     mModel3dView.SetProperty(Model3dView::Property::MATERIAL_URL, MATERIAL_FILE[mModelCounter]);
202     return true;
203   }
204
205   /**
206    * Change shader button signal function
207    */
208   bool OnChangeLightingClicked(Toolkit::Button button)
209   {
210     if( mIlluminationShader == Model3dView::DIFFUSE_WITH_NORMAL_MAP )
211     {
212       mModel3dView.SetProperty(Model3dView::Property::ILLUMINATION_TYPE, Model3dView::DIFFUSE_WITH_TEXTURE);
213       mIlluminationShader = Model3dView::IlluminationType(mModel3dView.GetProperty<int>(Model3dView::Property::ILLUMINATION_TYPE));
214     }
215     else if( mIlluminationShader == Model3dView::DIFFUSE_WITH_TEXTURE )
216     {
217       mModel3dView.SetProperty(Model3dView::Property::ILLUMINATION_TYPE, Model3dView::DIFFUSE);
218       mIlluminationShader = Model3dView::IlluminationType(mModel3dView.GetProperty<int>(Model3dView::Property::ILLUMINATION_TYPE));
219    }
220     else if( mIlluminationShader == Model3dView::DIFFUSE )
221     {
222       mModel3dView.SetProperty(Model3dView::Property::ILLUMINATION_TYPE, Model3dView::DIFFUSE_WITH_NORMAL_MAP);
223       mIlluminationShader = Model3dView::IlluminationType(mModel3dView.GetProperty<int>(Model3dView::Property::ILLUMINATION_TYPE));
224    }
225
226     return true;
227   }
228
229   /**
230    * Function to pause resume all animations
231    */
232   void PauseAnimations()
233   {
234     if( mPlaying )
235     {
236       mRotationAnimation.Pause();
237       mLightAnimation.Pause();
238
239       mPlaying = false;
240     }
241     else
242     {
243       mRotationAnimation.Play();
244       mLightAnimation.Play();
245
246       mPlaying = true;
247     }
248   }
249
250   /**
251    * Pause button signal function
252    */
253   bool OnPauseAnimationsClicked(Toolkit::Button button)
254   {
255     PauseAnimations();
256
257     return true;
258   }
259
260   /**
261    * Main key event handler
262    */
263   void OnKeyEvent(const KeyEvent& event)
264   {
265     if(event.state == KeyEvent::Down)
266     {
267       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
268       {
269         mApplication.Quit();
270       }
271       else
272       {
273         PauseAnimations();
274       }
275     }
276   }
277
278
279 private:
280   Application&  mApplication;
281
282   int mModelCounter;
283   Model3dView mModel3dView;
284
285   Layer mButtonLayer;
286   TapGestureDetector mTapDetector;
287
288   Model3dView::IlluminationType mIlluminationShader;
289
290   Animation mRotationAnimation;
291   Animation mLightAnimation;
292   bool mPlaying;
293
294   bool mScaled;
295 };
296
297 int DALI_EXPORT_API main( int argc, char **argv )
298 {
299   Application application = Application::New( &argc, &argv );
300   Model3dViewController test( application );
301   application.MainLoop();
302   return 0;
303 }