- We don't need to make crash when multiple nodes had same name.
- DALi actor also allows duplicated name.
- Because name is not an unique key, make AnimationDefinition use Actor ID as a key.(for glTF)
- glTF don't use name as a key.
Change-Id: Ibcb3e21640cf2a8124bb450b73159eeaf1cdf4f3
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
},
{
"mesh" : 1,
- "name" : "AnimatedCube2"
+ "name" : "AnimatedCube"
},
{
],\r
"nodes": [\r
{\r
+ "name" : "node0",\r
"children": [\r
1\r
],\r
]\r
},\r
{\r
+ "name" : "node1",\r
"children": [\r
2\r
]\r
},\r
{\r
+ "name" : "node2",\r
"mesh": 0,\r
"rotation": [\r
-0.0,\r
]\r
},\r
{\r
+ "name" : "node3",\r
"mesh": 1\r
}\r
],\r
actor.SetProperty(Actor::Property::NAME, "ChristopherPlummer");
AnimatedProperty animProp {
+ INVALID_INDEX,
"ChristopherPlummer",
"position",
KeyFrames(),
auto actor = Actor::New();
actor.SetProperty(Actor::Property::NAME, "ChristopherPlummer");
- auto getActor = [&actor](const std::string& name) {
- return actor.FindChildByName(name);
+ auto getActor = [&actor](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+ return actor.FindChildByName(property.mNodeName);
};
for (bool b: { false, true })
animDef.mEndAction = Animation::BAKE_FINAL;
animDef.mSpeedFactor = .7f;
animDef.mProperties.push_back(AnimatedProperty{
+ INVALID_INDEX,
"ChristopherPlummer",
"position",
KeyFrames(),
auto actor = Actor::New();
actor.SetProperty(Actor::Property::NAME, "ChristopherPlummer");
- auto getActor = [&actor](const std::string& name) {
- return actor.FindChildByName(name);
+ auto getActor = [&actor](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+ return actor.FindChildByName(property.mNodeName);
};
KeyFrames kf = KeyFrames::New();
animDef.mEndAction = Animation::BAKE_FINAL;
animDef.mSpeedFactor = .7f;
animDef.mProperties.push_back(AnimatedProperty{
+ INVALID_INDEX,
"ChristopherPlummer",
"position",
kf,
first.SetProperty(Actor::Property::NAME, "first");
root.Add(first);
- auto getActor = [&root](const std::string& name) {
- return root.FindChildByName(name);
+ auto getActor = [&root](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+ return root.FindChildByName(property.mNodeName);
};
Animation animation = animDef.ReAnimate(getActor);
{"node-renderable-mesh-invalid-type", "Invalid Mesh index type"},
{"node-renderable-mesh-out-of-bounds", "out of bounds"},
{"node-child-invalid-type", "invalid index type"},
- {"node-name-already-used", "name already used"},
// from ParseAnimations()
{"animation-failed-to-open", "Failed to open animation data"}};
for(auto& i : pathExceptionPairs)
actor.RegisterProperty(weightName, 0.0f);
}
- auto getActor = [&actor](const std::string& name) {
- return actor.FindChildByName(name);
+ auto getActor = [&actor](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+ return actor.FindChildByName(property.mNodeName);
};
auto anim = animDef.ReAnimate(getActor);
END_TEST;
}
+
+
+int UtcDaliGltfLoaderAnimationLoadingTest(void)
+{
+ Context ctx;
+
+ ShaderDefinitionFactory sdf;
+ sdf.SetResources(ctx.resources);
+ auto& resources = ctx.resources;
+
+ LoadGltfScene(TEST_RESOURCE_DIR "/BoxAnimated.gltf", sdf, ctx.loadResult);
+
+ auto& scene = ctx.scene;
+ auto& roots = scene.GetRoots();
+ DALI_TEST_EQUAL(roots.size(), 1u);
+
+ ViewProjection viewProjection;
+ Transforms xforms{
+ MatrixStack{},
+ viewProjection};
+ NodeDefinition::CreateParams nodeParams{
+ resources,
+ xforms,
+ };
+
+ Customization::Choices choices;
+
+ TestApplication app;
+
+ Actor root = Actor::New();
+ SetActorCentered(root);
+ for(auto iRoot : roots)
+ {
+ auto resourceRefs = resources.CreateRefCounter();
+ scene.CountResourceRefs(iRoot, choices, resourceRefs);
+ resources.CountEnvironmentReferences(resourceRefs);
+ resources.LoadResources(resourceRefs, ctx.pathProvider);
+ if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
+ {
+ scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
+ scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
+ scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
+ root.Add(actor);
+ }
+ }
+
+ DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions.size(), 1u);
+ DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions[0].mProperties.size(), 2u);
+
+ uint32_t id = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].mProperties[0].mNodeIndex)->mNodeId;
+ DALI_TEST_EQUAL(id, root.FindChildByName("node2").GetProperty<int32_t>(Dali::Actor::Property::ID));
+ uint32_t id2 = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].mProperties[1].mNodeIndex)->mNodeId;
+ DALI_TEST_EQUAL(id2, root.FindChildByName("node0").GetProperty<int32_t>(Dali::Actor::Property::ID));
+
+ END_TEST;
+}
TestApplication testApp;
NodeDefinition nodeDef{
"testRootNode",
+ INVALID_INDEX,
Vector3{-100.f, 100.f, -500.f},
Quaternion{Radian(Degree(45.f)), Vector3::ZAXIS},
Vector3{2.f, 4.f, 8.f},
auto node2 = new NodeDefinition();
node2->mName = node->mName;
result = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ node2 });
- DALI_TEST_EQUAL(result, static_cast<NodeDefinition*>(nullptr)); // failed
- DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 1u); // still
- DALI_TEST_EQUAL(sceneDef.GetNode(0), node); // still
- DALI_TEST_EQUAL(sceneDef.FindNode(node->mName), node); // still
+ DALI_TEST_EQUAL(result, node2);
+ DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 2u);
+ DALI_TEST_EQUAL(sceneDef.GetNode(1), node2);
auto child = new NodeDefinition();
child->mName = "Second";
result = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ child });
DALI_TEST_EQUAL(result, child);
- DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 2u);
- DALI_TEST_EQUAL(sceneDef.GetNode(1), child);
+ DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 3u);
+ DALI_TEST_EQUAL(sceneDef.GetNode(2), child);
DALI_TEST_EQUAL(sceneDef.FindNode(child->mName), child);
- DALI_TEST_EQUAL(node->mChildren[0], 1u); // these are hooked up by AddNode, base on parent idx.
+ DALI_TEST_EQUAL(node->mChildren[0], 2u); // these are hooked up by AddNode, base on parent idx.
END_TEST;
}
if(!animations.empty())
{
- auto getActor = [&](const std::string& name) {
- return mModelRoot.FindChildByName(name);
+ auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) {
+ return mModelRoot.FindChildById(scene.GetNode(property.mNodeIndex)->mNodeId);
};
mAnimations.clear();
{
void AnimatedProperty::Animate(Animation& anim, GetActor getActor)
{
- if(Actor actor = getActor(mNodeName))
+ if(Actor actor = getActor(*this))
{
Property prop = GetProperty(actor);
if(mKeyFrames)
// INTERNAL INCLUDES
#include "dali-scene3d/public-api/api.h"
+#include "dali-scene3d/public-api/loader/index.h"
+
// EXTERNAL INCLUDES
#include <functional>
{
public: // METHODS
/**
- * @brief Function to obtain an Actor based on its name. Its processing will
+ * @brief Function to obtain an Actor based on its property. Its processing will
* ignore empty handles returned by it.
*/
- using GetActor = std::function<Actor(const std::string&)>;
+ using GetActor = std::function<Actor(const AnimatedProperty&)>;
/**
* @return The Property object (of the given @a actor) whose value is being animated.
bool mIsRelative;
};
+ Index mNodeIndex = INVALID_INDEX;
std::string mNodeName;
std::string mPropertyName;
return duration;
}
-float LoadBlendShapeKeyFrames(const std::string& path, const gt::Animation::Channel& channel, const std::string& nodeName, uint32_t& propertyIndex, std::vector<Dali::Scene3D::Loader::AnimatedProperty>& properties)
+float LoadBlendShapeKeyFrames(const std::string& path, const gt::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, std::vector<Dali::Scene3D::Loader::AnimatedProperty>& properties)
{
const gltf2::Accessor& input = *channel.mSampler->mInput;
const gltf2::Accessor& output = *channel.mSampler->mOutput;
{
AnimatedProperty& animatedProperty = properties[propertyIndex++];
- animatedProperty.mNodeName = nodeName;
+ animatedProperty.mNodeIndex = nodeIndex;
snprintf(pWeightName, remainingSize, "%d]", weightIndex);
animatedProperty.mPropertyName = std::string(weightNameBuffer);
}
uint32_t numberOfProperties = 0u;
-
- for(const auto& channel : animation.mChannels)
- {
- numberOfProperties += channel.mSampler->mOutput->mCount;
- }
- animationDef.mProperties.resize(numberOfProperties);
-
- Index propertyIndex = 0u;
for(const auto& channel : animation.mChannels)
{
- std::string nodeName;
- if(!channel.mTarget.mNode->mName.empty())
+ if(channel.mTarget.mPath == gt::Animation::Channel::Target::WEIGHTS)
{
- nodeName = channel.mTarget.mNode->mName;
+ numberOfProperties += channel.mSampler->mOutput->mCount / channel.mSampler->mInput->mCount;
}
else
{
- Index index = context.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex());
- nodeName = context.mOutput.mScene.GetNode(index)->mName;
+ numberOfProperties++;
}
+ }
+ animationDef.mProperties.resize(numberOfProperties);
+ Index propertyIndex = 0u;
+ for(const auto& channel : animation.mChannels)
+ {
+ Index nodeIndex = context.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex());
float duration = 0.f;
switch(channel.mTarget.mPath)
{
AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
- animatedProperty.mNodeName = nodeName;
+ animatedProperty.mNodeIndex = nodeIndex;
animatedProperty.mPropertyName = POSITION_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
{
AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
- animatedProperty.mNodeName = nodeName;
+ animatedProperty.mNodeIndex = nodeIndex;
animatedProperty.mPropertyName = ORIENTATION_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
{
AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
- animatedProperty.mNodeName = nodeName;
+ animatedProperty.mNodeIndex = nodeIndex;
animatedProperty.mPropertyName = SCALE_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
}
case gt::Animation::Channel::Target::WEIGHTS:
{
- duration = LoadBlendShapeKeyFrames(context.mPath, channel, nodeName, propertyIndex, animationDef.mProperties);
+ duration = LoadBlendShapeKeyFrames(context.mPath, channel, nodeIndex, propertyIndex, animationDef.mProperties);
break;
}
const std::string NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
-Actor NodeDefinition::CreateActor(CreateParams& params) const
+Actor NodeDefinition::CreateActor(CreateParams& params)
{
Actor actor = Actor::New();
+ mNodeId = actor.GetProperty<int32_t>(Dali::Actor::Property::ID);
+
SetActorCentered(actor);
actor.SetProperty(Actor::Property::NAME, mName);
* @brief Creates a DALi Actor from this definition only.
* @note Not recursive.
*/
- Actor CreateActor(CreateParams& params) const;
+ Actor CreateActor(CreateParams& params);
/**
* @brief Gets local space matrix of this node
static const std::string ORIGINAL_MATRIX_PROPERTY_NAME;
std::string mName;
+ uint32_t mNodeId = INVALID_INDEX;
Vector3 mPosition = Vector3::ZERO;
Quaternion mOrientation = Quaternion::IDENTITY;
}
#endif //DEBUG_JOINTS
-class ActorCreatorVisitor : public NodeDefinition::IConstVisitor
+class ActorCreatorVisitor : public NodeDefinition::IVisitor
{
public:
ActorCreatorVisitor(NodeDefinition::CreateParams& params)
{
}
- void Start(const NodeDefinition& n)
+ void Start(NodeDefinition& n)
{
mCreationContext.mXforms.modelStack.Push(n.GetLocalSpace());
mActorStack.push_back(a);
}
- void Finish(const NodeDefinition& n)
+ void Finish(NodeDefinition& n)
{
mActorStack.pop_back();
mCreationContext.mXforms.modelStack.Pop();
Visit(iNode, choices, refCounterVisitor);
}
-Actor SceneDefinition::CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params) const
+Actor SceneDefinition::CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params)
{
ActorCreatorVisitor actorCreatorVisitor(params);
NodeDefinition* SceneDefinition::AddNode(std::unique_ptr<NodeDefinition>&& nodeDef)
{
- if(!nodeDef->mName.empty() && FindNode(nodeDef->mName))
- {
- return nullptr;
- }
-
// add next index (to which we're about to push) as a child to the designated parent, if any.
if(nodeDef->mParentIdx != INVALID_INDEX)
{
* from node definitions.
* @return Handle to the root actor.
*/
- Actor CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params) const;
+ Actor CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params);
/*
* @brief Creates / update a registry of mappings from customization tags to