#include <dali-scene3d/public-api/loader/node-definition.h>
#include <dali-scene3d/public-api/loader/scene-definition.h>
#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
using namespace Dali;
Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector<Dali::Scene3D::Loader::BlendshapeShaderConfigurationRequest>&& requests)
{
std::vector<std::string> errors;
- auto onError = [&errors](const std::string& msg)
- { errors.push_back(msg); };
+ auto onError = [&errors](const std::string& msg) { errors.push_back(msg); };
if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError))
{
Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION);
{
return;
}
-
GetImplementation(node).AddLight(light, lightIndex);
uint32_t childrenCount = node.GetChildCount();
}
}
+void UpdateBlendShapeNodeMapRecursively(Model::BlendShapeModelNodeMap& resultMap, const Scene3D::ModelNode& node)
+{
+ if(!node)
+ {
+ return;
+ }
+ const auto childCount = node.GetChildCount();
+ for(auto i = 0u; i < childCount; ++i)
+ {
+ UpdateBlendShapeNodeMapRecursively(resultMap, Scene3D::ModelNode::DownCast(node.GetChildAt(i)));
+ }
+
+ std::vector<std::string> blendShapeNames;
+ node.RetrieveBlendShapeNames(blendShapeNames);
+ for(const auto& iter : blendShapeNames)
+ {
+ // Append or create new list.
+ resultMap[iter].push_back(node);
+ }
+}
+
} // anonymous namespace
Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
return Scene3D::ModelNode::DownCast(childActor);
}
+void Model::RetrieveBlendShapeNames(std::vector<std::string>& blendShapeNames) const
+{
+ blendShapeNames.reserve(blendShapeNames.size() + mBlendShapeModelNodeMap.size());
+ for(const auto& iter : mBlendShapeModelNodeMap)
+ {
+ blendShapeNames.push_back(iter.first);
+ }
+}
+
+void Model::RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector<Scene3D::ModelNode>& modelNodes) const
+{
+ auto iter = mBlendShapeModelNodeMap.find(std::string(blendShapeName));
+ if(iter != mBlendShapeModelNodeMap.end())
+ {
+ const auto& modelNodeList = iter->second;
+ modelNodes.reserve(modelNodes.size() + modelNodeList.size());
+ for(const auto& nodeIter : modelNodeList)
+ {
+ modelNodes.push_back(nodeIter);
+ }
+ }
+}
+
+Dali::Animation Model::GenerateMotionDataAnimation(Scene3D::MotionData motionData)
+{
+ Dali::Animation animation;
+
+ // TODO : Collect duplicated codes.
+
+ if(motionData)
+ {
+ const uint32_t motionCount = motionData.GetMotionCount();
+ for(uint32_t i = 0u; i < motionCount; ++i)
+ {
+ auto motionIndex = motionData.GetIndex(i);
+ auto motionValue = motionData.GetValue(i);
+ if(motionIndex && motionValue)
+ {
+ if(motionIndex.GetModelNodeId() != Property::INVALID_KEY)
+ {
+ Scene3D::ModelNode modelNode;
+ if(motionIndex.GetModelNodeId().type == Property::Key::Type::STRING)
+ {
+ modelNode = FindChildModelNodeByName(motionIndex.GetModelNodeId().stringKey);
+ }
+ else if(motionIndex.GetModelNodeId().type == Property::Key::Type::INDEX)
+ {
+ // TODO : Not implement yet.
+ }
+
+ if(modelNode)
+ {
+ KeyFrames keyFrames = motionValue.GetKeyFrames();
+
+ if(keyFrames)
+ {
+ // Try to use index first. If failed, try to use name
+ Property::Index animatedPropertyIndex = motionIndex.GetPropertyIndex(modelNode);
+ if(animatedPropertyIndex != Property::INVALID_INDEX)
+ {
+ if(DALI_UNLIKELY(!animation))
+ {
+ animation = Animation::New(motionData.GetDuration());
+ }
+ animation.AnimateBetween(Dali::Property(modelNode, animatedPropertyIndex), keyFrames);
+ }
+ else
+ {
+ std::string animatedPropertyName = motionIndex.GetPropertyName(modelNode);
+ Dali::Property property(modelNode, animatedPropertyName);
+ if(property.propertyIndex != Property::INVALID_INDEX)
+ {
+ if(DALI_UNLIKELY(!animation))
+ {
+ animation = Animation::New(motionData.GetDuration());
+ }
+ animation.AnimateBetween(property, keyFrames);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Scene3D::BlendShapeIndex blendShapeIndex = Scene3D::BlendShapeIndex::DownCast(motionIndex);
+ if(blendShapeIndex && blendShapeIndex.GetBlendShapeId().type == Property::Key::Type::STRING)
+ {
+ // Special case : For BlendShapeIndex that doesn't have ModelNodeId and has string BlendShapeId,
+ // we need to animate all kind of blendshapes
+
+ KeyFrames keyFrames = motionValue.GetKeyFrames();
+
+ if(keyFrames)
+ {
+ std::vector<Scene3D::ModelNode> modelNodes;
+ RetrieveModelNodesByBlendShapeName(blendShapeIndex.GetBlendShapeId().stringKey, modelNodes);
+
+ for(auto& modelNode : modelNodes)
+ {
+ // Try to use index first. If failed, try to use name
+ Property::Index animatedPropertyIndex = motionIndex.GetPropertyIndex(modelNode);
+ if(animatedPropertyIndex != Property::INVALID_INDEX)
+ {
+ if(DALI_UNLIKELY(!animation))
+ {
+ animation = Animation::New(motionData.GetDuration());
+ }
+ animation.AnimateBetween(Dali::Property(modelNode, animatedPropertyIndex), keyFrames);
+ }
+ else
+ {
+ std::string animatedPropertyName = motionIndex.GetPropertyName(modelNode);
+ Dali::Property property(modelNode, animatedPropertyName);
+
+ if(property.propertyIndex != Property::INVALID_INDEX)
+ {
+ if(DALI_UNLIKELY(!animation))
+ {
+ animation = Animation::New(motionData.GetDuration());
+ }
+ animation.AnimateBetween(property, keyFrames);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return animation;
+}
+
+void Model::SetMotionData(Scene3D::MotionData motionData)
+{
+ // TODO : Collect duplicated codes.
+ if(motionData)
+ {
+ const uint32_t motionCount = motionData.GetMotionCount();
+ for(uint32_t i = 0u; i < motionCount; ++i)
+ {
+ auto motionIndex = motionData.GetIndex(i);
+ auto motionValue = motionData.GetValue(i);
+ if(motionIndex && motionValue)
+ {
+ if(motionIndex.GetModelNodeId() != Property::INVALID_KEY)
+ {
+ Scene3D::ModelNode modelNode;
+ if(motionIndex.GetModelNodeId().type == Property::Key::Type::STRING)
+ {
+ modelNode = FindChildModelNodeByName(motionIndex.GetModelNodeId().stringKey);
+ }
+ else if(motionIndex.GetModelNodeId().type == Property::Key::Type::INDEX)
+ {
+ // TODO : Not implement yet.
+ }
+
+ if(modelNode)
+ {
+ Property::Value value = motionValue.GetPropertyValue();
+
+ if(value.GetType() != Property::Type::NONE)
+ {
+ // Try to use index first. If failed, try to use name
+ Property::Index propertyIndex = motionIndex.GetPropertyIndex(modelNode);
+ if(propertyIndex != Property::INVALID_INDEX)
+ {
+ modelNode.SetProperty(propertyIndex, value);
+ }
+ else
+ {
+ std::string propertyName = motionIndex.GetPropertyName(modelNode);
+ Dali::Property property(modelNode, propertyName);
+ if(property.propertyIndex != Property::INVALID_INDEX)
+ {
+ modelNode.SetProperty(property.propertyIndex, value);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Scene3D::BlendShapeIndex blendShapeIndex = Scene3D::BlendShapeIndex::DownCast(motionIndex);
+ if(blendShapeIndex && blendShapeIndex.GetBlendShapeId().type == Property::Key::Type::STRING)
+ {
+ // Special case : For BlendShapeIndex that doesn't have ModelNodeId and has string BlendShapeId,
+ // we need to animate all kind of blendshapes
+
+ Property::Value value = motionValue.GetPropertyValue();
+
+ if(value.GetType() != Property::Type::NONE)
+ {
+ std::vector<Scene3D::ModelNode> modelNodes;
+ RetrieveModelNodesByBlendShapeName(blendShapeIndex.GetBlendShapeId().stringKey, modelNodes);
+
+ for(auto& modelNode : modelNodes)
+ {
+ // Try to use index first. If failed, try to use name
+ Property::Index propertyIndex = motionIndex.GetPropertyIndex(modelNode);
+ if(propertyIndex != Property::INVALID_INDEX)
+ {
+ modelNode.SetProperty(propertyIndex, value);
+ }
+ else
+ {
+ std::string propertyName = motionIndex.GetPropertyName(modelNode);
+ Dali::Property property(modelNode, propertyName);
+ if(property.propertyIndex != Property::INVALID_INDEX)
+ {
+ modelNode.SetProperty(property.propertyIndex, value);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
///////////////////////////////////////////////////////////
//
// Private methods
resources.GenerateResources();
for(auto iRoot : scene.GetRoots())
{
- if(auto actor = scene.CreateNodes(iRoot, resourceChoices, nodeParams))
+ if(auto modelNode = scene.CreateNodes(iRoot, resourceChoices, nodeParams))
{
- scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
- ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
+ scene.ConfigureSkinningShaders(resources, modelNode, std::move(nodeParams.mSkinnables));
+ ConfigureBlendShapeShaders(resources, scene, modelNode, std::move(nodeParams.mBlendshapeRequests));
- scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
+ scene.ApplyConstraints(modelNode, std::move(nodeParams.mConstrainables));
- mModelRoot.Add(actor);
+ mModelRoot.Add(modelNode);
}
AddModelTreeToAABB(AABB, scene, resourceChoices, iRoot, nodeParams, Matrix::IDENTITY);
}
+ UpdateBlendShapeNodeMap();
+
mNaturalSize = AABB.CalculateSize();
mModelPivot = AABB.CalculatePivot();
mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
mAnimations.clear();
if(!mModelLoadTask->GetAnimations().empty())
{
- auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property)
- {
+ auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) {
if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX)
{
return mModelRoot.FindChildByName(property.mNodeName);
}
}
+void Model::UpdateBlendShapeNodeMap()
+{
+ // Remove privous node map
+ mBlendShapeModelNodeMap.clear();
+
+ UpdateBlendShapeNodeMapRecursively(mBlendShapeModelNodeMap, mModelRoot);
+}
+
} // namespace Internal
} // namespace Scene3D
} // namespace Dali