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