2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "shared/view.h"
21 #include <dali/dali.h>
22 #include <dali-toolkit/dali-toolkit.h>
23 #include <dali-toolkit/devel-api/controls/buttons/button-devel.h>
24 #include <dali-toolkit/devel-api/controls/shadow-view/shadow-view.h>
29 using namespace Dali::Toolkit;
31 using namespace DemoHelper;
35 const char* BACKGROUND_IMAGE( DEMO_IMAGE_DIR "background-default.png" );
36 const char* TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
38 const char* APPLICATION_TITLE_PAN_LIGHT( "Lighting: Pan Light" );
39 const char* APPLICATION_TITLE_ROTATE_OBJECT( "Lighting: Rotate Object" );
40 const char* APPLICATION_TITLE_PAN_SCENE( "Lighting: Pan Scene" );
41 const char* APPLICATION_TITLE_ROTATE_SCENE( "Lighting: Rotate Scene" );
42 const char* CHANGE_EFFECT_IMAGE( DEMO_IMAGE_DIR "icon-change.png" );
43 const char* CHANGE_EFFECT_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-change-selected.png" );
44 const char* RESET_ICON( DEMO_IMAGE_DIR "icon-reset.png" );
45 const char* RESET_ICON_SELECTED( DEMO_IMAGE_DIR "icon-reset-selected.png" );
47 const char* SCENE_IMAGE_1( DEMO_IMAGE_DIR "gallery-small-10.jpg");
48 const char* SCENE_IMAGE_2( DEMO_IMAGE_DIR "gallery-small-42.jpg");
49 const char* SCENE_IMAGE_3( DEMO_IMAGE_DIR "gallery-small-48.jpg");
51 const float MIN_PINCH_SCALE( 0.3f );
52 const float MAX_PINCH_SCALE( 2.05f );
54 const float R3_2(0.8660254);
55 const Vector3 TOP_POINT( 0.0f, -1.0f, 0.0f);
56 const Vector3 LEFT_POINT( -R3_2, 0.5f, 0.0f);
57 const Vector3 RIGHT_POINT( R3_2, 0.5f, 0.0f);
58 const Vector3 FRONT_POINT( 0.0f, 0.0f, 20.0f);
60 const Vector2 DEFAULT_STAGE_SIZE( 480.0f, 800.0f );
62 const float X_ROTATION_DISPLACEMENT_FACTOR = 60.f;
63 const float Y_ROTATION_DISPLACEMENT_FACTOR = 60.f;
64 const float LIGHT_PAN_X_DISPLACEMENT_FACTOR = 1/360.f;
65 const float LIGHT_PAN_Y_DISPLACEMENT_FACTOR = 1/360.f;
70 * This example shows a fixed point light onto an animating set of images
71 * casting a shadow onto a wall. The whole scene can be rotated.
74 class TestApp : public ConnectionTracker
80 * @param application class, stored as reference
82 TestApp(Application &app)
98 mPanGestureDetector(),
99 mPinchGestureDetector(),
100 mTapGestureDetector(),
101 mTranslation( 22.0f, -1.0f, 0.0f ),
102 mSceneXRotation( Degree(-6.0f) ), // Initial values give a reasonable off-straight view.
103 mSceneYRotation( Degree(20.0f) ),
104 mLightXRotation( Degree(-1.5f) ),
105 mLightYRotation( Degree(-9.5f) ),
106 mObjectXRotation(0.0f),
107 mObjectYRotation(0.0f),
109 mScaleAtPinchStart(0.6f),
110 mAngle1Index( Property::INVALID_INDEX ),
111 mAngle3Index( Property::INVALID_INDEX ),
113 mPanState( PAN_LIGHT )
115 app.InitSignal().Connect(this, &TestApp::Create);
116 app.TerminateSignal().Connect(this, &TestApp::Terminate);
121 // Nothing to do here; All the members of this class get deleted automatically and they delete their children
126 struct RotationConstraint
128 RotationConstraint(float sign)
133 void operator()( Quaternion& current, const PropertyInputContainer& inputs )
135 Radian angle( inputs[0]->GetFloat() );
136 current = Quaternion( angle * mSign, Vector3::YAXIS );
143 * This method gets called once the main loop of application is up and running
145 void Create(Application& app)
147 srand(0); // Want repeatable path
149 Stage::GetCurrent().KeyEventSignal().Connect(this, &TestApp::OnKeyEvent);
151 CreateToolbarAndView(app);
152 CreateShadowViewAndLights();
156 void CreateToolbarAndView(Application& app)
158 // Creates a default view with a default tool bar.
159 // The view is added to the stage.
160 Toolkit::ToolBar toolBar;
161 mContents = DemoHelper::CreateView( app,
168 // Add an effect-changing button on the right of the tool bar.
169 Toolkit::PushButton effectChangeButton = Toolkit::PushButton::New();
170 effectChangeButton.SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, CHANGE_EFFECT_IMAGE );
171 effectChangeButton.SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, CHANGE_EFFECT_IMAGE_SELECTED );
172 effectChangeButton.ClickedSignal().Connect( this, &TestApp::OnEffectButtonClicked );
173 toolBar.AddControl( effectChangeButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
175 // Add title to the tool bar.
176 mTitleActor = DemoHelper::CreateToolBarLabel( "" );
177 toolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Toolkit::Alignment::HorizontalCenter );
180 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_LIGHT) );
183 Toolkit::PushButton resetButton = Toolkit::PushButton::New();
184 resetButton.SetProperty( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, RESET_ICON );
185 resetButton.SetProperty( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, RESET_ICON_SELECTED );
186 resetButton.ClickedSignal().Connect( this, &TestApp::OnResetPressed );
187 toolBar.AddControl( resetButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalCenter, DemoHelper::DEFAULT_PLAY_PADDING );
190 mView.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
192 mContents.SetBehavior(Layer::LAYER_3D);
193 mContents.SetPosition(mTranslation);
194 mContents.SetOrientation( CalculateWorldRotation( mSceneXRotation, mSceneYRotation ) );
195 mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
197 mPanGestureDetector = PanGestureDetector::New();
198 mPanGestureDetector.Attach( mView );
199 mPanGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPan);
201 mPinchGestureDetector = PinchGestureDetector::New();
202 mPinchGestureDetector.Attach( mView );
203 mPinchGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPinch);
205 mTapGestureDetector = TapGestureDetector::New();
206 mTapGestureDetector.Attach( mView );
207 mTapGestureDetector.DetectedSignal().Connect(this, &TestApp::OnTap);
212 void CreateShadowViewAndLights()
214 mShadowView = Toolkit::ShadowView::New();
215 mShadowView.SetName("Container");
216 mShadowView.SetParentOrigin(ParentOrigin::CENTER);
217 mShadowView.SetAnchorPoint(AnchorPoint::CENTER);
218 mShadowView.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
219 mShadowView.SetPointLightFieldOfView( Math::PI / 2.0f);
220 mContents.Add(mShadowView);
222 mShadowPlaneBg = ImageView::New( DEMO_IMAGE_DIR "brick-wall.jpg" );
223 mShadowPlaneBg.SetParentOrigin(ParentOrigin::CENTER);
224 mShadowPlaneBg.SetAnchorPoint(AnchorPoint::CENTER);
225 mShadowPlaneBg.SetName("Plane");
226 mShadowPlaneBg.SetSize(1000.0f, 1000.0f);
227 mContents.Add(mShadowPlaneBg);
228 mShadowPlaneBg.SetPosition(Vector3(50.0f, 50.0f, -200.0f));
230 mShadowView.SetShadowPlaneBackground(mShadowPlaneBg);
231 mShadowView.Activate();
233 mLightAnchor = Actor::New();
234 mLightAnchor.SetParentOrigin(ParentOrigin::CENTER);
235 mLightAnchor.SetAnchorPoint(AnchorPoint::CENTER);
236 mLightAnchor.SetOrientation( CalculateWorldRotation( mLightXRotation, mLightYRotation ) );
238 // Work out a scaling factor as the initial light position was calculated for desktop
239 // Need to scale light position as scene actor size is based on stage size (i.e. much bigger on device)
240 Vector2 stageSize( Stage::GetCurrent().GetSize() );
241 float scaleFactor = stageSize.x / DEFAULT_STAGE_SIZE.x;
243 mCastingLight = Actor::New();
244 mCastingLight.SetParentOrigin(ParentOrigin::CENTER);
245 mCastingLight.SetAnchorPoint(AnchorPoint::CENTER);
246 mCastingLight.SetPosition( Vector3( 0.0f, 0.0f, 800.0f ) * scaleFactor );
248 TextLabel text = TextLabel::New( "Light" );
249 text.SetProperty( TextLabel::Property::POINT_SIZE, 20.0f );
250 text.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
251 text.SetColor( Color::BLUE );
253 mCastingLight.Add(text);
254 mLightAnchor.Add(mCastingLight);
255 mShadowPlaneBg.Add(mLightAnchor);
257 text.SetParentOrigin(ParentOrigin::CENTER);
258 mShadowView.SetPointLight(mCastingLight);
263 mSceneActor = Actor::New();
264 mSceneActor.SetParentOrigin(ParentOrigin::CENTER);
266 // Create and add images to the scene actor:
267 mImageActor1 = ImageView::New( SCENE_IMAGE_1 );
268 mImageActor2 = ImageView::New( SCENE_IMAGE_2 );
269 mImageActor3 = ImageView::New( SCENE_IMAGE_3 );
271 mImageActor1.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
272 mImageActor2.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
273 mImageActor3.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
275 mImageActor2.SetParentOrigin(ParentOrigin::CENTER);
277 mImageActor1.SetParentOrigin(ParentOrigin::CENTER_LEFT);
278 mImageActor1.SetAnchorPoint(AnchorPoint::CENTER_RIGHT);
280 mImageActor3.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
281 mImageActor3.SetAnchorPoint(AnchorPoint::CENTER_LEFT);
283 mSceneActor.Add(mImageActor2);
284 mImageActor2.Add(mImageActor1);
285 mImageActor2.Add(mImageActor3);
287 Property::Index angleIndex = mImageActor2.RegisterProperty("angle", Property::Value( Dali::ANGLE_30 ) );
288 Source angleSrc( mImageActor2, angleIndex );
290 Constraint constraint = Constraint::New<Quaternion>( mImageActor1, Actor::Property::ORIENTATION, RotationConstraint(-1.0f) );
291 constraint.AddSource( angleSrc );
294 constraint = Constraint::New<Quaternion>( mImageActor3, Actor::Property::ORIENTATION, RotationConstraint(+1.0f) );
295 constraint.AddSource( angleSrc );
298 mSceneAnimation = Animation::New(2.5f);
300 // Want to animate angle from 30 => -30 and back again smoothly.
302 mSceneAnimation.AnimateTo( Property( mImageActor2, angleIndex ), Property::Value(-Dali::ANGLE_30), AlphaFunction::SIN );
304 mSceneAnimation.SetLooping(true);
305 mSceneAnimation.Play();
307 mSceneActor.SetSize(250.0f, 250.0f);
308 mSceneActor.SetPosition(0.0f, 0.0f, 130.0f);
309 mShadowView.Add(mSceneActor);
313 Quaternion CalculateWorldRotation( Radian XRotation, Radian YRotation )
315 Quaternion p( XRotation, Vector3::XAXIS );
316 Quaternion q( YRotation, Vector3::YAXIS );
320 void OnTap(Dali::Actor actor, const TapGesture& gesture)
322 if( mSceneAnimation )
326 mSceneAnimation.Pause();
331 mSceneAnimation.Play();
337 void OnPan(Actor actor, const PanGesture& gesture)
339 switch (gesture.state)
341 case Gesture::Continuing:
347 mLightXRotation = mLightXRotation - gesture.displacement.y * LIGHT_PAN_X_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis
348 mLightXRotation = Clamp(mLightXRotation, -Dali::ANGLE_45, Dali::ANGLE_45 );
349 mLightYRotation = mLightYRotation + gesture.displacement.x * LIGHT_PAN_Y_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis
350 mLightYRotation = Clamp(mLightYRotation, -Dali::ANGLE_45, Dali::ANGLE_45 );
351 mLightAnchor.SetOrientation( CalculateWorldRotation( mLightXRotation, mLightYRotation ) );
357 mTranslation += Vector3(gesture.displacement.x, gesture.displacement.y, 0.f);
358 mContents.SetPosition(mTranslation);
364 mSceneXRotation = mSceneXRotation - gesture.displacement.y / X_ROTATION_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis
365 mSceneXRotation = Clamp( mSceneXRotation, -Dali::ANGLE_90, Dali::ANGLE_90 );
366 mSceneYRotation = mSceneYRotation + gesture.displacement.x / Y_ROTATION_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis
367 mSceneYRotation = Clamp( mSceneYRotation, -Dali::ANGLE_90, Dali::ANGLE_90 );
368 mContents.SetOrientation( CalculateWorldRotation( mSceneXRotation, mSceneYRotation ) );
374 mObjectXRotation = mObjectXRotation - gesture.displacement.y / X_ROTATION_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis
375 mObjectYRotation = mObjectYRotation + gesture.displacement.x / Y_ROTATION_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis
376 mSceneActor.SetOrientation( CalculateWorldRotation( mObjectXRotation, mObjectYRotation ) );
383 case Gesture::Finished:
384 // Start animation at last known speed
392 void OnPinch(Actor actor, const PinchGesture& gesture)
394 if (gesture.state == Gesture::Started)
396 mScaleAtPinchStart = mContents.GetCurrentScale().x;
398 mPinchScale = Clamp(mScaleAtPinchStart * gesture.scale, MIN_PINCH_SCALE, MAX_PINCH_SCALE);
400 mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
403 void Terminate(Application& app)
407 Stage::GetCurrent().Remove(mSceneActor);
411 Stage::GetCurrent().Remove(mView);
415 void OnKeyEvent(const KeyEvent& event)
417 if(event.state == KeyEvent::Down)
419 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
426 bool OnEffectButtonClicked( Toolkit::Button button )
431 mPanState = ROTATE_OBJECT;
432 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_ROTATE_OBJECT) );
435 mPanState = ROTATE_SCENE;
436 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_ROTATE_SCENE) );
439 mPanState = PAN_SCENE;
440 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_SCENE) );
443 mPanState = PAN_LIGHT;
444 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_LIGHT) );
453 bool OnResetPressed( Toolkit::Button button )
456 mTranslation = Vector3::ZERO;
457 mContents.SetPosition(mTranslation);
459 // Align scene so that light anchor orientation is Z Axis
460 mSceneXRotation = -mLightXRotation;
461 mSceneYRotation = -mLightYRotation;
462 mContents.SetOrientation( CalculateWorldRotation( mSceneXRotation, mSceneYRotation ) );
469 Toolkit::Control mView;
472 Animation mAnimation;
473 Animation mSceneAnimation;
475 Toolkit::ShadowView mShadowView;
476 ImageView mShadowPlaneBg;
477 ImageView mShadowPlane;
480 ImageView mImageActor1;
481 ImageView mImageActor2;
482 ImageView mImageActor3;
483 PanGestureDetector mPanGestureDetector;
484 PinchGestureDetector mPinchGestureDetector;
485 TapGestureDetector mTapGestureDetector;
486 Vector3 mTranslation;
487 Radian mSceneXRotation;
488 Radian mSceneYRotation;
489 Radian mLightXRotation;
490 Radian mLightYRotation;
491 Radian mObjectXRotation;
492 Radian mObjectYRotation;
494 float mScaleAtPinchStart;
496 Property::Index mAngle1Index;
497 Property::Index mAngle3Index;
499 Toolkit::TextLabel mTitleActor;
512 /*****************************************************************************/
514 int DALI_EXPORT_API main(int argc, char **argv)
516 Application app = Application::New(&argc, &argv, DEMO_THEME_PATH);