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 <dali/internal/event/common/stage-impl.h>
26 #include <dali/integration-api/system-overlay.h>
27 #include <dali/internal/event/actors/layer-impl.h>
28 #include <dali/internal/event/actors/layer-list.h>
29 #include <dali/internal/event/actors/camera-actor-impl.h>
30 #include <dali/internal/event/actor-attachments/camera-attachment-impl.h>
31 #include <dali/internal/event/common/system-overlay-impl.h>
32 #include <dali/internal/event/common/thread-local-storage.h>
33 #include <dali/internal/event/common/property-notification-manager.h>
34 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
35 #include <dali/internal/update/nodes/node.h>
36 #include <dali/internal/event/common/object-registry-impl.h>
37 #include <dali/integration-api/platform-abstraction.h>
38 #include <dali/public-api/common/constants.h>
39 #include <dali/public-api/render-tasks/render-task-list.h>
41 #ifdef DYNAMICS_SUPPORT
42 #include <dali/internal/event/dynamics/dynamics-world-config-impl.h>
43 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
44 #include <dali/integration-api/dynamics/dynamics-factory-intf.h>
45 #include <dali/integration-api/dynamics/dynamics-world-settings.h>
49 using namespace boost;
51 using Dali::Internal::SceneGraph::Node;
62 const float DEFAULT_STEREO_BASE( 65.0f );
64 } // unnamed namespace
66 StagePtr Stage::New( AnimationPlaylist& playlist,
67 PropertyNotificationManager& propertyNotificationManager,
68 SceneGraph::UpdateManager& updateManager,
69 NotificationManager& notificationManager )
71 return StagePtr( new Stage( playlist, propertyNotificationManager, updateManager, notificationManager ) );
74 void Stage::Initialize()
76 mObjectRegistry = ObjectRegistry::New();
78 // Create the ordered list of layers
79 mLayerList = LayerList::New( *this, false/*not system-level*/ );
81 // The stage owns the default layer
82 mRootLayer = Layer::NewRoot( *this, *mLayerList, mUpdateManager, false/*not system-level*/ );
83 mRootLayer->SetName("RootLayer");
85 // Create the default camera actor first; this is needed by the RenderTaskList
86 CreateDefaultCameraActor();
88 // Create the list of render-tasks
89 mRenderTaskList = RenderTaskList::New( mUpdateManager, *this, false/*not system-level*/ );
91 // Create the default render-task
92 Dali::RenderTask defaultRenderTask = mRenderTaskList->CreateTask();
95 void Stage::Uninitialize()
97 // Remove actors added to SystemOverlay
98 delete mSystemOverlay;
99 mSystemOverlay = NULL;
103 Remove(*(mDefaultCamera.Get()));
108 // we are closing down so just delete the root, no point emit disconnect
109 // signals or send messages to update
114 StagePtr Stage::GetCurrent()
116 return ThreadLocalStorage::Get().GetCurrentStage();
119 bool Stage::IsInstalled()
121 return ThreadLocalStorage::Created();
124 ObjectRegistry& Stage::GetObjectRegistry()
126 return *mObjectRegistry;
129 Layer& Stage::GetRootActor()
134 SceneGraph::UpdateManager& Stage::GetUpdateManager()
136 return mUpdateManager;
139 EventToUpdate& Stage::GetUpdateInterface()
141 return mUpdateManager.GetEventToUpdate();
144 AnimationPlaylist& Stage::GetAnimationPlaylist()
146 return mAnimationPlaylist;
149 PropertyNotificationManager& Stage::GetPropertyNotificationManager()
151 return mPropertyNotificationManager;
154 void Stage::Add( Actor& actor )
156 mRootLayer->Add( actor );
159 void Stage::Remove( Actor& actor )
161 mRootLayer->Remove( actor );
164 void Stage::SetSize(float width, float height)
166 // Internally we want to report the actual size of the stage.
168 mSize.height = height;
170 // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
171 mDefaultCamera->SetPerspectiveProjection( mSize );
173 // The depth of the stage gets set to the maximun of these values
174 mRootLayer->SetSize( mSize );
176 // Repeat for SystemOverlay actors
179 mSystemOverlay->GetImpl()->SetSize( mSize.width, mSize.height );
182 SetDefaultSurfaceRectMessage( mUpdateManager, Rect<int>( 0, 0, width, height ) );
185 Vector2 Stage::GetSize() const
190 RenderTaskList& Stage::GetRenderTaskList() const
192 return *mRenderTaskList;
195 void Stage::CreateDefaultCameraActor()
197 // The default camera attributes and position is such that
198 // children of the default layer, can be positioned at (0,0) and
199 // be at the top-left of the viewport.
200 mDefaultCamera = CameraActor::New( Size::ZERO );
201 mDefaultCamera->SetParentOrigin(ParentOrigin::CENTER);
202 Add(*(mDefaultCamera.Get()));
205 Actor& Stage::GetDefaultRootActor()
210 CameraActor& Stage::GetDefaultCameraActor()
212 return *mDefaultCamera;
215 unsigned int Stage::GetLayerCount() const
217 return mLayerList->GetLayerCount();
220 Dali::Layer Stage::GetLayer( unsigned int depth ) const
222 return Dali::Layer(mLayerList->GetLayer( depth ));
225 Dali::Layer Stage::GetRootLayer() const
227 return Dali::Layer( mRootLayer.Get() );
230 LayerList& Stage::GetLayerList()
235 Integration::SystemOverlay& Stage::GetSystemOverlay()
237 // Lazily create system-level if requested
238 if( !mSystemOverlay )
240 mSystemOverlay = new Integration::SystemOverlay( SystemOverlay::New( *this ) );
241 DALI_ASSERT_ALWAYS( NULL != mSystemOverlay && "Failed to create system overlay" );
243 mSystemOverlay->GetImpl()->SetSize( mSize.width, mSize.height );
246 return *mSystemOverlay;
249 SystemOverlay* Stage::GetSystemOverlayInternal()
251 SystemOverlay* overlay( NULL );
255 overlay = mSystemOverlay->GetImpl();
261 void Stage::SetViewMode( ViewMode viewMode )
263 if( mViewMode != viewMode )
265 DALI_LOG_INFO( Debug::Filter::gActor, Debug::Concise, "View mode changed from %d to %d\n", mViewMode, viewMode);
267 if( mViewMode == MONO )
269 mDefaultCamera->SetRotation( Degree( 180.0f ), Vector3::YAXIS );
270 mRenderTaskList->GetTask(0).SetSourceActor( Dali::Actor() );
272 //Create camera and RenderTask for left eye
273 mLeftCamera = CameraActor::New( Size::ZERO );
274 mLeftCamera->SetParentOrigin( ParentOrigin::CENTER );
275 mDefaultCamera->Add( *mLeftCamera.Get() );
276 mLeftRenderTask = mRenderTaskList->CreateTask();
277 mLeftRenderTask.SetCameraActor( Dali::CameraActor( mLeftCamera.Get() ) );
278 mLeftCamera->SetType( Dali::Camera::FREE_LOOK );
280 //Create camera and RenderTask for right eye
281 mRightCamera = CameraActor::New( Size::ZERO );
282 mRightCamera->SetParentOrigin( ParentOrigin::CENTER );
283 mDefaultCamera->Add( *mRightCamera.Get() );
284 mRightRenderTask = mRenderTaskList->CreateTask();
285 mRightRenderTask.SetClearColor( Vector4( 1.0f,0.0f,0.0f,1.0f));
287 mRightRenderTask.SetCameraActor( Dali::CameraActor( mRightCamera.Get() ) );
288 mRightCamera->SetType( Dali::Camera::FREE_LOOK );
292 mViewMode = viewMode;
298 // delete extra stereoscopic render tasks and cameras
299 mRenderTaskList->RemoveTask( mLeftRenderTask );
300 mDefaultCamera->Remove( *mLeftCamera.Get() );
301 mLeftRenderTask.Reset();
303 mRenderTaskList->RemoveTask( mRightRenderTask );
304 mDefaultCamera->Remove( *mRightCamera.Get() );
305 mRightRenderTask.Reset();
306 mRightCamera.Reset();
308 mDefaultCamera->SetRotation( Degree( 0.0f ), Vector3::YAXIS );
309 mDefaultCamera->SetType( Dali::Camera::LOOK_AT_TARGET );
310 mRenderTaskList->GetTask(0).SetSourceActor( Dali::Layer(mRootLayer.Get()) );
314 case STEREO_HORIZONTAL:
316 //Stereo mode with horizontal split is for landscape mode. That's the reason for the cameras being rotated
317 //Top camera renders the scene as seen from the right eye and bottom camera as seen from left.
319 //Calculate separation in pixels along vertical axis ( mStereoBase is defined in millimetres )
320 const float stereoBase( ( (mStereoBase / 25.4f) * GetDpi().y ) * 0.5f );
322 //Calculate aspect ratio
323 float aspect = mSize.width / (mSize.height * 0.5f);
325 mLeftCamera->SetPerspectiveProjection( mSize, Vector2( 0.0f,stereoBase) );
326 mLeftCamera->SetAspectRatio( aspect );
327 mLeftCamera->SetRotation( Degree(-90.0f), Vector3::ZAXIS );
328 mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
329 mLeftRenderTask.SetViewport( Viewport(0, mSize.height * 0.5f, mSize.width, mSize.height * 0.5f) );
331 mRightCamera->SetPerspectiveProjection( mSize, Vector2( 0.0, -stereoBase) );
332 mRightCamera->SetAspectRatio( aspect );
333 mRightCamera->SetRotation( Degree(-90.0f), Vector3::ZAXIS );
334 mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
335 mRightRenderTask.SetViewport( Viewport(0, 0, mSize.width, mSize.height * 0.5f ) );
339 case STEREO_VERTICAL:
341 //Calculate separation in pixels along horizontal axis
342 const float stereoBase( ( (mStereoBase / 25.4f) * GetDpi().x ) * 0.5f );
344 //Recalculate fov based on viewport size
345 const float fov = 2.0f * std::atan( mSize.y / (2.0f * std::max( mSize.x*0.5f, mSize.y )) );
347 mLeftCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(stereoBase,0.0f) );
348 mLeftCamera->SetFieldOfView( fov );
349 mLeftCamera->SetRotation( Degree(0.0f), Vector3::ZAXIS );
350 mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
351 mLeftRenderTask.SetViewport( Viewport(0, 0, mSize.width * 0.5f, mSize.height ) );
353 mRightCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(-stereoBase,0.0f) );
354 mRightCamera->SetFieldOfView( fov );
355 mRightCamera->SetRotation( Degree(0.0f), Vector3::ZAXIS );
356 mRightCamera->SetPosition( Vector3( -stereoBase, 0.0f, 0.0f ) );
357 mRightRenderTask.SetViewport( Viewport(mSize.width * 0.5f, 0, mSize.width * 0.5f, mSize.height ) );
361 case STEREO_INTERLACED:
369 ViewMode Stage::GetViewMode() const
374 void Stage::SetStereoBase( float stereoBase )
376 if( ! Equals( mStereoBase, stereoBase ) )
378 DALI_LOG_INFO( Debug::Filter::gActor, Debug::Concise, "old( %.2f) new(%.2f)", mStereoBase, stereoBase );
379 mStereoBase = stereoBase;
383 case STEREO_HORIZONTAL:
385 stereoBase = mStereoBase / 25.4f * GetDpi().y * 0.5f;
386 float aspect = mSize.width / (mSize.height * 0.5f);
388 mLeftCamera->SetPerspectiveProjection( mSize, Vector2( 0.0, stereoBase) );
389 mLeftCamera->SetAspectRatio( aspect );
390 mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
392 mRightCamera->SetPerspectiveProjection( mSize, Vector2( 0.0, -stereoBase) );
393 mRightCamera->SetAspectRatio( aspect );
394 mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
398 case STEREO_VERTICAL:
400 stereoBase = mStereoBase / 25.4f * GetDpi().x * 0.5f;
401 const float fov = 2.0f * std::atan( mSize.y / (2.0f * std::max( mSize.x*0.5f, mSize.y )) );
403 mLeftCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(stereoBase,0.0f) );
404 mLeftCamera->SetFieldOfView( fov );
405 mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
407 mRightCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(-stereoBase,0.0f) );
408 mRightCamera->SetFieldOfView( fov );
409 mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
419 float Stage::GetStereoBase() const
424 void Stage::SetBackgroundColor(Vector4 color)
426 // Cache for public GetBackgroundColor()
427 mBackgroundColor = color;
429 // Send message to change color in next frame
430 SetBackgroundColorMessage( mUpdateManager, color );
433 Vector4 Stage::GetBackgroundColor() const
435 return mBackgroundColor;
438 Vector2 Stage::GetDpi() const
443 void Stage::SetDpi(Vector2 dpi)
448 #ifdef DYNAMICS_SUPPORT
450 DynamicsNotifier& Stage::GetDynamicsNotifier()
452 return mDynamicsNotifier;
455 DynamicsWorldPtr Stage::InitializeDynamics(DynamicsWorldConfigPtr config)
457 if( !mDynamicsFactory )
459 mDynamicsFactory = ThreadLocalStorage::Get().GetPlatformAbstraction().GetDynamicsFactory();
462 if( mDynamicsFactory && !mDynamicsWorld )
464 if( mDynamicsFactory->InitializeDynamics( *(config->GetSettings()) ) )
466 mDynamicsWorld = DynamicsWorld::New();
467 mDynamicsWorld->Initialize( *this, *mDynamicsFactory, config );
470 return mDynamicsWorld;
473 DynamicsWorldPtr Stage::GetDynamicsWorld()
475 return mDynamicsWorld;
478 void Stage::TerminateDynamics()
482 mDynamicsWorld->Terminate(*this);
483 mDynamicsWorld = NULL;
487 #endif // DYNAMICS_SUPPORT
489 void Stage::KeepRendering( float durationSeconds )
491 // Send message to keep rendering
492 KeepRenderingMessage( mUpdateManager, durationSeconds );
495 void Stage::EmitKeyEventSignal(const KeyEvent& event)
497 // Emit the key event signal when no actor in the stage has gained the key input focus
499 mKeyEventSignalV2.Emit( event );
502 void Stage::EmitEventProcessingFinishedSignal()
504 mEventProcessingFinishedSignalV2.Emit();
507 void Stage::EmitTouchedSignal( const TouchEvent& touch )
509 mTouchedSignalV2.Emit( touch );
512 Dali::Stage::KeyEventSignalV2& Stage::KeyEventSignal()
514 return mKeyEventSignalV2;
517 Dali::Stage::EventProcessingFinishedSignalV2& Stage::EventProcessingFinishedSignal()
519 return mEventProcessingFinishedSignalV2;
522 Dali::Stage::TouchedSignalV2& Stage::TouchedSignal()
524 return mTouchedSignalV2;
527 Stage::Stage( AnimationPlaylist& playlist,
528 PropertyNotificationManager& propertyNotificationManager,
529 SceneGraph::UpdateManager& updateManager,
530 NotificationManager& notificationManager )
531 : mAnimationPlaylist( playlist ),
532 mPropertyNotificationManager(propertyNotificationManager),
533 mUpdateManager(updateManager),
534 mNotificationManager(notificationManager),
535 mSize(Vector2::ZERO),
536 mBackgroundColor(Dali::Stage::DEFAULT_BACKGROUND_COLOR),
538 mStereoBase( DEFAULT_STEREO_BASE ),
539 #ifdef DYNAMICS_SUPPORT
540 mDynamicsFactory(NULL),
548 delete mSystemOverlay;
550 mObjectRegistry.Reset();
553 } // namespace Internal