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>
25 using namespace Dali::Toolkit;
27 using namespace DemoHelper;
31 const char* gModelFile = DALI_MODEL_DIR "AlbumCute.dae";
32 const char* gBinaryModelFile = DALI_MODEL_DIR "AlbumCute.dali-bin";
34 const char* BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-default.png" );
35 const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
37 const char* APPLICATION_TITLE_PAN_LIGHT( "Lighting: Pan Light" );
38 const char* APPLICATION_TITLE_PAN_OBJECT( "Lighting: Pan Object" );
39 const char* APPLICATION_TITLE_PAN_SCENE( "Lighting: Pan Scene" );
40 const char* APPLICATION_TITLE_ROTATE_SCENE( "Lighting: Rotate Scene" );
41 const char* CHANGE_EFFECT_IMAGE( DALI_IMAGE_DIR "icon-change.png" );
42 const char* RESET_ICON( DALI_IMAGE_DIR "icon-reset.png" );
44 const Quaternion JAUNTY_ROTATION(Math::PI/5.0f, Math::PI/5.0f, 0.0f); // Euler angles
45 const float MIN_PINCH_SCALE( 0.3f );
46 const float MAX_PINCH_SCALE( 2.05f );
48 const float R3_2(0.8660254);
49 const Vector3 TOP_POINT( 0.0f, -1.0f, 0.0f);
50 const Vector3 LEFT_POINT( -R3_2, 0.5f, 0.0f);
51 const Vector3 RIGHT_POINT( R3_2, 0.5f, 0.0f);
52 const Vector3 FRONT_POINT( 0.0f, 0.0f, 20.0f);
54 const Vector2 DEFAULT_STAGE_SIZE( 480.0f, 800.0f );
59 * This example shows a fixed point light onto an animating model
60 * casting a shadow onto a wall. The whole scene can be rotated.
63 class TestApp : public ConnectionTracker
69 * @param application class, stored as reference
71 TestApp(Application &app)
74 mTranslation(Vector3::ZERO),
77 mLightLongitudinal(0.0f),
79 mObjectLongitudinal(0.0f),
80 mObjectAxisTilt(0.0f),
82 mScaleAtPinchStart(0.5f),
85 app.InitSignal().Connect(this, &TestApp::Create);
86 app.TerminateSignal().Connect(this, &TestApp::Terminate);
91 // Nothing to do here; All the members of this class get deleted automatically and they delete their children
95 struct PositionInFrontOf
101 Vector3 operator()( const Vector3& current, const PropertyInput& property )
103 Vector3 position = property.GetVector3();
109 struct QuaternionEqualToConstraint
111 QuaternionEqualToConstraint()
115 Quaternion operator()( const Quaternion& current, const PropertyInput& property )
117 return property.GetQuaternion();
123 * This method gets called once the main loop of application is up and running
125 void Create(Application& app)
127 srand(0); // Want repeatable path
129 Stage::GetCurrent().KeyEventSignal().Connect(this, &TestApp::OnKeyEvent);
131 mModel = Model::New(gBinaryModelFile); // trigger model load
132 mModel.LoadingFinishedSignal().Connect(this, &TestApp::BinaryModelLoaded);
134 CreateToolbarAndView(app);
135 CreateShadowViewAndLights();
138 void CreateToolbarAndView(Application& app)
140 // Creates a default view with a default tool bar.
141 // The view is added to the stage.
142 Toolkit::ToolBar toolBar;
143 mContents = DemoHelper::CreateView( app,
150 // Add an effect-changing button on the right of the tool bar.
151 Image imageChangeEffect = Image::New( CHANGE_EFFECT_IMAGE );
152 Toolkit::PushButton effectChangeButton = Toolkit::PushButton::New();
153 effectChangeButton.SetBackgroundImage(imageChangeEffect);
154 effectChangeButton.ClickedSignal().Connect( this, &TestApp::OnEffectButtonClicked );
155 toolBar.AddControl( effectChangeButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
157 // Add title to the tool bar.
158 mTitleActor = Toolkit::TextView::New();
159 toolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Toolkit::Alignment::HorizontalCenter );
162 mTitleActor.SetText( APPLICATION_TITLE_PAN_SCENE );
163 mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_PAN_SCENE ) );
164 mTitleActor.SetStyleToCurrentText( DemoHelper::GetDefaultTextStyle() );
167 Image resetImage = Image::New( RESET_ICON );
168 Toolkit::PushButton resetButton = Toolkit::PushButton::New();
169 resetButton.SetBackgroundImage( resetImage );
170 resetButton.ClickedSignal().Connect( this, &TestApp::OnResetPressed );
171 toolBar.AddControl( resetButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalCenter, DemoHelper::DEFAULT_PLAY_PADDING );
174 mView.SetPosition(Vector3(0.0f, 0.0f, -50));
176 mContents.SetPosition(mTranslation);
177 mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
178 mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
180 mPanGestureDetector = PanGestureDetector::New();
181 mPanGestureDetector.Attach( mView );
182 mPanGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPan);
184 mPinchGestureDetector = PinchGestureDetector::New();
185 mPinchGestureDetector.Attach( mView );
186 mPinchGestureDetector.DetectedSignal().Connect(this, &TestApp::OnPinch);
188 mTapGestureDetector = TapGestureDetector::New(1, 1);
189 mTapGestureDetector.Attach( mView );
190 mTapGestureDetector.DetectedSignal().Connect(this, &TestApp::OnTap);
194 * This method gets called once the model is loaded by the resource manager
196 void BinaryModelLoaded(Model model)
198 if( model.GetLoadingState() == ResourceLoadingSucceeded )
200 std::cout << "Succeeded loading binary model" << std::endl;
206 std::cout << "Failed loading binary model" << std::endl;
208 mModel = Model::New(gModelFile);
209 mModel.LoadingFinishedSignal().Connect(this, &TestApp::ModelLoaded);
213 void ModelLoaded(Model model)
215 if( model.GetLoadingState() == ResourceLoadingSucceeded )
217 std::cout << "Succeeded loading collada model" << std::endl;
219 model.Save(gBinaryModelFile);
224 std::cout << "Failed loading collada model" << std::endl;
230 void CreateShadowViewAndLights()
232 mShadowView = Toolkit::ShadowView::New();
233 mShadowView.SetName("Container");
234 mShadowView.SetParentOrigin(ParentOrigin::CENTER);
235 mShadowView.SetAnchorPoint(AnchorPoint::CENTER);
236 mShadowView.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
237 mShadowView.SetPointLightFieldOfView( Math::PI / 2.0f);
238 mContents.Add(mShadowView);
240 Image brickWall = Image::New(DALI_IMAGE_DIR "brick-wall.jpg");
241 mShadowPlaneBg = ImageActor::New(brickWall);
242 mShadowPlaneBg.SetParentOrigin(ParentOrigin::CENTER);
243 mShadowPlaneBg.SetAnchorPoint(AnchorPoint::CENTER);
244 mShadowPlaneBg.SetName("Plane");
245 mShadowPlaneBg.SetSize(1000.0f, 1000.0f);
246 mContents.Add(mShadowPlaneBg);
247 mShadowPlaneBg.SetPosition(Vector3(50.0f, 50.0f, -200.0f));
249 mShadowView.SetShadowPlane(mShadowPlaneBg);
250 mShadowView.Activate();
252 mLightAnchor = Actor::New();
253 mLightAnchor.SetParentOrigin(ParentOrigin::CENTER);
254 mLightAnchor.SetAnchorPoint(AnchorPoint::CENTER);
255 mLightAnchor.SetRotation(CalculateWorldRotation(Radian(mLightLongitudinal), Radian(mLightAxisTilt)));
257 // Work out a scaling factor as the initial light position was calculated for desktop
258 // Need to scale light position as model size is based on stage size (i.e. much bigger on device)
259 Vector2 stageSize( Stage::GetCurrent().GetSize() );
260 float scaleFactor = stageSize.x / DEFAULT_STAGE_SIZE.x;
262 mCastingLight = Actor::New();
263 mCastingLight.SetParentOrigin(ParentOrigin::CENTER);
264 mCastingLight.SetAnchorPoint(AnchorPoint::CENTER);
265 mCastingLight.SetPosition( Vector3( 0.0f, 0.0f, 800.0f ) * scaleFactor );
267 TextActor text = TextActor::New("Light", Font::New(FontParameters("Times New Roman", "Book", PointSize(20.0f))));
268 text.SetColor(Color::BLUE);
270 mCastingLight.Add(text);
271 mLightAnchor.Add(mCastingLight);
272 mShadowPlaneBg.Add(mLightAnchor);
274 text.SetParentOrigin(ParentOrigin::CENTER);
275 mShadowView.SetPointLight(mCastingLight);
280 mModelActor = ModelActorFactory::BuildActorTree(mModel, ""); // Gets root actor
284 Vector2 stageSize(Stage::GetCurrent().GetSize());
286 mModelActor.SetSize(250.0f, 250.0f);
287 mModelActor.SetPosition(0.0f, 0.0f, 130.0f);
290 Light keylight = Light::New("KeyLight");
291 keylight.SetFallOff(Vector2(10000.0f, 10000.0f));
292 //keylight.SetSpecularColor(Vector3::ZERO);
293 mKeyLightActor = LightActor::New();
294 mKeyLightActor.SetParentOrigin(ParentOrigin::CENTER);
295 mKeyLightActor.SetName(keylight.GetName());
297 //Add all the actors to the stage
298 mCastingLight.Add(mKeyLightActor);
299 mKeyLightActor.SetLight(keylight);
301 mShadowView.Add(mModelActor);
304 if (mModel.NumberOfAnimations())
306 mModelAnimation = ModelActorFactory::BuildAnimation(mModel, mModelActor, 0);
307 mModelAnimation.SetDuration(4.0f);
308 mModelAnimation.SetLooping(true);
309 mModelAnimation.Play();
316 Quaternion CalculateWorldRotation(Radian longitude, Radian axisTilt )
318 Quaternion q(longitude, Vector3::YAXIS);
319 Quaternion p(axisTilt, Vector3::XAXIS);
323 void OnTap(Dali::Actor actor, TapGesture gesture)
327 //mAnimation.Pause();
328 mModelAnimation.Pause();
334 mModelAnimation.Play();
339 void OnPan(Actor actor, PanGesture gesture)
341 switch (gesture.state)
343 case Gesture::Continuing:
349 mLightLongitudinal += gesture.displacement.x/4.0f;
350 mLightAxisTilt -= gesture.displacement.y/6.0f;
351 mLightAxisTilt = Clamp<float>(mLightAxisTilt, -90.0f, 90.0f);
352 mLightAnchor.SetRotation(CalculateWorldRotation(Radian(mLightLongitudinal), Radian(mLightAxisTilt)));
358 mTranslation += Vector3(gesture.displacement.x, gesture.displacement.y, 0.f);
359 mContents.SetPosition(mTranslation);
365 mLongitudinal += gesture.displacement.x/4.0f;
366 mAxisTilt -= gesture.displacement.y/6.0f;
367 mAxisTilt = Clamp<float>(mAxisTilt, -90.0f, 90.0f);
368 mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
374 mObjectLongitudinal += gesture.displacement.x/4.0f;
375 mObjectAxisTilt -= gesture.displacement.y/6.0f;
376 mObjectAxisTilt = Clamp<float>(mObjectAxisTilt, -90.0f, 90.0f);
377 mModelActor.SetRotation(CalculateWorldRotation(Radian(mObjectLongitudinal), Radian(mObjectAxisTilt)));
384 case Gesture::Finished:
385 // Start animation at last known speed
393 void OnPinch(Actor actor, PinchGesture gesture)
395 if (gesture.state == Gesture::Started)
397 mScaleAtPinchStart = mContents.GetCurrentScale().x;
399 mPinchScale = Clamp(mScaleAtPinchStart * gesture.scale, MIN_PINCH_SCALE, MAX_PINCH_SCALE);
401 mContents.SetScale(mPinchScale, mPinchScale, mPinchScale);
404 void Terminate(Application& app)
408 Stage::GetCurrent().Remove(mModelActor);
412 Stage::GetCurrent().Remove(mKeyLightActor);
416 Stage::GetCurrent().Remove(mView);
420 void OnKeyEvent(const KeyEvent& event)
422 if(event.state == KeyEvent::Down)
424 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
431 bool OnEffectButtonClicked( Toolkit::Button button )
436 mPanState = ROTATE_SCENE;
437 mTitleActor.SetText( APPLICATION_TITLE_ROTATE_SCENE );
438 mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_ROTATE_SCENE ) );
441 mPanState = PAN_LIGHT;
442 mTitleActor.SetText( APPLICATION_TITLE_PAN_LIGHT );
443 mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_PAN_LIGHT ) );
446 mPanState = PAN_OBJECT;
447 mTitleActor.SetText( APPLICATION_TITLE_PAN_OBJECT );
448 mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_PAN_OBJECT ) );
451 mPanState = PAN_SCENE;
452 mTitleActor.SetText( APPLICATION_TITLE_PAN_SCENE );
453 mTitleActor.SetSize( Font::New().MeasureText( APPLICATION_TITLE_PAN_SCENE ) );
459 mTitleActor.SetStyleToCurrentText(DemoHelper::GetDefaultTextStyle());
464 bool OnResetPressed( Toolkit::Button button )
467 mTranslation = Vector3::ZERO;
468 mContents.SetPosition(mTranslation);
469 // Align scene so that light anchor orientation is Z Axis
470 mAxisTilt = -mLightAxisTilt;
471 mLongitudinal = -mLightLongitudinal;
472 mContents.SetRotation(CalculateWorldRotation(Radian(mLongitudinal), Radian(mAxisTilt)));
483 LightActor mKeyLightActor;
484 Animation mAnimation;
485 Animation mModelAnimation;
487 Toolkit::ShadowView mShadowView;
488 ImageActor mShadowPlaneBg;
489 ImageActor mShadowPlane;
493 PanGestureDetector mPanGestureDetector;
494 PinchGestureDetector mPinchGestureDetector;
495 TapGestureDetector mTapGestureDetector;
496 Vector3 mTranslation;
497 Degree mLongitudinal;
499 Degree mLightLongitudinal;
500 Degree mLightAxisTilt;
501 Degree mObjectLongitudinal;
502 Degree mObjectAxisTilt;
504 float mScaleAtPinchStart;
506 Toolkit::TextView mTitleActor;
519 /*****************************************************************************/
522 RunTest(Application& app)
528 /*****************************************************************************/
531 main(int argc, char **argv)
533 Application app = Application::New(&argc, &argv);