79971ff85b4c518e913d26c61005e14128276e3a
[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",                   INTEGER,  true,    false,   true,   Dali::CameraActor::Property::TYPE                  )
50 DALI_PROPERTY( "projectionMode",         INTEGER,  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   mPropertyChanged(false)
172 {
173 }
174
175 CameraActor::~CameraActor()
176 {
177   if(EventThreadServices::IsCoreRunning())
178   {
179     // Create scene-object and transfer ownership through message
180     RemoveCameraMessage(GetEventThreadServices().GetUpdateManager(), mSceneObject);
181   }
182 }
183
184 void CameraActor::OnInitialize()
185 {
186   // Create scene-object and keep raw pointer for message passing.
187   SceneGraph::Camera* sceneGraphCamera = SceneGraph::Camera::New();
188
189   // Store a pointer to this camera node inside the scene-graph camera.
190   sceneGraphCamera->SetNode(&GetNode());
191
192   mSceneObject = sceneGraphCamera;
193   OwnerPointer<SceneGraph::Camera> sceneGraphCameraOwner(sceneGraphCamera);
194
195   // Send message to inform update of this camera (and move ownership).
196   AddCameraMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphCameraOwner);
197 }
198
199 void CameraActor::OnSceneConnectionInternal()
200 {
201   // If the canvas size has not been set, then use the size of the scene to which we've been added
202   // in order to set up the current projection
203   if(!mPropertyChanged && ((mCanvasSize.width < Math::MACHINE_EPSILON_1000) || (mCanvasSize.height < Math::MACHINE_EPSILON_1000)))
204   {
205     if(mProjectionMode == Dali::Camera::ORTHOGRAPHIC_PROJECTION)
206     {
207       SetOrthographicProjection(GetScene().GetSize());
208     }
209     else //if(mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION)
210     {
211       SetPerspectiveProjection(GetScene().GetSize());
212     }
213   }
214 }
215
216 void CameraActor::SetReflectByPlane(const Vector4& plane)
217 {
218   if(mSceneObject)
219   {
220     SetReflectByPlaneMessage(GetEventThreadServices(), *mSceneObject, plane);
221   }
222 }
223
224 void CameraActor::SetTarget(const Vector3& target)
225 {
226   mPropertyChanged = true;
227   if(target != mTarget) // using range epsilon
228   {
229     mTarget = target;
230
231     SetTargetPositionMessage(GetEventThreadServices(), *mSceneObject, mTarget);
232   }
233 }
234
235 Vector3 CameraActor::GetTarget() const
236 {
237   return mTarget;
238 }
239
240 void CameraActor::SetType(Dali::Camera::Type type)
241 {
242   if(type != mType)
243   {
244     mType = type;
245
246     // sceneObject is being used in a separate thread; queue a message to set
247     SetTypeMessage(GetEventThreadServices(), *mSceneObject, mType);
248   }
249 }
250
251 Dali::Camera::Type CameraActor::GetType() const
252 {
253   return mType;
254 }
255
256 void CameraActor::SetProjectionMode(Dali::Camera::ProjectionMode mode)
257 {
258   if(mode != mProjectionMode)
259   {
260     mProjectionMode = mode;
261
262     // sceneObject is being used in a separate thread; queue a message to set
263     SetProjectionModeMessage(GetEventThreadServices(), *mSceneObject, mProjectionMode);
264   }
265 }
266
267 Dali::Camera::ProjectionMode CameraActor::GetProjectionMode() const
268 {
269   return mProjectionMode;
270 }
271
272 void CameraActor::SetFieldOfView(float fieldOfView)
273 {
274   mPropertyChanged = true;
275   if(!Equals(fieldOfView, mFieldOfView))
276   {
277     mFieldOfView = fieldOfView;
278
279     // sceneObject is being used in a separate thread; queue a message to set
280     SetFieldOfViewMessage(GetEventThreadServices(), *mSceneObject, mFieldOfView);
281   }
282 }
283
284 float CameraActor::GetFieldOfView() const
285 {
286   return mFieldOfView;
287 }
288
289 void CameraActor::SetAspectRatio(float aspectRatio)
290 {
291   mPropertyChanged = true;
292   if(!Equals(aspectRatio, mAspectRatio))
293   {
294     mAspectRatio = aspectRatio;
295
296     // sceneObject is being used in a separate thread; queue a message to set
297     SetAspectRatioMessage(GetEventThreadServices(), *mSceneObject, mAspectRatio);
298   }
299 }
300
301 float CameraActor::GetAspectRatio() const
302 {
303   return mAspectRatio;
304 }
305
306 void CameraActor::SetNearClippingPlane(float nearClippingPlane)
307 {
308   mPropertyChanged = true;
309   if(!Equals(nearClippingPlane, mNearClippingPlane))
310   {
311     mNearClippingPlane = nearClippingPlane;
312
313     // sceneObject is being used in a separate thread; queue a message to set
314     SetNearClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mNearClippingPlane);
315   }
316 }
317
318 float CameraActor::GetNearClippingPlane() const
319 {
320   return mNearClippingPlane;
321 }
322
323 void CameraActor::SetFarClippingPlane(float farClippingPlane)
324 {
325   mPropertyChanged = true;
326   if(!Equals(farClippingPlane, mFarClippingPlane))
327   {
328     mFarClippingPlane = farClippingPlane;
329
330     // sceneObject is being used in a separate thread; queue a message to set
331     SetFarClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mFarClippingPlane);
332   }
333 }
334
335 float CameraActor::GetFarClippingPlane() const
336 {
337   return mFarClippingPlane;
338 }
339
340 void CameraActor::SetLeftClippingPlane(float leftClippingPlane)
341 {
342   mPropertyChanged = true;
343   if(!Equals(leftClippingPlane, mLeftClippingPlane))
344   {
345     mLeftClippingPlane = leftClippingPlane;
346
347     // sceneObject is being used in a separate thread; queue a message to set
348     SetLeftClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mLeftClippingPlane);
349   }
350 }
351
352 void CameraActor::SetRightClippingPlane(float rightClippingPlane)
353 {
354   mPropertyChanged = true;
355   if(!Equals(rightClippingPlane, mRightClippingPlane))
356   {
357     mRightClippingPlane = rightClippingPlane;
358
359     // sceneObject is being used in a separate thread; queue a message to set
360     SetRightClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mRightClippingPlane);
361   }
362 }
363
364 void CameraActor::SetTopClippingPlane(float topClippingPlane)
365 {
366   mPropertyChanged = true;
367   if(!Equals(topClippingPlane, mTopClippingPlane))
368   {
369     mTopClippingPlane = topClippingPlane;
370
371     // sceneObject is being used in a separate thread; queue a message to set
372     SetTopClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mTopClippingPlane);
373   }
374 }
375
376 void CameraActor::SetBottomClippingPlane(float bottomClippingPlane)
377 {
378   mPropertyChanged = true;
379   if(!Equals(bottomClippingPlane, mBottomClippingPlane))
380   {
381     mBottomClippingPlane = bottomClippingPlane;
382
383     // sceneObject is being used in a separate thread; queue a message to set
384     SetBottomClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mBottomClippingPlane);
385   }
386 }
387
388 void CameraActor::SetInvertYAxis(bool invertYAxis)
389 {
390   if(invertYAxis != mInvertYAxis)
391   {
392     mInvertYAxis = invertYAxis;
393
394     // sceneObject is being used in a separate thread; queue a message to set
395     SetInvertYAxisMessage(GetEventThreadServices(), *mSceneObject, mInvertYAxis);
396   }
397 }
398
399 bool CameraActor::GetInvertYAxis() const
400 {
401   return mInvertYAxis;
402 }
403
404 void CameraActor::SetPerspectiveProjection(const Size& size)
405 {
406   SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
407   mCanvasSize = size;
408
409   if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
410   {
411     // If the size given is invalid, i.e. ZERO, then check if we've been added to a scene
412     if(OnScene())
413     {
414       // We've been added to a scene already, set the canvas size to the scene's size
415       mCanvasSize = GetScene().GetSize();
416     }
417     else
418     {
419       // We've not been added to a scene yet, so just return.
420       // We'll set the canvas size when we get added to a scene later
421       return;
422     }
423   }
424
425   float width  = mCanvasSize.width;
426   float height = mCanvasSize.height;
427
428   float nearClippingPlane;
429   float farClippingPlane;
430   float cameraZ;
431   CalculateClippingAndZ(width, height, nearClippingPlane, farClippingPlane, cameraZ);
432
433   // calculate the position of the camera to have the desired aspect ratio
434   const float fieldOfView = 2.0f * std::atan(height * 0.5f / cameraZ);
435
436   // unless it is too small, we want at least as much space to the back as we have torwards the front
437   const float minClippingFarPlane = 2.f * nearClippingPlane;
438   if(farClippingPlane < minClippingFarPlane)
439   {
440     farClippingPlane = minClippingFarPlane;
441   }
442
443   const float aspectRatio = width / height;
444
445   // sceneObject is being used in a separate thread; queue a message to set
446   SetFieldOfView(fieldOfView);
447   SetNearClippingPlane(nearClippingPlane);
448   SetFarClippingPlane(farClippingPlane);
449   SetLeftClippingPlane(width * -0.5f);
450   SetRightClippingPlane(width * 0.5f);
451   SetTopClippingPlane(height * 0.5f);     // Top is +ve to keep consistency with orthographic values
452   SetBottomClippingPlane(height * -0.5f); // Bottom is -ve to keep consistency with orthographic values
453   SetAspectRatio(aspectRatio);
454   SetZ(cameraZ);
455 }
456
457 void CameraActor::SetOrthographicProjection(const Vector2& size)
458 {
459   SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
460   mCanvasSize = size;
461
462   if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
463   {
464     // If the size given is invalid, i.e. ZERO, then check if we've been added to a scene
465     if(OnScene())
466     {
467       // We've been added to a scene already, set the canvas size to the scene's size
468       mCanvasSize = GetScene().GetSize();
469     }
470     else
471     {
472       // We've not been added to a scene yet, so just return.
473       // We'll set the canvas size when we get added to a scene later
474       return;
475     }
476   }
477
478   // Choose near, far and Z parameters to match the SetPerspectiveProjection above.
479   float nearClippingPlane;
480   float farClippingPlane;
481   float cameraZ;
482   CalculateClippingAndZ(size.width, size.height, nearClippingPlane, farClippingPlane, cameraZ);
483   SetOrthographicProjection(-size.x * 0.5f, size.x * 0.5f, size.y * 0.5f, size.y * -0.5f, nearClippingPlane, farClippingPlane);
484   SetZ(cameraZ);
485 }
486
487 void CameraActor::SetOrthographicProjection(float left, float right, float top, float bottom, float near, float far)
488 {
489   SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
490   SetLeftClippingPlane(left);
491   SetRightClippingPlane(right);
492   SetTopClippingPlane(top);
493   SetBottomClippingPlane(bottom);
494   SetNearClippingPlane(near);
495   SetFarClippingPlane(far);
496 }
497
498 bool CameraActor::BuildPickingRay(const Vector2&  screenCoordinates,
499                                   const Viewport& viewport,
500                                   Vector4&        rayOrigin,
501                                   Vector4&        rayDirection)
502 {
503   bool success = true;
504   if(mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION)
505   {
506     // Build a picking ray in the world reference system.
507     // ray starts from the camera world position
508     rayOrigin   = GetNode().GetWorldMatrix(0).GetTranslation();
509     rayOrigin.w = 1.0f;
510
511     // Transform the touch point from the screen coordinate system to the world coordinates system.
512     Vector4       near(screenCoordinates.x - static_cast<float>(viewport.x),
513                  static_cast<float>(viewport.height) - (screenCoordinates.y - static_cast<float>(viewport.y)),
514                  0.f,
515                  1.f);
516     const Matrix& inverseViewProjection = mSceneObject->GetInverseViewProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
517     success                             = Unproject(near, inverseViewProjection, static_cast<float>(viewport.width), static_cast<float>(viewport.height), near);
518
519     // Compute the ray's director vector.
520     rayDirection.x = near.x - rayOrigin.x;
521     rayDirection.y = near.y - rayOrigin.y;
522     rayDirection.z = near.z - rayOrigin.z;
523     rayDirection.Normalize();
524     rayDirection.w = 1.f;
525   }
526   else
527   {
528     float nearPlaneDistance = GetNearClippingPlane();
529     BuildOrthoPickingRay(GetViewMatrix(),
530                          GetProjectionMatrix(),
531                          viewport,
532                          screenCoordinates.x,
533                          screenCoordinates.y,
534                          rayOrigin,
535                          rayDirection,
536                          nearPlaneDistance);
537   }
538
539   return success;
540 }
541
542 const Matrix& CameraActor::GetViewMatrix() const
543 {
544   if(OnScene())
545   {
546     return mSceneObject->GetViewMatrix(GetEventThreadServices().GetEventBufferIndex());
547   }
548   else
549   {
550     return Matrix::IDENTITY;
551   }
552 }
553
554 const Matrix& CameraActor::GetProjectionMatrix() const
555 {
556   if(OnScene())
557   {
558     return mSceneObject->GetProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
559   }
560   else
561   {
562     return Matrix::IDENTITY;
563   }
564 }
565 const SceneGraph::Camera* CameraActor::GetCamera() const
566 {
567   return mSceneObject;
568 }
569
570 void CameraActor::RotateProjection(int rotationAngle)
571 {
572   // sceneObject is being used in a separate thread; queue a message to set
573   RotateProjectionMessage(GetEventThreadServices(), *mSceneObject, rotationAngle);
574 }
575
576 void CameraActor::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
577 {
578   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
579   {
580     Actor::SetDefaultProperty(index, propertyValue);
581   }
582   else
583   {
584     switch(index)
585     {
586       case Dali::CameraActor::Property::TYPE:
587       {
588         Dali::Camera::Type cameraType = Dali::Camera::Type(propertyValue.Get<int>());
589         SetType(cameraType);
590         break;
591       }
592       case Dali::CameraActor::Property::PROJECTION_MODE:
593       {
594         Dali::Camera::ProjectionMode projectionMode = Dali::Camera::ProjectionMode(propertyValue.Get<int>());
595         SetProjectionMode(projectionMode);
596         break;
597       }
598       case Dali::CameraActor::Property::FIELD_OF_VIEW:
599       {
600         SetFieldOfView(propertyValue.Get<float>()); // set to 0 in case property is not float
601         break;
602       }
603       case Dali::CameraActor::Property::ASPECT_RATIO:
604       {
605         SetAspectRatio(propertyValue.Get<float>()); // set to 0 in case property is not float
606         break;
607       }
608       case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
609       {
610         SetNearClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
611         break;
612       }
613       case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
614       {
615         SetFarClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
616         break;
617       }
618       case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
619       {
620         SetLeftClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
621         break;
622       }
623       case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
624       {
625         SetRightClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
626         break;
627       }
628       case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
629       {
630         SetTopClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
631         break;
632       }
633       case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
634       {
635         SetBottomClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
636         break;
637       }
638       case Dali::CameraActor::Property::TARGET_POSITION:
639       {
640         SetTarget(propertyValue.Get<Vector3>()); // set to 0 in case property is not Vector3
641         break;
642       }
643       case Dali::CameraActor::Property::PROJECTION_MATRIX:
644       {
645         DALI_LOG_WARNING("projection-matrix is read-only\n");
646         break;
647       }
648       case Dali::CameraActor::Property::VIEW_MATRIX:
649       {
650         DALI_LOG_WARNING("view-matrix is read-only\n");
651         break;
652       }
653       case Dali::CameraActor::Property::INVERT_Y_AXIS:
654       {
655         SetInvertYAxis(propertyValue.Get<bool>()); // set to false in case property is not bool
656         break;
657       }
658       case Dali::DevelCameraActor::Property::REFLECTION_PLANE:
659       {
660         SetReflectByPlane(propertyValue.Get<Vector4>());
661         break;
662       }
663
664       default:
665       {
666         DALI_LOG_WARNING("Unknown property (%d)\n", index);
667         break;
668       }
669     } // switch(index)
670
671   } // else
672 }
673
674 Property::Value CameraActor::GetDefaultProperty(Property::Index index) const
675 {
676   Property::Value ret;
677   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
678   {
679     ret = Actor::GetDefaultProperty(index);
680   }
681   else
682   {
683     switch(index)
684     {
685       case Dali::CameraActor::Property::TYPE:
686       {
687         ret = mType;
688         break;
689       }
690       case Dali::CameraActor::Property::PROJECTION_MODE:
691       {
692         ret = mProjectionMode;
693         break;
694       }
695       case Dali::CameraActor::Property::FIELD_OF_VIEW:
696       {
697         ret = mFieldOfView;
698         break;
699       }
700       case Dali::CameraActor::Property::ASPECT_RATIO:
701       {
702         ret = mAspectRatio;
703         break;
704       }
705       case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
706       {
707         ret = mNearClippingPlane;
708         break;
709       }
710       case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
711       {
712         ret = mFarClippingPlane;
713         break;
714       }
715       case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
716       {
717         ret = mLeftClippingPlane;
718         break;
719       }
720       case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
721       {
722         ret = mRightClippingPlane;
723         break;
724       }
725       case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
726       {
727         ret = mTopClippingPlane;
728         break;
729       }
730       case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
731       {
732         ret = mBottomClippingPlane;
733         break;
734       }
735       case Dali::CameraActor::Property::TARGET_POSITION:
736       {
737         ret = mTarget;
738         break;
739       }
740       case Dali::CameraActor::Property::PROJECTION_MATRIX:
741       {
742         ret = GetProjectionMatrix(); // Only on scene-graph
743         break;
744       }
745       case Dali::CameraActor::Property::VIEW_MATRIX:
746       {
747         ret = GetViewMatrix(); // Only on scene-graph
748         break;
749       }
750       case Dali::CameraActor::Property::INVERT_Y_AXIS:
751       {
752         ret = mInvertYAxis;
753         break;
754       }
755     } // switch(index)
756   }
757
758   return ret;
759 }
760
761 Property::Value CameraActor::GetDefaultPropertyCurrentValue(Property::Index index) const
762 {
763   Property::Value ret;
764   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
765   {
766     ret = Actor::GetDefaultPropertyCurrentValue(index);
767   }
768   else
769   {
770     ret = GetDefaultProperty(index); // Most are event-side properties, the scene-graph properties are only on the scene-graph
771   }
772
773   return ret;
774 }
775
776 const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty(Property::Index index) const
777 {
778   const PropertyInputImpl* property(nullptr);
779
780   switch(index)
781   {
782     case Dali::CameraActor::Property::PROJECTION_MATRIX:
783     {
784       property = mSceneObject->GetProjectionMatrix();
785       break;
786     }
787     case Dali::CameraActor::Property::VIEW_MATRIX:
788     {
789       property = mSceneObject->GetViewMatrix();
790       break;
791     }
792       // no default on purpose as we chain method up to actor
793   }
794   if(!property)
795   {
796     property = Actor::GetSceneObjectInputProperty(index);
797   }
798
799   return property;
800 }
801
802 void CameraActor::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
803 {
804   // If Position or Orientation are explicitly set, make mPropertyChanged flag true.
805   if(index == Dali::Actor::Property::POSITION ||
806      index == Dali::Actor::Property::POSITION_X ||
807      index == Dali::Actor::Property::POSITION_Y ||
808      index == Dali::Actor::Property::POSITION_Z ||
809      index == Dali::Actor::Property::ORIENTATION)
810   {
811     mPropertyChanged = true;
812   }
813 }
814
815 } // namespace Internal
816
817 } // namespace Dali