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