Property refactor in dali-core: Demo changes for compiling
[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     mTitleActor = Toolkit::TextView::New();
174     toolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Toolkit::Alignment::HorizontalCenter );
175
176     // Set Title text
177     mTitleActor.SetText( APPLICATION_TITLE_PAN_SCENE );
178     mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_PAN_SCENE ) );
179     mTitleActor.SetStyleToCurrentText( DemoHelper::GetDefaultTextStyle() );
180
181     //Add a reset button
182     Image resetImage = ResourceImage::New( RESET_ICON );
183     Toolkit::PushButton resetButton = Toolkit::PushButton::New();
184     resetButton.SetBackgroundImage( resetImage );
185     resetButton.ClickedSignal().Connect( this, &TestApp::OnResetPressed );
186     toolBar.AddControl( resetButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalCenter, DemoHelper::DEFAULT_PLAY_PADDING );
187
188     // Setup
189     mView.SetPosition(Vector3(0.0f, 0.0f, -50));
190
191     mContents.SetPosition(mTranslation);
192     mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
193     mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
194
195     mPanGestureDetector = PanGestureDetector::New();
196     mPanGestureDetector.Attach( mView );
197     mPanGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPan);
198
199     mPinchGestureDetector = PinchGestureDetector::New();
200     mPinchGestureDetector.Attach( mView );
201     mPinchGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPinch);
202
203     mTapGestureDetector = TapGestureDetector::New(1, 1);
204     mTapGestureDetector.Attach( mView );
205     mTapGestureDetector.DetectedSignal().Connect(this, &TestApp::OnTap);
206   }
207
208
209
210   void CreateShadowViewAndLights()
211   {
212     mShadowView = Toolkit::ShadowView::New();
213     mShadowView.SetName("Container");
214     mShadowView.SetParentOrigin(ParentOrigin::CENTER);
215     mShadowView.SetAnchorPoint(AnchorPoint::CENTER);
216     mShadowView.SetSizeMode( SIZE_EQUAL_TO_PARENT );
217     mShadowView.SetPointLightFieldOfView( Math::PI / 2.0f);
218     mContents.Add(mShadowView);
219
220     Image brickWall = ResourceImage::New(DALI_IMAGE_DIR "brick-wall.jpg");
221     mShadowPlaneBg = ImageActor::New(brickWall);
222     mShadowPlaneBg.SetParentOrigin(ParentOrigin::CENTER);
223     mShadowPlaneBg.SetAnchorPoint(AnchorPoint::CENTER);
224     mShadowPlaneBg.SetName("Plane");
225     mShadowPlaneBg.SetSize(1000.0f, 1000.0f);
226     mContents.Add(mShadowPlaneBg);
227     mShadowPlaneBg.SetPosition(Vector3(50.0f, 50.0f, -200.0f));
228
229     mShadowView.SetShadowPlane(mShadowPlaneBg);
230     mShadowView.Activate();
231
232     mLightAnchor = Actor::New();
233     mLightAnchor.SetParentOrigin(ParentOrigin::CENTER);
234     mLightAnchor.SetAnchorPoint(AnchorPoint::CENTER);
235     mLightAnchor.SetRotation(CalculateWorldRotation(Radian(mLightLongitudinal), Radian(mLightAxisTilt)));
236
237     // Work out a scaling factor as the initial light position was calculated for desktop
238     // Need to scale light position as scene actor size is based on stage size (i.e. much bigger on device)
239     Vector2 stageSize( Stage::GetCurrent().GetSize() );
240     float scaleFactor = stageSize.x / DEFAULT_STAGE_SIZE.x;
241
242     mCastingLight = Actor::New();
243     mCastingLight.SetParentOrigin(ParentOrigin::CENTER);
244     mCastingLight.SetAnchorPoint(AnchorPoint::CENTER);
245     mCastingLight.SetPosition( Vector3( 0.0f, 0.0f, 800.0f ) * scaleFactor );
246
247     TextStyle style;
248     style.SetFontPointSize( PointSize(DemoHelper::ScalePointSize(20.0f)) );
249     style.SetFontName("Times New Roman");
250     style.SetFontStyle("Book");
251
252     TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_ON );
253     TextActor text = TextActor::New("Light", parameters);
254     text.SetColor(Color::BLUE);
255
256     mCastingLight.Add(text);
257     mLightAnchor.Add(mCastingLight);
258     mShadowPlaneBg.Add(mLightAnchor);
259
260     text.SetParentOrigin(ParentOrigin::CENTER);
261     mShadowView.SetPointLight(mCastingLight);
262   }
263
264   void CreateScene()
265   {
266     mSceneActor = Actor::New();
267     mSceneActor.SetParentOrigin(ParentOrigin::CENTER);
268
269     // Create and add images to the scene actor:
270     mImageActor1 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_1) );
271     mImageActor2 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_2) );
272     mImageActor3 = ImageActor::New( ResourceImage::New(SCENE_IMAGE_3) );
273
274
275     mImageActor2.SetParentOrigin(ParentOrigin::CENTER);
276
277     mImageActor1.SetParentOrigin(ParentOrigin::CENTER_LEFT);
278     mImageActor1.SetAnchorPoint(AnchorPoint::CENTER_RIGHT);
279
280     mImageActor3.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
281     mImageActor3.SetAnchorPoint(AnchorPoint::CENTER_LEFT);
282
283     mSceneActor.Add(mImageActor2);
284     mImageActor2.Add(mImageActor1);
285     mImageActor2.Add(mImageActor3);
286
287     Property::Index angleIndex = mImageActor2.RegisterProperty("angle", Property::Value(30.0f));
288     Source angleSrc( mImageActor2, angleIndex );
289     mImageActor1.ApplyConstraint(Constraint::New<Quaternion>( Actor::Property::Rotation, angleSrc,
290                                                               RotationConstraint(-1.0f)));
291     mImageActor3.ApplyConstraint(Constraint::New<Quaternion>( Actor::Property::Rotation, angleSrc,
292                                                               RotationConstraint(+1.0f)));
293
294     mSceneAnimation = Animation::New(2.5f);
295
296     // Want to animate angle from 30 => -30 and back again smoothly.
297
298     mSceneAnimation.AnimateTo( Property( mImageActor2, angleIndex ), Property::Value(-30.0f), AlphaFunctions::Sin );
299
300     mSceneAnimation.SetLooping(true);
301     mSceneAnimation.Play();
302
303     mSceneActor.SetSize(250.0f, 250.0f);
304     mSceneActor.SetPosition(0.0f, 0.0f, 130.0f);
305     mShadowView.Add(mSceneActor);
306   }
307
308
309   Quaternion CalculateWorldRotation(Radian longitude, Radian axisTilt )
310   {
311     Quaternion q(longitude, Vector3::YAXIS);
312     Quaternion p(axisTilt, Vector3::XAXIS);
313     return p*q;
314   }
315
316   void OnTap(Dali::Actor actor, const TapGesture& gesture)
317   {
318     if( mSceneAnimation )
319     {
320       if( ! mPaused )
321       {
322         mSceneAnimation.Pause();
323         mPaused = true;
324       }
325       else
326       {
327         mSceneAnimation.Play();
328         mPaused = false;
329       }
330     }
331   }
332
333   void OnPan(Actor actor, const PanGesture& gesture)
334   {
335     switch (gesture.state)
336     {
337       case Gesture::Continuing:
338       {
339         switch(mPanState)
340         {
341           case PAN_LIGHT:
342           {
343             mLightLongitudinal += gesture.displacement.x/4.0f;
344             mLightAxisTilt -= gesture.displacement.y/6.0f;
345             mLightAxisTilt = Clamp<float>(mLightAxisTilt, -90.0f, 90.0f);
346             mLightAnchor.SetRotation(CalculateWorldRotation(Radian(mLightLongitudinal), Radian(mLightAxisTilt)));
347             break;
348           }
349
350           case PAN_SCENE:
351           {
352             mTranslation += Vector3(gesture.displacement.x, gesture.displacement.y, 0.f);
353             mContents.SetPosition(mTranslation);
354             break;
355           }
356
357           case ROTATE_SCENE:
358           {
359             mLongitudinal += gesture.displacement.x/4.0f;
360             mAxisTilt -= gesture.displacement.y/6.0f;
361             mAxisTilt = Clamp<float>(mAxisTilt, -90.0f, 90.0f);
362             mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
363             break;
364           }
365
366           case PAN_OBJECT:
367           {
368             mObjectLongitudinal += gesture.displacement.x/4.0f;
369             mObjectAxisTilt -= gesture.displacement.y/6.0f;
370             mObjectAxisTilt = Clamp<float>(mObjectAxisTilt, -90.0f, 90.0f);
371             mSceneActor.SetRotation(CalculateWorldRotation(Radian(mObjectLongitudinal), Radian(mObjectAxisTilt)));
372             break;
373           }
374         }
375       }
376       break;
377
378       case Gesture::Finished:
379         // Start animation at last known speed
380         break;
381
382       default:
383         break;
384     }
385   }
386
387   void OnPinch(Actor actor, const PinchGesture& gesture)
388   {
389     if (gesture.state == Gesture::Started)
390     {
391       mScaleAtPinchStart = mContents.GetCurrentScale().x;
392     }
393     mPinchScale = Clamp(mScaleAtPinchStart * gesture.scale, MIN_PINCH_SCALE, MAX_PINCH_SCALE);
394
395     mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
396   }
397
398   void Terminate(Application& app)
399   {
400     if( mSceneActor )
401     {
402       Stage::GetCurrent().Remove(mSceneActor);
403     }
404     if( mView )
405     {
406       Stage::GetCurrent().Remove(mView);
407     }
408   }
409
410   void OnKeyEvent(const KeyEvent& event)
411   {
412     if(event.state == KeyEvent::Down)
413     {
414       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
415       {
416         mApp.Quit();
417       }
418     }
419   }
420
421   bool OnEffectButtonClicked( Toolkit::Button button )
422   {
423     switch(mPanState)
424     {
425       case PAN_SCENE:
426         mPanState = ROTATE_SCENE;
427         mTitleActor.SetText( APPLICATION_TITLE_ROTATE_SCENE );
428         mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_ROTATE_SCENE ) );
429         break;
430       case ROTATE_SCENE:
431         mPanState = PAN_LIGHT;
432         mTitleActor.SetText( APPLICATION_TITLE_PAN_LIGHT );
433         mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_PAN_LIGHT ) );
434         break;
435       case PAN_LIGHT:
436         mPanState = PAN_OBJECT;
437         mTitleActor.SetText( APPLICATION_TITLE_PAN_OBJECT );
438         mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_PAN_OBJECT ) );
439         break;
440       case PAN_OBJECT:
441         mPanState = PAN_SCENE;
442         mTitleActor.SetText( APPLICATION_TITLE_PAN_SCENE );
443         mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_PAN_SCENE ) );
444         break;
445       default:
446         break;
447     }
448
449     mTitleActor.SetStyleToCurrentText(DemoHelper::GetDefaultTextStyle());
450
451     return true;
452   }
453
454   bool OnResetPressed( Toolkit::Button button )
455   {
456     // Reset translation
457     mTranslation = Vector3::ZERO;
458     mContents.SetPosition(mTranslation);
459
460     // Align scene so that light anchor orientation is Z Axis
461     mAxisTilt = -mLightAxisTilt;
462     mLongitudinal = -mLightLongitudinal;
463     mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
464
465     return true;
466   }
467
468 private:
469   Application&              mApp;
470   Toolkit::View             mView;
471   Layer                     mContents;
472   Actor                     mSceneActor;
473   Animation                 mAnimation;
474   Animation                 mSceneAnimation;
475   bool                      mPaused;
476   Toolkit::ShadowView       mShadowView;
477   ImageActor                mShadowPlaneBg;
478   ImageActor                mShadowPlane;
479   Actor                     mCastingLight;
480   Actor                     mLightAnchor;
481   ImageActor                mImageActor1;
482   ImageActor                mImageActor2;
483   ImageActor                mImageActor3;
484   PanGestureDetector        mPanGestureDetector;
485   PinchGestureDetector      mPinchGestureDetector;
486   TapGestureDetector        mTapGestureDetector;
487   Vector3                   mTranslation;
488   Degree                    mLongitudinal;
489   Degree                    mAxisTilt;
490   Degree                    mLightLongitudinal;
491   Degree                    mLightAxisTilt;
492   Degree                    mObjectLongitudinal;
493   Degree                    mObjectAxisTilt;
494   float                     mPinchScale;
495   float                     mScaleAtPinchStart;
496
497   Property::Index           mAngle1Index;
498   Property::Index           mAngle3Index;
499
500   Toolkit::TextView         mTitleActor;
501
502   enum PanState
503   {
504     PAN_SCENE,
505     ROTATE_SCENE,
506     PAN_LIGHT,
507     PAN_OBJECT
508   };
509
510   PanState                  mPanState;
511 };
512
513 /*****************************************************************************/
514
515 static void
516 RunTest(Application& app)
517 {
518   TestApp theApp(app);
519   app.MainLoop();
520 }
521
522 /*****************************************************************************/
523
524 int
525 main(int argc, char **argv)
526 {
527   Application app = Application::New(&argc, &argv);
528
529   RunTest(app);
530
531   return 0;
532 }