Merge "Use update object size in CalculateActorScreenPosition" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / camera-actor-impl.cpp
1 /*
2  * Copyright (c) 2022 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/devel-api/actors/camera-actor-devel.h>
27 #include <dali/internal/event/common/projection.h>
28 #include <dali/internal/event/common/property-helper.h>
29 #include <dali/internal/event/common/thread-local-storage.h>
30 #include <dali/public-api/object/type-registry.h>
31
32 #include <dali/internal/update/manager/update-manager.h>
33
34 namespace Dali
35 {
36 namespace Internal
37 {
38 namespace
39 {
40 // Properties
41
42 /**
43  * We want to discourage the use of property strings (minimize string comparisons),
44  * particularly for the default properties.
45  *              Name                     Type   writable animatable constraint-input  enum for index-checking
46  */
47 // clang-format off
48 DALI_PROPERTY_TABLE_BEGIN
49 DALI_PROPERTY( "type",                   STRING,   true,    false,   true,   Dali::CameraActor::Property::TYPE                  )
50 DALI_PROPERTY( "projectionMode",         STRING,   true,    false,   true,   Dali::CameraActor::Property::PROJECTION_MODE       )
51 DALI_PROPERTY( "fieldOfView",            FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FIELD_OF_VIEW         )
52 DALI_PROPERTY( "aspectRatio",            FLOAT,    true,    false,   true,   Dali::CameraActor::Property::ASPECT_RATIO          )
53 DALI_PROPERTY( "nearPlaneDistance",      FLOAT,    true,    false,   true,   Dali::CameraActor::Property::NEAR_PLANE_DISTANCE   )
54 DALI_PROPERTY( "farPlaneDistance",       FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FAR_PLANE_DISTANCE    )
55 DALI_PROPERTY( "leftPlaneDistance",      FLOAT,    true,    false,   true,   Dali::CameraActor::Property::LEFT_PLANE_DISTANCE   )
56 DALI_PROPERTY( "rightPlaneDistance",     FLOAT,    true,    false,   true,   Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE  )
57 DALI_PROPERTY( "topPlaneDistance",       FLOAT,    true,    false,   true,   Dali::CameraActor::Property::TOP_PLANE_DISTANCE    )
58 DALI_PROPERTY( "bottomPlaneDistance",    FLOAT,    true,    false,   true,   Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE )
59 DALI_PROPERTY( "targetPosition",         VECTOR3,  true,    false,   true,   Dali::CameraActor::Property::TARGET_POSITION       )
60 DALI_PROPERTY( "projectionMatrix",       MATRIX,   false,   false,   true,   Dali::CameraActor::Property::PROJECTION_MATRIX     )
61 DALI_PROPERTY( "viewMatrix",             MATRIX,   false,   false,   true,   Dali::CameraActor::Property::VIEW_MATRIX           )
62 DALI_PROPERTY( "invertYAxis",            BOOLEAN,  true,    false,   true,   Dali::CameraActor::Property::INVERT_Y_AXIS         )
63 DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX, CameraDefaultProperties )
64 // clang-format on
65
66 // calculate the far plane distance for a 16bit depth buffer with 4 bits per unit precision
67 void CalculateClippingAndZ(float width, float height, float& nearClippingPlane, float& farClippingPlane, float& cameraZ)
68 {
69   nearClippingPlane = std::max(width, height);
70   farClippingPlane  = nearClippingPlane + static_cast<float>(0xFFFF >> 4);
71   cameraZ           = 2.0f * nearClippingPlane;
72 }
73
74 BaseHandle Create()
75 {
76   return Dali::CameraActor::New();
77 }
78
79 TypeRegistration mType(typeid(Dali::CameraActor), typeid(Dali::Actor), Create, CameraDefaultProperties);
80
81 /**
82  * Builds the picking ray in the world reference system from an orthographic camera
83  * The ray origin is the screen coordinate in the near plane translated to a parallel
84  * plane at the camera origin. The ray direction is the direction the camera is facing
85  * (i.e. Z=-1 in view space).
86  */
87 void BuildOrthoPickingRay(const Matrix&   viewMatrix,
88                           const Matrix&   projectionMatrix,
89                           const Viewport& viewport,
90                           float           screenX,
91                           float           screenY,
92                           Vector4&        rayOrigin,
93                           Vector4&        rayDir,
94                           float           nearPlaneDistance)
95 {
96   //          inv( modelMatrix )          inv( viewMatrix )    inv( projectionMatrix )           normalize
97   //          <-----------------         <-----------------         <--------------           <-------------
98   //  Local                      World                      Camera                 Normalized                 Screen
99   // reference                  reference                  reference                  clip                  coordinates
100   //  system                     system                     system                 coordinates
101   //          ----------------->         ----------------->         -------------->           ------------->
102   //             modelMatrix                 viewMatrix             projectionMatrix             viewport
103
104   // Transforms the touch point from the screen reference system to the world reference system.
105   Matrix invViewProjection(false); // Don't initialize.
106   Matrix::Multiply(invViewProjection, viewMatrix, projectionMatrix);
107   if(!invViewProjection.Invert())
108   {
109     DALI_ASSERT_DEBUG(false);
110   }
111
112   Vector4 near(screenX - static_cast<float>(viewport.x),
113                static_cast<float>(viewport.height) - (screenY - static_cast<float>(viewport.y)),
114                0.f,
115                1.f);
116   if(!Unproject(near, invViewProjection, static_cast<float>(viewport.width), static_cast<float>(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(*CreateNode()));
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(const SceneGraph::Node& node)
157 : Actor(Actor::BASIC, node),
158   mSceneObject(nullptr),
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(&GetNode());
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::OnSceneConnectionInternal()
199 {
200   // If the canvas size has not been set, then use the size of the scene to which we've been added
201   // in order to set up the current projection
202   if((mCanvasSize.width < Math::MACHINE_EPSILON_1000) || (mCanvasSize.height < Math::MACHINE_EPSILON_1000))
203   {
204     if(mProjectionMode == Dali::Camera::ORTHOGRAPHIC_PROJECTION)
205     {
206       SetOrthographicProjection(GetScene().GetSize());
207     }
208     else //if(mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION)
209     {
210       SetPerspectiveProjection(GetScene().GetSize());
211     }
212   }
213 }
214
215 void CameraActor::SetReflectByPlane(const Vector4& plane)
216 {
217   if(mSceneObject)
218   {
219     SetReflectByPlaneMessage(GetEventThreadServices(), *mSceneObject, plane);
220   }
221 }
222
223 void CameraActor::SetTarget(const Vector3& target)
224 {
225   if(target != mTarget) // using range epsilon
226   {
227     mTarget = target;
228
229     SetTargetPositionMessage(GetEventThreadServices(), *mSceneObject, mTarget);
230   }
231 }
232
233 Vector3 CameraActor::GetTarget() const
234 {
235   return mTarget;
236 }
237
238 void CameraActor::SetType(Dali::Camera::Type type)
239 {
240   if(type != mType)
241   {
242     mType = type;
243
244     // sceneObject is being used in a separate thread; queue a message to set
245     SetTypeMessage(GetEventThreadServices(), *mSceneObject, mType);
246   }
247 }
248
249 Dali::Camera::Type CameraActor::GetType() const
250 {
251   return mType;
252 }
253
254 void CameraActor::SetProjectionMode(Dali::Camera::ProjectionMode mode)
255 {
256   if(mode != mProjectionMode)
257   {
258     mProjectionMode = mode;
259
260     // sceneObject is being used in a separate thread; queue a message to set
261     SetProjectionModeMessage(GetEventThreadServices(), *mSceneObject, mProjectionMode);
262   }
263 }
264
265 Dali::Camera::ProjectionMode CameraActor::GetProjectionMode() const
266 {
267   return mProjectionMode;
268 }
269
270 void CameraActor::SetFieldOfView(float fieldOfView)
271 {
272   if(!Equals(fieldOfView, mFieldOfView))
273   {
274     mFieldOfView = fieldOfView;
275
276     // sceneObject is being used in a separate thread; queue a message to set
277     SetFieldOfViewMessage(GetEventThreadServices(), *mSceneObject, mFieldOfView);
278   }
279 }
280
281 float CameraActor::GetFieldOfView() const
282 {
283   return mFieldOfView;
284 }
285
286 void CameraActor::SetAspectRatio(float aspectRatio)
287 {
288   if(!Equals(aspectRatio, mAspectRatio))
289   {
290     mAspectRatio = aspectRatio;
291
292     // sceneObject is being used in a separate thread; queue a message to set
293     SetAspectRatioMessage(GetEventThreadServices(), *mSceneObject, mAspectRatio);
294   }
295 }
296
297 float CameraActor::GetAspectRatio() const
298 {
299   return mAspectRatio;
300 }
301
302 void CameraActor::SetNearClippingPlane(float nearClippingPlane)
303 {
304   if(!Equals(nearClippingPlane, mNearClippingPlane))
305   {
306     mNearClippingPlane = nearClippingPlane;
307
308     // sceneObject is being used in a separate thread; queue a message to set
309     SetNearClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mNearClippingPlane);
310   }
311 }
312
313 float CameraActor::GetNearClippingPlane() const
314 {
315   return mNearClippingPlane;
316 }
317
318 void CameraActor::SetFarClippingPlane(float farClippingPlane)
319 {
320   if(!Equals(farClippingPlane, mFarClippingPlane))
321   {
322     mFarClippingPlane = farClippingPlane;
323
324     // sceneObject is being used in a separate thread; queue a message to set
325     SetFarClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mFarClippingPlane);
326   }
327 }
328
329 float CameraActor::GetFarClippingPlane() const
330 {
331   return mFarClippingPlane;
332 }
333
334 void CameraActor::SetLeftClippingPlane(float leftClippingPlane)
335 {
336   if(!Equals(leftClippingPlane, mLeftClippingPlane))
337   {
338     mLeftClippingPlane = leftClippingPlane;
339
340     // sceneObject is being used in a separate thread; queue a message to set
341     SetLeftClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mLeftClippingPlane);
342   }
343 }
344
345 void CameraActor::SetRightClippingPlane(float rightClippingPlane)
346 {
347   if(!Equals(rightClippingPlane, mRightClippingPlane))
348   {
349     mRightClippingPlane = rightClippingPlane;
350
351     // sceneObject is being used in a separate thread; queue a message to set
352     SetRightClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mRightClippingPlane);
353   }
354 }
355
356 void CameraActor::SetTopClippingPlane(float topClippingPlane)
357 {
358   if(!Equals(topClippingPlane, mTopClippingPlane))
359   {
360     mTopClippingPlane = topClippingPlane;
361
362     // sceneObject is being used in a separate thread; queue a message to set
363     SetTopClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mTopClippingPlane);
364   }
365 }
366
367 void CameraActor::SetBottomClippingPlane(float bottomClippingPlane)
368 {
369   if(!Equals(bottomClippingPlane, mBottomClippingPlane))
370   {
371     mBottomClippingPlane = bottomClippingPlane;
372
373     // sceneObject is being used in a separate thread; queue a message to set
374     SetBottomClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mBottomClippingPlane);
375   }
376 }
377
378 void CameraActor::SetInvertYAxis(bool invertYAxis)
379 {
380   if(invertYAxis != mInvertYAxis)
381   {
382     mInvertYAxis = invertYAxis;
383
384     // sceneObject is being used in a separate thread; queue a message to set
385     SetInvertYAxisMessage(GetEventThreadServices(), *mSceneObject, mInvertYAxis);
386   }
387 }
388
389 bool CameraActor::GetInvertYAxis() const
390 {
391   return mInvertYAxis;
392 }
393
394 void CameraActor::SetPerspectiveProjection(const Size& size)
395 {
396   SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
397   mCanvasSize = size;
398
399   if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
400   {
401     // If the size given is invalid, i.e. ZERO, then check if we've been added to a scene
402     if(OnScene())
403     {
404       // We've been added to a scene already, set the canvas size to the scene's size
405       mCanvasSize = GetScene().GetSize();
406     }
407     else
408     {
409       // We've not been added to a scene yet, so just return.
410       // We'll set the canvas size when we get added to a scene later
411       return;
412     }
413   }
414
415   float width  = mCanvasSize.width;
416   float height = mCanvasSize.height;
417
418   float nearClippingPlane;
419   float farClippingPlane;
420   float cameraZ;
421   CalculateClippingAndZ(width, height, nearClippingPlane, farClippingPlane, cameraZ);
422
423   // calculate the position of the camera to have the desired aspect ratio
424   const float fieldOfView = 2.0f * std::atan(height * 0.5f / cameraZ);
425
426   // unless it is too small, we want at least as much space to the back as we have torwards the front
427   const float minClippingFarPlane = 2.f * nearClippingPlane;
428   if(farClippingPlane < minClippingFarPlane)
429   {
430     farClippingPlane = minClippingFarPlane;
431   }
432
433   const float aspectRatio = width / height;
434
435   // sceneObject is being used in a separate thread; queue a message to set
436   SetFieldOfView(fieldOfView);
437   SetNearClippingPlane(nearClippingPlane);
438   SetFarClippingPlane(farClippingPlane);
439   SetLeftClippingPlane(width * -0.5f);
440   SetRightClippingPlane(width * 0.5f);
441   SetTopClippingPlane(height * 0.5f);     // Top is +ve to keep consistency with orthographic values
442   SetBottomClippingPlane(height * -0.5f); // Bottom is -ve to keep consistency with orthographic values
443   SetAspectRatio(aspectRatio);
444   SetZ(cameraZ);
445 }
446
447 void CameraActor::SetOrthographicProjection(const Vector2& size)
448 {
449   SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
450   mCanvasSize = size;
451
452   if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
453   {
454     // If the size given is invalid, i.e. ZERO, then check if we've been added to a scene
455     if(OnScene())
456     {
457       // We've been added to a scene already, set the canvas size to the scene's size
458       mCanvasSize = GetScene().GetSize();
459     }
460     else
461     {
462       // We've not been added to a scene yet, so just return.
463       // We'll set the canvas size when we get added to a scene later
464       return;
465     }
466   }
467
468   // Choose near, far and Z parameters to match the SetPerspectiveProjection above.
469   float nearClippingPlane;
470   float farClippingPlane;
471   float cameraZ;
472   CalculateClippingAndZ(size.width, size.height, nearClippingPlane, farClippingPlane, cameraZ);
473   SetOrthographicProjection(-size.x * 0.5f, size.x * 0.5f, size.y * 0.5f, size.y * -0.5f, nearClippingPlane, farClippingPlane);
474   SetZ(cameraZ);
475 }
476
477 void CameraActor::SetOrthographicProjection(float left, float right, float top, float bottom, float near, float far)
478 {
479   SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
480   SetLeftClippingPlane(left);
481   SetRightClippingPlane(right);
482   SetTopClippingPlane(top);
483   SetBottomClippingPlane(bottom);
484   SetNearClippingPlane(near);
485   SetFarClippingPlane(far);
486 }
487
488 bool CameraActor::BuildPickingRay(const Vector2&  screenCoordinates,
489                                   const Viewport& viewport,
490                                   Vector4&        rayOrigin,
491                                   Vector4&        rayDirection)
492 {
493   bool success = true;
494   if(mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION)
495   {
496     // Build a picking ray in the world reference system.
497     // ray starts from the camera world position
498     rayOrigin   = GetNode().GetWorldMatrix(0).GetTranslation();
499     rayOrigin.w = 1.0f;
500
501     // Transform the touch point from the screen coordinate system to the world coordinates system.
502     Vector4       near(screenCoordinates.x - static_cast<float>(viewport.x),
503                  static_cast<float>(viewport.height) - (screenCoordinates.y - static_cast<float>(viewport.y)),
504                  0.f,
505                  1.f);
506     const Matrix& inverseViewProjection = mSceneObject->GetInverseViewProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
507     success                             = Unproject(near, inverseViewProjection, static_cast<float>(viewport.width), static_cast<float>(viewport.height), near);
508
509     // Compute the ray's director vector.
510     rayDirection.x = near.x - rayOrigin.x;
511     rayDirection.y = near.y - rayOrigin.y;
512     rayDirection.z = near.z - rayOrigin.z;
513     rayDirection.Normalize();
514     rayDirection.w = 1.f;
515   }
516   else
517   {
518     float nearPlaneDistance = GetNearClippingPlane();
519     BuildOrthoPickingRay(GetViewMatrix(),
520                          GetProjectionMatrix(),
521                          viewport,
522                          screenCoordinates.x,
523                          screenCoordinates.y,
524                          rayOrigin,
525                          rayDirection,
526                          nearPlaneDistance);
527   }
528
529   return success;
530 }
531
532 const Matrix& CameraActor::GetViewMatrix() const
533 {
534   if(OnScene())
535   {
536     return mSceneObject->GetViewMatrix(GetEventThreadServices().GetEventBufferIndex());
537   }
538   else
539   {
540     return Matrix::IDENTITY;
541   }
542 }
543
544 const Matrix& CameraActor::GetProjectionMatrix() const
545 {
546   if(OnScene())
547   {
548     return mSceneObject->GetProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
549   }
550   else
551   {
552     return Matrix::IDENTITY;
553   }
554 }
555 const SceneGraph::Camera* CameraActor::GetCamera() const
556 {
557   return mSceneObject;
558 }
559
560 void CameraActor::RotateProjection(int rotationAngle)
561 {
562   // sceneObject is being used in a separate thread; queue a message to set
563   RotateProjectionMessage(GetEventThreadServices(), *mSceneObject, rotationAngle);
564 }
565
566 void CameraActor::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
567 {
568   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
569   {
570     Actor::SetDefaultProperty(index, propertyValue);
571   }
572   else
573   {
574     switch(index)
575     {
576       case Dali::CameraActor::Property::TYPE:
577       {
578         std::string s(propertyValue.Get<std::string>());
579         if(s == "LOOK_AT_TARGET")
580         {
581           SetType(Dali::Camera::LOOK_AT_TARGET);
582         }
583         else if(s == "FREE_LOOK")
584         {
585           SetType(Dali::Camera::FREE_LOOK);
586         }
587         break;
588       }
589       case Dali::CameraActor::Property::PROJECTION_MODE:
590       {
591         std::string s(propertyValue.Get<std::string>());
592         if(s == "PERSPECTIVE_PROJECTION")
593         {
594           SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
595         }
596         else if(s == "ORTHOGRAPHIC_PROJECTION")
597         {
598           SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
599         }
600         break;
601       }
602       case Dali::CameraActor::Property::FIELD_OF_VIEW:
603       {
604         SetFieldOfView(propertyValue.Get<float>()); // set to 0 in case property is not float
605         break;
606       }
607       case Dali::CameraActor::Property::ASPECT_RATIO:
608       {
609         SetAspectRatio(propertyValue.Get<float>()); // set to 0 in case property is not float
610         break;
611       }
612       case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
613       {
614         SetNearClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
615         break;
616       }
617       case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
618       {
619         SetFarClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
620         break;
621       }
622       case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
623       {
624         SetLeftClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
625         break;
626       }
627       case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
628       {
629         SetRightClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
630         break;
631       }
632       case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
633       {
634         SetTopClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
635         break;
636       }
637       case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
638       {
639         SetBottomClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
640         break;
641       }
642       case Dali::CameraActor::Property::TARGET_POSITION:
643       {
644         SetTarget(propertyValue.Get<Vector3>()); // set to 0 in case property is not Vector3
645         break;
646       }
647       case Dali::CameraActor::Property::PROJECTION_MATRIX:
648       {
649         DALI_LOG_WARNING("projection-matrix is read-only\n");
650         break;
651       }
652       case Dali::CameraActor::Property::VIEW_MATRIX:
653       {
654         DALI_LOG_WARNING("view-matrix is read-only\n");
655         break;
656       }
657       case Dali::CameraActor::Property::INVERT_Y_AXIS:
658       {
659         SetInvertYAxis(propertyValue.Get<bool>()); // set to false in case property is not bool
660         break;
661       }
662       case Dali::DevelCameraActor::Property::REFLECTION_PLANE:
663       {
664         SetReflectByPlane(propertyValue.Get<Vector4>());
665         break;
666       }
667
668       default:
669       {
670         DALI_LOG_WARNING("Unknown property (%d)\n", index);
671         break;
672       }
673     } // switch(index)
674
675   } // else
676 }
677
678 Property::Value CameraActor::GetDefaultProperty(Property::Index index) const
679 {
680   Property::Value ret;
681   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
682   {
683     ret = Actor::GetDefaultProperty(index);
684   }
685   else
686   {
687     switch(index)
688     {
689       case Dali::CameraActor::Property::TYPE:
690       {
691         if(Dali::Camera::LOOK_AT_TARGET == mType)
692         {
693           ret = "LOOK_AT_TARGET";
694         }
695         else if(Dali::Camera::FREE_LOOK == mType)
696         {
697           ret = "FREE_LOOK";
698         }
699         break;
700       }
701       case Dali::CameraActor::Property::PROJECTION_MODE:
702       {
703         if(Dali::Camera::PERSPECTIVE_PROJECTION == mProjectionMode)
704         {
705           ret = "PERSPECTIVE_PROJECTION";
706         }
707         else if(Dali::Camera::ORTHOGRAPHIC_PROJECTION == mProjectionMode)
708         {
709           ret = "ORTHOGRAPHIC_PROJECTION";
710         }
711         break;
712       }
713       case Dali::CameraActor::Property::FIELD_OF_VIEW:
714       {
715         ret = mFieldOfView;
716         break;
717       }
718       case Dali::CameraActor::Property::ASPECT_RATIO:
719       {
720         ret = mAspectRatio;
721         break;
722       }
723       case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
724       {
725         ret = mNearClippingPlane;
726         break;
727       }
728       case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
729       {
730         ret = mFarClippingPlane;
731         break;
732       }
733       case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
734       {
735         ret = mLeftClippingPlane;
736         break;
737       }
738       case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
739       {
740         ret = mRightClippingPlane;
741         break;
742       }
743       case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
744       {
745         ret = mTopClippingPlane;
746         break;
747       }
748       case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
749       {
750         ret = mBottomClippingPlane;
751         break;
752       }
753       case Dali::CameraActor::Property::TARGET_POSITION:
754       {
755         ret = mTarget;
756         break;
757       }
758       case Dali::CameraActor::Property::PROJECTION_MATRIX:
759       {
760         ret = GetProjectionMatrix(); // Only on scene-graph
761         break;
762       }
763       case Dali::CameraActor::Property::VIEW_MATRIX:
764       {
765         ret = GetViewMatrix(); // Only on scene-graph
766         break;
767       }
768       case Dali::CameraActor::Property::INVERT_Y_AXIS:
769       {
770         ret = mInvertYAxis;
771         break;
772       }
773     } // switch(index)
774   }
775
776   return ret;
777 }
778
779 Property::Value CameraActor::GetDefaultPropertyCurrentValue(Property::Index index) const
780 {
781   Property::Value ret;
782   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
783   {
784     ret = Actor::GetDefaultPropertyCurrentValue(index);
785   }
786   else
787   {
788     ret = GetDefaultProperty(index); // Most are event-side properties, the scene-graph properties are only on the scene-graph
789   }
790
791   return ret;
792 }
793
794 const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty(Property::Index index) const
795 {
796   const PropertyInputImpl* property(nullptr);
797
798   switch(index)
799   {
800     case Dali::CameraActor::Property::PROJECTION_MATRIX:
801     {
802       property = mSceneObject->GetProjectionMatrix();
803       break;
804     }
805     case Dali::CameraActor::Property::VIEW_MATRIX:
806     {
807       property = mSceneObject->GetViewMatrix();
808       break;
809     }
810       // no default on purpose as we chain method up to actor
811   }
812   if(!property)
813   {
814     property = Actor::GetSceneObjectInputProperty(index);
815   }
816
817   return property;
818 }
819
820 } // namespace Internal
821
822 } // namespace Dali