5f118f990b7bf4075abdf32353b10e5c57a98e6e
[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/common/property-base.h>
33 #include <dali/internal/update/manager/update-manager.h>
34
35 namespace Dali
36 {
37 namespace Internal
38 {
39 namespace
40 {
41 // Properties
42
43 /**
44  * We want to discourage the use of property strings (minimize string comparisons),
45  * particularly for the default properties.
46  *              Name                     Type   writable animatable constraint-input  enum for index-checking
47  */
48 // clang-format off
49 DALI_PROPERTY_TABLE_BEGIN
50 DALI_PROPERTY( "type",                   INTEGER,  true,    false,   true,   Dali::CameraActor::Property::TYPE                  )
51 DALI_PROPERTY( "projectionMode",         INTEGER,  true,    false,   true,   Dali::CameraActor::Property::PROJECTION_MODE       )
52 DALI_PROPERTY( "fieldOfView",            FLOAT,    true,    true,    true,   Dali::CameraActor::Property::FIELD_OF_VIEW         )
53 DALI_PROPERTY( "aspectRatio",            FLOAT,    true,    false,   true,   Dali::CameraActor::Property::ASPECT_RATIO          )
54 DALI_PROPERTY( "nearPlaneDistance",      FLOAT,    true,    false,   true,   Dali::CameraActor::Property::NEAR_PLANE_DISTANCE   )
55 DALI_PROPERTY( "farPlaneDistance",       FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FAR_PLANE_DISTANCE    )
56 DALI_PROPERTY( "leftPlaneDistance",      FLOAT,    true,    false,   true,   Dali::CameraActor::Property::LEFT_PLANE_DISTANCE   )
57 DALI_PROPERTY( "rightPlaneDistance",     FLOAT,    true,    false,   true,   Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE  )
58 DALI_PROPERTY( "topPlaneDistance",       FLOAT,    true,    false,   true,   Dali::CameraActor::Property::TOP_PLANE_DISTANCE    )
59 DALI_PROPERTY( "bottomPlaneDistance",    FLOAT,    true,    false,   true,   Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE )
60 DALI_PROPERTY( "targetPosition",         VECTOR3,  true,    false,   true,   Dali::CameraActor::Property::TARGET_POSITION       )
61 DALI_PROPERTY( "projectionMatrix",       MATRIX,   false,   false,   true,   Dali::CameraActor::Property::PROJECTION_MATRIX     )
62 DALI_PROPERTY( "viewMatrix",             MATRIX,   false,   false,   true,   Dali::CameraActor::Property::VIEW_MATRIX           )
63 DALI_PROPERTY( "invertYAxis",            BOOLEAN,  true,    false,   true,   Dali::CameraActor::Property::INVERT_Y_AXIS         )
64 DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX, CameraDefaultProperties )
65 // clang-format on
66
67 // calculate the far plane distance for a 16bit depth buffer with 4 bits per unit precision
68 void CalculateClippingAndZ(float width, float height, float& nearClippingPlane, float& farClippingPlane, float& cameraZ)
69 {
70   nearClippingPlane = std::max(width, height);
71   farClippingPlane  = nearClippingPlane + static_cast<float>(0xFFFF >> 4);
72   cameraZ           = 2.0f * nearClippingPlane;
73 }
74
75 BaseHandle Create()
76 {
77   return Dali::CameraActor::New();
78 }
79
80 TypeRegistration mType(typeid(Dali::CameraActor), typeid(Dali::Actor), Create, CameraDefaultProperties);
81
82 /**
83  * Builds the picking ray in the world reference system from an orthographic camera
84  * The ray origin is the screen coordinate in the near plane translated to a parallel
85  * plane at the camera origin. The ray direction is the direction the camera is facing
86  * (i.e. Z=-1 in view space).
87  */
88 void BuildOrthoPickingRay(const Matrix&   viewMatrix,
89                           const Matrix&   projectionMatrix,
90                           const Viewport& viewport,
91                           float           screenX,
92                           float           screenY,
93                           Vector4&        rayOrigin,
94                           Vector4&        rayDir,
95                           float           nearPlaneDistance)
96 {
97   //          inv( modelMatrix )          inv( viewMatrix )    inv( projectionMatrix )           normalize
98   //          <-----------------         <-----------------         <--------------           <-------------
99   //  Local                      World                      Camera                 Normalized                 Screen
100   // reference                  reference                  reference                  clip                  coordinates
101   //  system                     system                     system                 coordinates
102   //          ----------------->         ----------------->         -------------->           ------------->
103   //             modelMatrix                 viewMatrix             projectionMatrix             viewport
104
105   // Transforms the touch point from the screen reference system to the world reference system.
106   Matrix invViewProjection(false); // Don't initialize.
107   Matrix::Multiply(invViewProjection, viewMatrix, projectionMatrix);
108   if(!invViewProjection.Invert())
109   {
110     DALI_ASSERT_DEBUG(false);
111   }
112
113   Vector4 near(screenX - static_cast<float>(viewport.x),
114                static_cast<float>(viewport.height) - (screenY - static_cast<float>(viewport.y)),
115                0.f,
116                1.f);
117   if(!Unproject(near, invViewProjection, static_cast<float>(viewport.width), static_cast<float>(viewport.height), rayOrigin))
118   {
119     DALI_ASSERT_DEBUG(false);
120   }
121
122   Matrix invView = viewMatrix;
123   if(!invView.Invert())
124   {
125     DALI_ASSERT_DEBUG(false);
126   }
127
128   Vector4 cameraOrigin    = invView * Vector4(0.f, 0.f, 0.f, 1.f);
129   Vector4 nearPlaneOrigin = invView * Vector4(0.0f, 0.0f, -nearPlaneDistance, 1.0f);
130
131   // Vector pointing from the camera to the near plane
132   rayDir = cameraOrigin - nearPlaneOrigin;
133   rayOrigin -= rayDir;
134   rayDir.Normalize();
135   rayDir.w = 1.0f;
136 }
137
138 } // namespace
139
140 CameraActorPtr CameraActor::New(const Size& size)
141 {
142   // create camera. Cameras are owned by the update manager
143   SceneGraph::Camera*            camera = SceneGraph::Camera::New();
144   OwnerPointer<SceneGraph::Node> transferOwnership(camera);
145   Internal::ThreadLocalStorage*  tls = Internal::ThreadLocalStorage::GetInternal();
146
147   DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null");
148
149   // Send ownership of camera.
150   AddNodeMessage(tls->GetUpdateManager(), transferOwnership);
151
152   CameraActorPtr actor(new CameraActor(*camera));
153
154   // Second-phase construction
155   actor->Initialize();
156
157   actor->SetName("DefaultCamera");
158   actor->SetPerspectiveProjection(size);
159
160   // By default Actors face in the positive Z direction in world space
161   // CameraActors should face in the negative Z direction, towards the other actors
162   actor->SetOrientation(Quaternion(Dali::ANGLE_180, Vector3::YAXIS));
163
164   return actor;
165 }
166
167 CameraActor::CameraActor(const SceneGraph::Node& node)
168 : Actor(Actor::BASIC, node),
169   mTarget(SceneGraph::Camera::DEFAULT_TARGET_POSITION),
170   mType(SceneGraph::Camera::DEFAULT_TYPE),
171   mProjectionMode(SceneGraph::Camera::DEFAULT_MODE),
172   mProjectionDirection(SceneGraph::Camera::DEFAULT_PROJECTION_DIRECTION),
173   mFieldOfView(SceneGraph::Camera::DEFAULT_FIELD_OF_VIEW),
174   mAspectRatio(SceneGraph::Camera::DEFAULT_ASPECT_RATIO),
175   mNearClippingPlane(SceneGraph::Camera::DEFAULT_NEAR_CLIPPING_PLANE),
176   mFarClippingPlane(SceneGraph::Camera::DEFAULT_FAR_CLIPPING_PLANE),
177   mLeftClippingPlane(SceneGraph::Camera::DEFAULT_LEFT_CLIPPING_PLANE),
178   mRightClippingPlane(SceneGraph::Camera::DEFAULT_RIGHT_CLIPPING_PLANE),
179   mTopClippingPlane(SceneGraph::Camera::DEFAULT_TOP_CLIPPING_PLANE),
180   mBottomClippingPlane(SceneGraph::Camera::DEFAULT_BOTTOM_CLIPPING_PLANE),
181   mInvertYAxis(SceneGraph::Camera::DEFAULT_INVERT_Y_AXIS),
182   mPropertyChanged(false)
183 {
184 }
185
186 CameraActor::~CameraActor()
187 {
188 }
189
190 void CameraActor::OnSceneConnectionInternal()
191 {
192   // If the canvas size has not been set, then use the size of the scene to which we've been added
193   // in order to set up the current projection
194   if(!mPropertyChanged && ((mCanvasSize.width < Math::MACHINE_EPSILON_1000) || (mCanvasSize.height < Math::MACHINE_EPSILON_1000)))
195   {
196     if(mProjectionMode == Dali::Camera::ORTHOGRAPHIC_PROJECTION)
197     {
198       SetOrthographicProjection(GetScene().GetSize());
199     }
200     else //if(mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION)
201     {
202       SetPerspectiveProjection(GetScene().GetSize());
203     }
204   }
205 }
206
207 void CameraActor::SetReflectByPlane(const Vector4& plane)
208 {
209   SetReflectByPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), plane);
210 }
211
212 void CameraActor::SetTarget(const Vector3& target)
213 {
214   mPropertyChanged = true;
215   if(target != mTarget) // using range epsilon
216   {
217     mTarget = target;
218
219     SetTargetPositionMessage(GetEventThreadServices(), GetCameraSceneObject(), mTarget);
220   }
221 }
222
223 Vector3 CameraActor::GetTarget() const
224 {
225   return mTarget;
226 }
227
228 void CameraActor::SetType(Dali::Camera::Type type)
229 {
230   if(type != mType)
231   {
232     mType = type;
233
234     // sceneObject is being used in a separate thread; queue a message to set
235     SetTypeMessage(GetEventThreadServices(), GetCameraSceneObject(), mType);
236   }
237 }
238
239 Dali::Camera::Type CameraActor::GetType() const
240 {
241   return mType;
242 }
243
244 void CameraActor::SetProjectionMode(Dali::Camera::ProjectionMode mode)
245 {
246   if(mode != mProjectionMode)
247   {
248     mProjectionMode = mode;
249
250     // sceneObject is being used in a separate thread; queue a message to set
251     SetProjectionModeMessage(GetEventThreadServices(), GetCameraSceneObject(), mProjectionMode);
252   }
253 }
254
255 Dali::Camera::ProjectionMode CameraActor::GetProjectionMode() const
256 {
257   return mProjectionMode;
258 }
259
260 void CameraActor::SetProjectionDirection(Dali::DevelCameraActor::ProjectionDirection direction)
261 {
262   mPropertyChanged = true;
263   if(direction != mProjectionDirection)
264   {
265     mProjectionDirection = direction;
266
267     // sceneObject is being used in a separate thread; queue a message to set
268     SetProjectionDirectionMessage(GetEventThreadServices(), GetCameraSceneObject(), mProjectionDirection);
269   }
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     BakeFieldOfViewMessage(GetEventThreadServices(), GetCameraSceneObject(), mFieldOfView);
281   }
282 }
283
284 float CameraActor::GetFieldOfView() const
285 {
286   return mFieldOfView;
287 }
288
289 float CameraActor::GetCurrentFieldOfView() const
290 {
291   // node is being used in a separate thread; copy the value from the previous update
292   return GetCameraSceneObject().GetFieldOfView(GetEventThreadServices().GetEventBufferIndex());
293 }
294
295 void CameraActor::SetAspectRatio(float aspectRatio)
296 {
297   mPropertyChanged = true;
298   if(!Equals(aspectRatio, mAspectRatio))
299   {
300     mAspectRatio = aspectRatio;
301
302     // sceneObject is being used in a separate thread; queue a message to set
303     SetAspectRatioMessage(GetEventThreadServices(), GetCameraSceneObject(), mAspectRatio);
304   }
305 }
306
307 float CameraActor::GetAspectRatio() const
308 {
309   return mAspectRatio;
310 }
311
312 void CameraActor::SetNearClippingPlane(float nearClippingPlane)
313 {
314   mPropertyChanged = true;
315   if(!Equals(nearClippingPlane, mNearClippingPlane))
316   {
317     mNearClippingPlane = nearClippingPlane;
318
319     // sceneObject is being used in a separate thread; queue a message to set
320     SetNearClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mNearClippingPlane);
321   }
322 }
323
324 float CameraActor::GetNearClippingPlane() const
325 {
326   return mNearClippingPlane;
327 }
328
329 void CameraActor::SetFarClippingPlane(float farClippingPlane)
330 {
331   mPropertyChanged = true;
332   if(!Equals(farClippingPlane, mFarClippingPlane))
333   {
334     mFarClippingPlane = farClippingPlane;
335
336     // sceneObject is being used in a separate thread; queue a message to set
337     SetFarClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mFarClippingPlane);
338   }
339 }
340
341 float CameraActor::GetFarClippingPlane() const
342 {
343   return mFarClippingPlane;
344 }
345
346 void CameraActor::SetLeftClippingPlane(float leftClippingPlane)
347 {
348   mPropertyChanged = true;
349   if(!Equals(leftClippingPlane, mLeftClippingPlane))
350   {
351     mLeftClippingPlane = leftClippingPlane;
352
353     // sceneObject is being used in a separate thread; queue a message to set
354     SetLeftClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mLeftClippingPlane);
355   }
356 }
357
358 void CameraActor::SetRightClippingPlane(float rightClippingPlane)
359 {
360   mPropertyChanged = true;
361   if(!Equals(rightClippingPlane, mRightClippingPlane))
362   {
363     mRightClippingPlane = rightClippingPlane;
364
365     // sceneObject is being used in a separate thread; queue a message to set
366     SetRightClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mRightClippingPlane);
367   }
368 }
369
370 void CameraActor::SetTopClippingPlane(float topClippingPlane)
371 {
372   mPropertyChanged = true;
373   if(!Equals(topClippingPlane, mTopClippingPlane))
374   {
375     mTopClippingPlane = topClippingPlane;
376
377     // sceneObject is being used in a separate thread; queue a message to set
378     SetTopClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mTopClippingPlane);
379   }
380 }
381
382 void CameraActor::SetBottomClippingPlane(float bottomClippingPlane)
383 {
384   mPropertyChanged = true;
385   if(!Equals(bottomClippingPlane, mBottomClippingPlane))
386   {
387     mBottomClippingPlane = bottomClippingPlane;
388
389     // sceneObject is being used in a separate thread; queue a message to set
390     SetBottomClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mBottomClippingPlane);
391   }
392 }
393
394 void CameraActor::SetInvertYAxis(bool invertYAxis)
395 {
396   if(invertYAxis != mInvertYAxis)
397   {
398     mInvertYAxis = invertYAxis;
399
400     // sceneObject is being used in a separate thread; queue a message to set
401     SetInvertYAxisMessage(GetEventThreadServices(), GetCameraSceneObject(), mInvertYAxis);
402   }
403 }
404
405 bool CameraActor::GetInvertYAxis() const
406 {
407   return mInvertYAxis;
408 }
409
410 void CameraActor::SetPerspectiveProjection(const Size& size)
411 {
412   SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
413   mCanvasSize = size;
414
415   if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
416   {
417     // If the size given is invalid, i.e. ZERO, then check if we've been added to a scene
418     if(OnScene())
419     {
420       // We've been added to a scene already, set the canvas size to the scene's size
421       mCanvasSize = GetScene().GetSize();
422     }
423     else
424     {
425       // We've not been added to a scene yet, so just return.
426       // We'll set the canvas size when we get added to a scene later
427       return;
428     }
429   }
430
431   float width  = mCanvasSize.width;
432   float height = mCanvasSize.height;
433
434   float nearClippingPlane;
435   float farClippingPlane;
436   float cameraZ;
437   CalculateClippingAndZ(width, height, nearClippingPlane, farClippingPlane, cameraZ);
438
439   // calculate the position of the camera to have the desired aspect ratio
440   const float fieldOfView = 2.0f * std::atan((mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? height : width) * 0.5f / cameraZ);
441
442   // unless it is too small, we want at least as much space to the back as we have torwards the front
443   const float minClippingFarPlane = 2.f * nearClippingPlane;
444   if(farClippingPlane < minClippingFarPlane)
445   {
446     farClippingPlane = minClippingFarPlane;
447   }
448
449   const float aspectRatio = width / height;
450
451   // sceneObject is being used in a separate thread; queue a message to set
452   SetFieldOfView(fieldOfView);
453   SetNearClippingPlane(nearClippingPlane);
454   SetFarClippingPlane(farClippingPlane);
455   SetLeftClippingPlane(width * -0.5f);
456   SetRightClippingPlane(width * 0.5f);
457   SetTopClippingPlane(height * 0.5f);     // Top is +ve to keep consistency with orthographic values
458   SetBottomClippingPlane(height * -0.5f); // Bottom is -ve to keep consistency with orthographic values
459   SetAspectRatio(aspectRatio);
460   SetZ(cameraZ);
461 }
462
463 void CameraActor::SetOrthographicProjection(const Vector2& size)
464 {
465   SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
466   mCanvasSize = size;
467
468   if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
469   {
470     // If the size given is invalid, i.e. ZERO, then check if we've been added to a scene
471     if(OnScene())
472     {
473       // We've been added to a scene already, set the canvas size to the scene's size
474       mCanvasSize = GetScene().GetSize();
475     }
476     else
477     {
478       // We've not been added to a scene yet, so just return.
479       // We'll set the canvas size when we get added to a scene later
480       return;
481     }
482   }
483
484   // Choose near, far and Z parameters to match the SetPerspectiveProjection above.
485   float nearClippingPlane;
486   float farClippingPlane;
487   float cameraZ;
488   CalculateClippingAndZ(size.width, size.height, nearClippingPlane, farClippingPlane, cameraZ);
489   SetOrthographicProjection(-size.x * 0.5f, size.x * 0.5f, size.y * 0.5f, size.y * -0.5f, nearClippingPlane, farClippingPlane);
490   SetZ(cameraZ);
491 }
492
493 void CameraActor::SetOrthographicProjection(float left, float right, float top, float bottom, float near, float far)
494 {
495   SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
496   SetLeftClippingPlane(left);
497   SetRightClippingPlane(right);
498   SetTopClippingPlane(top);
499   SetBottomClippingPlane(bottom);
500   SetNearClippingPlane(near);
501   SetFarClippingPlane(far);
502 }
503
504 bool CameraActor::BuildPickingRay(const Vector2&  screenCoordinates,
505                                   const Viewport& viewport,
506                                   Vector4&        rayOrigin,
507                                   Vector4&        rayDirection)
508 {
509   bool success = true;
510   if(mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION)
511   {
512     // Build a picking ray in the world reference system.
513     // ray starts from the camera world position
514     rayOrigin   = GetNode().GetWorldMatrix(0).GetTranslation();
515     rayOrigin.w = 1.0f;
516
517     // Transform the touch point from the screen coordinate system to the world coordinates system.
518     Vector4       near(screenCoordinates.x - static_cast<float>(viewport.x),
519                  static_cast<float>(viewport.height) - (screenCoordinates.y - static_cast<float>(viewport.y)),
520                  0.f,
521                  1.f);
522     const Matrix& inverseViewProjection = GetCameraSceneObject().GetInverseViewProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
523     success                             = Unproject(near, inverseViewProjection, static_cast<float>(viewport.width), static_cast<float>(viewport.height), near);
524
525     // Compute the ray's director vector.
526     rayDirection.x = near.x - rayOrigin.x;
527     rayDirection.y = near.y - rayOrigin.y;
528     rayDirection.z = near.z - rayOrigin.z;
529     rayDirection.Normalize();
530     rayDirection.w = 1.f;
531   }
532   else
533   {
534     float nearPlaneDistance = GetNearClippingPlane();
535     BuildOrthoPickingRay(GetViewMatrix(),
536                          GetProjectionMatrix(),
537                          viewport,
538                          screenCoordinates.x,
539                          screenCoordinates.y,
540                          rayOrigin,
541                          rayDirection,
542                          nearPlaneDistance);
543   }
544
545   return success;
546 }
547
548 const Matrix& CameraActor::GetViewMatrix() const
549 {
550   if(OnScene())
551   {
552     return GetCameraSceneObject().GetViewMatrix(GetEventThreadServices().GetEventBufferIndex());
553   }
554   else
555   {
556     return Matrix::IDENTITY;
557   }
558 }
559
560 const Matrix& CameraActor::GetProjectionMatrix() const
561 {
562   if(OnScene())
563   {
564     return GetCameraSceneObject().GetProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
565   }
566   else
567   {
568     return Matrix::IDENTITY;
569   }
570 }
571 const SceneGraph::Camera& CameraActor::GetCameraSceneObject() const
572 {
573   return static_cast<const SceneGraph::Camera&>(GetNode());
574 }
575
576 void CameraActor::RotateProjection(int rotationAngle)
577 {
578   // sceneObject is being used in a separate thread; queue a message to set
579   RotateProjectionMessage(GetEventThreadServices(), GetCameraSceneObject(), rotationAngle);
580 }
581
582 void CameraActor::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
583 {
584   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
585   {
586     Actor::SetDefaultProperty(index, propertyValue);
587   }
588   else
589   {
590     switch(index)
591     {
592       case Dali::CameraActor::Property::TYPE:
593       {
594         Dali::Camera::Type cameraType = Dali::Camera::Type(propertyValue.Get<int>());
595         SetType(cameraType);
596         break;
597       }
598       case Dali::CameraActor::Property::PROJECTION_MODE:
599       {
600         Dali::Camera::ProjectionMode projectionMode = Dali::Camera::ProjectionMode(propertyValue.Get<int>());
601         SetProjectionMode(projectionMode);
602         break;
603       }
604       case Dali::CameraActor::Property::FIELD_OF_VIEW:
605       {
606         SetFieldOfView(propertyValue.Get<float>()); // set to 0 in case property is not float
607         break;
608       }
609       case Dali::CameraActor::Property::ASPECT_RATIO:
610       {
611         SetAspectRatio(propertyValue.Get<float>()); // set to 0 in case property is not float
612         break;
613       }
614       case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
615       {
616         SetNearClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
617         break;
618       }
619       case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
620       {
621         SetFarClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
622         break;
623       }
624       case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
625       {
626         SetLeftClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
627         break;
628       }
629       case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
630       {
631         SetRightClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
632         break;
633       }
634       case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
635       {
636         SetTopClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
637         break;
638       }
639       case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
640       {
641         SetBottomClippingPlane(propertyValue.Get<float>()); // set to 0 in case property is not float
642         break;
643       }
644       case Dali::CameraActor::Property::TARGET_POSITION:
645       {
646         SetTarget(propertyValue.Get<Vector3>()); // set to 0 in case property is not Vector3
647         break;
648       }
649       case Dali::CameraActor::Property::PROJECTION_MATRIX:
650       {
651         DALI_LOG_WARNING("projection-matrix is read-only\n");
652         break;
653       }
654       case Dali::CameraActor::Property::VIEW_MATRIX:
655       {
656         DALI_LOG_WARNING("view-matrix is read-only\n");
657         break;
658       }
659       case Dali::CameraActor::Property::INVERT_Y_AXIS:
660       {
661         SetInvertYAxis(propertyValue.Get<bool>()); // set to false in case property is not bool
662         break;
663       }
664       case Dali::DevelCameraActor::Property::REFLECTION_PLANE:
665       {
666         SetReflectByPlane(propertyValue.Get<Vector4>());
667         break;
668       }
669       case Dali::DevelCameraActor::Property::PROJECTION_DIRECTION:
670       {
671         Dali::DevelCameraActor::ProjectionDirection projectionDirection = Dali::DevelCameraActor::ProjectionDirection(propertyValue.Get<int>());
672         SetProjectionDirection(projectionDirection);
673         break;
674       }
675
676       default:
677       {
678         DALI_LOG_WARNING("Unknown property (%d)\n", index);
679         break;
680       }
681     } // switch(index)
682
683   } // else
684 }
685
686 Property::Value CameraActor::GetDefaultProperty(Property::Index index) const
687 {
688   Property::Value ret;
689   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
690   {
691     ret = Actor::GetDefaultProperty(index);
692   }
693   else
694   {
695     switch(index)
696     {
697       case Dali::CameraActor::Property::TYPE:
698       {
699         ret = mType;
700         break;
701       }
702       case Dali::CameraActor::Property::PROJECTION_MODE:
703       {
704         ret = mProjectionMode;
705         break;
706       }
707       case Dali::CameraActor::Property::FIELD_OF_VIEW:
708       {
709         ret = mFieldOfView;
710         break;
711       }
712       case Dali::CameraActor::Property::ASPECT_RATIO:
713       {
714         ret = mAspectRatio;
715         break;
716       }
717       case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
718       {
719         ret = mNearClippingPlane;
720         break;
721       }
722       case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
723       {
724         ret = mFarClippingPlane;
725         break;
726       }
727       case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
728       {
729         ret = mLeftClippingPlane;
730         break;
731       }
732       case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
733       {
734         ret = mRightClippingPlane;
735         break;
736       }
737       case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
738       {
739         ret = mTopClippingPlane;
740         break;
741       }
742       case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
743       {
744         ret = mBottomClippingPlane;
745         break;
746       }
747       case Dali::CameraActor::Property::TARGET_POSITION:
748       {
749         ret = mTarget;
750         break;
751       }
752       case Dali::CameraActor::Property::PROJECTION_MATRIX:
753       {
754         ret = GetProjectionMatrix(); // Only on scene-graph
755         break;
756       }
757       case Dali::CameraActor::Property::VIEW_MATRIX:
758       {
759         ret = GetViewMatrix(); // Only on scene-graph
760         break;
761       }
762       case Dali::CameraActor::Property::INVERT_Y_AXIS:
763       {
764         ret = mInvertYAxis;
765         break;
766       }
767       case Dali::DevelCameraActor::Property::PROJECTION_DIRECTION:
768       {
769         ret = mProjectionDirection;
770         break;
771       }
772     } // switch(index)
773   }
774
775   return ret;
776 }
777
778 Property::Value CameraActor::GetDefaultPropertyCurrentValue(Property::Index index) const
779 {
780   Property::Value ret;
781   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
782   {
783     ret = Actor::GetDefaultPropertyCurrentValue(index);
784   }
785   else
786   {
787     switch(index)
788     {
789       case Dali::CameraActor::Property::FIELD_OF_VIEW:
790       {
791         ret = GetCurrentFieldOfView();
792         break;
793       }
794       default:
795       {
796         ret = GetDefaultProperty(index); // Most are event-side properties, the scene-graph properties are only on the scene-graph
797       }
798     } // switch(index)
799   }
800
801   return ret;
802 }
803
804 void CameraActor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
805 {
806   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
807   {
808     Actor::OnNotifyDefaultPropertyAnimation(animation, index, value, animationType);
809   }
810   else
811   {
812     switch(animationType)
813     {
814       case Animation::TO:
815       case Animation::BETWEEN:
816       {
817         switch(index)
818         {
819           case Dali::CameraActor::Property::FIELD_OF_VIEW:
820           {
821             value.Get(mFieldOfView);
822             break;
823           }
824         }
825         break;
826       }
827       case Animation::BY:
828       {
829         switch(index)
830         {
831           case Dali::CameraActor::Property::FIELD_OF_VIEW:
832           {
833             AdjustValue<float>(mFieldOfView, value);
834             break;
835           }
836         }
837         break;
838       }
839     }
840   }
841 }
842
843 const SceneGraph::PropertyBase* CameraActor::GetSceneObjectAnimatableProperty(Property::Index index) const
844 {
845   const SceneGraph::PropertyBase* property(nullptr);
846   switch(index)
847   {
848     case Dali::CameraActor::Property::FIELD_OF_VIEW:
849     {
850       property = GetCameraSceneObject().GetFieldOfView();
851       break;
852     }
853       // no default on purpose as we chain method up to actor
854   }
855   if(!property)
856   {
857     // not our property, ask base
858     property = Actor::GetSceneObjectAnimatableProperty(index);
859   }
860
861   return property;
862 }
863 const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty(Property::Index index) const
864 {
865   const PropertyInputImpl* property(nullptr);
866
867   switch(index)
868   {
869     case Dali::CameraActor::Property::FIELD_OF_VIEW:
870     {
871       property = GetCameraSceneObject().GetFieldOfView();
872       break;
873     }
874     case Dali::CameraActor::Property::PROJECTION_MATRIX:
875     {
876       property = GetCameraSceneObject().GetProjectionMatrix();
877       break;
878     }
879     case Dali::CameraActor::Property::VIEW_MATRIX:
880     {
881       property = GetCameraSceneObject().GetViewMatrix();
882       break;
883     }
884       // no default on purpose as we chain method up to actor
885   }
886   if(!property)
887   {
888     property = Actor::GetSceneObjectInputProperty(index);
889   }
890
891   return property;
892 }
893
894 void CameraActor::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
895 {
896   // If Position or Orientation are explicitly set, make mPropertyChanged flag true.
897   if(index == Dali::Actor::Property::POSITION ||
898      index == Dali::Actor::Property::POSITION_X ||
899      index == Dali::Actor::Property::POSITION_Y ||
900      index == Dali::Actor::Property::POSITION_Z ||
901      index == Dali::Actor::Property::ORIENTATION)
902   {
903     mPropertyChanged = true;
904   }
905 }
906
907 } // namespace Internal
908
909 } // namespace Dali