[Tizen] Remove model-node-data-impl 30/292230/1
authorseungho baek <sbsh.baek@samsung.com>
Wed, 19 Apr 2023 09:20:00 +0000 (18:20 +0900)
committerseungho baek <sbsh.baek@samsung.com>
Tue, 2 May 2023 05:20:27 +0000 (14:20 +0900)
Change-Id: Iba64ae2ecbc67d42093affbc364693ff163551b6
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
automated-tests/src/dali-scene3d/utc-Dali-ModelNode.cpp
dali-scene3d/internal/file.list
dali-scene3d/internal/model-components/model-node-data-impl.cpp [deleted file]
dali-scene3d/internal/model-components/model-node-data-impl.h [deleted file]
dali-scene3d/internal/model-components/model-node-impl.cpp
dali-scene3d/internal/model-components/model-node-impl.h

index e124bc6..3aaecc6 100644 (file)
@@ -21,6 +21,7 @@
 #include <iostream>
 
 #include <dali-scene3d/public-api/model-components/model-node.h>
+#include "mesh-builder.h"
 
 using namespace Dali;
 using namespace Dali::Toolkit;
@@ -35,10 +36,6 @@ void model_components_model_node_cleanup(void)
   test_return_value = TET_PASS;
 }
 
-namespace
-{
-} // namespace
-
 // Negative test case for a method
 int UtcDaliModelNodeUninitialized(void)
 {
@@ -293,4 +290,80 @@ int UtcDaliModelNodeFindChildModelNodeByName(void)
   DALI_TEST_EQUALS(child2, modelNode2, TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliModelNodeCustomNode1(void)
+{
+  tet_infoline(" UtcDaliModelNodeCustomNode1.");
+
+  ToolkitTestApplication application;
+
+  Scene3D::ModelNode      modelNode      = Scene3D::ModelNode::New();
+  Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+  Scene3D::Material       material       = Scene3D::Material::New();
+  Geometry                geometry       = CreateQuadGeometry();
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 0, TEST_LOCATION);
+
+  modelNode.AddModelPrimitive(modelPrimitive);
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 0, TEST_LOCATION);
+  
+  modelPrimitive.SetGeometry(geometry);
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 0, TEST_LOCATION);
+
+  modelPrimitive.SetMaterial(material);
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelNodeCustomNode2(void)
+{
+  tet_infoline(" UtcDaliModelNodeCustomNode2.");
+
+  ToolkitTestApplication application;
+
+  Scene3D::ModelNode      modelNode      = Scene3D::ModelNode::New();
+  Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+  Scene3D::Material       material       = Scene3D::Material::New();
+  Geometry                geometry       = CreateQuadGeometry();
+  modelPrimitive.SetGeometry(geometry);
+  modelPrimitive.SetMaterial(material);
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 0, TEST_LOCATION);
+
+  modelNode.AddModelPrimitive(modelPrimitive);
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliModelNodeCustomNode3(void)
+{
+  tet_infoline(" UtcDaliModelNodeCustomNode3.");
+
+  ToolkitTestApplication application;
+
+  Scene3D::ModelNode      modelNode      = Scene3D::ModelNode::New();
+  Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+  Scene3D::Material       material       = Scene3D::Material::New();
+  Geometry                geometry       = CreateQuadGeometry();
+  modelPrimitive.SetGeometry(geometry);
+  modelPrimitive.SetMaterial(material);
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 0, TEST_LOCATION);
+
+  modelNode.AddModelPrimitive(modelPrimitive);
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 1, TEST_LOCATION);
+
+  modelNode.AddModelPrimitive(modelPrimitive);
+
+  DALI_TEST_EQUALS(modelNode.GetRendererCount(), 1, TEST_LOCATION);
+
+  END_TEST;
+}
index 063c0d1..064afbf 100644 (file)
@@ -15,7 +15,6 @@ set(scene3d_src_files ${scene3d_src_files}
        ${scene3d_internal_dir}/loader/json-reader.cpp
        ${scene3d_internal_dir}/loader/json-util.cpp
        ${scene3d_internal_dir}/model-components/material-impl.cpp
-       ${scene3d_internal_dir}/model-components/model-node-data-impl.cpp
        ${scene3d_internal_dir}/model-components/model-node-impl.cpp
        ${scene3d_internal_dir}/model-components/model-primitive-impl.cpp
 )
diff --git a/dali-scene3d/internal/model-components/model-node-data-impl.cpp b/dali-scene3d/internal/model-components/model-node-data-impl.cpp
deleted file mode 100644 (file)
index c6808bc..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (c) 2023 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali-scene3d/internal/model-components/model-node-data-impl.h>
-
-// EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
-#include <dali/public-api/object/type-registry-helper.h>
-#include <dali/public-api/object/type-registry.h>
-
-// INTERNAL INCLUDES
-#include <dali-scene3d/internal/model-components/model-primitive-impl.h>
-#include <dali-scene3d/public-api/model-components/model-node.h>
-
-namespace
-{
-} // namespace
-
-namespace Dali
-{
-namespace Scene3D
-{
-namespace Internal
-{
-namespace
-{
-/**
- * Creates control through type registry
- */
-BaseHandle Create()
-{
-  return Scene3D::ModelNode::New();
-}
-
-// Setup properties, signals and actions using the type-registry.
-DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelNode, Dali::CustomActor, Create);
-DALI_TYPE_REGISTRATION_END()
-} // unnamed namespace
-
-ModelNode::Impl::Impl(ModelNode& modelNodeImpl)
-: mModelNodeImpl(modelNodeImpl)
-{
-}
-
-ModelNode::Impl::~Impl()
-{
-  for(auto&& primitive : mModelPrimitiveContainer)
-  {
-    GetImplementation(primitive).RemovePrimitiveObserver(this);
-  }
-  for(auto&& boneData : mBoneDataContainer)
-  {
-    boneData.primitive.Reset();
-    if(boneData.constraint)
-    {
-      boneData.constraint.Remove();
-      boneData.constraint.Reset();
-    }
-  }
-}
-
-void ModelNode::Impl::OnSceneConnection(int depth)
-{
-}
-
-void ModelNode::Impl::OnSceneDisconnection()
-{
-}
-
-void ModelNode::Impl::OnRendererCreated(Renderer renderer)
-{
-  mModelNodeImpl.Self().AddRenderer(renderer);
-}
-
-// Public Method
-
-void ModelNode::Impl::AddModelPrimitive(Scene3D::ModelPrimitive modelPrimitive)
-{
-  for(auto&& primitive : mModelPrimitiveContainer)
-  {
-    if(primitive == modelPrimitive)
-    {
-      return;
-    }
-  }
-
-  mModelPrimitiveContainer.push_back(modelPrimitive);
-
-  Actor self = mModelNodeImpl.Self();
-
-  GetImplementation(modelPrimitive).AddPrimitiveObserver(this);
-  if(mDiffuseTexture && mSpecularTexture)
-  {
-    GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
-  }
-
-  Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
-  if(renderer)
-  {
-    uint32_t rendererCount = self.GetRendererCount();
-    bool     exist         = false;
-    for(uint32_t i = 0; i < rendererCount; ++i)
-    {
-      if(renderer == self.GetRendererAt(i))
-      {
-        exist = true;
-        break;
-      }
-    }
-    if(!exist)
-    {
-      self.AddRenderer(renderer);
-    }
-  }
-}
-
-void ModelNode::Impl::RemoveModelPrimitive(Scene3D::ModelPrimitive modelPrimitive)
-{
-  uint32_t primitiveCount = GetModelPrimitiveCount();
-  for(uint32_t i = 0; i < primitiveCount; ++i)
-  {
-    if(mModelPrimitiveContainer[i] != modelPrimitive)
-    {
-      continue;
-    }
-    RemoveModelPrimitive(i);
-    break;
-  }
-}
-
-void ModelNode::Impl::RemoveModelPrimitive(uint32_t index)
-{
-  if(index >= mModelPrimitiveContainer.size())
-  {
-    return;
-  }
-
-  Actor self = mModelNodeImpl.Self();
-  GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
-
-  Dali::Renderer renderer = GetImplementation(mModelPrimitiveContainer[index]).GetRenderer();
-  if(renderer)
-  {
-    self.RemoveRenderer(renderer);
-  }
-
-  mModelPrimitiveContainer.erase(mModelPrimitiveContainer.begin() + index);
-}
-
-Scene3D::ModelPrimitive ModelNode::Impl::GetModelPrimitive(uint32_t index) const
-{
-  if(index < mModelPrimitiveContainer.size())
-  {
-    return mModelPrimitiveContainer[index];
-  }
-  return Scene3D::ModelPrimitive();
-}
-
-void ModelNode::Impl::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
-{
-  mDiffuseTexture       = diffuseTexture;
-  mSpecularTexture      = specularTexture;
-  mIblScaleFactor       = iblScaleFactor;
-  mSpecularMipmapLevels = specularMipmapLevels;
-  for(auto&& primitive : mModelPrimitiveContainer)
-  {
-    GetImplementation(primitive).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
-  }
-}
-
-void ModelNode::Impl::SetImageBasedLightScaleFactor(float iblScaleFactor)
-{
-  mIblScaleFactor = iblScaleFactor;
-  for(auto&& primitive : mModelPrimitiveContainer)
-  {
-    GetImplementation(primitive).SetImageBasedLightScaleFactor(iblScaleFactor);
-  }
-}
-
-void ModelNode::Impl::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
-{
-  GetImplementation(primitive).SetBlendShapeData(data);
-}
-
-void ModelNode::Impl::SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex)
-{
-  Dali::Scene3D::Loader::Skinning::BoneData boneData;
-  boneData.primitive = primitive;
-  boneData.boneIndex = boneIndex;
-  char propertyNameBuffer[32];
-  snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Dali::Scene3D::Loader::Skinning::BONE_UNIFORM_NAME, boneIndex);
-  boneData.propertyName  = propertyNameBuffer;
-  boneData.inverseMatrix = inverseMatrix;
-  mBoneDataContainer.push_back(std::move(boneData));
-
-  UpdateBoneMatrix(primitive);
-}
-
-void ModelNode::Impl::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
-{
-  for(auto&& boneData : mBoneDataContainer)
-  {
-    if(boneData.primitive != primitive)
-    {
-      continue;
-    }
-
-    Dali::Renderer renderer = GetImplementation(primitive).GetRenderer();
-    if(!renderer)
-    {
-      continue;
-    }
-
-    if(boneData.constraint)
-    {
-      boneData.constraint.Remove();
-      boneData.constraint.Reset();
-    }
-
-    if(renderer.GetPropertyIndex(boneData.propertyName) == Property::INVALID_INDEX)
-    {
-      auto propBoneXform = renderer.RegisterProperty(boneData.propertyName, Matrix{false});
-
-      Matrix inverseMatrix = boneData.inverseMatrix;
-      // Constrain bone matrix to joint transform.
-      boneData.constraint = Constraint::New<Matrix>(renderer, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs)
-                                                    { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
-
-      Actor joint           = mModelNodeImpl.Self();
-      boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
-      boneData.constraint.ApplyPost();
-    }
-    break;
-  }
-}
-
-} // namespace Internal
-
-} // namespace Scene3D
-
-} // namespace Dali
diff --git a/dali-scene3d/internal/model-components/model-node-data-impl.h b/dali-scene3d/internal/model-components/model-node-data-impl.h
deleted file mode 100644 (file)
index b19a82f..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_DATA_IMPL_H
-#define DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_DATA_IMPL_H
-
-/*
- * Copyright (c) 2023 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/animation/constraints.h>
-#include <dali/public-api/common/dali-vector.h>
-#include <dali/public-api/object/type-registry.h>
-
-// INTERNAL INCLUDES
-#include <dali-scene3d/internal/model-components/model-node-impl.h>
-#include <dali-scene3d/internal/model-components/model-primitive-modify-observer.h>
-#include <dali-scene3d/public-api/loader/skinning-details.h>
-
-namespace Dali
-{
-namespace Scene3D
-{
-namespace Internal
-{
-/**
- * @brief Holds the Implementation for the internal model node class
- */
-class ModelNode::Impl : public ModelPrimitiveModifyObserver
-{
-public:
-  using ModelPrimitiveContainer = std::vector<Scene3D::ModelPrimitive>;
-  using BoneDataContainer       = std::vector<Dali::Scene3D::Loader::Skinning::BoneData>;
-
-  /**
-   * @brief Constructor.
-   * @param[in] modelNodeImpl The control which owns this implementation
-   */
-  Impl(ModelNode& modelNodeImpl);
-
-  /**
-   * @brief Destructor.
-   */
-  ~Impl();
-
-public:
-  /**
-   * @copydoc Dali::Scene3D::Internal::ModelNode::OnSceneConnection()
-   */
-  void OnSceneConnection(int depth);
-
-  /**
-   * @copydoc Dali::Scene3D::Internal::ModelNode::OnSceneConnection()
-   */
-  void OnSceneDisconnection();
-
-public: // Public Method
-  /**
-   * @copydoc Dali::Scene3D::ModelNode::GetModelPrimitiveCount()
-   */
-  inline uint32_t GetModelPrimitiveCount() const
-  {
-    return static_cast<uint32_t>(mModelPrimitiveContainer.size());
-  }
-
-  /**
-   * @copydoc Dali::Scene3D::ModelNode::AddModelPrimitive()
-   */
-  void AddModelPrimitive(Scene3D::ModelPrimitive modelPrimitive);
-
-  /**
-   * @copydoc Dali::Scene3D::ModelNode::RemoveModelPrimitive()
-   */
-  void RemoveModelPrimitive(Scene3D::ModelPrimitive modelPrimitive);
-
-  /**
-   * @copydoc Dali::Scene3D::ModelNode::RemoveModelPrimitive()
-   */
-  void RemoveModelPrimitive(uint32_t index);
-
-  /**
-   * @copydoc Dali::Scene3D::ModelNode::GetModelPrimitive()
-   */
-  Scene3D::ModelPrimitive GetModelPrimitive(uint32_t index) const;
-
-  /**
-   * @brief Sets the diffuse and specular image-based lighting textures for a ModelPrimitive.
-   *
-   * @param[in] diffuseTexture The diffuse texture.
-   * @param[in] specularTexture The specular texture.
-   * @param[in] iblScaleFactor The scale factor for the image-based lighting.
-   * @param[in] specularMipmapLevels The number of mipmap levels for the specular texture.
-   */
-  void SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels);
-
-  /**
-   * @brief Sets the scale factor for image-based lighting.
-   *
-   * @param[in] iblScaleFactor The scale factor for image-based lighting.
-   */
-  void SetImageBasedLightScaleFactor(float iblScaleFactor);
-
-  /**
-   * @brief Sets the blend shape data for a ModelPrimitive.
-   *
-   * @param[in] data The blend shape data.
-   * @param[in] primitive The ModelPrimitive to set the blend shape data for.
-   */
-  void SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive);
-
-  /**
-   * @brief Sets the bone matrix for a ModelPrimitive and bone index.
-   *
-   * @param[in] inverseMatrix The inverse matrix of the bone.
-   * @param[in] primitive The ModelPrimitive to set the bone matrix for.
-   * @param[in] boneIndex The index of the bone to set the matrix for.
-   */
-  void SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex);
-
-  /**
-   * @brief Called when a Renderer of ModelPrimitive is created.
-   *
-   * @param[in] renderer The Renderer that is created.
-   */
-  void OnRendererCreated(Renderer renderer) override;
-
-private:
-  /**
-   * @brief Updates the bone matrix for a ModelPrimitive.
-   *
-   * @param[in] primitive The ModelPrimitive to set the bone matrix for.
-   */
-  void UpdateBoneMatrix(Scene3D::ModelPrimitive primitive);
-
-private:
-  ModelNode&              mModelNodeImpl;           ///< Owner of this data
-  ModelPrimitiveContainer mModelPrimitiveContainer; ///< List of model primitives
-  BoneDataContainer       mBoneDataContainer;
-  Dali::Texture           mSpecularTexture;
-  Dali::Texture           mDiffuseTexture;
-  float                   mIblScaleFactor{1.0f};
-  uint32_t                mSpecularMipmapLevels{1u};
-};
-
-} // namespace Internal
-
-} // namespace Scene3D
-
-} // namespace Dali
-
-#endif // DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_DATA_IMPL_H
index 60dca00..257cbd0 100644 (file)
 
 // EXTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
 
 // INTERNAL INCLUDES
-#include <dali-scene3d/internal/model-components/model-node-data-impl.h>
+#include <dali-scene3d/internal/model-components/model-primitive-impl.h>
 
 namespace Dali
 {
@@ -30,6 +32,21 @@ namespace Scene3D
 {
 namespace Internal
 {
+namespace
+{
+/**
+ * Creates control through type registry
+ */
+BaseHandle Create()
+{
+  return Scene3D::ModelNode::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelNode, Dali::CustomActor, Create);
+DALI_TYPE_REGISTRATION_END()
+} // unnamed namespace
+
 Dali::Scene3D::ModelNode ModelNode::New()
 {
   // Create the implementation, temporarily owned on stack
@@ -46,8 +63,7 @@ Dali::Scene3D::ModelNode ModelNode::New()
 }
 
 ModelNode::ModelNode()
-: CustomActorImpl(ActorFlags::DISABLE_SIZE_NEGOTIATION),
-  mImpl(new Impl(*this))
+: CustomActorImpl(ActorFlags::DISABLE_SIZE_NEGOTIATION)
 {
 }
 
@@ -66,12 +82,10 @@ void ModelNode::OnInitialize()
 
 void ModelNode::OnSceneConnection(int depth)
 {
-  mImpl->OnSceneConnection(depth);
 }
 
 void ModelNode::OnSceneDisconnection()
 {
-  mImpl->OnSceneDisconnection();
 }
 
 void ModelNode::OnChildAdd(Actor& child)
@@ -139,7 +153,7 @@ void ModelNode::OnLayoutNegotiated(float size, Dimension::Type dimension)
 ModelNode& GetImplementation(Dali::Scene3D::ModelNode& handle)
 {
   CustomActorImpl& customInterface = handle.GetImplementation();
-  ModelNode& impl = dynamic_cast<Internal::ModelNode&>(customInterface);
+  ModelNode&       impl            = dynamic_cast<Internal::ModelNode&>(customInterface);
   return impl;
 }
 
@@ -155,27 +169,88 @@ const ModelNode& GetImplementation(const Dali::Scene3D::ModelNode& handle)
 
 uint32_t ModelNode::GetModelPrimitiveCount() const
 {
-  return mImpl->GetModelPrimitiveCount();
+  return static_cast<uint32_t>(mModelPrimitiveContainer.size());
 }
 
 void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
 {
-  mImpl->AddModelPrimitive(modelPrimitive);
+  for(auto&& primitive : mModelPrimitiveContainer)
+  {
+    if(primitive == modelPrimitive)
+    {
+      return;
+    }
+  }
+
+  mModelPrimitiveContainer.push_back(modelPrimitive);
+
+  Actor self = Self();
+  GetImplementation(modelPrimitive).AddPrimitiveObserver(this);
+  if(mDiffuseTexture && mSpecularTexture)
+  {
+    GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
+  }
+
+  Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
+  if(renderer)
+  {
+    uint32_t rendererCount = self.GetRendererCount();
+    bool     exist         = false;
+    for(uint32_t i = 0; i < rendererCount; ++i)
+    {
+      if(renderer == self.GetRendererAt(i))
+      {
+        exist = true;
+        break;
+      }
+    }
+    if(!exist)
+    {
+      self.AddRenderer(renderer);
+    }
+  }
 }
 
 void ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
 {
-  mImpl->RemoveModelPrimitive(modelPrimitive);
+  uint32_t primitiveCount = GetModelPrimitiveCount();
+  for(uint32_t i = 0; i < primitiveCount; ++i)
+  {
+    if(mModelPrimitiveContainer[i] != modelPrimitive)
+    {
+      continue;
+    }
+    RemoveModelPrimitive(i);
+    break;
+  }
 }
 
 void ModelNode::RemoveModelPrimitive(uint32_t index)
 {
-  mImpl->RemoveModelPrimitive(index);
+  if(index >= mModelPrimitiveContainer.size())
+  {
+    return;
+  }
+
+  Actor self = Self();
+  GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
+
+  Dali::Renderer renderer = GetImplementation(mModelPrimitiveContainer[index]).GetRenderer();
+  if(renderer)
+  {
+    self.RemoveRenderer(renderer);
+  }
+
+  mModelPrimitiveContainer.erase(mModelPrimitiveContainer.begin() + index);
 }
 
 Dali::Scene3D::ModelPrimitive ModelNode::GetModelPrimitive(uint32_t index) const
 {
-  return mImpl->GetModelPrimitive(index);
+  if(index < mModelPrimitiveContainer.size())
+  {
+    return mModelPrimitiveContainer[index];
+  }
+  return Scene3D::ModelPrimitive();
 }
 
 Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName)
@@ -186,22 +261,91 @@ Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName
 
 void ModelNode::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
 {
-  mImpl->SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
+  mDiffuseTexture       = diffuseTexture;
+  mSpecularTexture      = specularTexture;
+  mIblScaleFactor       = iblScaleFactor;
+  mSpecularMipmapLevels = specularMipmapLevels;
+  for(auto&& primitive : mModelPrimitiveContainer)
+  {
+    GetImplementation(primitive).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
+  }
 }
 
 void ModelNode::SetImageBasedLightScaleFactor(float iblScaleFactor)
 {
-  mImpl->SetImageBasedLightScaleFactor(iblScaleFactor);
+  mIblScaleFactor = iblScaleFactor;
+  for(auto&& primitive : mModelPrimitiveContainer)
+  {
+    GetImplementation(primitive).SetImageBasedLightScaleFactor(iblScaleFactor);
+  }
 }
 
 void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
 {
-  mImpl->SetBlendShapeData(data, primitive);
+  GetImplementation(primitive).SetBlendShapeData(data);
 }
 
 void ModelNode::SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex)
 {
-  mImpl->SetBoneMatrix(inverseMatrix, primitive, boneIndex);
+  Dali::Scene3D::Loader::Skinning::BoneData boneData;
+  boneData.primitive = primitive;
+  boneData.boneIndex = boneIndex;
+  char propertyNameBuffer[32];
+  snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Dali::Scene3D::Loader::Skinning::BONE_UNIFORM_NAME, boneIndex);
+  boneData.propertyName  = propertyNameBuffer;
+  boneData.inverseMatrix = inverseMatrix;
+  mBoneDataContainer.push_back(std::move(boneData));
+
+  UpdateBoneMatrix(primitive);
+}
+
+void ModelNode::OnRendererCreated(Renderer renderer)
+{
+  Self().AddRenderer(renderer);
+}
+
+void ModelNode::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
+{
+  for(auto&& boneData : mBoneDataContainer)
+  {
+    if(boneData.primitive != primitive)
+    {
+      continue;
+    }
+
+    Dali::Renderer renderer = GetImplementation(primitive).GetRenderer();
+    if(!renderer)
+    {
+      continue;
+    }
+
+    Dali::Shader shader = renderer.GetShader();
+    if(!shader)
+    {
+      continue;
+    }
+
+    if(boneData.constraint)
+    {
+      boneData.constraint.Remove();
+      boneData.constraint.Reset();
+    }
+
+    if(shader.GetPropertyIndex(boneData.propertyName) == Property::INVALID_INDEX)
+    {
+      auto propBoneXform = shader.RegisterProperty(boneData.propertyName, Matrix{false});
+
+      Matrix inverseMatrix = boneData.inverseMatrix;
+      // Constrain bone matrix to joint transform.
+      boneData.constraint = Constraint::New<Matrix>(shader, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs)
+                                                    { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
+
+      Actor joint = Self();
+      boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
+      boneData.constraint.ApplyPost();
+    }
+    break;
+  }
 }
 
 } // namespace Internal
index d216bb5..e3c718c 100644 (file)
@@ -24,7 +24,9 @@
 #include <memory> // for std::unique_ptr
 
 // INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/model-primitive-modify-observer.h>
 #include <dali-scene3d/public-api/loader/mesh-definition.h>
+#include <dali-scene3d/public-api/loader/skinning-details.h>
 #include <dali-scene3d/public-api/model-components/model-node.h>
 #include <dali-scene3d/public-api/model-components/model-primitive.h>
 
@@ -44,9 +46,12 @@ namespace Internal
  *
  * @SINCE_2_2.99
  */
-class DALI_SCENE3D_API ModelNode : public CustomActorImpl
+class DALI_SCENE3D_API ModelNode : public CustomActorImpl, public ModelPrimitiveModifyObserver
 {
 public:
+  using ModelPrimitiveContainer = std::vector<Scene3D::ModelPrimitive>;
+  using BoneDataContainer       = std::vector<Dali::Scene3D::Loader::Skinning::BoneData>;
+
   // Creation & Destruction
   /**
    * @brief Creates a new ModelNodeImpl instance that does not require touch by default.
@@ -244,6 +249,21 @@ public: // Public Method
    */
   void SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex);
 
+  /**
+   * @brief Called when a Renderer of ModelPrimitive is created.
+   *
+   * @param[in] renderer The Renderer that is created.
+   */
+  void OnRendererCreated(Renderer renderer) override;
+
+private:
+  /**
+   * @brief Updates the bone matrix for a ModelPrimitive.
+   *
+   * @param[in] primitive The ModelPrimitive to set the bone matrix for.
+   */
+  void UpdateBoneMatrix(Scene3D::ModelPrimitive primitive);
+
 private:
   /// @cond internal
 
@@ -253,11 +273,13 @@ private:
   DALI_INTERNAL ModelNode& operator=(const ModelNode&) = delete; ///< Deleted copy assignment operator.
   DALI_INTERNAL ModelNode& operator=(ModelNode&&)      = delete; ///< Deleted move assignment operator.
 
-public:
-  class DALI_INTERNAL Impl; // Class declaration is public so we can internally add devel API's to the ModelNode's Impl
-
 private:
-  const std::unique_ptr<Impl> mImpl;
+  ModelPrimitiveContainer mModelPrimitiveContainer; ///< List of model primitives
+  BoneDataContainer       mBoneDataContainer;
+  Dali::Texture           mSpecularTexture;
+  Dali::Texture           mDiffuseTexture;
+  float                   mIblScaleFactor{1.0f};
+  uint32_t                mSpecularMipmapLevels{1u};
   /// @endcond
 };