Improved layout in text-field example
[platform/core/uifw/dali-demo.git] / examples / shadow-bone-lighting / shadow-bone-lighting-example.cpp
1 /*
2  * Copyright (c) 2014 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 // INTERNAL INCLUDES
19 #include "shared/view.h"
20
21 #include <dali/dali.h>
22 #include <dali-toolkit/dali-toolkit.h>
23 #include <iostream>
24
25 using namespace Dali;
26 using namespace Dali::Toolkit;
27 using std::string;
28 using namespace DemoHelper;
29
30 namespace
31 {
32 const char* BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-default.png" );
33 const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
34
35 //const char* APPLICATION_TITLE_PAN_LIGHT( "Lighting: Pan Light" );
36 //const char* APPLICATION_TITLE_PAN_OBJECT( "Lighting: Pan Object" );
37 //const char* APPLICATION_TITLE_PAN_SCENE( "Lighting: Pan Scene" );
38 //const char* APPLICATION_TITLE_ROTATE_SCENE( "Lighting: Rotate Scene" );
39 const char* CHANGE_EFFECT_IMAGE( DALI_IMAGE_DIR "icon-change.png" );
40 const char* RESET_ICON( DALI_IMAGE_DIR "icon-reset.png" );
41
42 const char* SCENE_IMAGE_1( DALI_IMAGE_DIR "gallery-small-10.jpg");
43 const char* SCENE_IMAGE_2( DALI_IMAGE_DIR "gallery-small-42.jpg");
44 const char* SCENE_IMAGE_3( DALI_IMAGE_DIR "gallery-small-48.jpg");
45
46 const Quaternion JAUNTY_ROTATION(Math::PI/5.0f, Math::PI/5.0f, 0.0f); // Euler angles
47 const float MIN_PINCH_SCALE( 0.3f );
48 const float MAX_PINCH_SCALE( 2.05f );
49
50 const float R3_2(0.8660254);
51 const Vector3 TOP_POINT(  0.0f, -1.0f,  0.0f);
52 const Vector3 LEFT_POINT( -R3_2, 0.5f,  0.0f);
53 const Vector3 RIGHT_POINT( R3_2, 0.5f,  0.0f);
54 const Vector3 FRONT_POINT( 0.0f, 0.0f, 20.0f);
55
56 const Vector2 DEFAULT_STAGE_SIZE( 480.0f, 800.0f );
57
58 }
59
60 /**
61  * This example shows a fixed point light onto an animating set of images
62  * casting a shadow onto a wall. The whole scene can be rotated.
63  */
64
65 class TestApp : public ConnectionTracker
66 {
67 public:
68
69   /**
70    * Constructor
71    * @param application class, stored as reference
72    */
73   TestApp(Application &app)
74   : mApp(app),
75     mPaused(false),
76     mTranslation(Vector3::ZERO),
77     mLongitudinal(15.0f),
78     mAxisTilt(30.0f),
79     mLightLongitudinal(0.0f),
80     mLightAxisTilt(0.0f),
81     mObjectLongitudinal(0.0f),
82     mObjectAxisTilt(0.0f),
83     mPinchScale(0.5f),
84     mScaleAtPinchStart(0.5f),
85     mPanState(PAN_SCENE)
86   {
87     app.InitSignal().Connect(this, &TestApp::Create);
88     app.TerminateSignal().Connect(this, &TestApp::Terminate);
89   }
90
91   ~TestApp()
92   {
93     // Nothing to do here; All the members of this class get deleted automatically and they delete their children
94   }
95
96 public:
97   struct PositionInFrontOf
98   {
99     PositionInFrontOf()
100     {
101     }
102
103     Vector3 operator()( const Vector3& current, const PropertyInput& property )
104     {
105       Vector3 position = property.GetVector3();
106       position.z += 1.0f;
107       return position;
108     }
109   };
110
111   struct QuaternionEqualToConstraint
112   {
113     QuaternionEqualToConstraint()
114     {
115     }
116
117     Quaternion operator()( const Quaternion& current, const PropertyInput& property )
118     {
119       return property.GetQuaternion();
120     }
121   };
122
123   struct RotationConstraint
124   {
125     RotationConstraint(float sign)
126     : mSign(sign)
127     {
128     }
129
130     Quaternion operator()( const Quaternion& current, const PropertyInput& property )
131     {
132       Degree angle(property.GetFloat());
133       return Quaternion( Radian(angle) * mSign, Vector3::YAXIS );
134     }
135
136     float mSign;
137   };
138
139   /**
140    * This method gets called once the main loop of application is up and running
141    */
142   void Create(Application& app)
143   {
144     srand(0); // Want repeatable path
145
146     Stage::GetCurrent().KeyEventSignal().Connect(this, &TestApp::OnKeyEvent);
147
148     CreateToolbarAndView(app);
149     CreateShadowViewAndLights();
150     CreateScene();
151   }
152
153   void CreateToolbarAndView(Application& app)
154   {
155     // Creates a default view with a default tool bar.
156     // The view is added to the stage.
157     Toolkit::ToolBar toolBar;
158     mContents = DemoHelper::CreateView( app,
159                                         mView,
160                                         toolBar,
161                                         BACKGROUND_IMAGE,
162                                         TOOLBAR_IMAGE,
163                                         "" );
164
165     // Add an effect-changing button on the right of the tool bar.
166     Image imageChangeEffect = ResourceImage::New( CHANGE_EFFECT_IMAGE );
167     Toolkit::PushButton effectChangeButton = Toolkit::PushButton::New();
168     effectChangeButton.SetBackgroundImage(imageChangeEffect);
169     effectChangeButton.ClickedSignal().Connect( this, &TestApp::OnEffectButtonClicked );
170     toolBar.AddControl( effectChangeButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
171
172     // Add title to the tool bar.
173     // TODO
174
175     //Add a reset button
176     Image resetImage = ResourceImage::New( RESET_ICON );
177     Toolkit::PushButton resetButton = Toolkit::PushButton::New();
178     resetButton.SetBackgroundImage( resetImage );
179     resetButton.ClickedSignal().Connect( this, &TestApp::OnResetPressed );
180     toolBar.AddControl( resetButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalCenter, DemoHelper::DEFAULT_PLAY_PADDING );
181
182     // Setup
183     mView.SetPosition(Vector3(0.0f, 0.0f, -50));
184
185     mContents.SetPosition(mTranslation);
186     mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
187     mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
188
189     mPanGestureDetector = PanGestureDetector::New();
190     mPanGestureDetector.Attach( mView );
191     mPanGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPan);
192
193     mPinchGestureDetector = PinchGestureDetector::New();
194     mPinchGestureDetector.Attach( mView );
195     mPinchGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPinch);
196
197     mTapGestureDetector = TapGestureDetector::New();
198     mTapGestureDetector.Attach( mView );
199     mTapGestureDetector.DetectedSignal().Connect(this, &TestApp::OnTap);
200   }
201
202
203
204   void CreateShadowViewAndLights()
205   {
206     mShadowView = Toolkit::ShadowView::New();
207     mShadowView.SetName("Container");
208     mShadowView.SetParentOrigin(ParentOrigin::CENTER);
209     mShadowView.SetAnchorPoint(AnchorPoint::CENTER);
210     mShadowView.SetSizeMode( SIZE_EQUAL_TO_PARENT );
211     mShadowView.SetPointLightFieldOfView( Math::PI / 2.0f);
212     mContents.Add(mShadowView);
213
214     Image brickWall = ResourceImage::New(DALI_IMAGE_DIR "brick-wall.jpg");
215     mShadowPlaneBg = ImageActor::New(brickWall);
216     mShadowPlaneBg.SetParentOrigin(ParentOrigin::CENTER);
217     mShadowPlaneBg.SetAnchorPoint(AnchorPoint::CENTER);
218     mShadowPlaneBg.SetName("Plane");
219     mShadowPlaneBg.SetSize(1000.0f, 1000.0f);
220     mContents.Add(mShadowPlaneBg);
221     mShadowPlaneBg.SetPosition(Vector3(50.0f, 50.0f, -200.0f));
222
223     mShadowView.SetShadowPlane(mShadowPlaneBg);
224     mShadowView.Activate();
225
226     mLightAnchor = Actor::New();
227     mLightAnchor.SetParentOrigin(ParentOrigin::CENTER);
228     mLightAnchor.SetAnchorPoint(AnchorPoint::CENTER);
229     mLightAnchor.SetRotation(CalculateWorldRotation(Radian(mLightLongitudinal), Radian(mLightAxisTilt)));
230
231     // Work out a scaling factor as the initial light position was calculated for desktop
232     // Need to scale light position as scene actor size is based on stage size (i.e. much bigger on device)
233     Vector2 stageSize( Stage::GetCurrent().GetSize() );
234     float scaleFactor = stageSize.x / DEFAULT_STAGE_SIZE.x;
235
236     mCastingLight = Actor::New();
237     mCastingLight.SetParentOrigin(ParentOrigin::CENTER);
238     mCastingLight.SetAnchorPoint(AnchorPoint::CENTER);
239     mCastingLight.SetPosition( Vector3( 0.0f, 0.0f, 800.0f ) * scaleFactor );
240
241     mLightAnchor.Add(mCastingLight);
242     mShadowPlaneBg.Add(mLightAnchor);
243
244     mShadowView.SetPointLight(mCastingLight);
245   }
246
247   void CreateScene()
248   {
249     mSceneActor = Actor::New();
250     mSceneActor.SetParentOrigin(ParentOrigin::CENTER);
251
252     // Create and add images to the scene actor:
253     mImageActor1 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_1) );
254     mImageActor2 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_2) );
255     mImageActor3 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_3) );
256
257
258     mImageActor2.SetParentOrigin(ParentOrigin::CENTER);
259
260     mImageActor1.SetParentOrigin(ParentOrigin::CENTER_LEFT);
261     mImageActor1.SetAnchorPoint(AnchorPoint::CENTER_RIGHT);
262
263     mImageActor3.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
264     mImageActor3.SetAnchorPoint(AnchorPoint::CENTER_LEFT);
265
266     mSceneActor.Add(mImageActor2);
267     mImageActor2.Add(mImageActor1);
268     mImageActor2.Add(mImageActor3);
269
270     Property::Index angleIndex = mImageActor2.RegisterProperty("angle", Property::Value(30.0f));
271     Source angleSrc( mImageActor2, angleIndex );
272     mImageActor1.ApplyConstraint(Constraint::New<Quaternion>( Actor::Property::Rotation, angleSrc,
273                                                               RotationConstraint(-1.0f)));
274     mImageActor3.ApplyConstraint(Constraint::New<Quaternion>( Actor::Property::Rotation, angleSrc,
275                                                               RotationConstraint(+1.0f)));
276
277     mSceneAnimation = Animation::New(2.5f);
278
279     // Want to animate angle from 30 => -30 and back again smoothly.
280
281     mSceneAnimation.AnimateTo( Property( mImageActor2, angleIndex ), Property::Value(-30.0f), AlphaFunctions::Sin );
282
283     mSceneAnimation.SetLooping(true);
284     mSceneAnimation.Play();
285
286     mSceneActor.SetSize(250.0f, 250.0f);
287     mSceneActor.SetPosition(0.0f, 0.0f, 130.0f);
288     mShadowView.Add(mSceneActor);
289   }
290
291
292   Quaternion CalculateWorldRotation(Radian longitude, Radian axisTilt )
293   {
294     Quaternion q(longitude, Vector3::YAXIS);
295     Quaternion p(axisTilt, Vector3::XAXIS);
296     return p*q;
297   }
298
299   void OnTap(Dali::Actor actor, const TapGesture& gesture)
300   {
301     if( mSceneAnimation )
302     {
303       if( ! mPaused )
304       {
305         mSceneAnimation.Pause();
306         mPaused = true;
307       }
308       else
309       {
310         mSceneAnimation.Play();
311         mPaused = false;
312       }
313     }
314   }
315
316   void OnPan(Actor actor, const PanGesture& gesture)
317   {
318     switch (gesture.state)
319     {
320       case Gesture::Continuing:
321       {
322         switch(mPanState)
323         {
324           case PAN_LIGHT:
325           {
326             mLightLongitudinal += gesture.displacement.x/4.0f;
327             mLightAxisTilt -= gesture.displacement.y/6.0f;
328             mLightAxisTilt = Clamp<float>(mLightAxisTilt, -90.0f, 90.0f);
329             mLightAnchor.SetRotation(CalculateWorldRotation(Radian(mLightLongitudinal), Radian(mLightAxisTilt)));
330             break;
331           }
332
333           case PAN_SCENE:
334           {
335             mTranslation += Vector3(gesture.displacement.x, gesture.displacement.y, 0.f);
336             mContents.SetPosition(mTranslation);
337             break;
338           }
339
340           case ROTATE_SCENE:
341           {
342             mLongitudinal += gesture.displacement.x/4.0f;
343             mAxisTilt -= gesture.displacement.y/6.0f;
344             mAxisTilt = Clamp<float>(mAxisTilt, -90.0f, 90.0f);
345             mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
346             break;
347           }
348
349           case PAN_OBJECT:
350           {
351             mObjectLongitudinal += gesture.displacement.x/4.0f;
352             mObjectAxisTilt -= gesture.displacement.y/6.0f;
353             mObjectAxisTilt = Clamp<float>(mObjectAxisTilt, -90.0f, 90.0f);
354             mSceneActor.SetRotation(CalculateWorldRotation(Radian(mObjectLongitudinal), Radian(mObjectAxisTilt)));
355             break;
356           }
357         }
358       }
359       break;
360
361       case Gesture::Finished:
362         // Start animation at last known speed
363         break;
364
365       default:
366         break;
367     }
368   }
369
370   void OnPinch(Actor actor, const PinchGesture& gesture)
371   {
372     if (gesture.state == Gesture::Started)
373     {
374       mScaleAtPinchStart = mContents.GetCurrentScale().x;
375     }
376     mPinchScale = Clamp(mScaleAtPinchStart * gesture.scale, MIN_PINCH_SCALE, MAX_PINCH_SCALE);
377
378     mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
379   }
380
381   void Terminate(Application& app)
382   {
383     if( mSceneActor )
384     {
385       Stage::GetCurrent().Remove(mSceneActor);
386     }
387     if( mView )
388     {
389       Stage::GetCurrent().Remove(mView);
390     }
391   }
392
393   void OnKeyEvent(const KeyEvent& event)
394   {
395     if(event.state == KeyEvent::Down)
396     {
397       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
398       {
399         mApp.Quit();
400       }
401     }
402   }
403
404   bool OnEffectButtonClicked( Toolkit::Button button )
405   {
406     return true;
407   }
408
409   bool OnResetPressed( Toolkit::Button button )
410   {
411     // Reset translation
412     mTranslation = Vector3::ZERO;
413     mContents.SetPosition(mTranslation);
414
415     // Align scene so that light anchor orientation is Z Axis
416     mAxisTilt = -mLightAxisTilt;
417     mLongitudinal = -mLightLongitudinal;
418     mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
419
420     return true;
421   }
422
423 private:
424   Application&              mApp;
425   Toolkit::View             mView;
426   Layer                     mContents;
427   Actor                     mSceneActor;
428   Animation                 mAnimation;
429   Animation                 mSceneAnimation;
430   bool                      mPaused;
431   Toolkit::ShadowView       mShadowView;
432   ImageActor                mShadowPlaneBg;
433   ImageActor                mShadowPlane;
434   Actor                     mCastingLight;
435   Actor                     mLightAnchor;
436   ImageActor                mImageActor1;
437   ImageActor                mImageActor2;
438   ImageActor                mImageActor3;
439   PanGestureDetector        mPanGestureDetector;
440   PinchGestureDetector      mPinchGestureDetector;
441   TapGestureDetector        mTapGestureDetector;
442   Vector3                   mTranslation;
443   Degree                    mLongitudinal;
444   Degree                    mAxisTilt;
445   Degree                    mLightLongitudinal;
446   Degree                    mLightAxisTilt;
447   Degree                    mObjectLongitudinal;
448   Degree                    mObjectAxisTilt;
449   float                     mPinchScale;
450   float                     mScaleAtPinchStart;
451
452   Property::Index           mAngle1Index;
453   Property::Index           mAngle3Index;
454
455   enum PanState
456   {
457     PAN_SCENE,
458     ROTATE_SCENE,
459     PAN_LIGHT,
460     PAN_OBJECT
461   };
462
463   PanState                  mPanState;
464 };
465
466 /*****************************************************************************/
467
468 static void
469 RunTest(Application& app)
470 {
471   TestApp theApp(app);
472   app.MainLoop();
473 }
474
475 /*****************************************************************************/
476
477 int
478 main(int argc, char **argv)
479 {
480   Application app = Application::New(&argc, &argv);
481
482   RunTest(app);
483
484   return 0;
485 }