Size negotiation patch 4: Remove SetRelayoutEnabled
[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: Rotate 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 float MIN_PINCH_SCALE( 0.3f );
47 const float MAX_PINCH_SCALE( 2.05f );
48
49 const float R3_2(0.8660254);
50 const Vector3 TOP_POINT(  0.0f, -1.0f,  0.0f);
51 const Vector3 LEFT_POINT( -R3_2, 0.5f,  0.0f);
52 const Vector3 RIGHT_POINT( R3_2, 0.5f,  0.0f);
53 const Vector3 FRONT_POINT( 0.0f, 0.0f, 20.0f);
54
55 const Vector2 DEFAULT_STAGE_SIZE( 480.0f, 800.0f );
56
57 const float X_ROTATION_DISPLACEMENT_FACTOR = 60.f;
58 const float Y_ROTATION_DISPLACEMENT_FACTOR = 60.f;
59 const float LIGHT_PAN_X_DISPLACEMENT_FACTOR = 180.f;
60 const float LIGHT_PAN_Y_DISPLACEMENT_FACTOR = 180.f;
61
62 }
63
64 /**
65  * This example shows a fixed point light onto an animating set of images
66  * casting a shadow onto a wall. The whole scene can be rotated.
67  */
68
69 class TestApp : public ConnectionTracker
70 {
71 public:
72
73   /**
74    * Constructor
75    * @param application class, stored as reference
76    */
77   TestApp(Application &app)
78   : mApp(app),
79     mPaused(false),
80     mTranslation(Vector3::ZERO),
81     mSceneYRotation( Dali::ANGLE_30 * 0.5f ),
82     mSceneXRotation( Dali::ANGLE_30 ),
83     mLightYRotation(0.0f),
84     mLightXRotation(0.0f),
85     mObjectYRotation(0.0f),
86     mObjectXRotation(0.0f),
87     mPinchScale(0.5f),
88     mScaleAtPinchStart(0.5f),
89     mPanState(PAN_SCENE)
90   {
91     app.InitSignal().Connect(this, &TestApp::Create);
92     app.TerminateSignal().Connect(this, &TestApp::Terminate);
93   }
94
95   ~TestApp()
96   {
97     // Nothing to do here; All the members of this class get deleted automatically and they delete their children
98   }
99
100 public:
101
102   struct RotationConstraint
103   {
104     RotationConstraint(float sign)
105     : mSign(sign)
106     {
107     }
108
109     void operator()( Quaternion& current, const PropertyInputContainer& inputs )
110     {
111       Radian angle( inputs[0]->GetFloat() );
112       current = Quaternion( angle * mSign, Vector3::YAXIS );
113     }
114
115     float mSign;
116   };
117
118   /**
119    * This method gets called once the main loop of application is up and running
120    */
121   void Create(Application& app)
122   {
123     DemoHelper::RequestThemeChange();
124
125     srand(0); // Want repeatable path
126
127     Stage::GetCurrent().KeyEventSignal().Connect(this, &TestApp::OnKeyEvent);
128
129     CreateToolbarAndView(app);
130     CreateShadowViewAndLights();
131     CreateScene();
132   }
133
134   void CreateToolbarAndView(Application& app)
135   {
136     // Creates a default view with a default tool bar.
137     // The view is added to the stage.
138     Toolkit::ToolBar toolBar;
139     mContents = DemoHelper::CreateView( app,
140                                         mView,
141                                         toolBar,
142                                         BACKGROUND_IMAGE,
143                                         TOOLBAR_IMAGE,
144                                         "" );
145
146     // Add an effect-changing button on the right of the tool bar.
147     Image imageChangeEffect = ResourceImage::New( CHANGE_EFFECT_IMAGE );
148     Toolkit::PushButton effectChangeButton = Toolkit::PushButton::New();
149     effectChangeButton.SetBackgroundImage(imageChangeEffect);
150     effectChangeButton.ClickedSignal().Connect( this, &TestApp::OnEffectButtonClicked );
151     toolBar.AddControl( effectChangeButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
152
153     // Add title to the tool bar.
154     mTitleActor = DemoHelper::CreateToolBarLabel( "" );
155     toolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Toolkit::Alignment::HorizontalCenter );
156
157     // Set Title text
158     mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_SCENE) );
159
160     //Add a reset button
161     Image resetImage = ResourceImage::New( RESET_ICON );
162     Toolkit::PushButton resetButton = Toolkit::PushButton::New();
163     resetButton.SetBackgroundImage( resetImage );
164     resetButton.ClickedSignal().Connect( this, &TestApp::OnResetPressed );
165     toolBar.AddControl( resetButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalCenter, DemoHelper::DEFAULT_PLAY_PADDING );
166
167     // Setup
168     mView.SetPosition(Vector3(0.0f, 0.0f, -50));
169
170     mContents.SetPosition(mTranslation);
171     mContents.SetOrientation( CalculateWorldRotation( mSceneXRotation, mSceneYRotation ) );
172     mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
173
174     mPanGestureDetector = PanGestureDetector::New();
175     mPanGestureDetector.Attach( mView );
176     mPanGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPan);
177
178     mPinchGestureDetector = PinchGestureDetector::New();
179     mPinchGestureDetector.Attach( mView );
180     mPinchGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPinch);
181
182     mTapGestureDetector = TapGestureDetector::New();
183     mTapGestureDetector.Attach( mView );
184     mTapGestureDetector.DetectedSignal().Connect(this, &TestApp::OnTap);
185   }
186
187
188
189   void CreateShadowViewAndLights()
190   {
191     mShadowView = Toolkit::ShadowView::New();
192     mShadowView.SetName("Container");
193     mShadowView.SetParentOrigin(ParentOrigin::CENTER);
194     mShadowView.SetAnchorPoint(AnchorPoint::CENTER);
195     mShadowView.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
196     mShadowView.SetPointLightFieldOfView( Math::PI / 2.0f);
197     mContents.Add(mShadowView);
198
199     Image brickWall = ResourceImage::New(DALI_IMAGE_DIR "brick-wall.jpg");
200     mShadowPlaneBg = ImageActor::New(brickWall);
201     mShadowPlaneBg.SetParentOrigin(ParentOrigin::CENTER);
202     mShadowPlaneBg.SetAnchorPoint(AnchorPoint::CENTER);
203     mShadowPlaneBg.SetName("Plane");
204     mShadowPlaneBg.SetSize(1000.0f, 1000.0f);
205     mContents.Add(mShadowPlaneBg);
206     mShadowPlaneBg.SetPosition(Vector3(50.0f, 50.0f, -200.0f));
207
208     mShadowView.SetShadowPlane(mShadowPlaneBg);
209     mShadowView.Activate();
210
211     mLightAnchor = Actor::New();
212     mLightAnchor.SetParentOrigin(ParentOrigin::CENTER);
213     mLightAnchor.SetAnchorPoint(AnchorPoint::CENTER);
214     mLightAnchor.SetOrientation( CalculateWorldRotation( mLightXRotation, mLightYRotation ) );
215
216     // Work out a scaling factor as the initial light position was calculated for desktop
217     // Need to scale light position as scene actor size is based on stage size (i.e. much bigger on device)
218     Vector2 stageSize( Stage::GetCurrent().GetSize() );
219     float scaleFactor = stageSize.x / DEFAULT_STAGE_SIZE.x;
220
221     mCastingLight = Actor::New();
222     mCastingLight.SetParentOrigin(ParentOrigin::CENTER);
223     mCastingLight.SetAnchorPoint(AnchorPoint::CENTER);
224     mCastingLight.SetPosition( Vector3( 0.0f, 0.0f, 800.0f ) * scaleFactor );
225
226     TextLabel text = TextLabel::New( "Light" );
227     text.SetProperty( TextLabel::Property::POINT_SIZE, 20.0f );
228     text.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
229     text.SetColor( Color::BLUE );
230
231     mCastingLight.Add(text);
232     mLightAnchor.Add(mCastingLight);
233     mShadowPlaneBg.Add(mLightAnchor);
234
235     text.SetParentOrigin(ParentOrigin::CENTER);
236     mShadowView.SetPointLight(mCastingLight);
237   }
238
239   void CreateScene()
240   {
241     mSceneActor = Actor::New();
242     mSceneActor.SetParentOrigin(ParentOrigin::CENTER);
243
244     // Create and add images to the scene actor:
245     mImageActor1 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_1) );
246     mImageActor2 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_2) );
247     mImageActor3 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_3) );
248
249     mImageActor1.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
250     mImageActor2.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
251     mImageActor3.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
252
253     mImageActor2.SetParentOrigin(ParentOrigin::CENTER);
254
255     mImageActor1.SetParentOrigin(ParentOrigin::CENTER_LEFT);
256     mImageActor1.SetAnchorPoint(AnchorPoint::CENTER_RIGHT);
257
258     mImageActor3.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
259     mImageActor3.SetAnchorPoint(AnchorPoint::CENTER_LEFT);
260
261     mSceneActor.Add(mImageActor2);
262     mImageActor2.Add(mImageActor1);
263     mImageActor2.Add(mImageActor3);
264
265     Property::Index angleIndex = mImageActor2.RegisterProperty("angle", Property::Value( Dali::ANGLE_30 ) );
266     Source angleSrc( mImageActor2, angleIndex );
267
268     Constraint constraint = Constraint::New<Quaternion>( mImageActor1, Actor::Property::ORIENTATION, RotationConstraint(-1.0f) );
269     constraint.AddSource( angleSrc );
270     constraint.Apply();
271
272     constraint = Constraint::New<Quaternion>( mImageActor3, Actor::Property::ORIENTATION, RotationConstraint(+1.0f) );
273     constraint.AddSource( angleSrc );
274     constraint.Apply();
275
276     mSceneAnimation = Animation::New(2.5f);
277
278     // Want to animate angle from 30 => -30 and back again smoothly.
279
280     mSceneAnimation.AnimateTo( Property( mImageActor2, angleIndex ), Property::Value(-Dali::ANGLE_30), AlphaFunctions::Sin );
281
282     mSceneAnimation.SetLooping(true);
283     mSceneAnimation.Play();
284
285     mSceneActor.SetSize(250.0f, 250.0f);
286     mSceneActor.SetPosition(0.0f, 0.0f, 130.0f);
287     mShadowView.Add(mSceneActor);
288   }
289
290
291   Quaternion CalculateWorldRotation( Radian XRotation, Radian YRotation )
292   {
293     Quaternion p( XRotation, Vector3::XAXIS );
294     Quaternion q( YRotation, Vector3::YAXIS );
295     return p*q;
296   }
297
298   void OnTap(Dali::Actor actor, const TapGesture& gesture)
299   {
300     if( mSceneAnimation )
301     {
302       if( ! mPaused )
303       {
304         mSceneAnimation.Pause();
305         mPaused = true;
306       }
307       else
308       {
309         mSceneAnimation.Play();
310         mPaused = false;
311       }
312     }
313   }
314
315   void OnPan(Actor actor, const PanGesture& gesture)
316   {
317     switch (gesture.state)
318     {
319       case Gesture::Continuing:
320       {
321         switch(mPanState)
322         {
323           case PAN_LIGHT:
324           {
325             mLightXRotation = mLightXRotation - gesture.displacement.y / LIGHT_PAN_X_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis
326             mLightXRotation = Clamp(mLightXRotation, -Dali::ANGLE_45, Dali::ANGLE_45 );
327             mLightYRotation = mLightYRotation + gesture.displacement.x / LIGHT_PAN_Y_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis
328             mLightYRotation = Clamp(mLightYRotation, -Dali::ANGLE_45, Dali::ANGLE_45 );
329             mLightAnchor.SetOrientation( CalculateWorldRotation( mLightXRotation, mLightYRotation ) );
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             mSceneXRotation = mSceneXRotation - gesture.displacement.y / X_ROTATION_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis
343             mSceneXRotation = Clamp( mSceneXRotation, -Dali::ANGLE_90, Dali::ANGLE_90 );
344             mSceneYRotation = mSceneYRotation + gesture.displacement.x / Y_ROTATION_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis
345             mSceneYRotation = Clamp( mSceneYRotation, -Dali::ANGLE_90, Dali::ANGLE_90 );
346             mContents.SetOrientation( CalculateWorldRotation( mSceneXRotation, mSceneYRotation ) );
347             break;
348           }
349
350           case ROTATE_OBJECT:
351           {
352             mObjectXRotation = mObjectXRotation - gesture.displacement.y / X_ROTATION_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis
353             mObjectYRotation = mObjectYRotation + gesture.displacement.x / Y_ROTATION_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis
354             mSceneActor.SetOrientation( CalculateWorldRotation( mObjectXRotation, mObjectYRotation ) );
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     switch(mPanState)
407     {
408       case PAN_SCENE:
409         mPanState = ROTATE_SCENE;
410         mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_ROTATE_SCENE) );
411         break;
412       case ROTATE_SCENE:
413         mPanState = PAN_LIGHT;
414         mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_LIGHT) );
415         break;
416       case PAN_LIGHT:
417         mPanState = ROTATE_OBJECT;
418         mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_OBJECT) );
419         break;
420       case ROTATE_OBJECT:
421         mPanState = PAN_SCENE;
422         mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_SCENE) );
423         break;
424       default:
425         break;
426     }
427
428     return true;
429   }
430
431   bool OnResetPressed( Toolkit::Button button )
432   {
433     // Reset translation
434     mTranslation = Vector3::ZERO;
435     mContents.SetPosition(mTranslation);
436
437     // Align scene so that light anchor orientation is Z Axis
438     mSceneXRotation = -mLightXRotation;
439     mSceneYRotation = -mLightYRotation;
440     mContents.SetOrientation( CalculateWorldRotation( mSceneXRotation, mSceneYRotation ) );
441
442     return true;
443   }
444
445 private:
446   Application&              mApp;
447   Toolkit::View             mView;
448   Layer                     mContents;
449   Actor                     mSceneActor;
450   Animation                 mAnimation;
451   Animation                 mSceneAnimation;
452   bool                      mPaused;
453   Toolkit::ShadowView       mShadowView;
454   ImageActor                mShadowPlaneBg;
455   ImageActor                mShadowPlane;
456   Actor                     mCastingLight;
457   Actor                     mLightAnchor;
458   ImageActor                mImageActor1;
459   ImageActor                mImageActor2;
460   ImageActor                mImageActor3;
461   PanGestureDetector        mPanGestureDetector;
462   PinchGestureDetector      mPinchGestureDetector;
463   TapGestureDetector        mTapGestureDetector;
464   Vector3                   mTranslation;
465   Radian                    mSceneYRotation;
466   Radian                    mSceneXRotation;
467   Radian                    mLightYRotation;
468   Radian                    mLightXRotation;
469   Radian                    mObjectYRotation;
470   Radian                    mObjectXRotation;
471   float                     mPinchScale;
472   float                     mScaleAtPinchStart;
473
474   Property::Index           mAngle1Index;
475   Property::Index           mAngle3Index;
476
477   Toolkit::TextLabel         mTitleActor;
478
479   enum PanState
480   {
481     PAN_SCENE,
482     ROTATE_SCENE,
483     PAN_LIGHT,
484     ROTATE_OBJECT
485   };
486
487   PanState                  mPanState;
488 };
489
490 /*****************************************************************************/
491
492 static void
493 RunTest(Application& app)
494 {
495   TestApp theApp(app);
496   app.MainLoop();
497 }
498
499 /*****************************************************************************/
500
501 int
502 main(int argc, char **argv)
503 {
504   Application app = Application::New(&argc, &argv);
505
506   RunTest(app);
507
508   return 0;
509 }