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