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