4530783938368eb4eb16b2b5829a23066acc5db6
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / camera-actor-impl.cpp
1 /*
2  * Copyright (c) 2018 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 // CLASS HEADER
19 #include <dali/internal/event/actors/camera-actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <cstring> // for strcmp
24
25 // INTERNAL INCLUDES
26 #include <dali/public-api/common/stage.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/integration-api/debug.h>
29 #include <dali/internal/event/common/property-helper.h>
30 #include <dali/internal/event/common/stage-impl.h>
31 #include <dali/internal/event/render-tasks/render-task-impl.h>
32 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
33 #include <dali/internal/event/common/projection.h>
34 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
35
36 namespace Dali
37 {
38
39 namespace Internal
40 {
41
42 namespace
43 {
44
45 // Properties
46
47 /**
48  * We want to discourage the use of property strings (minimize string comparisons),
49  * particularly for the default properties.
50  *              Name                     Type   writable animatable constraint-input  enum for index-checking
51  */
52 DALI_PROPERTY_TABLE_BEGIN
53 DALI_PROPERTY( "type",                   STRING,   true,    false,   true,   Dali::CameraActor::Property::TYPE                  )
54 DALI_PROPERTY( "projectionMode",         STRING,   true,    false,   true,   Dali::CameraActor::Property::PROJECTION_MODE       )
55 DALI_PROPERTY( "fieldOfView",            FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FIELD_OF_VIEW         )
56 DALI_PROPERTY( "aspectRatio",            FLOAT,    true,    false,   true,   Dali::CameraActor::Property::ASPECT_RATIO          )
57 DALI_PROPERTY( "nearPlaneDistance",      FLOAT,    true,    false,   true,   Dali::CameraActor::Property::NEAR_PLANE_DISTANCE   )
58 DALI_PROPERTY( "farPlaneDistance",       FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FAR_PLANE_DISTANCE    )
59 DALI_PROPERTY( "leftPlaneDistance",      FLOAT,    true,    false,   true,   Dali::CameraActor::Property::LEFT_PLANE_DISTANCE   )
60 DALI_PROPERTY( "rightPlaneDistance",     FLOAT,    true,    false,   true,   Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE  )
61 DALI_PROPERTY( "topPlaneDistance",       FLOAT,    true,    false,   true,   Dali::CameraActor::Property::TOP_PLANE_DISTANCE    )
62 DALI_PROPERTY( "bottomPlaneDistance",    FLOAT,    true,    false,   true,   Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE )
63 DALI_PROPERTY( "targetPosition",         VECTOR3,  true,    false,   true,   Dali::CameraActor::Property::TARGET_POSITION       )
64 DALI_PROPERTY( "projectionMatrix",       MATRIX,   false,   false,   true,   Dali::CameraActor::Property::PROJECTION_MATRIX     )
65 DALI_PROPERTY( "viewMatrix",             MATRIX,   false,   false,   true,   Dali::CameraActor::Property::VIEW_MATRIX           )
66 DALI_PROPERTY( "invertYAxis",            BOOLEAN,  true,    false,   true,   Dali::CameraActor::Property::INVERT_Y_AXIS         )
67 DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
68
69 // calculate the far plane distance for a 16bit depth buffer with 4 bits per unit precision
70 void CalculateClippingAndZ( float width, float height, float& nearClippingPlane, float& farClippingPlane, float& cameraZ )
71 {
72   nearClippingPlane = std::max( width, height );
73   farClippingPlane = nearClippingPlane + static_cast<float>( 0xFFFF >> 4 );
74   cameraZ = 2.0f * nearClippingPlane;
75 }
76
77 BaseHandle Create()
78 {
79   return Dali::CameraActor::New();
80 }
81
82 TypeRegistration mType( typeid( Dali::CameraActor ), typeid( Dali::Actor ), Create );
83
84 /**
85  * Builds the picking ray in the world reference system from an orthographic camera
86  * The ray origin is the screen coordinate in the near plane translated to a parallel
87  * plane at the camera origin. The ray direction is the direction the camera is facing
88  * (i.e. Z=-1 in view space).
89  */
90 void BuildOrthoPickingRay( const Matrix& viewMatrix,
91                            const Matrix& projectionMatrix,
92                            const Viewport& viewport,
93                            float screenX,
94                            float screenY,
95                            Vector4& rayOrigin,
96                            Vector4& rayDir,
97                            float nearPlaneDistance )
98 {
99   //          inv( modelMatrix )          inv( viewMatrix )    inv( projectionMatrix )           normalize
100   //          <-----------------         <-----------------         <--------------           <-------------
101   //  Local                      World                      Camera                 Normalized                 Screen
102   // reference                  reference                  reference                  clip                  coordinates
103   //  system                     system                     system                 coordinates
104   //          ----------------->         ----------------->         -------------->           ------------->
105   //             modelMatrix                 viewMatrix             projectionMatrix             viewport
106
107   // Transforms the touch point from the screen reference system to the world reference system.
108   Matrix invViewProjection( false ); // Don't initialize.
109   Matrix::Multiply( invViewProjection, viewMatrix, projectionMatrix );
110   if( !invViewProjection.Invert() )
111   {
112     DALI_ASSERT_DEBUG( false );
113   }
114
115   Vector4 near( screenX - static_cast<float>( viewport.x ),
116                 static_cast<float>( viewport.height ) - (screenY - static_cast<float>( viewport.y ) ),
117                 0.f, 1.f );
118   if( !Unproject( near, invViewProjection, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), rayOrigin ) )
119   {
120     DALI_ASSERT_DEBUG( false );
121   }
122
123   Matrix invView = viewMatrix;
124   if( !invView.Invert() )
125   {
126     DALI_ASSERT_DEBUG( false );
127   }
128
129   Vector4 cameraOrigin = invView * Vector4( 0.f, 0.f, 0.f, 1.f );
130   Vector4 nearPlaneOrigin = invView * Vector4( 0.0f, 0.0f, -nearPlaneDistance, 1.0f);
131
132   // Vector pointing from the camera to the near plane
133   rayDir = cameraOrigin - nearPlaneOrigin;
134   rayOrigin -= rayDir;
135   rayDir.Normalize();
136   rayDir.w = 1.0f;
137 }
138
139 } // namespace
140
141 CameraActorPtr CameraActor::New( const Size& size )
142 {
143   CameraActorPtr actor( new CameraActor() );
144
145   // Second-phase construction
146   actor->Initialize();
147
148   actor->SetName( "DefaultCamera" );
149   actor->SetPerspectiveProjection( size );
150
151   // By default Actors face in the positive Z direction in world space
152   // CameraActors should face in the negative Z direction, towards the other actors
153   actor->SetOrientation( Quaternion( Dali::ANGLE_180, Vector3::YAXIS ) );
154
155   return actor;
156 }
157
158 CameraActor::CameraActor()
159 : Actor( Actor::BASIC ),
160   mSceneObject( NULL ),
161   mTarget( SceneGraph::Camera::DEFAULT_TARGET_POSITION ),
162   mType( SceneGraph::Camera::DEFAULT_TYPE ),
163   mProjectionMode( SceneGraph::Camera::DEFAULT_MODE ),
164   mFieldOfView( SceneGraph::Camera::DEFAULT_FIELD_OF_VIEW ),
165   mAspectRatio( SceneGraph::Camera::DEFAULT_ASPECT_RATIO ),
166   mNearClippingPlane( SceneGraph::Camera::DEFAULT_NEAR_CLIPPING_PLANE ),
167   mFarClippingPlane( SceneGraph::Camera::DEFAULT_FAR_CLIPPING_PLANE ),
168   mLeftClippingPlane( SceneGraph::Camera::DEFAULT_LEFT_CLIPPING_PLANE ),
169   mRightClippingPlane( SceneGraph::Camera::DEFAULT_RIGHT_CLIPPING_PLANE ),
170   mTopClippingPlane( SceneGraph::Camera::DEFAULT_TOP_CLIPPING_PLANE ),
171   mBottomClippingPlane( SceneGraph::Camera::DEFAULT_BOTTOM_CLIPPING_PLANE ),
172   mInvertYAxis( SceneGraph::Camera::DEFAULT_INVERT_Y_AXIS )
173 {
174 }
175
176 CameraActor::~CameraActor()
177 {
178   if( EventThreadServices::IsCoreRunning() )
179   {
180     // Create scene-object and transfer ownership through message
181     RemoveCameraMessage( GetEventThreadServices().GetUpdateManager(), mSceneObject );
182   }
183 }
184
185 void CameraActor::OnInitialize()
186 {
187   // Create scene-object and keep raw pointer for message passing.
188   SceneGraph::Camera* sceneGraphCamera = SceneGraph::Camera::New();
189
190   // Store a pointer to this camera node inside the scene-graph camera.
191   sceneGraphCamera->SetNode( mNode );
192
193   mSceneObject = sceneGraphCamera;
194   OwnerPointer< SceneGraph::Camera > sceneGraphCameraOwner( sceneGraphCamera );
195
196   // Send message to inform update of this camera (and move ownership).
197   AddCameraMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphCameraOwner );
198 }
199
200 void CameraActor::SetTarget( const Vector3& target )
201 {
202   if( target != mTarget ) // using range epsilon
203   {
204     mTarget = target;
205
206     SetTargetPositionMessage( GetEventThreadServices(),  *mSceneObject, mTarget );
207   }
208 }
209
210 Vector3 CameraActor::GetTarget() const
211 {
212   return mTarget;
213 }
214
215 void CameraActor::SetType( Dali::Camera::Type type )
216 {
217   if( type != mType )
218   {
219     mType = type;
220
221     // sceneObject is being used in a separate thread; queue a message to set
222     SetTypeMessage( GetEventThreadServices(), *mSceneObject, mType );
223   }
224 }
225
226 Dali::Camera::Type CameraActor::GetType() const
227 {
228   return mType;
229 }
230
231 void CameraActor::SetProjectionMode( Dali::Camera::ProjectionMode mode )
232 {
233   if( mode != mProjectionMode )
234   {
235     mProjectionMode = mode;
236
237     // sceneObject is being used in a separate thread; queue a message to set
238     SetProjectionModeMessage( GetEventThreadServices(), *mSceneObject, mProjectionMode );
239   }
240 }
241
242 Dali::Camera::ProjectionMode CameraActor::GetProjectionMode() const
243 {
244   return mProjectionMode;
245 }
246
247 void CameraActor::SetFieldOfView( float fieldOfView )
248 {
249   if( ! Equals( fieldOfView, mFieldOfView ) )
250   {
251     mFieldOfView = fieldOfView;
252
253     // sceneObject is being used in a separate thread; queue a message to set
254     SetFieldOfViewMessage( GetEventThreadServices(), *mSceneObject, mFieldOfView );
255   }
256 }
257
258 float CameraActor::GetFieldOfView() const
259 {
260   return mFieldOfView;
261 }
262
263 void CameraActor::SetAspectRatio( float aspectRatio )
264 {
265   if( ! Equals( aspectRatio, mAspectRatio ) )
266   {
267     mAspectRatio = aspectRatio;
268
269     // sceneObject is being used in a separate thread; queue a message to set
270     SetAspectRatioMessage( GetEventThreadServices(), *mSceneObject, mAspectRatio );
271   }
272 }
273
274 float CameraActor::GetAspectRatio() const
275 {
276   return mAspectRatio;
277 }
278
279 void CameraActor::SetNearClippingPlane( float nearClippingPlane )
280 {
281   if( ! Equals( nearClippingPlane, mNearClippingPlane ) )
282   {
283     mNearClippingPlane = nearClippingPlane;
284
285     // sceneObject is being used in a separate thread; queue a message to set
286     SetNearClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mNearClippingPlane );
287   }
288 }
289
290 float CameraActor::GetNearClippingPlane() const
291 {
292   return mNearClippingPlane;
293 }
294
295 void CameraActor::SetFarClippingPlane( float farClippingPlane )
296 {
297   if( ! Equals( farClippingPlane, mFarClippingPlane ) )
298   {
299     mFarClippingPlane = farClippingPlane;
300
301     // sceneObject is being used in a separate thread; queue a message to set
302     SetFarClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mFarClippingPlane );
303   }
304 }
305
306 float CameraActor::GetFarClippingPlane() const
307 {
308   return mFarClippingPlane;
309 }
310
311 void CameraActor::SetLeftClippingPlane( float leftClippingPlane )
312 {
313   if( ! Equals( leftClippingPlane, mLeftClippingPlane ) )
314   {
315     mLeftClippingPlane = leftClippingPlane;
316
317     // sceneObject is being used in a separate thread; queue a message to set
318     SetLeftClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mLeftClippingPlane );
319   }
320 }
321
322 void CameraActor::SetRightClippingPlane( float rightClippingPlane )
323 {
324   if( ! Equals( rightClippingPlane, mRightClippingPlane ) )
325   {
326     mRightClippingPlane = rightClippingPlane;
327
328     // sceneObject is being used in a separate thread; queue a message to set
329     SetRightClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mRightClippingPlane );
330   }
331 }
332
333 void CameraActor::SetTopClippingPlane( float topClippingPlane )
334 {
335   if( ! Equals( topClippingPlane, mTopClippingPlane ) )
336   {
337     mTopClippingPlane = topClippingPlane;
338
339     // sceneObject is being used in a separate thread; queue a message to set
340     SetTopClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mTopClippingPlane );
341   }
342 }
343
344 void CameraActor::SetBottomClippingPlane( float bottomClippingPlane )
345 {
346   if( ! Equals( bottomClippingPlane, mBottomClippingPlane ) )
347   {
348     mBottomClippingPlane = bottomClippingPlane;
349
350     // sceneObject is being used in a separate thread; queue a message to set
351     SetBottomClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mBottomClippingPlane );
352   }
353 }
354
355 void CameraActor::SetInvertYAxis(bool invertYAxis)
356 {
357   if( invertYAxis != mInvertYAxis )
358   {
359     mInvertYAxis = invertYAxis;
360
361     // sceneObject is being used in a separate thread; queue a message to set
362     SetInvertYAxisMessage( GetEventThreadServices(), *mSceneObject, mInvertYAxis );
363   }
364 }
365
366 bool CameraActor::GetInvertYAxis() const
367 {
368   return mInvertYAxis;
369 }
370
371 void CameraActor::SetPerspectiveProjection( const Size& size, const Vector2& stereoBias /* = Vector2::ZERO */ )
372 {
373   float width = size.width;
374   float height = size.height;
375
376   if( Size::ZERO == size )
377   {
378     StagePtr stage = Stage::GetCurrent();
379     if( stage )
380     {
381       const Size& stageSize = stage->GetSize();
382
383       width = stageSize.width;
384       height = stageSize.height;
385     }
386   }
387
388   if( ( width < Math::MACHINE_EPSILON_1000 ) || ( height < Math::MACHINE_EPSILON_1000 ) )
389   {
390     // On the stage initialization this method is called but the size has not been set.
391     // There is no point to set any value if width or height is zero.
392     return;
393   }
394
395   float nearClippingPlane;
396   float farClippingPlane;
397   float cameraZ;
398   CalculateClippingAndZ( width, height, nearClippingPlane, farClippingPlane, cameraZ );
399
400   // calculate the position of the camera to have the desired aspect ratio
401   const float fieldOfView = 2.0f * std::atan( height * 0.5f / cameraZ );
402
403   // unless it is too small, we want at least as much space to the back as we have torwards the front
404   const float minClippingFarPlane = 2.f * nearClippingPlane;
405   if ( farClippingPlane < minClippingFarPlane )
406   {
407     farClippingPlane = minClippingFarPlane;
408   }
409
410   const float aspectRatio = width / height;
411
412   SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
413   SetFieldOfView( fieldOfView );
414   SetNearClippingPlane( nearClippingPlane );
415   SetFarClippingPlane( farClippingPlane );
416   SetAspectRatio( aspectRatio );
417   // sceneObject is being used in a separate thread; queue a message to set
418   SetStereoBiasMessage( GetEventThreadServices(), *mSceneObject, stereoBias );
419   SetZ( cameraZ );
420 }
421
422
423 void CameraActor::SetOrthographicProjection( const Vector2& size )
424 {
425   // Choose near, far and Z parameters to match the SetPerspectiveProjection above.
426   float nearClippingPlane;
427   float farClippingPlane;
428   float cameraZ;
429   CalculateClippingAndZ( size.width, size.height, nearClippingPlane, farClippingPlane, cameraZ );
430   SetOrthographicProjection( -size.x*0.5f, size.x*0.5f, size.y*0.5f, -size.y*0.5f,
431                              nearClippingPlane, farClippingPlane );
432   SetZ( cameraZ );
433 }
434
435 void CameraActor::SetOrthographicProjection( float left, float right, float top, float bottom, float near, float far )
436 {
437   SetLeftClippingPlane( left );
438   SetRightClippingPlane( right );
439   SetTopClippingPlane( top );
440   SetBottomClippingPlane( bottom );
441   SetNearClippingPlane( near );
442   SetFarClippingPlane( far );
443   SetProjectionMode( Dali::Camera::ORTHOGRAPHIC_PROJECTION );
444 }
445
446 bool CameraActor::BuildPickingRay( const Vector2& screenCoordinates,
447                                    const Viewport& viewport,
448                                    Vector4& rayOrigin,
449                                    Vector4& rayDirection )
450 {
451   bool success = true;
452   if( mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION )
453   {
454     // Build a picking ray in the world reference system.
455     // ray starts from the camera world position
456     rayOrigin = mNode->GetWorldMatrix(0).GetTranslation();
457     rayOrigin.w = 1.0f;
458
459     // Transform the touch point from the screen coordinate system to the world coordinates system.
460     Vector4 near( screenCoordinates.x - static_cast<float>(viewport.x),
461                   static_cast<float>( viewport.height ) - (screenCoordinates.y - static_cast<float>( viewport.y ) ),
462                   0.f, 1.f );
463     const Matrix& inverseViewProjection = mSceneObject->GetInverseViewProjectionMatrix( GetEventThreadServices().GetEventBufferIndex() );
464     success = Unproject( near, inverseViewProjection, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), near );
465
466     // Compute the ray's director vector.
467     rayDirection.x = near.x - rayOrigin.x;
468     rayDirection.y = near.y - rayOrigin.y;
469     rayDirection.z = near.z - rayOrigin.z;
470     rayDirection.Normalize();
471     rayDirection.w = 1.f;
472   }
473   else
474   {
475     float nearPlaneDistance = GetNearClippingPlane();
476     BuildOrthoPickingRay( GetViewMatrix(),
477                           GetProjectionMatrix(),
478                           viewport, screenCoordinates.x,
479                           screenCoordinates.y,
480                           rayOrigin,
481                           rayDirection,
482                           nearPlaneDistance );
483   }
484
485   return success;
486 }
487
488 const Matrix& CameraActor::GetViewMatrix() const
489 {
490   if ( OnStage() )
491   {
492     return mSceneObject->GetViewMatrix( GetEventThreadServices().GetEventBufferIndex() );
493   }
494   else
495   {
496     return Matrix::IDENTITY;
497   }
498 }
499
500 const Matrix& CameraActor::GetProjectionMatrix() const
501 {
502   if ( OnStage() )
503   {
504     return mSceneObject->GetProjectionMatrix( GetEventThreadServices().GetEventBufferIndex() );
505   }
506   else
507   {
508     return Matrix::IDENTITY;
509   }
510 }
511 const SceneGraph::Camera* CameraActor::GetCamera() const
512 {
513   return mSceneObject;
514 }
515
516 unsigned int CameraActor::GetDefaultPropertyCount() const
517 {
518   return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
519 }
520
521 void CameraActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
522 {
523   Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
524
525   indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
526
527   int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
528   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
529   {
530     indices.PushBack( index );
531   }
532 }
533
534 bool CameraActor::IsDefaultPropertyWritable( Property::Index index ) const
535 {
536   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
537   {
538     return Actor::IsDefaultPropertyWritable( index );
539   }
540
541   return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].writable;
542 }
543
544 bool CameraActor::IsDefaultPropertyAnimatable( Property::Index index ) const
545 {
546   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
547   {
548     return Actor::IsDefaultPropertyAnimatable( index );
549   }
550
551   return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].animatable;
552 }
553
554 bool CameraActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
555 {
556   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
557   {
558     return Actor::IsDefaultPropertyAConstraintInput( index );
559   }
560
561   return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].constraintInput;
562 }
563
564 Property::Type CameraActor::GetDefaultPropertyType( Property::Index index ) const
565 {
566   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
567   {
568     return Actor::GetDefaultPropertyType( index );
569   }
570   else
571   {
572     index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
573
574     if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
575     {
576       return DEFAULT_PROPERTY_DETAILS[index].type;
577     }
578     else
579     {
580       // index out-of-bounds
581       return Property::NONE;
582     }
583   }
584 }
585
586 const char* CameraActor::GetDefaultPropertyName( Property::Index index ) const
587 {
588   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
589   {
590     return Actor::GetDefaultPropertyName(index);
591   }
592   else
593   {
594     index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
595
596     if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
597     {
598       return DEFAULT_PROPERTY_DETAILS[index].name;
599     }
600     return NULL;
601   }
602 }
603
604 Property::Index CameraActor::GetDefaultPropertyIndex(const std::string& name) const
605 {
606   Property::Index index = Property::INVALID_INDEX;
607
608   // Look for name in current class' default properties
609   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
610   {
611     if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
612     {
613       index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
614       break;
615     }
616   }
617
618   // If not found, check in base class
619   if( Property::INVALID_INDEX == index )
620   {
621     index = Actor::GetDefaultPropertyIndex( name );
622   }
623
624   return index;
625 }
626
627 void CameraActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
628 {
629   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
630   {
631     Actor::SetDefaultProperty(index, propertyValue);
632   }
633   else
634   {
635     switch(index)
636     {
637       case Dali::CameraActor::Property::TYPE:
638       {
639         std::string s( propertyValue.Get<std::string>() );
640         if(s == "LOOK_AT_TARGET")
641         {
642           SetType( Dali::Camera::LOOK_AT_TARGET );
643         }
644         else if(s == "FREE_LOOK")
645         {
646           SetType( Dali::Camera::FREE_LOOK );
647         }
648         break;
649       }
650       case Dali::CameraActor::Property::PROJECTION_MODE:
651       {
652         std::string s( propertyValue.Get<std::string>() );
653         if( s == "PERSPECTIVE_PROJECTION" )
654         {
655           SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION );
656         }
657         else if( s == "ORTHOGRAPHIC_PROJECTION" )
658         {
659           SetProjectionMode( Dali::Camera::ORTHOGRAPHIC_PROJECTION );
660         }
661         break;
662       }
663       case Dali::CameraActor::Property::FIELD_OF_VIEW:
664       {
665         SetFieldOfView( propertyValue.Get<float>() ); // set to 0 in case property is not float
666         break;
667       }
668       case Dali::CameraActor::Property::ASPECT_RATIO:
669       {
670         SetAspectRatio( propertyValue.Get<float>() ); // set to 0 in case property is not float
671         break;
672       }
673       case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
674       {
675         SetNearClippingPlane( propertyValue.Get<float>() ); // set to 0 in case property is not float
676         break;
677       }
678       case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
679       {
680         SetFarClippingPlane( propertyValue.Get<float>() ); // set to 0 in case property is not float
681         break;
682       }
683       case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
684       {
685         SetLeftClippingPlane( propertyValue.Get<float>() ); // set to 0 in case property is not float
686         break;
687       }
688       case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
689       {
690         SetRightClippingPlane( propertyValue.Get<float>() ); // set to 0 in case property is not float
691         break;
692       }
693       case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
694       {
695         SetTopClippingPlane( propertyValue.Get<float>() ); // set to 0 in case property is not float
696         break;
697       }
698       case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
699       {
700         SetBottomClippingPlane( propertyValue.Get<float>() ); // set to 0 in case property is not float
701         break;
702       }
703       case Dali::CameraActor::Property::TARGET_POSITION:
704       {
705         SetTarget( propertyValue.Get<Vector3>() ); // set to 0 in case property is not Vector3
706         break;
707       }
708       case Dali::CameraActor::Property::PROJECTION_MATRIX:
709       {
710         DALI_LOG_WARNING( "projection-matrix is read-only\n" );
711         break;
712       }
713       case Dali::CameraActor::Property::VIEW_MATRIX:
714       {
715         DALI_LOG_WARNING( "view-matrix is read-only\n" );
716         break;
717       }
718       case Dali::CameraActor::Property::INVERT_Y_AXIS:
719       {
720         SetInvertYAxis( propertyValue.Get<bool>() ); // set to false in case property is not bool
721         break;
722       }
723       default:
724       {
725         DALI_LOG_WARNING( "Unknown property (%d)\n", index );
726         break;
727       }
728     } // switch(index)
729
730   } // else
731 }
732
733 Property::Value CameraActor::GetDefaultProperty( Property::Index index ) const
734 {
735   Property::Value ret;
736   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
737   {
738     ret = Actor::GetDefaultProperty(index);
739   }
740   else
741   {
742     switch(index)
743     {
744       case Dali::CameraActor::Property::TYPE:
745       {
746         if( Dali::Camera::LOOK_AT_TARGET == mType )
747         {
748           ret = "LOOK_AT_TARGET";
749         }
750         else if( Dali::Camera::FREE_LOOK == mType )
751         {
752           ret = "FREE_LOOK";
753         }
754         break;
755       }
756       case Dali::CameraActor::Property::PROJECTION_MODE:
757       {
758         if( Dali::Camera::PERSPECTIVE_PROJECTION == mProjectionMode )
759         {
760           ret = "PERSPECTIVE_PROJECTION";
761         }
762         else if( Dali::Camera::ORTHOGRAPHIC_PROJECTION == mProjectionMode )
763         {
764           ret = "ORTHOGRAPHIC_PROJECTION";
765         }
766         break;
767       }
768       case Dali::CameraActor::Property::FIELD_OF_VIEW:
769       {
770         ret = mFieldOfView;
771         break;
772       }
773       case Dali::CameraActor::Property::ASPECT_RATIO:
774       {
775         ret = mAspectRatio;
776         break;
777       }
778       case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
779       {
780         ret = mNearClippingPlane;
781         break;
782       }
783       case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
784       {
785         ret = mFarClippingPlane;
786         break;
787       }
788       case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
789       {
790         ret = mLeftClippingPlane;
791         break;
792       }
793       case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
794       {
795         ret = mRightClippingPlane;
796         break;
797       }
798       case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
799       {
800         ret = mTopClippingPlane;
801         break;
802       }
803       case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
804       {
805         ret = mBottomClippingPlane;
806         break;
807       }
808       case Dali::CameraActor::Property::TARGET_POSITION:
809       {
810         ret = mTarget;
811         break;
812       }
813       case Dali::CameraActor::Property::PROJECTION_MATRIX:
814       {
815         ret = GetProjectionMatrix(); // Only on scene-graph
816         break;
817       }
818       case Dali::CameraActor::Property::VIEW_MATRIX:
819       {
820         ret = GetViewMatrix(); // Only on scene-graph
821         break;
822       }
823       case Dali::CameraActor::Property::INVERT_Y_AXIS:
824       {
825         ret = mInvertYAxis;
826         break;
827       }
828     } // switch(index)
829   }
830
831   return ret;
832 }
833
834 Property::Value CameraActor::GetDefaultPropertyCurrentValue( Property::Index index ) const
835 {
836   Property::Value ret;
837   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
838   {
839     ret = Actor::GetDefaultPropertyCurrentValue(index);
840   }
841   else
842   {
843     ret = GetDefaultProperty( index ); // Most are event-side properties, the scene-graph properties are only on the scene-graph
844   }
845
846   return ret;
847 }
848
849 const SceneGraph::PropertyBase* CameraActor::GetSceneObjectAnimatableProperty( Property::Index index ) const
850 {
851   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
852
853   const SceneGraph::PropertyBase* property( NULL );
854
855   // This method should only return a property of an object connected to the scene-graph
856   if ( !OnStage() )
857   {
858     return property;
859   }
860
861   // let actor handle animatable properties, we have no animatable properties
862   if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
863   {
864     property = Actor::GetSceneObjectAnimatableProperty(index);
865   }
866
867   return property;
868 }
869
870 const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty( Property::Index index ) const
871 {
872   const PropertyInputImpl* property( NULL );
873
874   // This method should only return a property of an object connected to the scene-graph
875   if ( !OnStage() )
876   {
877     return property;
878   }
879
880   // if its an actor default property or a custom property (actor already handles custom properties)
881   if( ( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) || ( index >= DEFAULT_PROPERTY_MAX_COUNT ) )
882   {
883     property = Actor::GetSceneObjectInputProperty( index );
884   }
885   else
886   {
887     switch( index )
888     {
889       case Dali::CameraActor::Property::PROJECTION_MATRIX:
890       {
891         property = mSceneObject->GetProjectionMatrix();
892         break;
893       }
894       case Dali::CameraActor::Property::VIEW_MATRIX:
895       {
896         property = mSceneObject->GetViewMatrix();
897         break;
898       }
899       default:
900         DALI_LOG_WARNING("Not an input property (%d)\n", index);
901         break;
902     }
903   }
904
905   return property;
906 }
907
908 } // namespace Internal
909
910 } // namespace Dali