2 * Copyright (c) 2014 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>
26 using namespace Dali::Toolkit;
28 using namespace DemoHelper;
32 const char* BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-default.png" );
33 const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
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" );
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");
46 const float MIN_PINCH_SCALE( 0.3f );
47 const float MAX_PINCH_SCALE( 2.05f );
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);
55 const Vector2 DEFAULT_STAGE_SIZE( 480.0f, 800.0f );
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;
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.
69 class TestApp : public ConnectionTracker
75 * @param application class, stored as reference
77 TestApp(Application &app)
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),
88 mScaleAtPinchStart(0.5f),
91 app.InitSignal().Connect(this, &TestApp::Create);
92 app.TerminateSignal().Connect(this, &TestApp::Terminate);
97 // Nothing to do here; All the members of this class get deleted automatically and they delete their children
102 struct RotationConstraint
104 RotationConstraint(float sign)
109 void operator()( Quaternion& current, const PropertyInputContainer& inputs )
111 Radian angle( inputs[0]->GetFloat() );
112 current = Quaternion( angle * mSign, Vector3::YAXIS );
119 * This method gets called once the main loop of application is up and running
121 void Create(Application& app)
123 DemoHelper::RequestThemeChange();
125 srand(0); // Want repeatable path
127 Stage::GetCurrent().KeyEventSignal().Connect(this, &TestApp::OnKeyEvent);
129 CreateToolbarAndView(app);
130 CreateShadowViewAndLights();
134 void CreateToolbarAndView(Application& app)
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,
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 );
153 // Add title to the tool bar.
154 mTitleActor = DemoHelper::CreateToolBarLabel( "" );
155 toolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Toolkit::Alignment::HorizontalCenter );
158 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_SCENE) );
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 );
168 mView.SetPosition(Vector3(0.0f, 0.0f, -50));
170 mContents.SetPosition(mTranslation);
171 mContents.SetOrientation( CalculateWorldRotation( mSceneXRotation, mSceneYRotation ) );
172 mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
174 mPanGestureDetector = PanGestureDetector::New();
175 mPanGestureDetector.Attach( mView );
176 mPanGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPan);
178 mPinchGestureDetector = PinchGestureDetector::New();
179 mPinchGestureDetector.Attach( mView );
180 mPinchGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPinch);
182 mTapGestureDetector = TapGestureDetector::New();
183 mTapGestureDetector.Attach( mView );
184 mTapGestureDetector.DetectedSignal().Connect(this, &TestApp::OnTap);
189 void CreateShadowViewAndLights()
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);
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));
208 mShadowView.SetShadowPlane(mShadowPlaneBg);
209 mShadowView.Activate();
211 mLightAnchor = Actor::New();
212 mLightAnchor.SetParentOrigin(ParentOrigin::CENTER);
213 mLightAnchor.SetAnchorPoint(AnchorPoint::CENTER);
214 mLightAnchor.SetOrientation( CalculateWorldRotation( mLightXRotation, mLightYRotation ) );
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;
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 );
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 );
231 mCastingLight.Add(text);
232 mLightAnchor.Add(mCastingLight);
233 mShadowPlaneBg.Add(mLightAnchor);
235 text.SetParentOrigin(ParentOrigin::CENTER);
236 mShadowView.SetPointLight(mCastingLight);
241 mSceneActor = Actor::New();
242 mSceneActor.SetParentOrigin(ParentOrigin::CENTER);
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) );
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 );
253 mImageActor2.SetParentOrigin(ParentOrigin::CENTER);
255 mImageActor1.SetParentOrigin(ParentOrigin::CENTER_LEFT);
256 mImageActor1.SetAnchorPoint(AnchorPoint::CENTER_RIGHT);
258 mImageActor3.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
259 mImageActor3.SetAnchorPoint(AnchorPoint::CENTER_LEFT);
261 mSceneActor.Add(mImageActor2);
262 mImageActor2.Add(mImageActor1);
263 mImageActor2.Add(mImageActor3);
265 Property::Index angleIndex = mImageActor2.RegisterProperty("angle", Property::Value( Dali::ANGLE_30 ) );
266 Source angleSrc( mImageActor2, angleIndex );
268 Constraint constraint = Constraint::New<Quaternion>( mImageActor1, Actor::Property::ORIENTATION, RotationConstraint(-1.0f) );
269 constraint.AddSource( angleSrc );
272 constraint = Constraint::New<Quaternion>( mImageActor3, Actor::Property::ORIENTATION, RotationConstraint(+1.0f) );
273 constraint.AddSource( angleSrc );
276 mSceneAnimation = Animation::New(2.5f);
278 // Want to animate angle from 30 => -30 and back again smoothly.
280 mSceneAnimation.AnimateTo( Property( mImageActor2, angleIndex ), Property::Value(-Dali::ANGLE_30), AlphaFunctions::Sin );
282 mSceneAnimation.SetLooping(true);
283 mSceneAnimation.Play();
285 mSceneActor.SetSize(250.0f, 250.0f);
286 mSceneActor.SetPosition(0.0f, 0.0f, 130.0f);
287 mShadowView.Add(mSceneActor);
291 Quaternion CalculateWorldRotation( Radian XRotation, Radian YRotation )
293 Quaternion p( XRotation, Vector3::XAXIS );
294 Quaternion q( YRotation, Vector3::YAXIS );
298 void OnTap(Dali::Actor actor, const TapGesture& gesture)
300 if( mSceneAnimation )
304 mSceneAnimation.Pause();
309 mSceneAnimation.Play();
315 void OnPan(Actor actor, const PanGesture& gesture)
317 switch (gesture.state)
319 case Gesture::Continuing:
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 ) );
335 mTranslation += Vector3(gesture.displacement.x, gesture.displacement.y, 0.f);
336 mContents.SetPosition(mTranslation);
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 ) );
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 ) );
361 case Gesture::Finished:
362 // Start animation at last known speed
370 void OnPinch(Actor actor, const PinchGesture& gesture)
372 if (gesture.state == Gesture::Started)
374 mScaleAtPinchStart = mContents.GetCurrentScale().x;
376 mPinchScale = Clamp(mScaleAtPinchStart * gesture.scale, MIN_PINCH_SCALE, MAX_PINCH_SCALE);
378 mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
381 void Terminate(Application& app)
385 Stage::GetCurrent().Remove(mSceneActor);
389 Stage::GetCurrent().Remove(mView);
393 void OnKeyEvent(const KeyEvent& event)
395 if(event.state == KeyEvent::Down)
397 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
404 bool OnEffectButtonClicked( Toolkit::Button button )
409 mPanState = ROTATE_SCENE;
410 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_ROTATE_SCENE) );
413 mPanState = PAN_LIGHT;
414 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_LIGHT) );
417 mPanState = ROTATE_OBJECT;
418 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_OBJECT) );
421 mPanState = PAN_SCENE;
422 mTitleActor.SetProperty( TextLabel::Property::TEXT, std::string(APPLICATION_TITLE_PAN_SCENE) );
431 bool OnResetPressed( Toolkit::Button button )
434 mTranslation = Vector3::ZERO;
435 mContents.SetPosition(mTranslation);
437 // Align scene so that light anchor orientation is Z Axis
438 mSceneXRotation = -mLightXRotation;
439 mSceneYRotation = -mLightYRotation;
440 mContents.SetOrientation( CalculateWorldRotation( mSceneXRotation, mSceneYRotation ) );
450 Animation mAnimation;
451 Animation mSceneAnimation;
453 Toolkit::ShadowView mShadowView;
454 ImageActor mShadowPlaneBg;
455 ImageActor mShadowPlane;
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;
472 float mScaleAtPinchStart;
474 Property::Index mAngle1Index;
475 Property::Index mAngle3Index;
477 Toolkit::TextLabel mTitleActor;
490 /*****************************************************************************/
493 RunTest(Application& app)
499 /*****************************************************************************/
502 main(int argc, char **argv)
504 Application app = Application::New(&argc, &argv);