[Tizen] Add MotionData class and generate Animation by this
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / model-components / model-node-impl.cpp
index 60dca00..a37d4a8 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/light/light-impl.h>
+#include <dali-scene3d/internal/model-components/model-primitive-impl.h>
 
 namespace Dali
 {
@@ -30,6 +33,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 +64,7 @@ Dali::Scene3D::ModelNode ModelNode::New()
 }
 
 ModelNode::ModelNode()
-: CustomActorImpl(ActorFlags::DISABLE_SIZE_NEGOTIATION),
-  mImpl(new Impl(*this))
+: CustomActorImpl(ActorFlags::DISABLE_SIZE_NEGOTIATION)
 {
 }
 
@@ -58,6 +75,7 @@ ModelNode::~ModelNode()
 void ModelNode::Initialize()
 {
   OnInitialize();
+  mLights.resize(Scene3D::Internal::Light::GetMaximumEnabledLightCount());
 }
 
 void ModelNode::OnInitialize()
@@ -66,12 +84,10 @@ void ModelNode::OnInitialize()
 
 void ModelNode::OnSceneConnection(int depth)
 {
-  mImpl->OnSceneConnection(depth);
 }
 
 void ModelNode::OnSceneDisconnection()
 {
-  mImpl->OnSceneDisconnection();
 }
 
 void ModelNode::OnChildAdd(Actor& child)
@@ -139,7 +155,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 +171,107 @@ 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);
+  }
+
+  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
+  for(uint32_t i = 0; i < maxLightCount; ++i)
+  {
+    if(mLights[i])
+    {
+      GetImplementation(modelPrimitive).AddLight(mLights[i], i);
+    }
+  }
+
+  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;
+  }
+
+  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
+  for(uint32_t i = 0; i < maxLightCount; ++i)
+  {
+    if(mLights[i])
+    {
+      GetImplementation(mModelPrimitiveContainer[index]).RemoveLight(i);
+    }
+  }
+
+  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)
@@ -184,24 +280,136 @@ Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName
   return Scene3D::ModelNode::DownCast(childActor);
 }
 
+void ModelNode::RetrieveBlendShapeNames(std::vector<std::string>& blendShapeNames) const
+{
+  blendShapeNames.reserve(blendShapeNames.size() + mBlendShapeIndexMap.size());
+  for(const auto& iter : mBlendShapeIndexMap)
+  {
+    blendShapeNames.push_back(iter.first);
+  }
+}
+
+Loader::BlendShapes::Index ModelNode::GetBlendShapeIndexByName(std::string_view blendShapeName) const
+{
+  auto iter = mBlendShapeIndexMap.find(std::string(blendShapeName));
+  if(iter != mBlendShapeIndexMap.end())
+  {
+    return iter->second;
+  }
+  return Loader::BlendShapes::INVALID_INDEX;
+}
+
 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::AddLight(Scene3D::Light light, uint32_t lightIndex)
+{
+  mLights[lightIndex] = light;
+  for(auto&& primitive : mModelPrimitiveContainer)
+  {
+    GetImplementation(primitive).AddLight(light, lightIndex);
+  }
+}
+
+void ModelNode::RemoveLight(uint32_t lightIndex)
+{
+  for(auto&& primitive : mModelPrimitiveContainer)
+  {
+    GetImplementation(primitive).RemoveLight(lightIndex);
+  }
+  mLights[lightIndex].Reset();
 }
 
 void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
 {
-  mImpl->SetBlendShapeData(data, primitive);
+  // Update mBlendShapeIndexMap
+  mBlendShapeIndexMap.clear();
+  const auto blendShapeCount = data.names.size();
+  for(Loader::BlendShapes::Index index = 0u; index < blendShapeCount; ++index)
+  {
+    auto& name = data.names[index];
+    if(!name.empty())
+    {
+      mBlendShapeIndexMap[name] = index;
+    }
+  }
+
+  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;
+    }
+
+    if(boneData.constraint)
+    {
+      boneData.constraint.Remove();
+      boneData.constraint.Reset();
+    }
+
+    auto propBoneXform = renderer.GetPropertyIndex(boneData.propertyName);
+    if(propBoneXform == Property::INVALID_INDEX)
+    {
+      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 = Self();
+    boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
+    boneData.constraint.ApplyPost();
+    break;
+  }
 }
 
 } // namespace Internal