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