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