Make SceneGraph::Camera as Node + FieldOfView animatable 59/282859/12
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 12 Oct 2022 10:53:39 +0000 (19:53 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Wed, 19 Oct 2022 08:26:50 +0000 (17:26 +0900)
Previously, SceneGraph::Camera was not a SceneGraph::Node.
If we try to animate property of Camera, then
we use some PropertyBase s.t. PropertyOwner(==Node) doesn't owned.

To fix this logical unmatched issue, we make SceneGraph::Camera
as sub-class of SceneGraph::Node.

Moreover, We make Camera's FieldOfView Animatable.

After this patch merged, we try to refactor Camera's properties
and make them animatable.

Change-Id: I184f75b51a2152aea52879adc1e783cea7d190a0
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
18 files changed:
automated-tests/src/dali/utc-Dali-CameraActor.cpp
dali/internal/event/actors/camera-actor-impl.cpp
dali/internal/event/actors/camera-actor-impl.h
dali/internal/event/render-tasks/render-task-impl.cpp
dali/internal/render/common/render-manager.cpp
dali/internal/update/common/discard-queue.cpp
dali/internal/update/common/discard-queue.h
dali/internal/update/manager/render-instruction-processor.cpp
dali/internal/update/manager/render-task-processor.cpp
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/nodes/scene-graph-layer.h
dali/internal/update/render-tasks/scene-graph-camera.cpp
dali/internal/update/render-tasks/scene-graph-camera.h
dali/internal/update/render-tasks/scene-graph-render-task.cpp
dali/internal/update/render-tasks/scene-graph-render-task.h

index 7a37225..72ae59e 100644 (file)
@@ -1312,7 +1312,15 @@ int UtcDaliCameraActorDefaultProperties(void)
   for(std::vector<Property::Index>::iterator iter = indices.begin(); iter != indices.end(); ++iter)
   {
     DALI_TEST_EQUALS(*iter, actor.GetPropertyIndex(actor.GetPropertyName(*iter)), TEST_LOCATION);
-    DALI_TEST_CHECK(!actor.IsPropertyAnimatable(*iter));
+
+    if(*iter == CameraActor::Property::FIELD_OF_VIEW)
+    {
+      DALI_TEST_CHECK(actor.IsPropertyAnimatable(*iter));
+    }
+    else
+    {
+      DALI_TEST_CHECK(!actor.IsPropertyAnimatable(*iter));
+    }
 
     if((*iter == CameraActor::Property::PROJECTION_MATRIX) ||
        (*iter == CameraActor::Property::VIEW_MATRIX))
@@ -1435,7 +1443,7 @@ int UtcDaliCameraActorDefaultPropertiesInherited(void)
       // camera own
       {"type", Property::INTEGER, true, false, true, Dali::CameraActor::Property::TYPE},
       {"projectionMode", Property::INTEGER, true, false, true, Dali::CameraActor::Property::PROJECTION_MODE},
-      {"fieldOfView", Property::FLOAT, true, false, true, Dali::CameraActor::Property::FIELD_OF_VIEW},
+      {"fieldOfView", Property::FLOAT, true, true, true, Dali::CameraActor::Property::FIELD_OF_VIEW},
       {"aspectRatio", Property::FLOAT, true, false, true, Dali::CameraActor::Property::ASPECT_RATIO},
       {"nearPlaneDistance", Property::FLOAT, true, false, true, Dali::CameraActor::Property::NEAR_PLANE_DISTANCE},
       {"farPlaneDistance", Property::FLOAT, true, false, true, Dali::CameraActor::Property::FAR_PLANE_DISTANCE},
@@ -1537,7 +1545,7 @@ int UtcDaliCameraActorReadProjectionMatrix(void)
   END_TEST;
 }
 
-int UtcDaliCameraActorAnimatedProperties(void)
+int UtcDaliCameraActorAnimatedProperties01(void)
 {
   TestApplication application;
   tet_infoline("Testing Dali::Internal::CameraActor::GetSceneObjectAnimatableProperty()");
@@ -1559,6 +1567,151 @@ int UtcDaliCameraActorAnimatedProperties(void)
   END_TEST;
 }
 
+int UtcDaliCameraActorAnimatedProperties02(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Internal::CameraActor::GetSceneObjectAnimatableProperty()");
+
+  CameraActor camera = application.GetScene().GetRenderTaskList().GetTask(0u).GetCameraActor();
+  Actor       actor  = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  actor.SetProperty(Actor::Property::POSITION, Vector2(0.1f, 0.0f));
+  application.GetScene().Add(actor);
+
+  camera.SetFieldOfView(0.1f);
+
+  Constraint constraint = Constraint::New<float>(actor, Actor::Property::POSITION_X, EqualToConstraint());
+  constraint.AddSource(Source(camera, CameraActor::Property::FIELD_OF_VIEW));
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<float>(Actor::Property::POSITION_X), 0.1f, TEST_LOCATION);
+
+  camera.SetFieldOfView(0.5f);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<float>(Actor::Property::POSITION_X), 0.5f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliCameraActorAnimatedProperties03(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Internal::CameraActor::GetSceneObjectAnimatableProperty()");
+
+  CameraActor camera = application.GetScene().GetRenderTaskList().GetTask(0u).GetCameraActor();
+
+  // Add dummy actor
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  actor.SetProperty(Actor::Property::POSITION, Vector2(0.1f, 0.0f));
+  application.GetScene().Add(actor);
+
+  Radian sourceFoV = Radian(0.6f);
+  Radian targetFoV = Radian(0.1f);
+
+  Matrix expectedProjectionMatrix1;
+  Matrix expectedProjectionMatrix2;
+  Matrix expectedProjectionMatrix3;
+
+  // Reduce near-far value for projection matrix epsilon
+  camera.SetNearClippingPlane(1.0f);
+  camera.SetFarClippingPlane(3.0f);
+
+  // Build expect projection matrix
+  camera.SetFieldOfView(sourceFoV.radian);
+  application.SendNotification();
+  application.Render();
+  camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(expectedProjectionMatrix1);
+
+  camera.SetFieldOfView(sourceFoV.radian * 0.6f + targetFoV.radian * 0.4f);
+  application.SendNotification();
+  application.Render();
+  camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(expectedProjectionMatrix2);
+
+  camera.SetFieldOfView(targetFoV.radian);
+  application.SendNotification();
+  application.Render();
+  camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(expectedProjectionMatrix3);
+
+  auto TestAnimationProgress = [&]() {
+    Matrix projectionMatrix;
+
+    application.SendNotification();
+    application.Render(0);
+
+    // progress 0.0
+    DALI_TEST_EQUALS(camera.GetCurrentProperty<float>(CameraActor::Property::FIELD_OF_VIEW), sourceFoV.radian, TEST_LOCATION);
+
+    camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(projectionMatrix);
+    DALI_TEST_EQUALS(projectionMatrix, expectedProjectionMatrix1, Epsilon<100000>::value, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(400);
+
+    // progress 0.4
+    DALI_TEST_EQUALS(camera.GetCurrentProperty<float>(CameraActor::Property::FIELD_OF_VIEW), sourceFoV.radian * 0.6f + targetFoV.radian * 0.4f, TEST_LOCATION);
+
+    camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(projectionMatrix);
+    DALI_TEST_EQUALS(projectionMatrix, expectedProjectionMatrix2, Epsilon<100000>::value, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(600);
+
+    // progress 1.0
+    DALI_TEST_EQUALS(camera.GetCurrentProperty<float>(CameraActor::Property::FIELD_OF_VIEW), targetFoV.radian, TEST_LOCATION);
+
+    camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(projectionMatrix);
+    DALI_TEST_EQUALS(projectionMatrix, expectedProjectionMatrix3, Epsilon<100000>::value, TEST_LOCATION);
+
+    // Ensure Animate finished.
+    application.SendNotification();
+    application.Render(16);
+  };
+
+  // AnimateTo
+  {
+    tet_printf("AnimateTo\n");
+    camera.SetProperty(CameraActor::Property::FIELD_OF_VIEW, sourceFoV.radian);
+    Animation animation = Animation::New(1.0f);
+    animation.AnimateTo(Property(camera, CameraActor::Property::FIELD_OF_VIEW), targetFoV.radian);
+    animation.AnimateTo(Property(camera, Actor::Property::POSITION_X), 0.0f); ///< For line coverage.
+    animation.Play();
+
+    TestAnimationProgress();
+  }
+
+  // AnimateBetween
+  {
+    tet_printf("AnimateBetween\n");
+    Animation animation = Animation::New(1.0f);
+    KeyFrames keyFrames = KeyFrames::New();
+    keyFrames.Add(0.0f, sourceFoV.radian);
+    keyFrames.Add(1.0f, targetFoV.radian);
+    animation.AnimateBetween(Property(camera, CameraActor::Property::FIELD_OF_VIEW), keyFrames);
+    animation.Play();
+
+    TestAnimationProgress();
+  }
+
+  // AnimateBy
+  {
+    tet_printf("AnimateBy\n");
+    camera.SetProperty(CameraActor::Property::FIELD_OF_VIEW, sourceFoV.radian);
+    Animation animation = Animation::New(1.0f);
+    animation.AnimateBy(Property(camera, CameraActor::Property::FIELD_OF_VIEW), targetFoV.radian - sourceFoV.radian);
+    animation.Play();
+
+    TestAnimationProgress();
+  }
+
+  END_TEST;
+}
+
 int UtcDaliCameraActorPropertyIndices(void)
 {
   TestApplication application;
index 0025ac8..5f118f9 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/public-api/object/type-registry.h>
 
+#include <dali/internal/update/common/property-base.h>
 #include <dali/internal/update/manager/update-manager.h>
 
 namespace Dali
@@ -48,7 +49,7 @@ namespace
 DALI_PROPERTY_TABLE_BEGIN
 DALI_PROPERTY( "type",                   INTEGER,  true,    false,   true,   Dali::CameraActor::Property::TYPE                  )
 DALI_PROPERTY( "projectionMode",         INTEGER,  true,    false,   true,   Dali::CameraActor::Property::PROJECTION_MODE       )
-DALI_PROPERTY( "fieldOfView",            FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FIELD_OF_VIEW         )
+DALI_PROPERTY( "fieldOfView",            FLOAT,    true,    true,    true,   Dali::CameraActor::Property::FIELD_OF_VIEW         )
 DALI_PROPERTY( "aspectRatio",            FLOAT,    true,    false,   true,   Dali::CameraActor::Property::ASPECT_RATIO          )
 DALI_PROPERTY( "nearPlaneDistance",      FLOAT,    true,    false,   true,   Dali::CameraActor::Property::NEAR_PLANE_DISTANCE   )
 DALI_PROPERTY( "farPlaneDistance",       FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FAR_PLANE_DISTANCE    )
@@ -138,7 +139,17 @@ void BuildOrthoPickingRay(const Matrix&   viewMatrix,
 
 CameraActorPtr CameraActor::New(const Size& size)
 {
-  CameraActorPtr actor(new CameraActor(*CreateNode()));
+  // create camera. Cameras are owned by the update manager
+  SceneGraph::Camera*            camera = SceneGraph::Camera::New();
+  OwnerPointer<SceneGraph::Node> transferOwnership(camera);
+  Internal::ThreadLocalStorage*  tls = Internal::ThreadLocalStorage::GetInternal();
+
+  DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null");
+
+  // Send ownership of camera.
+  AddNodeMessage(tls->GetUpdateManager(), transferOwnership);
+
+  CameraActorPtr actor(new CameraActor(*camera));
 
   // Second-phase construction
   actor->Initialize();
@@ -155,7 +166,6 @@ CameraActorPtr CameraActor::New(const Size& size)
 
 CameraActor::CameraActor(const SceneGraph::Node& node)
 : Actor(Actor::BASIC, node),
-  mSceneObject(nullptr),
   mTarget(SceneGraph::Camera::DEFAULT_TARGET_POSITION),
   mType(SceneGraph::Camera::DEFAULT_TYPE),
   mProjectionMode(SceneGraph::Camera::DEFAULT_MODE),
@@ -175,26 +185,6 @@ CameraActor::CameraActor(const SceneGraph::Node& node)
 
 CameraActor::~CameraActor()
 {
-  if(EventThreadServices::IsCoreRunning())
-  {
-    // Create scene-object and transfer ownership through message
-    RemoveCameraMessage(GetEventThreadServices().GetUpdateManager(), mSceneObject);
-  }
-}
-
-void CameraActor::OnInitialize()
-{
-  // Create scene-object and keep raw pointer for message passing.
-  SceneGraph::Camera* sceneGraphCamera = SceneGraph::Camera::New();
-
-  // Store a pointer to this camera node inside the scene-graph camera.
-  sceneGraphCamera->SetNode(&GetNode());
-
-  mSceneObject = sceneGraphCamera;
-  OwnerPointer<SceneGraph::Camera> sceneGraphCameraOwner(sceneGraphCamera);
-
-  // Send message to inform update of this camera (and move ownership).
-  AddCameraMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphCameraOwner);
 }
 
 void CameraActor::OnSceneConnectionInternal()
@@ -216,10 +206,7 @@ void CameraActor::OnSceneConnectionInternal()
 
 void CameraActor::SetReflectByPlane(const Vector4& plane)
 {
-  if(mSceneObject)
-  {
-    SetReflectByPlaneMessage(GetEventThreadServices(), *mSceneObject, plane);
-  }
+  SetReflectByPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), plane);
 }
 
 void CameraActor::SetTarget(const Vector3& target)
@@ -229,7 +216,7 @@ void CameraActor::SetTarget(const Vector3& target)
   {
     mTarget = target;
 
-    SetTargetPositionMessage(GetEventThreadServices(), *mSceneObject, mTarget);
+    SetTargetPositionMessage(GetEventThreadServices(), GetCameraSceneObject(), mTarget);
   }
 }
 
@@ -245,7 +232,7 @@ void CameraActor::SetType(Dali::Camera::Type type)
     mType = type;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetTypeMessage(GetEventThreadServices(), *mSceneObject, mType);
+    SetTypeMessage(GetEventThreadServices(), GetCameraSceneObject(), mType);
   }
 }
 
@@ -261,7 +248,7 @@ void CameraActor::SetProjectionMode(Dali::Camera::ProjectionMode mode)
     mProjectionMode = mode;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetProjectionModeMessage(GetEventThreadServices(), *mSceneObject, mProjectionMode);
+    SetProjectionModeMessage(GetEventThreadServices(), GetCameraSceneObject(), mProjectionMode);
   }
 }
 
@@ -278,7 +265,7 @@ void CameraActor::SetProjectionDirection(Dali::DevelCameraActor::ProjectionDirec
     mProjectionDirection = direction;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetProjectionDirectionMessage(GetEventThreadServices(), *mSceneObject, mProjectionDirection);
+    SetProjectionDirectionMessage(GetEventThreadServices(), GetCameraSceneObject(), mProjectionDirection);
   }
 }
 
@@ -290,7 +277,7 @@ void CameraActor::SetFieldOfView(float fieldOfView)
     mFieldOfView = fieldOfView;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetFieldOfViewMessage(GetEventThreadServices(), *mSceneObject, mFieldOfView);
+    BakeFieldOfViewMessage(GetEventThreadServices(), GetCameraSceneObject(), mFieldOfView);
   }
 }
 
@@ -299,6 +286,12 @@ float CameraActor::GetFieldOfView() const
   return mFieldOfView;
 }
 
+float CameraActor::GetCurrentFieldOfView() const
+{
+  // node is being used in a separate thread; copy the value from the previous update
+  return GetCameraSceneObject().GetFieldOfView(GetEventThreadServices().GetEventBufferIndex());
+}
+
 void CameraActor::SetAspectRatio(float aspectRatio)
 {
   mPropertyChanged = true;
@@ -307,7 +300,7 @@ void CameraActor::SetAspectRatio(float aspectRatio)
     mAspectRatio = aspectRatio;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetAspectRatioMessage(GetEventThreadServices(), *mSceneObject, mAspectRatio);
+    SetAspectRatioMessage(GetEventThreadServices(), GetCameraSceneObject(), mAspectRatio);
   }
 }
 
@@ -324,7 +317,7 @@ void CameraActor::SetNearClippingPlane(float nearClippingPlane)
     mNearClippingPlane = nearClippingPlane;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetNearClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mNearClippingPlane);
+    SetNearClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mNearClippingPlane);
   }
 }
 
@@ -341,7 +334,7 @@ void CameraActor::SetFarClippingPlane(float farClippingPlane)
     mFarClippingPlane = farClippingPlane;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetFarClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mFarClippingPlane);
+    SetFarClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mFarClippingPlane);
   }
 }
 
@@ -358,7 +351,7 @@ void CameraActor::SetLeftClippingPlane(float leftClippingPlane)
     mLeftClippingPlane = leftClippingPlane;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetLeftClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mLeftClippingPlane);
+    SetLeftClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mLeftClippingPlane);
   }
 }
 
@@ -370,7 +363,7 @@ void CameraActor::SetRightClippingPlane(float rightClippingPlane)
     mRightClippingPlane = rightClippingPlane;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetRightClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mRightClippingPlane);
+    SetRightClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mRightClippingPlane);
   }
 }
 
@@ -382,7 +375,7 @@ void CameraActor::SetTopClippingPlane(float topClippingPlane)
     mTopClippingPlane = topClippingPlane;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetTopClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mTopClippingPlane);
+    SetTopClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mTopClippingPlane);
   }
 }
 
@@ -394,7 +387,7 @@ void CameraActor::SetBottomClippingPlane(float bottomClippingPlane)
     mBottomClippingPlane = bottomClippingPlane;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetBottomClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mBottomClippingPlane);
+    SetBottomClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mBottomClippingPlane);
   }
 }
 
@@ -405,7 +398,7 @@ void CameraActor::SetInvertYAxis(bool invertYAxis)
     mInvertYAxis = invertYAxis;
 
     // sceneObject is being used in a separate thread; queue a message to set
-    SetInvertYAxisMessage(GetEventThreadServices(), *mSceneObject, mInvertYAxis);
+    SetInvertYAxisMessage(GetEventThreadServices(), GetCameraSceneObject(), mInvertYAxis);
   }
 }
 
@@ -526,7 +519,7 @@ bool CameraActor::BuildPickingRay(const Vector2&  screenCoordinates,
                  static_cast<float>(viewport.height) - (screenCoordinates.y - static_cast<float>(viewport.y)),
                  0.f,
                  1.f);
-    const Matrix& inverseViewProjection = mSceneObject->GetInverseViewProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
+    const Matrix& inverseViewProjection = GetCameraSceneObject().GetInverseViewProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
     success                             = Unproject(near, inverseViewProjection, static_cast<float>(viewport.width), static_cast<float>(viewport.height), near);
 
     // Compute the ray's director vector.
@@ -556,7 +549,7 @@ const Matrix& CameraActor::GetViewMatrix() const
 {
   if(OnScene())
   {
-    return mSceneObject->GetViewMatrix(GetEventThreadServices().GetEventBufferIndex());
+    return GetCameraSceneObject().GetViewMatrix(GetEventThreadServices().GetEventBufferIndex());
   }
   else
   {
@@ -568,22 +561,22 @@ const Matrix& CameraActor::GetProjectionMatrix() const
 {
   if(OnScene())
   {
-    return mSceneObject->GetProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
+    return GetCameraSceneObject().GetProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
   }
   else
   {
     return Matrix::IDENTITY;
   }
 }
-const SceneGraph::Camera* CameraActor::GetCamera() const
+const SceneGraph::Camera& CameraActor::GetCameraSceneObject() const
 {
-  return mSceneObject;
+  return static_cast<const SceneGraph::Camera&>(GetNode());
 }
 
 void CameraActor::RotateProjection(int rotationAngle)
 {
   // sceneObject is being used in a separate thread; queue a message to set
-  RotateProjectionMessage(GetEventThreadServices(), *mSceneObject, rotationAngle);
+  RotateProjectionMessage(GetEventThreadServices(), GetCameraSceneObject(), rotationAngle);
 }
 
 void CameraActor::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
@@ -791,26 +784,101 @@ Property::Value CameraActor::GetDefaultPropertyCurrentValue(Property::Index inde
   }
   else
   {
-    ret = GetDefaultProperty(index); // Most are event-side properties, the scene-graph properties are only on the scene-graph
+    switch(index)
+    {
+      case Dali::CameraActor::Property::FIELD_OF_VIEW:
+      {
+        ret = GetCurrentFieldOfView();
+        break;
+      }
+      default:
+      {
+        ret = GetDefaultProperty(index); // Most are event-side properties, the scene-graph properties are only on the scene-graph
+      }
+    } // switch(index)
   }
 
   return ret;
 }
 
+void CameraActor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
+{
+  if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
+  {
+    Actor::OnNotifyDefaultPropertyAnimation(animation, index, value, animationType);
+  }
+  else
+  {
+    switch(animationType)
+    {
+      case Animation::TO:
+      case Animation::BETWEEN:
+      {
+        switch(index)
+        {
+          case Dali::CameraActor::Property::FIELD_OF_VIEW:
+          {
+            value.Get(mFieldOfView);
+            break;
+          }
+        }
+        break;
+      }
+      case Animation::BY:
+      {
+        switch(index)
+        {
+          case Dali::CameraActor::Property::FIELD_OF_VIEW:
+          {
+            AdjustValue<float>(mFieldOfView, value);
+            break;
+          }
+        }
+        break;
+      }
+    }
+  }
+}
+
+const SceneGraph::PropertyBase* CameraActor::GetSceneObjectAnimatableProperty(Property::Index index) const
+{
+  const SceneGraph::PropertyBase* property(nullptr);
+  switch(index)
+  {
+    case Dali::CameraActor::Property::FIELD_OF_VIEW:
+    {
+      property = GetCameraSceneObject().GetFieldOfView();
+      break;
+    }
+      // no default on purpose as we chain method up to actor
+  }
+  if(!property)
+  {
+    // not our property, ask base
+    property = Actor::GetSceneObjectAnimatableProperty(index);
+  }
+
+  return property;
+}
 const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty(Property::Index index) const
 {
   const PropertyInputImpl* property(nullptr);
 
   switch(index)
   {
+    case Dali::CameraActor::Property::FIELD_OF_VIEW:
+    {
+      property = GetCameraSceneObject().GetFieldOfView();
+      break;
+    }
     case Dali::CameraActor::Property::PROJECTION_MATRIX:
     {
-      property = mSceneObject->GetProjectionMatrix();
+      property = GetCameraSceneObject().GetProjectionMatrix();
       break;
     }
     case Dali::CameraActor::Property::VIEW_MATRIX:
     {
-      property = mSceneObject->GetViewMatrix();
+      property = GetCameraSceneObject().GetViewMatrix();
       break;
     }
       // no default on purpose as we chain method up to actor
index a817811..407dc18 100644 (file)
@@ -107,6 +107,13 @@ public:
   float GetFieldOfView() const;
 
   /**
+   * @brief Retrieve the CameraActor's field of view from update side.
+   * This field of view will be the fov set or animating but will be a frame behind.
+   * @return The field of view.
+   */
+  float GetCurrentFieldOfView() const;
+
+  /**
    * @copydoc Dali::CameraActor::SetAspectRatio
    */
   void SetAspectRatio(float aspectRatio);
@@ -204,10 +211,10 @@ public:
   const Matrix& GetProjectionMatrix() const;
 
   /**
-   * Return the scene graph camera (for RenderTask)
+   * Return the scene graph camera
    * @return The scene graph camera.
    */
-  const SceneGraph::Camera* GetCamera() const;
+  const SceneGraph::Camera& GetCameraSceneObject() const;
 
   /**
    * Rotate the projection.
@@ -233,6 +240,16 @@ public: // properties
   Property::Value GetDefaultPropertyCurrentValue(Property::Index index) const override;
 
   /**
+   * @copydoc Dali::Internal::Object::OnNotifyDefaultPropertyAnimation()
+   */
+  void OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType) override;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty(Property::Index index) const override;
+
+  /**
    * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
    */
   const PropertyInputImpl* GetSceneObjectInputProperty(Property::Index index) const override;
@@ -250,11 +267,6 @@ private:
   ~CameraActor() override;
 
   /**
-   * @copydoc Dali::Internal::Actor::OnInitialize()
-   */
-  void OnInitialize() override;
-
-  /**
    * @copydoc Dali::Internal::Actor::OnSceneConnectionInternal()
    */
   void OnSceneConnectionInternal() override;
@@ -264,9 +276,7 @@ private:
    */
   void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
 
-private:                                  // Data
-  const SceneGraph::Camera* mSceneObject; ///< Not owned
-
+private: // Data
   Vector3                                     mTarget;
   Vector2                                     mCanvasSize;
   Dali::Camera::Type                          mType;
index 6abed7f..8069b54 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -142,7 +142,7 @@ void RenderTask::SetCameraActor(CameraActor* cameraActor)
   mCameraActor.SetActor(cameraActor);
   if(cameraActor)
   {
-    SetCameraMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &cameraActor->GetNode(), cameraActor->GetCamera());
+    SetCameraMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &cameraActor->GetNode(), &cameraActor->GetCameraSceneObject());
   }
   else
   {
index bf8b4b2..fc2ceb7 100644 (file)
@@ -542,28 +542,24 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector<Rect<int>>&
     }
 
     const Camera* camera = instruction.GetCamera();
-    if(camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
+    if(camera && camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
     {
-      const Node* node = instruction.GetCamera()->GetNode();
-      if(node)
+      Vector3    position;
+      Vector3    scale;
+      Quaternion orientation;
+      camera->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
+
+      Vector3 orientationAxis;
+      Radian  orientationAngle;
+      orientation.ToAxisAngle(orientationAxis, orientationAngle);
+
+      if(position.x > Math::MACHINE_EPSILON_10000 ||
+         position.y > Math::MACHINE_EPSILON_10000 ||
+         orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
+         orientationAngle != ANGLE_180 ||
+         scale != Vector3(1.0f, 1.0f, 1.0f))
       {
-        Vector3    position;
-        Vector3    scale;
-        Quaternion orientation;
-        node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
-
-        Vector3 orientationAxis;
-        Radian  orientationAngle;
-        orientation.ToAxisAngle(orientationAxis, orientationAngle);
-
-        if(position.x > Math::MACHINE_EPSILON_10000 ||
-           position.y > Math::MACHINE_EPSILON_10000 ||
-           orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
-           orientationAngle != ANGLE_180 ||
-           scale != Vector3(1.0f, 1.0f, 1.0f))
-        {
-          return;
-        }
+        return;
       }
     }
     else
index 0a889a6..1a31897 100644 (file)
@@ -25,7 +25,6 @@
 #include <dali/internal/render/shaders/render-shader.h>
 #include <dali/internal/update/common/scene-graph-scene.h>
 #include <dali/internal/update/nodes/node.h>
-#include <dali/internal/update/render-tasks/scene-graph-camera.h>
 
 namespace Dali
 {
@@ -38,7 +37,6 @@ DiscardQueue::DiscardQueue(RenderQueue& renderQueue)
   mNodeQueue(),
   mShaderQueue(),
   mRendererQueue(),
-  mCameraQueue(),
   mSceneQueue()
 {
 }
@@ -77,13 +75,6 @@ void DiscardQueue::Add(BufferIndex updateBufferIndex, Renderer* renderer)
   mRendererQueue[updateBufferIndex].PushBack(renderer);
 }
 
-void DiscardQueue::Add(BufferIndex updateBufferIndex, Camera* camera)
-{
-  DALI_ASSERT_DEBUG(NULL != camera);
-
-  mCameraQueue[updateBufferIndex].PushBack(camera);
-}
-
 void DiscardQueue::Add(BufferIndex updateBufferIndex, Scene* scene)
 {
   DALI_ASSERT_DEBUG(NULL != scene);
@@ -97,7 +88,6 @@ void DiscardQueue::Clear(BufferIndex updateBufferIndex)
   mNodeQueue[updateBufferIndex].Clear();
   mRendererQueue[updateBufferIndex].Clear();
   mShaderQueue[updateBufferIndex].Clear();
-  mCameraQueue[updateBufferIndex].Clear();
   mSceneQueue[updateBufferIndex].Clear();
 }
 
index d45504a..3624898 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_DISCARD_QUEUE_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,7 +49,6 @@ class DiscardQueue
 public:
   using ShaderQueue   = OwnerContainer<Shader*>;
   using RendererQueue = OwnerContainer<Renderer*>;
-  using CameraQueue   = OwnerContainer<Camera*>;
   using SceneQueue    = OwnerContainer<Scene*>;
 
   /**
@@ -90,14 +89,6 @@ public:
   void Add(BufferIndex updateBufferIndex, Renderer* renderer);
 
   /**
-   * Adds an unwanted Camera to the discard queue.
-   * This is done because Render thread may use Matrices from the camera
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] camera The discarded renderer; DiscardQueue takes ownership.
-   */
-  void Add(BufferIndex updateBufferIndex, Camera* camera);
-
-  /**
    * Adds an unwanted Scene to the discard queue.
    * A message will be sent to clean up GL resources in the next Render.
    * @param[in] updateBufferIndex The current update buffer index.
@@ -126,7 +117,6 @@ private:
   OwnerContainer<Node*> mNodeQueue[2];
   ShaderQueue           mShaderQueue[2];
   RendererQueue         mRendererQueue[2];
-  CameraQueue           mCameraQueue[2];
   SceneQueue            mSceneQueue[2];
 };
 
index 74b76c1..3f85f40 100644 (file)
@@ -181,15 +181,15 @@ inline bool SetNodeUpdateArea(Node* node, bool isLayer3d, Matrix& nodeWorldMatri
  * @param viewport The viewport
  * @param cull Whether frustum culling is enabled or not
  */
-inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
-                                    RenderList&         renderList,
-                                    Renderable&         renderable,
-                                    const Matrix&       viewMatrix,
-                                    SceneGraph::Camera& camera,
-                                    bool                isLayer3d,
-                                    bool                viewportSet,
-                                    const Viewport&     viewport,
-                                    bool                cull)
+inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
+                                    RenderList&               renderList,
+                                    Renderable&               renderable,
+                                    const Matrix&             viewMatrix,
+                                    const SceneGraph::Camera& camera,
+                                    bool                      isLayer3d,
+                                    bool                      viewportSet,
+                                    const Viewport&           viewport,
+                                    bool                      cull)
 {
   bool    inside(true);
   Node*   node = renderable.mNode;
@@ -361,15 +361,15 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
  * @param isLayer3d Whether we are processing a 3D layer or not
  * @param cull Whether frustum culling is enabled or not
  */
-inline void AddRenderersToRenderList(BufferIndex          updateBufferIndex,
-                                     RenderList&          renderList,
-                                     RenderableContainer& renderers,
-                                     const Matrix&        viewMatrix,
-                                     SceneGraph::Camera&  camera,
-                                     bool                 isLayer3d,
-                                     bool                 viewportSet,
-                                     const Viewport&      viewport,
-                                     bool                 cull)
+inline void AddRenderersToRenderList(BufferIndex               updateBufferIndex,
+                                     RenderList&               renderList,
+                                     RenderableContainer&      renderers,
+                                     const Matrix&             viewMatrix,
+                                     const SceneGraph::Camera& camera,
+                                     bool                      isLayer3d,
+                                     bool                      viewportSet,
+                                     const Viewport&           viewport,
+                                     bool                      cull)
 {
   DALI_LOG_INFO(gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
 
@@ -558,8 +558,8 @@ void RenderInstructionProcessor::Prepare(BufferIndex                 updateBuffe
   bool               isRenderListAdded       = false;
   bool               isRootLayerDirty        = false;
 
-  const Matrix&       viewMatrix = renderTask.GetViewMatrix(updateBufferIndex);
-  SceneGraph::Camera& camera     = renderTask.GetCamera();
+  const Matrix&             viewMatrix = renderTask.GetViewMatrix(updateBufferIndex);
+  const SceneGraph::Camera& camera     = renderTask.GetCamera();
 
   Viewport viewport;
   bool     viewportSet = renderTask.QueryViewport(updateBufferIndex, viewport);
@@ -568,7 +568,7 @@ void RenderInstructionProcessor::Prepare(BufferIndex                 updateBuffe
   for(SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter)
   {
     Layer&      layer = **iter;
-    const bool  tryReuseRenderList(viewMatrixHasNotChanged && layer.CanReuseRenderers(&renderTask.GetCamera()));
+    const bool  tryReuseRenderList(viewMatrixHasNotChanged && layer.CanReuseRenderers(&camera));
     const bool  isLayer3D  = layer.GetBehavior() == Dali::Layer::LAYER_3D;
     RenderList* renderList = nullptr;
 
index 4aaee3b..0da46fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -226,13 +226,13 @@ bool ProcessTasks(BufferIndex                          updateBufferIndex,
   // Retrieve size of Scene and default camera position to update viewport of each RenderTask if the RenderTask uses ViewportGuideNode.
   RenderTaskList::RenderTaskContainer::Iterator iter                  = taskContainer.Begin();
   RenderTask&                                   defaultRenderTask     = **iter;
-  auto                                          defaultCamera         = defaultRenderTask.GetCamera().GetNode();
+  const Camera&                                 defaultCamera         = defaultRenderTask.GetCamera();
   auto                                          defaultRootNode       = defaultRenderTask.GetSourceNode();
   Vector3                                       defaultCameraPosition = Vector3::ZERO;
   Vector2                                       sceneSize             = Vector2::ZERO;
-  if(defaultCamera && defaultRootNode)
+  if(defaultRootNode)
   {
-    defaultCameraPosition = defaultCamera->GetWorldPosition(updateBufferIndex);
+    defaultCameraPosition = defaultCamera.GetWorldPosition(updateBufferIndex);
     sceneSize             = Vector2(defaultRootNode->GetSize(updateBufferIndex) * defaultRootNode->GetWorldScale(updateBufferIndex));
   }
 
index 879707b..cffa575 100644 (file)
@@ -268,7 +268,8 @@ struct UpdateManager::Impl
 
   Vector<Node*> nodes; ///< A container of all instantiated nodes
 
-  OwnerContainer<Camera*>        cameras;       ///< A container of cameras
+  Vector<Camera*> cameras; ///< A container of cameras. Note : these cameras are owned by Impl::nodes.
+
   OwnerContainer<PropertyOwner*> customObjects; ///< A container of owned objects (with custom properties)
 
   OwnerContainer<PropertyResetterBase*> propertyResetters;     ///< A container of property resetters
@@ -377,6 +378,12 @@ void UpdateManager::AddNode(OwnerPointer<Node>& node)
   Node* rawNode = node.Release();
   DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddNode\n", rawNode);
 
+  // Add camera nodes occured rarely.
+  if(DALI_UNLIKELY(rawNode->IsCamera()))
+  {
+    AddCamera(static_cast<Camera*>(rawNode));
+  }
+
   mImpl->nodes.PushBack(rawNode);
   rawNode->CreateTransform(&mImpl->transformManager);
 }
@@ -435,21 +442,40 @@ void UpdateManager::DestroyNode(Node* node)
     }
   }
 
+  // Remove camera nodes occured rarely.
+  if(DALI_UNLIKELY(node->IsCamera()))
+  {
+    RemoveCamera(static_cast<Camera*>(node));
+  }
+
   mImpl->discardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), node);
 
   // Notify the Node about impending destruction
   node->OnDestroy();
 }
 
-void UpdateManager::AddCamera(OwnerPointer<Camera>& camera)
+void UpdateManager::AddCamera(Camera* camera)
 {
-  mImpl->cameras.PushBack(camera.Release()); // takes ownership
+  DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddCamera\n", camera);
+
+  mImpl->cameras.PushBack(camera);
 }
 
 void UpdateManager::RemoveCamera(Camera* camera)
 {
-  // Find the camera and destroy it
-  EraseUsingDiscardQueue(mImpl->cameras, camera, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex());
+  DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] RemoveCamera\n", camera);
+
+  // Find the camera and remove it from list of cameras
+  Vector<Camera*>::Iterator iter    = mImpl->cameras.Begin();
+  Vector<Camera*>::Iterator endIter = mImpl->cameras.End();
+  for(; iter != endIter; ++iter)
+  {
+    if((*iter) == camera)
+    {
+      mImpl->cameras.Erase(iter);
+      break;
+    }
+  }
 }
 
 void UpdateManager::AddObject(OwnerPointer<PropertyOwner>& object)
index 9a4a0e6..99d7e72 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -176,18 +176,6 @@ public:
   void DestroyNode(Node* node);
 
   /**
-   * Add a camera on scene
-   * @param[in] camera The camera to add
-   */
-  void AddCamera(OwnerPointer<Camera>& camera);
-
-  /**
-   * Remove a camera from scene
-   * @param[in] camera to remove
-   */
-  void RemoveCamera(Camera* camera);
-
-  /**
    * Add a newly created object.
    * @param[in] object The object to add.
    * @post The object is owned by UpdateManager.
@@ -480,7 +468,7 @@ public:
    * @param[in] size The new size of the buffer
    * @post Sends a message to RenderManager to set the new data to the property buffer.
    */
-  void SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t> >& data, uint32_t size);
+  void SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size);
 
   /**
    * Adds a geometry to the RenderManager
@@ -668,6 +656,18 @@ private:
   UpdateManager& operator=(const UpdateManager& rhs);
 
   /**
+   * Add a camera on scene
+   * @param[in] camera The camera to add
+   */
+  void AddCamera(Camera* camera);
+
+  /**
+   * Remove a camera from scene
+   * @param[in] camera to remove
+   */
+  void RemoveCamera(Camera* camera);
+
+  /**
    * Helper to check whether the update-thread should keep going.
    * @param[in] elapsedSeconds The time in seconds since the previous update.
    * @return True if the update-thread should keep going.
@@ -757,7 +757,7 @@ private:
 inline void InstallRootMessage(UpdateManager& manager, OwnerPointer<Layer>& root)
 {
   // Message has ownership of Layer while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Layer> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Layer>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -783,7 +783,7 @@ inline void UninstallRootMessage(UpdateManager& manager, const Layer* constRoot)
 inline void AddNodeMessage(UpdateManager& manager, OwnerPointer<Node>& node)
 {
   // Message has ownership of Node while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Node> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Node>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -835,33 +835,10 @@ inline void DestroyNodeMessage(UpdateManager& manager, const Node& constNode)
   new(slot) LocalType(&manager, &UpdateManager::DestroyNode, &node);
 }
 
-inline void AddCameraMessage(UpdateManager& manager, OwnerPointer<Camera>& camera)
-{
-  // Message has ownership of Camera while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Camera> >;
-
-  // Reserve some memory inside the message queue
-  uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
-
-  // Construct message in the message queue memory; note that delete should not be called on the return value
-  new(slot) LocalType(&manager, &UpdateManager::AddCamera, camera);
-}
-
-inline void RemoveCameraMessage(UpdateManager& manager, const Camera* camera)
-{
-  using LocalType = MessageValue1<UpdateManager, Camera*>;
-
-  // Reserve some memory inside the message queue
-  uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
-
-  // Construct message in the message queue memory; note that delete should not be called on the return value
-  new(slot) LocalType(&manager, &UpdateManager::RemoveCamera, const_cast<Camera*>(camera));
-}
-
 inline void AddObjectMessage(UpdateManager& manager, OwnerPointer<PropertyOwner>& object)
 {
   // Message has ownership of object while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyOwner> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyOwner>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -883,7 +860,7 @@ inline void RemoveObjectMessage(UpdateManager& manager, const PropertyOwner* obj
 
 inline void AddAnimationMessage(UpdateManager& manager, OwnerPointer<SceneGraph::Animation>& animation)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::Animation> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::Animation>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -922,7 +899,7 @@ inline void RemoveAnimationMessage(UpdateManager& manager, const Animation& cons
 
 inline void AddRenderTaskListMessage(UpdateManager& manager, OwnerPointer<SceneGraph::RenderTaskList>& taskList)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::RenderTaskList> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::RenderTaskList>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -947,7 +924,7 @@ inline void RemoveRenderTaskListMessage(UpdateManager& manager, const RenderTask
 
 inline void AddSceneMessage(UpdateManager& manager, OwnerPointer<SceneGraph::Scene>& scene)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::Scene> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::Scene>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -973,7 +950,7 @@ inline void RemoveSceneMessage(UpdateManager& manager, const SceneGraph::Scene&
 inline void AddPropertyNotificationMessage(UpdateManager& manager, OwnerPointer<PropertyNotification>& propertyNotification)
 {
   // Message has ownership of PropertyNotification while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyNotification> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyNotification>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1015,7 +992,7 @@ inline void PropertyNotificationSetNotifyModeMessage(UpdateManager&
 // The render thread can safely change the Shader
 inline void AddShaderMessage(UpdateManager& manager, OwnerPointer<Shader>& shader)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Shader> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Shader>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1102,7 +1079,7 @@ inline void SetLayerDepthsMessage(UpdateManager& manager, const std::vector<Laye
 
 inline void AddRendererMessage(UpdateManager& manager, OwnerPointer<Renderer>& object)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Renderer> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Renderer>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1133,7 +1110,7 @@ inline void AttachRendererMessage(UpdateManager& manager, const Node& node, cons
 // The render thread can safely change the Shader
 inline void AddTextureSetMessage(UpdateManager& manager, OwnerPointer<TextureSet>& textureSet)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<TextureSet> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<TextureSet>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1157,7 +1134,7 @@ inline void RemoveTextureSetMessage(UpdateManager& manager, TextureSet& textureS
 inline void AddSamplerMessage(UpdateManager& manager, OwnerPointer<Render::Sampler>& sampler)
 {
   // Message has ownership of Sampler while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Sampler> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Sampler>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1202,7 +1179,7 @@ inline void SetWrapModeMessage(UpdateManager& manager, Render::Sampler& sampler,
 inline void AddVertexBuffer(UpdateManager& manager, OwnerPointer<Render::VertexBuffer>& vertexBuffer)
 {
   // Message has ownership of vertexBuffer while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::VertexBuffer> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::VertexBuffer>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1225,7 +1202,7 @@ inline void RemoveVertexBuffer(UpdateManager& manager, Render::VertexBuffer& ver
 inline void SetVertexBufferFormat(UpdateManager& manager, Render::VertexBuffer& vertexBuffer, OwnerPointer<Render::VertexBuffer::Format>& format)
 {
   // Message has ownership of VertexBuffer::Format while in transit from event -> update
-  using LocalType = MessageValue2<UpdateManager, Render::VertexBuffer*, OwnerPointer<Render::VertexBuffer::Format> >;
+  using LocalType = MessageValue2<UpdateManager, Render::VertexBuffer*, OwnerPointer<Render::VertexBuffer::Format>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1234,10 +1211,10 @@ inline void SetVertexBufferFormat(UpdateManager& manager, Render::VertexBuffer&
   new(slot) LocalType(&manager, &UpdateManager::SetVertexBufferFormat, &vertexBuffer, format);
 }
 
-inline void SetVertexBufferData(UpdateManager& manager, Render::VertexBuffer& vertexBuffer, OwnerPointer<Vector<uint8_t> >& data, uint32_t size)
+inline void SetVertexBufferData(UpdateManager& manager, Render::VertexBuffer& vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size)
 {
   // Message has ownership of VertexBuffer data while in transit from event -> update
-  using LocalType = MessageValue3<UpdateManager, Render::VertexBuffer*, OwnerPointer<Vector<uint8_t> >, uint32_t>;
+  using LocalType = MessageValue3<UpdateManager, Render::VertexBuffer*, OwnerPointer<Vector<uint8_t>>, uint32_t>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1249,7 +1226,7 @@ inline void SetVertexBufferData(UpdateManager& manager, Render::VertexBuffer& ve
 inline void AddGeometry(UpdateManager& manager, OwnerPointer<Render::Geometry>& geometry)
 {
   // Message has ownership of Geometry while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Geometry> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Geometry>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1352,7 +1329,7 @@ inline void SetGeometryTypeMessage(UpdateManager& manager, Render::Geometry& geo
 inline void AddTexture(UpdateManager& manager, OwnerPointer<Render::Texture>& texture)
 {
   // Message has ownership of Texture while in transit from event -> update
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Texture> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Texture>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1396,7 +1373,7 @@ inline void GenerateMipmapsMessage(UpdateManager& manager, Render::Texture& text
 
 inline void AddFrameBuffer(UpdateManager& manager, OwnerPointer<Render::FrameBuffer>& frameBuffer)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::FrameBuffer> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::FrameBuffer>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1451,7 +1428,7 @@ inline void AttachDepthStencilTextureToFrameBuffer(UpdateManager& manager, Rende
 
 inline void SetDepthIndicesMessage(UpdateManager& manager, OwnerPointer<NodeDepths>& nodeDepths)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<NodeDepths> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<NodeDepths>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
@@ -1462,7 +1439,7 @@ inline void SetDepthIndicesMessage(UpdateManager& manager, OwnerPointer<NodeDept
 
 inline void AddResetterMessage(UpdateManager& manager, OwnerPointer<PropertyResetterBase> resetter)
 {
-  using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyResetterBase> >;
+  using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyResetterBase>>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
index c7a1dbb..af5962d 100644 (file)
@@ -59,8 +59,8 @@ Node* Node::New()
 
 void Node::Delete(Node* node)
 {
-  // check we have a node not a layer
-  if(!node->mIsLayer)
+  // check we have a node not a derived node
+  if(!node->mIsLayer && !node->mIsCamera)
   {
     // Manually call the destructor
     node->~Node();
@@ -100,6 +100,7 @@ Node::Node()
   mClippingMode(ClippingMode::DISABLED),
   mIsRoot(false),
   mIsLayer(false),
+  mIsCamera(false),
   mPositionUsesAnchorPoint(true),
   mTransparent(false)
 {
index 64baf5b..2cb97a3 100644 (file)
@@ -103,7 +103,7 @@ public:
    * Query whether the node is a layer.
    * @return True if the node is a layer.
    */
-  bool IsLayer()
+  bool IsLayer() const
   {
     return mIsLayer;
   }
@@ -117,6 +117,17 @@ public:
     return nullptr;
   }
 
+  // Camera interface
+
+  /**
+   * Query whether the node is a camera.
+   * @return True if the node is a camera.
+   */
+  bool IsCamera() const
+  {
+    return mIsCamera;
+  }
+
   /**
    * Mark an node and its sub tree according to the updated flag.
    * @param[in] updated The updated flag
@@ -899,11 +910,11 @@ private: // from NodeDataProvider
   }
 
 private:
-  // Undefined
-  Node(const Node&);
-
-  // Undefined
-  Node& operator=(const Node& rhs);
+  // Delete copy and move
+  Node(const Node&) = delete;
+  Node(Node&&)      = delete;
+  Node& operator=(const Node& rhs) = delete;
+  Node& operator=(Node&& rhs) = delete;
 
   /**
    * Recursive helper to disconnect a Node and its children.
@@ -966,6 +977,7 @@ protected:
   ClippingMode::Type mClippingMode : 3;            ///< The clipping mode of this node
   bool               mIsRoot : 1;                  ///< True if the node cannot have a parent
   bool               mIsLayer : 1;                 ///< True if the node is a layer
+  bool               mIsCamera : 1;                ///< True if the node is a camera
   bool               mPositionUsesAnchorPoint : 1; ///< True if the node should use the anchor-point when calculating the position
   bool               mTransparent : 1;             ///< True if this node is transparent. This value do not affect children.
 
index ca9a0e0..01641b6 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_LAYER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -190,7 +190,7 @@ public:
    * to use is the same than the one used before ( Otherwise View transform will be different )
    *
    */
-  bool CanReuseRenderers(Camera* camera)
+  bool CanReuseRenderers(const Camera* camera)
   {
     bool bReturn(mAllChildTransformsClean[0] && mAllChildTransformsClean[1] && camera == mLastCamera);
     mLastCamera = camera;
@@ -218,11 +218,11 @@ private:
    */
   Layer();
 
-  // Undefined
-  Layer(const Layer&);
-
-  // Undefined
-  Layer& operator=(const Layer& rhs);
+  // Delete copy and move
+  Layer(const Layer&) = delete;
+  Layer(Layer&&)      = delete;
+  Layer& operator=(const Layer& rhs) = delete;
+  Layer& operator=(Layer&& rhs) = delete;
 
 public: // For update-algorithms
   RenderableContainer colorRenderables;
@@ -231,8 +231,8 @@ public: // For update-algorithms
 private:
   SortFunctionType mSortFunction; ///< Used to sort semi-transparent geometry
 
-  ClippingBox mClippingBox; ///< The clipping box, in window coordinates
-  Camera*     mLastCamera;  ///< Pointer to the last camera that has rendered the layer
+  ClippingBox   mClippingBox; ///< The clipping box, in window coordinates
+  const Camera* mLastCamera;  ///< Pointer to the last camera that has rendered the layer
 
   Dali::Layer::Behavior mBehavior; ///< The behavior of the layer
 
index e8350a0..d80acd6 100644 (file)
@@ -23,6 +23,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <dali/internal/common/memory-pool-object-allocator.h>
 #include <dali/internal/update/nodes/node.h>
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/math/math-utils.h>
@@ -45,6 +46,9 @@ namespace SceneGraph
 {
 namespace
 {
+//Memory pool used to allocate new camera. Memory used by this pool will be released when shutting down DALi
+MemoryPoolObjectAllocator<Camera> gCameraMemoryPool;
+
 template<typename T>
 T Sign(T value)
 {
@@ -165,10 +169,10 @@ const float                                       Camera::DEFAULT_FAR_CLIPPING_P
 const Vector3                                     Camera::DEFAULT_TARGET_POSITION(0.0f, 0.0f, 0.0f);
 
 Camera::Camera()
-: mUpdateViewFlag(UPDATE_COUNT),
+: Node(),
+  mUpdateViewFlag(UPDATE_COUNT),
   mUpdateProjectionFlag(UPDATE_COUNT),
   mProjectionRotation(0),
-  mNode(nullptr),
   mType(DEFAULT_TYPE),
   mProjectionMode(DEFAULT_MODE),
   mProjectionDirection(DEFAULT_PROJECTION_DIRECTION),
@@ -187,23 +191,20 @@ Camera::Camera()
   mInverseViewProjection(Matrix::IDENTITY),
   mFinalProjection(Matrix::IDENTITY)
 {
+  // set a flag the node to say this is a camera
+  mIsCamera = true;
 }
 
 Camera* Camera::New()
 {
-  return new Camera();
+  return new(gCameraMemoryPool.AllocateRawThreadSafe()) Camera();
 }
 
 Camera::~Camera() = default;
 
-void Camera::SetNode(const Node* node)
-{
-  mNode = node;
-}
-
-const Node* Camera::GetNode() const
+void Camera::operator delete(void* ptr)
 {
-  return mNode;
+  gCameraMemoryPool.FreeThreadSafe(static_cast<Camera*>(ptr));
 }
 
 void Camera::SetType(Dali::Camera::Type type)
@@ -229,9 +230,9 @@ void Camera::SetInvertYAxis(bool invertYAxis)
   mUpdateProjectionFlag = UPDATE_COUNT;
 }
 
-void Camera::SetFieldOfView(float fieldOfView)
+void Camera::BakeFieldOfView(BufferIndex updateBufferIndex, float fieldOfView)
 {
-  mFieldOfView          = fieldOfView;
+  mFieldOfView.Bake(updateBufferIndex, fieldOfView);
   mUpdateProjectionFlag = UPDATE_COUNT;
 }
 
@@ -370,6 +371,11 @@ const Matrix& Camera::GetFinalProjectionMatrix(BufferIndex bufferIndex) const
   return mFinalProjection[bufferIndex];
 }
 
+const PropertyBase* Camera::GetFieldOfView() const
+{
+  return &mFieldOfView;
+}
+
 const PropertyInputImpl* Camera::GetProjectionMatrix() const
 {
   return &mProjectionMatrix;
@@ -382,12 +388,12 @@ const PropertyInputImpl* Camera::GetViewMatrix() const
 
 void Camera::Update(BufferIndex updateBufferIndex)
 {
-  // if owning node has changes in world position we need to update camera for next 2 frames
-  if(mNode->IsLocalMatrixDirty())
+  // if this has changes in world position we need to update camera for next 2 frames
+  if(IsLocalMatrixDirty())
   {
     mUpdateViewFlag = UPDATE_COUNT;
   }
-  if(mNode->GetDirtyFlags() & NodePropertyFlags::VISIBLE)
+  if(GetDirtyFlags() & NodePropertyFlags::VISIBLE)
   {
     // If the visibility changes, the projection matrix needs to be re-calculated.
     // It may happen the first time an actor is rendered it's rendered only once and becomes invisible,
@@ -396,6 +402,12 @@ void Camera::Update(BufferIndex updateBufferIndex)
     mUpdateProjectionFlag = UPDATE_COUNT;
   }
 
+  // If projection matrix relative properties are animated now, flag change.
+  if(IsProjectionMatrixAnimated())
+  {
+    mUpdateProjectionFlag = UPDATE_COUNT;
+  }
+
   // if either matrix changed, we need to recalculate the inverse matrix for hit testing to work
   uint32_t viewUpdateCount       = UpdateViewMatrix(updateBufferIndex);
   uint32_t projectionUpdateCount = UpdateProjection(updateBufferIndex);
@@ -419,11 +431,16 @@ void Camera::Update(BufferIndex updateBufferIndex)
   }
 }
 
-bool Camera::ViewMatrixUpdated()
+bool Camera::ViewMatrixUpdated() const
 {
   return 0u != mUpdateViewFlag;
 }
 
+bool Camera::IsProjectionMatrixAnimated() const
+{
+  return !mFieldOfView.IsClean();
+}
+
 uint32_t Camera::UpdateViewMatrix(BufferIndex updateBufferIndex)
 {
   uint32_t retval(mUpdateViewFlag);
@@ -442,11 +459,11 @@ uint32_t Camera::UpdateViewMatrix(BufferIndex updateBufferIndex)
         case Dali::Camera::FREE_LOOK:
         {
           Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
-          viewMatrix         = mNode->GetWorldMatrix(updateBufferIndex);
+          viewMatrix         = GetWorldMatrix(updateBufferIndex);
 
           if(mUseReflection)
           {
-            const Matrix& owningNodeMatrix(mNode->GetWorldMatrix(updateBufferIndex));
+            const Matrix& owningNodeMatrix(GetWorldMatrix(updateBufferIndex));
             Vector3       position{}, scale{};
             Quaternion    orientation{};
             owningNodeMatrix.GetTransformComponents(position, orientation, scale);
@@ -466,7 +483,7 @@ uint32_t Camera::UpdateViewMatrix(BufferIndex updateBufferIndex)
         // camera orientation constrained to look at a target
         case Dali::Camera::LOOK_AT_TARGET:
         {
-          const Matrix& owningNodeMatrix(mNode->GetWorldMatrix(updateBufferIndex));
+          const Matrix& owningNodeMatrix(GetWorldMatrix(updateBufferIndex));
           Vector3       position, scale;
           Quaternion    orientation;
           owningNodeMatrix.GetTransformComponents(position, orientation, scale);
@@ -585,7 +602,7 @@ void Camera::UpdateFrustum(BufferIndex updateBufferIndex, bool normalize)
   mFrustum[updateBufferIndex ? 0 : 1] = planes;
 }
 
-bool Camera::CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius)
+bool Camera::CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius) const
 {
   const FrustumPlanes& planes = mFrustum[bufferIndex];
   for(uint32_t i = 0; i < 6; ++i)
@@ -598,7 +615,7 @@ bool Camera::CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin
   return true;
 }
 
-bool Camera::CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents)
+bool Camera::CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents) const
 {
   const FrustumPlanes& planes = mFrustum[bufferIndex];
   for(uint32_t i = 0; i < 6; ++i)
@@ -638,7 +655,7 @@ uint32_t Camera::UpdateProjection(BufferIndex updateBufferIndex)
           Matrix& projectionMatrix = mProjectionMatrix.Get(updateBufferIndex);
           Perspective(projectionMatrix,
                       mProjectionDirection,
-                      mFieldOfView,
+                      mFieldOfView[updateBufferIndex],
                       mAspectRatio,
                       mNearClippingPlane,
                       mFarClippingPlane,
index 2af3cec..e1bac63 100644 (file)
 #include <dali/internal/common/message.h>
 #include <dali/internal/common/type-abstraction-enums.h>
 #include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/animatable-property.h>
 #include <dali/internal/update/common/double-buffered.h>
 #include <dali/internal/update/common/inherited-property.h>
+#include <dali/internal/update/nodes/node.h>
 #include <dali/public-api/actors/camera-actor.h>
 #include <dali/public-api/math/rect.h>
 
@@ -46,13 +48,12 @@ struct ParameterType<Dali::Camera::ProjectionMode>
 
 namespace SceneGraph
 {
-class Node;
 class SceneController;
 
 /**
  * Scene-graph camera object
  */
-class Camera
+class Camera : public Node
 {
 public:
   static const Dali::Camera::Type                          DEFAULT_TYPE;
@@ -95,21 +96,15 @@ public:
   static Camera* New();
 
   /**
-   * Destructor
+   * Virtual destructor
    */
-  ~Camera();
+  ~Camera() override;
 
   /**
-   * Set the node this scene graph camera belongs to.
-   * @param[in] node The owning node.
+   * Overriden delete operator
+   * Deletes the camera from its global memory pool
    */
-  void SetNode(const Node* node);
-
-  /**
-   * Get the node this scene graph camera belongs to.
-   * @return node The owning node.
-   */
-  const Node* GetNode() const;
+  void operator delete(void* ptr);
 
   /**
    * @copydoc Dali::Internal::CameraActor::SetType
@@ -141,11 +136,6 @@ public:
   void SetProjectionDirection(Dali::DevelCameraActor::ProjectionDirection direction);
 
   /**
-   * @copydoc Dali::Internal::CameraActor::SetFieldOfView
-   */
-  void SetFieldOfView(float fieldOfView);
-
-  /**
    * @copydoc Dali::Internal::CameraActor::SetAspectRatio
    */
   void SetAspectRatio(float aspectRatio);
@@ -191,6 +181,23 @@ public:
   void SetTargetPosition(const Vector3& targetPosition);
 
   /**
+   * @brief Bakes the field of view.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] opacity The field of view.
+   */
+  void BakeFieldOfView(BufferIndex updateBufferIndex, float fieldOfView);
+
+  /**
+   * @brief Retrieve the field of view.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The field of view.
+   */
+  float GetFieldOfView(BufferIndex bufferIndex) const
+  {
+    return mFieldOfView[bufferIndex];
+  }
+
+  /**
    * Sets the reflection plane
    * @param[in] plane reflection plane
    */
@@ -221,7 +228,7 @@ public:
    *
    * @return false if the sphere lies outside of the frustum.
    */
-  bool CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius);
+  bool CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius) const;
 
   /**
    * @brief Check to see if a bounding box lies within the view frustum.
@@ -232,7 +239,7 @@ public:
    *
    * @return false if the cubeoid lies completely outside of the frustum, true otherwise
    */
-  bool CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents);
+  bool CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents) const;
 
   /**
    * Retrieve the projection-matrix; this is double buffered for input handling.
@@ -256,6 +263,13 @@ public:
   const Matrix& GetFinalProjectionMatrix(BufferIndex bufferIndex) const;
 
   /**
+   * Retrieve the field of view property querying interface.
+   * @pre The camera is on-stage.
+   * @return The field of view property querying interface.
+   */
+  const PropertyBase* GetFieldOfView() const;
+
+  /**
    * Retrieve the projection-matrix property querying interface.
    * @pre The camera is on-stage.
    * @return The projection-matrix property querying interface.
@@ -279,7 +293,12 @@ public:
   /**
    * @return true if the view matrix of camera is updated this or the previous frame
    */
-  bool ViewMatrixUpdated();
+  bool ViewMatrixUpdated() const;
+
+  /**
+   * @return true if the projection matrix projection matrix relative properties are animated this or the previous frame
+   */
+  bool IsProjectionMatrixAnimated() const;
 
 private:
   /**
@@ -287,11 +306,11 @@ private:
    */
   Camera();
 
-  // Non copyable
-  // Undefined
-  Camera(const Camera&);
-  // Undefined
-  Camera& operator=(const Camera& rhs);
+  // Delete copy and move
+  Camera(const Camera&) = delete;
+  Camera(Camera&&)      = delete;
+  Camera& operator=(const Camera& rhs) = delete;
+  Camera& operator=(Camera&& rhs) = delete;
 
   /**
    * Recalculates the view matrix.
@@ -323,10 +342,9 @@ private:
    */
   void AdjustNearPlaneForPerspective(Matrix& perspective, const Vector4& clipPlane);
 
-  uint32_t    mUpdateViewFlag;       ///< This is non-zero if the view matrix requires an update
-  uint32_t    mUpdateProjectionFlag; ///< This is non-zero if the projection matrix requires an update
-  int         mProjectionRotation;   ///< The rotaion angle of the projection
-  const Node* mNode;                 ///< The node this scene graph camera belongs to
+  uint32_t mUpdateViewFlag;       ///< This is non-zero if the view matrix requires an update
+  uint32_t mUpdateProjectionFlag; ///< This is non-zero if the projection matrix requires an update
+  int      mProjectionRotation;   ///< The rotaion angle of the projection
 
 public:                                                             // PROPERTIES
   Dali::Camera::Type                          mType;                // Non-animatable
@@ -334,7 +352,8 @@ public:                                                             // PROPERTIE
   Dali::DevelCameraActor::ProjectionDirection mProjectionDirection; // Non-animatable
   bool                                        mInvertYAxis;         // Non-animatable
 
-  float   mFieldOfView;
+  AnimatableProperty<float> mFieldOfView; // Animatable
+
   float   mAspectRatio;
   float   mLeftClippingPlane;
   float   mRightClippingPlane;
@@ -393,15 +412,15 @@ inline void SetProjectionDirectionMessage(EventThreadServices& eventThreadServic
   new(slot) LocalProjectionDirection(&camera, &Camera::SetProjectionDirection, parameter);
 }
 
-inline void SetFieldOfViewMessage(EventThreadServices& eventThreadServices, const Camera& camera, float parameter)
+inline void BakeFieldOfViewMessage(EventThreadServices& eventThreadServices, const Camera& camera, float parameter)
 {
-  using LocalType = MessageValue1<Camera, float>;
+  using LocalType = MessageDoubleBuffered1<Camera, float>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
 
   // Construct message in the message queue memory; note that delete should not be called on the return value
-  new(slot) LocalType(&camera, &Camera::SetFieldOfView, parameter);
+  new(slot) LocalType(&camera, &Camera::BakeFieldOfView, parameter);
 }
 
 inline void SetAspectRatioMessage(EventThreadServices& eventThreadServices, const Camera& camera, float parameter)
index b155781..90dca93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -356,7 +356,7 @@ const Matrix& RenderTask::GetViewMatrix(BufferIndex bufferIndex) const
   return mCamera->GetViewMatrix(bufferIndex);
 }
 
-SceneGraph::Camera& RenderTask::GetCamera() const
+const SceneGraph::Camera& RenderTask::GetCamera() const
 {
   DALI_ASSERT_DEBUG(nullptr != mCamera);
   return *mCamera;
@@ -417,7 +417,7 @@ void RenderTask::UpdateViewport(BufferIndex updateBufferIndex, Vector2 sceneSize
 {
   if(GetViewportGuideNode() && GetViewportGuideNode()->ConnectedToScene())
   {
-    Vector3 worldPosition  = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
+    Vector3 worldPosition = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
     worldPosition -= cameraPosition;
 
     Vector3 nodeSize = GetViewportGuideNode()->GetSize(updateBufferIndex) * GetViewportGuideNode()->GetWorldScale(updateBufferIndex);
index 7dfb7c1..0d5142c 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -311,7 +311,7 @@ public:
    *
    * @return The camera.
    */
-  SceneGraph::Camera& GetCamera() const;
+  const SceneGraph::Camera& GetCamera() const;
 
   /**
    * Retrieve the projection-matrix; this is double buffered for input handling.