Add MotionData class and generate Animation 94/293894/24
authorEunki Hong <eunkiki.hong@samsung.com>
Wed, 7 Jun 2023 12:53:06 +0000 (21:53 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Tue, 4 Jul 2023 15:52:08 +0000 (00:52 +0900)
This patch is implement NUI API by dali side

https://github.com/Samsung/TizenFX/pull/5227

Let we make APP developer use this API instead of using animation-definition.

Change-Id: Ifca479535500aeea49bf644160c23c5f3fc26665
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
45 files changed:
automated-tests/src/dali-scene3d/CMakeLists.txt
automated-tests/src/dali-scene3d/utc-Dali-BlendShapeIndex.cpp [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-Model.cpp
automated-tests/src/dali-scene3d/utc-Dali-MotionData.cpp [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-MotionIndex.cpp [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-MotionPropertyIndex.cpp [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-MotionTransformIndex.cpp [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-MotionValue.cpp [new file with mode: 0644]
dali-scene3d/dali-scene3d.h
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/model/model-impl.h
dali-scene3d/internal/file.list
dali-scene3d/internal/model-motion/motion-data-impl.cpp [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-data-impl.h [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-data-load-task.cpp [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-data-load-task.h [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.cpp [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.h [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-index/motion-index-impl.cpp [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.cpp [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.h [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.cpp [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.h [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-value-impl.cpp [new file with mode: 0644]
dali-scene3d/internal/model-motion/motion-value-impl.h [new file with mode: 0644]
dali-scene3d/public-api/controls/model/model.cpp
dali-scene3d/public-api/controls/model/model.h
dali-scene3d/public-api/file.list
dali-scene3d/public-api/loader/animated-property.cpp
dali-scene3d/public-api/loader/animated-property.h
dali-scene3d/public-api/loader/animation-definition.cpp
dali-scene3d/public-api/loader/animation-definition.h
dali-scene3d/public-api/model-motion/motion-data.cpp [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-data.h [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.cpp [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-index/motion-index.cpp [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-index/motion-index.h [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-index/motion-property-index.cpp [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.cpp [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-value.cpp [new file with mode: 0644]
dali-scene3d/public-api/model-motion/motion-value.h [new file with mode: 0644]

index 4dff80c..1eed33c 100755 (executable)
@@ -11,6 +11,7 @@ SET(TC_SOURCES
   utc-Dali-AnimationDefinition.cpp
   utc-Dali-AnimatedProperty.cpp
   utc-Dali-BvhLoader.cpp
+  utc-Dali-BlendShapeIndex.cpp
   utc-Dali-CameraParameters.cpp
   utc-Dali-EnvironmentMapLoader.cpp
   utc-Dali-EnvironmentDefinition.cpp
@@ -20,6 +21,11 @@ SET(TC_SOURCES
   utc-Dali-Model.cpp
   utc-Dali-ModelNode.cpp
   utc-Dali-ModelPrimitive.cpp
+  utc-Dali-MotionData.cpp
+  utc-Dali-MotionIndex.cpp
+  utc-Dali-MotionPropertyIndex.cpp
+  utc-Dali-MotionTransformIndex.cpp
+  utc-Dali-MotionValue.cpp
   utc-Dali-SceneView.cpp
   utc-Dali-MatrixStack.cpp
   utc-Dali-MeshDefinition.cpp
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-BlendShapeIndex.cpp b/automated-tests/src/dali-scene3d/utc-Dali-BlendShapeIndex.cpp
new file mode 100644 (file)
index 0000000..b7c34ff
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+using namespace Dali::Scene3D;
+
+void model_motion_blend_shape_index_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void model_motion_blend_shape_index_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+const char* const WEIGHTS_UNIFORM = "uBlendShapeWeight";
+
+std::string GetPropertyNameFromIndex(int index)
+{
+  if(index >= 0)
+  {
+    char weightNameBuffer[32];
+
+    // Get return value of snprintf to avoid SVACE.
+    [[maybe_unused]] auto prefixSize = snprintf(weightNameBuffer, sizeof(weightNameBuffer), "%s[%d]", WEIGHTS_UNIFORM, index);
+
+    return weightNameBuffer;
+  }
+  return "";
+}
+} // namespace
+
+// Positive test case for a method
+int UtcDaliBlendShapeIndexNew(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliBlendShapeIndexNew");
+
+  BlendShapeIndex blendShapeIndex = BlendShapeIndex::New();
+  DALI_TEST_CHECK(blendShapeIndex);
+  DALI_TEST_EQUALS(blendShapeIndex.GetModelNodeId().stringKey, "", TEST_LOCATION);
+  DALI_TEST_EQUALS(blendShapeIndex.GetBlendShapeId().indexKey, Property::INVALID_INDEX, TEST_LOCATION);
+
+  blendShapeIndex = BlendShapeIndex::New("dummy", 3u);
+  DALI_TEST_CHECK(blendShapeIndex);
+  DALI_TEST_EQUALS(blendShapeIndex.GetModelNodeId().stringKey, "dummy", TEST_LOCATION);
+  DALI_TEST_EQUALS(blendShapeIndex.GetBlendShapeId().indexKey, 3u, TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliBlendShapeIndexDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliBlendShapeIndexDownCast");
+
+  BlendShapeIndex blendShapeIndex = BlendShapeIndex::New();
+  BaseHandle      handle(blendShapeIndex);
+
+  BlendShapeIndex blendShapeIndex2 = BlendShapeIndex::DownCast(handle);
+  DALI_TEST_CHECK(blendShapeIndex);
+  DALI_TEST_CHECK(blendShapeIndex2);
+  DALI_TEST_CHECK(blendShapeIndex2 == blendShapeIndex);
+  END_TEST;
+}
+
+int UtcDaliBlendShapeIndexTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK(typeRegistry);
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo("BlendShapeIndex");
+  DALI_TEST_CHECK(typeInfo);
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK(handle);
+
+  BlendShapeIndex blendShapeIndex = BlendShapeIndex::DownCast(handle);
+  DALI_TEST_CHECK(blendShapeIndex);
+
+  END_TEST;
+}
+
+int UtcDaliBlendShapeIndexCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  BlendShapeIndex blendShapeIndex = BlendShapeIndex::New();
+  DALI_TEST_CHECK(blendShapeIndex);
+
+  BlendShapeIndex copy(blendShapeIndex);
+  DALI_TEST_CHECK(blendShapeIndex == copy);
+
+  BlendShapeIndex assign;
+  DALI_TEST_CHECK(!assign);
+
+  assign = copy;
+  DALI_TEST_CHECK(assign == blendShapeIndex);
+
+  END_TEST;
+}
+
+int UtcDaliBlendShapeIndexMoveConstructor(void)
+{
+  ToolkitTestApplication application;
+
+  BlendShapeIndex blendShapeIndex = BlendShapeIndex::New();
+  DALI_TEST_EQUALS(1, blendShapeIndex.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  BlendShapeIndex moved = std::move(blendShapeIndex);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(!blendShapeIndex);
+
+  END_TEST;
+}
+
+int UtcDaliBlendShapeIndexMoveAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  BlendShapeIndex blendShapeIndex = BlendShapeIndex::New();
+  DALI_TEST_EQUALS(1, blendShapeIndex.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  BlendShapeIndex moved;
+  moved = std::move(blendShapeIndex);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+// Method test
+
+int UtcDaliBlendShapeIndexGetPropertyName(void)
+{
+  std::string     expectPropertyName  = "";
+  Property::Index expectPropertyIndex = Property::INVALID_INDEX;
+
+  uint32_t blendShapeIndex;
+
+  MotionIndex index = BlendShapeIndex::New();
+
+  // Invalid motion index return empty string, invalid index
+  DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyName(), TEST_LOCATION);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetPropertyIndex(), TEST_LOCATION);
+
+  blendShapeIndex    = 0u;
+  index              = BlendShapeIndex::New("", blendShapeIndex);
+  expectPropertyName = GetPropertyNameFromIndex(blendShapeIndex);
+  DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyName(), TEST_LOCATION);
+
+  blendShapeIndex    = 45u;
+  index              = BlendShapeIndex::New("", blendShapeIndex);
+  expectPropertyName = GetPropertyNameFromIndex(blendShapeIndex);
+  DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyName(), TEST_LOCATION);
+
+  blendShapeIndex    = 109u;
+  index              = BlendShapeIndex::New("", blendShapeIndex);
+  expectPropertyName = GetPropertyNameFromIndex(blendShapeIndex);
+  DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyName(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliBlendShapeIndexSetGetBlendShapeId(void)
+{
+  Property::Index expectPropertyIndex = 0u;
+
+  BlendShapeIndex index = BlendShapeIndex::New("", expectPropertyIndex);
+
+  // Invalid motion index return empty string, invalid index
+  DALI_TEST_CHECK(index.GetBlendShapeId().type == Property::Key::Type::INDEX);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetBlendShapeId().indexKey, TEST_LOCATION);
+
+  std::string expectPropertyName = "hello";
+  index.SetBlendShapeId(expectPropertyName);
+  DALI_TEST_CHECK(index.GetBlendShapeId().type == Property::Key::Type::STRING);
+  DALI_TEST_EQUALS(expectPropertyName, index.GetBlendShapeId().stringKey, TEST_LOCATION);
+
+  expectPropertyIndex = 100u;
+  index.SetBlendShapeId(expectPropertyIndex);
+  DALI_TEST_CHECK(index.GetBlendShapeId().type == Property::Key::Type::INDEX);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetBlendShapeId().indexKey, TEST_LOCATION);
+
+  END_TEST;
+}
\ No newline at end of file
index b2d8169..30b755d 100644 (file)
 #include <dali-scene3d/public-api/controls/model/model.h>
 #include <dali-scene3d/public-api/model-components/model-node.h>
 
+#include <dali-scene3d/public-api/model-motion/motion-data.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h>
+
 #include <dali/devel-api/actors/camera-actor-devel.h>
 
 using namespace Dali;
@@ -56,6 +60,7 @@ const char* TEST_GLTF_FILE_NAME                    = TEST_RESOURCE_DIR "/Animate
 const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME     = TEST_RESOURCE_DIR "/animationTest.gltf";
 const char* TEST_GLTF_EXTRAS_FILE_NAME             = TEST_RESOURCE_DIR "/AnimatedMorphCubeAnimateNonZeroFrame.gltf";
 const char* TEST_GLTF_MULTIPLE_PRIMITIVE_FILE_NAME = TEST_RESOURCE_DIR "/simpleMultiplePrimitiveTest.gltf";
+const char* TEST_GLTF_MORPH_FILE_NAME              = TEST_RESOURCE_DIR "/AnimatedMorphCube.gltf";
 const char* TEST_DLI_FILE_NAME                     = TEST_RESOURCE_DIR "/arc.dli";
 const char* TEST_DLI_EXERCISE_FILE_NAME            = TEST_RESOURCE_DIR "/exercise.dli";
 
@@ -1539,3 +1544,146 @@ int UtcDaliModelRetrieveBlendShapeNames(void)
 
   END_TEST;
 }
+
+int UtcDaliModelGenerateMotionDataAnimation01(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_MORPH_FILE_NAME);
+  model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+  application.GetScene().Add(model);
+
+  gResourceReadyCalled = false;
+  model.ResourceReadySignal().Connect(&OnResourceReady);
+  DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
+  KeyFrames floatKeyFrames = KeyFrames::New();
+  floatKeyFrames.Add(0.0f, 1.0f);
+  floatKeyFrames.Add(1.0f, 0.5f);
+
+  float               duration   = 3.0f;
+  Scene3D::MotionData motionData = Scene3D::MotionData::New(duration);
+  motionData.Add(Scene3D::MotionTransformIndex::New("AnimatedMorphCube", Scene3D::MotionTransformIndex::TransformType::SCALE_Y), Scene3D::MotionValue::New(2.0f));
+  motionData.Add(Scene3D::MotionTransformIndex::New("AnimatedMorphCube", Scene3D::MotionTransformIndex::TransformType::SCALE_Z), Scene3D::MotionValue::New(floatKeyFrames));
+  motionData.Add(Scene3D::BlendShapeIndex::New("AnimatedMorphCube", 0), Scene3D::MotionValue::New(0.5f));
+  motionData.Add(Scene3D::BlendShapeIndex::New("AnimatedMorphCube", 1), Scene3D::MotionValue::New(floatKeyFrames));
+
+  Animation generatedAnimation = model.GenerateMotionDataAnimation(motionData);
+  DALI_TEST_CHECK(generatedAnimation);
+  DALI_TEST_EQUALS(generatedAnimation.GetDuration(), duration, TEST_LOCATION);
+
+  Scene3D::MotionData invalidMotionData = Scene3D::MotionData::New(duration);
+  invalidMotionData.Add(Scene3D::MotionTransformIndex::New("NotAnimatedMorphCube", Scene3D::MotionTransformIndex::TransformType::SCALE_Y), Scene3D::MotionValue::New(2.0f));
+  invalidMotionData.Add(Scene3D::MotionTransformIndex::New("NotAnimatedMorphCube", Scene3D::MotionTransformIndex::TransformType::SCALE_Z), Scene3D::MotionValue::New(floatKeyFrames));
+  invalidMotionData.Add(Scene3D::BlendShapeIndex::New("NotAnimatedMorphCube", 0), Scene3D::MotionValue::New(0.5f));
+  invalidMotionData.Add(Scene3D::BlendShapeIndex::New("NotAnimatedMorphCube", 1), Scene3D::MotionValue::New(floatKeyFrames));
+
+  generatedAnimation = model.GenerateMotionDataAnimation(invalidMotionData);
+  DALI_TEST_CHECK(!generatedAnimation); // Animation should be empty if motion data have invalid index.
+
+  END_TEST;
+}
+
+int UtcDaliModelSetMotionData(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_MORPH_FILE_NAME);
+  model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+  application.GetScene().Add(model);
+
+  gResourceReadyCalled = false;
+  model.ResourceReadySignal().Connect(&OnResourceReady);
+  DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
+  KeyFrames floatKeyFrames = KeyFrames::New();
+  floatKeyFrames.Add(0.0f, 1.0f);
+  floatKeyFrames.Add(1.0f, 0.5f);
+
+  float               duration   = 3.0f;
+  Scene3D::MotionData motionData = Scene3D::MotionData::New(duration);
+  motionData.Add(Scene3D::MotionTransformIndex::New("AnimatedMorphCube", Scene3D::MotionTransformIndex::TransformType::SCALE_Y), Scene3D::MotionValue::New(2.0f));
+  motionData.Add(Scene3D::MotionTransformIndex::New("AnimatedMorphCube", Scene3D::MotionTransformIndex::TransformType::SCALE_Z), Scene3D::MotionValue::New(floatKeyFrames));
+  motionData.Add(Scene3D::BlendShapeIndex::New("AnimatedMorphCube", 0), Scene3D::MotionValue::New(0.5f));
+  motionData.Add(Scene3D::BlendShapeIndex::New("AnimatedMorphCube", 1), Scene3D::MotionValue::New(floatKeyFrames));
+
+  auto cubeModelNode = model.FindChildModelNodeByName("AnimatedMorphCube");
+
+  float expectScaleX = cubeModelNode.GetProperty<float>(Actor::Property::SCALE_X);
+
+  model.SetMotionData(motionData);
+
+  DALI_TEST_EQUALS(cubeModelNode.GetProperty<float>(Actor::Property::SCALE_X), expectScaleX, TEST_LOCATION);
+  DALI_TEST_EQUALS(cubeModelNode.GetProperty<float>(Actor::Property::SCALE_Y), 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(cubeModelNode.GetProperty<float>(Actor::Property::SCALE_Z), 0.5f, TEST_LOCATION); ///< Last value of keyframes
+
+  END_TEST;
+}
+
+int UtcDaliModelBlendShapeMotionDataByName(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_EXTRAS_FILE_NAME);
+  model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+  application.GetScene().Add(model);
+
+  gResourceReadyCalled = false;
+  model.ResourceReadySignal().Connect(&OnResourceReady);
+  DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
+  KeyFrames floatKeyFrames = KeyFrames::New();
+  floatKeyFrames.Add(0.0f, 0.5f);
+  floatKeyFrames.Add(1.0f, 1.0f);
+
+  float               duration   = 3.0f;
+  Scene3D::MotionData motionData = Scene3D::MotionData::New(duration);
+  motionData.Add(Scene3D::BlendShapeIndex::New("Target_0"), Scene3D::MotionValue::New(0.5f));
+  motionData.Add(Scene3D::BlendShapeIndex::New("Target_1"), Scene3D::MotionValue::New(floatKeyFrames));
+
+  Animation generatedAnimation = model.GenerateMotionDataAnimation(motionData);
+  DALI_TEST_CHECK(generatedAnimation);
+  DALI_TEST_EQUALS(generatedAnimation.GetDuration(), duration, TEST_LOCATION);
+
+  model.SetMotionData(motionData);
+
+  // Get target ModelNode that has extras
+  Scene3D::ModelNode expectNode    = model.FindChildModelNodeByName("AnimatedMorphCube");
+  auto               propertyIndex = expectNode.GetPropertyIndex(motionData.GetIndex(0u).GetPropertyName(expectNode));
+
+  DALI_TEST_CHECK(propertyIndex != Property::INVALID_INDEX);
+  DALI_TEST_EQUALS(expectNode.GetProperty<float>(propertyIndex), 0.5f, TEST_LOCATION);
+
+  propertyIndex = expectNode.GetPropertyIndex(motionData.GetIndex(1u).GetPropertyName(expectNode));
+  DALI_TEST_CHECK(propertyIndex != Property::INVALID_INDEX);
+  DALI_TEST_EQUALS(expectNode.GetProperty<float>(propertyIndex), 1.0f, TEST_LOCATION);
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-MotionData.cpp b/automated-tests/src/dali-scene3d/utc-Dali-MotionData.cpp
new file mode 100644 (file)
index 0000000..54fc168
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * 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.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <fstream>
+#include <iostream>
+
+#include <toolkit-event-thread-callback.h>
+
+#include <dali-scene3d/public-api/model-motion/motion-data.h>
+#include <dali-scene3d/public-api/model-motion/motion-value.h>
+
+#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+using namespace Dali::Scene3D;
+
+void model_motion_motion_data_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void model_motion_motion_data_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+const char* TEST_BVH_FILE_NAME    = TEST_RESOURCE_DIR "/test.bvh";
+const char* TEST_FACIAL_FILE_NAME = TEST_RESOURCE_DIR "/facial-blendshape-animation.json";
+
+std::string ReadBufferFromFile(const std::string& url)
+{
+  std::string  rawString;
+  std::fstream fileStream;
+
+  fileStream.open(url, std::ios::in | std::ios::binary);
+  if(!fileStream.is_open())
+  {
+    DALI_LOG_WARNING("stream open failed for: \"%s\", in mode: \"%d\".\n", url.c_str(), static_cast<int>(std::ios::in | std::ios::binary));
+  }
+
+  // get length of file:
+  fileStream.seekg(0, std::ios::end);
+  auto length = fileStream.tellg();
+  fileStream.seekg(0, std::ios::beg);
+
+  rawString.resize(length);
+  fileStream.read(rawString.data(), length);
+
+  fileStream.close();
+
+  return rawString;
+}
+
+// For LoadCompleted
+static bool gLoadCompleted = false;
+void        OnLoadCompleted(MotionData data)
+{
+  gLoadCompleted = true;
+}
+} // namespace
+
+// Positive test case for a method
+int UtcDaliMotionDataNew(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionDataNew");
+
+  float      expectDuration = 0.0f;
+  MotionData motionData     = MotionData::New();
+  DALI_TEST_CHECK(motionData);
+  DALI_TEST_EQUALS(motionData.GetDuration(), expectDuration, TEST_LOCATION);
+
+  expectDuration = 10.0f;
+  motionData     = MotionData::New(expectDuration);
+  DALI_TEST_CHECK(motionData);
+  DALI_TEST_EQUALS(motionData.GetDuration(), expectDuration, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMotionDataDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionDataDownCast");
+
+  MotionData motionData = MotionData::New();
+  BaseHandle handle(motionData);
+
+  MotionData motionData2 = MotionData::DownCast(handle);
+  DALI_TEST_CHECK(motionData);
+  DALI_TEST_CHECK(motionData2);
+  DALI_TEST_CHECK(motionData2 == motionData);
+  END_TEST;
+}
+
+int UtcDaliMotionDataTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK(typeRegistry);
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo("MotionData");
+  DALI_TEST_CHECK(typeInfo);
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK(handle);
+
+  MotionData motionData = MotionData::DownCast(handle);
+  DALI_TEST_CHECK(motionData);
+
+  END_TEST;
+}
+
+int UtcDaliMotionDataCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionData motionData = MotionData::New();
+  DALI_TEST_CHECK(motionData);
+
+  MotionData copy(motionData);
+  DALI_TEST_CHECK(motionData == copy);
+
+  MotionData assign;
+  DALI_TEST_CHECK(!assign);
+
+  assign = copy;
+  DALI_TEST_CHECK(assign == motionData);
+
+  END_TEST;
+}
+
+int UtcDaliMotionDataMoveConstructor(void)
+{
+  ToolkitTestApplication application;
+
+  MotionData motionData = MotionData::New();
+  DALI_TEST_EQUALS(1, motionData.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  MotionData moved = std::move(motionData);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(!motionData);
+
+  END_TEST;
+}
+
+int UtcDaliMotionDataMoveAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionData motionData = MotionData::New();
+  DALI_TEST_EQUALS(1, motionData.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  MotionData moved;
+  moved = std::move(motionData);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+// Method test
+
+int UtcDaliMotionDataAddMotion(void)
+{
+  ToolkitTestApplication application;
+
+  MotionData motionData = MotionData::New(3.0f);
+
+  const uint32_t countMax = 4;
+  MotionIndex    index[countMax];
+  MotionValue    value[countMax];
+  for(uint32_t i = 0u; i < countMax; ++i)
+  {
+    // Generate index
+    if(i & 1)
+    {
+      index[i] = BlendShapeIndex::New("node", 0);
+    }
+    else
+    {
+      index[i] = MotionTransformIndex::New("node", MotionTransformIndex::TransformType::POSITION_X);
+    }
+
+    // Generate value
+    if(i & 2)
+    {
+      value[i] = MotionValue::New(3.0f);
+    }
+    else
+    {
+      KeyFrames keyFrames = KeyFrames::New();
+      keyFrames.Add(0.0f, 9.0f);
+      keyFrames.Add(1.0f, 5.0f);
+      value[i] = MotionValue::New(keyFrames);
+    }
+
+    DALI_TEST_CHECK(index[i]);
+    DALI_TEST_CHECK(value[i]);
+    motionData.Add(index[i], value[i]);
+
+    DALI_TEST_EQUALS(i + 1, motionData.GetMotionCount(), TEST_LOCATION);
+  }
+
+  for(uint32_t i = 0u; i < countMax; ++i)
+  {
+    DALI_TEST_EQUALS(index[i], motionData.GetIndex(i), TEST_LOCATION);
+    DALI_TEST_EQUALS(value[i], motionData.GetValue(i), TEST_LOCATION);
+  }
+
+  DALI_TEST_CHECK(!motionData.GetIndex(countMax));
+  DALI_TEST_CHECK(!motionData.GetValue(countMax));
+
+  motionData.Clear();
+
+  DALI_TEST_EQUALS(0u, motionData.GetMotionCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(!motionData.GetIndex(0u));
+  DALI_TEST_CHECK(!motionData.GetValue(0u));
+
+  END_TEST;
+}
+
+int UtcDaliMotionDataSetGetDuration(void)
+{
+  ToolkitTestApplication application;
+
+  float      expectDuration = 3.0f;
+  MotionData motionData     = MotionData::New(expectDuration);
+  DALI_TEST_EQUALS(motionData.GetDuration(), expectDuration, TEST_LOCATION);
+
+  expectDuration = 7.0f;
+  motionData.SetDuration(expectDuration);
+  DALI_TEST_EQUALS(motionData.GetDuration(), expectDuration, TEST_LOCATION);
+
+  expectDuration = 1.0f;
+  motionData.SetDuration(expectDuration);
+  DALI_TEST_EQUALS(motionData.GetDuration(), expectDuration, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliMotionDataLoadBvhAndFacialAsync(void)
+{
+  ToolkitTestApplication application;
+
+  for(uint32_t tc = 0; tc < 4; ++tc)
+  {
+    MotionData motionData = MotionData::New();
+    gLoadCompleted        = false;
+    motionData.LoadCompletedSignal().Connect(&OnLoadCompleted);
+
+    switch(tc)
+    {
+      case 0:
+      default:
+      {
+        motionData.LoadBvh(TEST_BVH_FILE_NAME);
+        break;
+      }
+      case 1:
+      {
+        motionData.LoadFacialAnimation(TEST_FACIAL_FILE_NAME);
+        break;
+      }
+      case 2:
+      {
+        std::string rawString = ReadBufferFromFile(TEST_BVH_FILE_NAME);
+        motionData.LoadBvhFromBuffer(reinterpret_cast<uint8_t*>(rawString.data()), static_cast<int>(rawString.length()));
+        break;
+      }
+      case 3:
+      {
+        std::string rawString = ReadBufferFromFile(TEST_FACIAL_FILE_NAME);
+        motionData.LoadFacialAnimationFromBuffer(reinterpret_cast<uint8_t*>(rawString.data()), static_cast<int>(rawString.length()));
+        break;
+      }
+    }
+
+    DALI_TEST_EQUALS(gLoadCompleted, false, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+    application.SendNotification();
+    application.Render();
+
+    // Check LoadCompletedSignal emitted.
+    DALI_TEST_EQUALS(gLoadCompleted, true, TEST_LOCATION);
+
+    // Check MotionData load successfully.
+    DALI_TEST_GREATER(motionData.GetMotionCount(), 0u, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliMotionDataLoadBvhAndFacialSync(void)
+{
+  ToolkitTestApplication application;
+
+  for(uint32_t tc = 0; tc < 4; ++tc)
+  {
+    MotionData motionData = MotionData::New();
+    gLoadCompleted        = false;
+    motionData.LoadCompletedSignal().Connect(&OnLoadCompleted);
+
+    switch(tc)
+    {
+      case 0:
+      default:
+      {
+        motionData.LoadBvh(TEST_BVH_FILE_NAME, Vector3::ONE, true);
+        break;
+      }
+      case 1:
+      {
+        motionData.LoadFacialAnimation(TEST_FACIAL_FILE_NAME, true);
+        break;
+      }
+      case 2:
+      {
+        std::string rawString = ReadBufferFromFile(TEST_BVH_FILE_NAME);
+        motionData.LoadBvhFromBuffer(reinterpret_cast<uint8_t*>(rawString.data()), static_cast<int>(rawString.length()), Vector3::ONE, true);
+        break;
+      }
+      case 3:
+      {
+        std::string rawString = ReadBufferFromFile(TEST_FACIAL_FILE_NAME);
+        motionData.LoadFacialAnimationFromBuffer(reinterpret_cast<uint8_t*>(rawString.data()), static_cast<int>(rawString.length()), true);
+        break;
+      }
+    }
+
+    // Check LoadCompletedSignal emitted.
+    DALI_TEST_EQUALS(gLoadCompleted, true, TEST_LOCATION);
+
+    // Check MotionData load successfully.
+    DALI_TEST_GREATER(motionData.GetMotionCount(), 0u, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliMotionDataLoadAsyncMultiple(void)
+{
+  ToolkitTestApplication application;
+
+  MotionData motionData = MotionData::New();
+  gLoadCompleted        = false;
+  motionData.LoadCompletedSignal().Connect(&OnLoadCompleted);
+
+  auto tryCount = 10u;
+  for(auto i = 0u; i < tryCount; ++i)
+  {
+    motionData.LoadBvh(TEST_BVH_FILE_NAME);
+  }
+
+  DALI_TEST_EQUALS(gLoadCompleted, false, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(gLoadCompleted, true, TEST_LOCATION);
+
+  // Check MotionData load successfully.
+  DALI_TEST_GREATER(motionData.GetMotionCount(), 0u, TEST_LOCATION);
+
+  // Check if completed request comes only 1 time.
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 1), false, TEST_LOCATION);
+
+  END_TEST;
+}
\ No newline at end of file
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-MotionIndex.cpp b/automated-tests/src/dali-scene3d/utc-Dali-MotionIndex.cpp
new file mode 100644 (file)
index 0000000..1e28a46
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+using namespace Dali::Scene3D;
+
+void model_motion_motion_index_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void model_motion_motion_index_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+} // namespace
+
+// Positive test case for a method
+int UtcDaliMotionIndexDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionIndexDownCast");
+
+  MotionIndex blendShapeIndex = BlendShapeIndex::New();
+  BaseHandle  handle(blendShapeIndex);
+
+  MotionIndex blendShapeIndex2 = MotionIndex::DownCast(handle);
+  DALI_TEST_CHECK(blendShapeIndex);
+  DALI_TEST_CHECK(blendShapeIndex2);
+  DALI_TEST_CHECK(blendShapeIndex2 == blendShapeIndex);
+  END_TEST;
+}
+
+int UtcDaliMotionIndexDownCastNotMatchedType(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionIndexDownCastNotMatchedType");
+
+  {
+    MotionIndex baseIndex = BlendShapeIndex::New();
+    DALI_TEST_CHECK(baseIndex);
+
+    BaseHandle handle(baseIndex);
+
+    MotionIndex motionPropertyIndex = MotionPropertyIndex::DownCast(handle);
+    DALI_TEST_CHECK(!motionPropertyIndex);
+
+    MotionIndex motionTransformIndex = MotionTransformIndex::DownCast(handle);
+    DALI_TEST_CHECK(!motionTransformIndex);
+
+    MotionIndex blendShapeIndex = BlendShapeIndex::DownCast(handle);
+    DALI_TEST_CHECK(blendShapeIndex);
+    DALI_TEST_CHECK(blendShapeIndex == baseIndex);
+  }
+  END_TEST;
+}
+
+int UtcDaliMotionIndexCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionIndex blendShapeIndex = BlendShapeIndex::New();
+  DALI_TEST_CHECK(blendShapeIndex);
+
+  MotionIndex copy(blendShapeIndex);
+  DALI_TEST_CHECK(blendShapeIndex == copy);
+
+  MotionIndex assign;
+  DALI_TEST_CHECK(!assign);
+
+  assign = copy;
+  DALI_TEST_CHECK(assign == blendShapeIndex);
+
+  END_TEST;
+}
+
+int UtcDaliMotionIndexMoveConstructor(void)
+{
+  ToolkitTestApplication application;
+
+  MotionIndex blendShapeIndex = MotionTransformIndex::New();
+  DALI_TEST_EQUALS(1, blendShapeIndex.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  MotionIndex moved = std::move(blendShapeIndex);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(!blendShapeIndex);
+
+  END_TEST;
+}
+
+int UtcDaliMotionIndexMoveAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionIndex blendShapeIndex = BlendShapeIndex::New();
+  DALI_TEST_EQUALS(1, blendShapeIndex.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  MotionIndex moved;
+  moved = std::move(blendShapeIndex);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+// Method test
+
+int UtcDaliMotionIndexSetGetModelNodeId(void)
+{
+  std::string expectModelNodeStringId = "nodeId";
+  MotionIndex index                   = MotionTransformIndex::New(expectModelNodeStringId, MotionTransformIndex::TransformType::POSITION);
+
+  auto propertyKey = index.GetModelNodeId();
+  DALI_TEST_CHECK(propertyKey.type == Property::Key::Type::STRING);
+  DALI_TEST_EQUALS(expectModelNodeStringId, propertyKey.stringKey, TEST_LOCATION);
+
+  expectModelNodeStringId = "anotherId";
+  index.SetModelNodeId(expectModelNodeStringId);
+
+  propertyKey = index.GetModelNodeId();
+  DALI_TEST_CHECK(propertyKey.type == Property::Key::Type::STRING);
+  DALI_TEST_EQUALS(expectModelNodeStringId, propertyKey.stringKey, TEST_LOCATION);
+
+  Property::Index expectModelNodeIndexId = 193u;
+  index.SetModelNodeId(expectModelNodeIndexId);
+
+  propertyKey = index.GetModelNodeId();
+  DALI_TEST_CHECK(propertyKey.type == Property::Key::Type::INDEX);
+  DALI_TEST_EQUALS(expectModelNodeIndexId, propertyKey.indexKey, TEST_LOCATION);
+
+  END_TEST;
+}
\ No newline at end of file
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-MotionPropertyIndex.cpp b/automated-tests/src/dali-scene3d/utc-Dali-MotionPropertyIndex.cpp
new file mode 100644 (file)
index 0000000..d0aa20d
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+using namespace Dali::Scene3D;
+
+void model_motion_motion_property_index_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void model_motion_motion_property_index_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+} // namespace
+
+// Positive test case for a method
+int UtcDaliMotionPropertyIndexNew(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionPropertyIndexNew");
+
+  MotionPropertyIndex motionPropertyIndex = MotionPropertyIndex::New();
+  DALI_TEST_CHECK(motionPropertyIndex);
+  DALI_TEST_EQUALS(motionPropertyIndex.GetModelNodeId().stringKey, "", TEST_LOCATION);
+  DALI_TEST_EQUALS(motionPropertyIndex.GetPropertyId().indexKey, Property::INVALID_INDEX, TEST_LOCATION);
+
+  motionPropertyIndex = MotionPropertyIndex::New("dummy", 3u);
+  DALI_TEST_CHECK(motionPropertyIndex);
+  DALI_TEST_EQUALS(motionPropertyIndex.GetModelNodeId().stringKey, "dummy", TEST_LOCATION);
+  DALI_TEST_EQUALS(motionPropertyIndex.GetPropertyId().indexKey, 3u, TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliMotionPropertyIndexDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionPropertyIndexDownCast");
+
+  MotionPropertyIndex motionPropertyIndex = MotionPropertyIndex::New();
+  BaseHandle          handle(motionPropertyIndex);
+
+  MotionPropertyIndex motionPropertyIndex2 = MotionPropertyIndex::DownCast(handle);
+  DALI_TEST_CHECK(motionPropertyIndex);
+  DALI_TEST_CHECK(motionPropertyIndex2);
+  DALI_TEST_CHECK(motionPropertyIndex2 == motionPropertyIndex);
+  END_TEST;
+}
+
+int UtcDaliMotionPropertyIndexTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK(typeRegistry);
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo("MotionPropertyIndex");
+  DALI_TEST_CHECK(typeInfo);
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK(handle);
+
+  MotionPropertyIndex motionPropertyIndex = MotionPropertyIndex::DownCast(handle);
+  DALI_TEST_CHECK(motionPropertyIndex);
+
+  END_TEST;
+}
+
+int UtcDaliMotionPropertyIndexCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionPropertyIndex motionPropertyIndex = MotionPropertyIndex::New();
+  DALI_TEST_CHECK(motionPropertyIndex);
+
+  MotionPropertyIndex copy(motionPropertyIndex);
+  DALI_TEST_CHECK(motionPropertyIndex == copy);
+
+  MotionPropertyIndex assign;
+  DALI_TEST_CHECK(!assign);
+
+  assign = copy;
+  DALI_TEST_CHECK(assign == motionPropertyIndex);
+
+  END_TEST;
+}
+
+int UtcDaliMotionPropertyIndexMoveConstructor(void)
+{
+  ToolkitTestApplication application;
+
+  MotionPropertyIndex motionPropertyIndex = MotionPropertyIndex::New();
+  DALI_TEST_EQUALS(1, motionPropertyIndex.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  MotionPropertyIndex moved = std::move(motionPropertyIndex);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(!motionPropertyIndex);
+
+  END_TEST;
+}
+
+int UtcDaliMotionPropertyIndexMoveAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionPropertyIndex motionPropertyIndex = MotionPropertyIndex::New();
+  DALI_TEST_EQUALS(1, motionPropertyIndex.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  MotionPropertyIndex moved;
+  moved = std::move(motionPropertyIndex);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+// Method test
+
+int UtcDaliMotionPropertyIndexGetPropertyName(void)
+{
+  std::string     expectPropertyName  = "";
+  Property::Index expectPropertyIndex = Property::INVALID_INDEX;
+
+  MotionIndex index = MotionPropertyIndex::New();
+
+  // Invalid motion index return empty string, invalid index
+  DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyName(), TEST_LOCATION);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetPropertyIndex(), TEST_LOCATION);
+
+  expectPropertyIndex = 0u;
+  index               = MotionPropertyIndex::New("", expectPropertyIndex);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetPropertyIndex(), TEST_LOCATION);
+
+  expectPropertyIndex = 45u;
+  index               = MotionPropertyIndex::New("", expectPropertyIndex);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetPropertyIndex(), TEST_LOCATION);
+
+  expectPropertyName = "name";
+  index              = MotionPropertyIndex::New("", expectPropertyName);
+  DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyName(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliMotionPropertyIndexSetGetPropertyId(void)
+{
+  Property::Index expectPropertyIndex = 0u;
+
+  MotionPropertyIndex index = MotionPropertyIndex::New("", expectPropertyIndex);
+
+  // Invalid motion index return empty string, invalid index
+  DALI_TEST_CHECK(index.GetPropertyId().type == Property::Key::Type::INDEX);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetPropertyId().indexKey, TEST_LOCATION);
+
+  std::string expectPropertyName = "hello";
+  index.SetPropertyId(expectPropertyName);
+  DALI_TEST_CHECK(index.GetPropertyId().type == Property::Key::Type::STRING);
+  DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyId().stringKey, TEST_LOCATION);
+
+  expectPropertyIndex = 100u;
+  index.SetPropertyId(expectPropertyIndex);
+  DALI_TEST_CHECK(index.GetPropertyId().type == Property::Key::Type::INDEX);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetPropertyId().indexKey, TEST_LOCATION);
+
+  END_TEST;
+}
\ No newline at end of file
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-MotionTransformIndex.cpp b/automated-tests/src/dali-scene3d/utc-Dali-MotionTransformIndex.cpp
new file mode 100644 (file)
index 0000000..0dd0814
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+using namespace Dali::Scene3D;
+
+void model_motion_motion_transform_index_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void model_motion_motion_transform_index_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+struct PropertyStringIndex
+{
+  const MotionTransformIndex::TransformType type;
+
+  const char* const     name;
+  const Property::Index index;
+};
+const PropertyStringIndex PROPERTY_TABLE[] =
+  {
+    {MotionTransformIndex::TransformType::POSITION, "position", Actor::Property::POSITION},
+    {MotionTransformIndex::TransformType::POSITION_X, "positionX", Actor::Property::POSITION_X},
+    {MotionTransformIndex::TransformType::POSITION_Y, "positionY", Actor::Property::POSITION_Y},
+    {MotionTransformIndex::TransformType::POSITION_Z, "positionZ", Actor::Property::POSITION_Z},
+    {MotionTransformIndex::TransformType::ORIENTATION, "orientation", Actor::Property::ORIENTATION},
+    {MotionTransformIndex::TransformType::SCALE, "scale", Actor::Property::SCALE},
+    {MotionTransformIndex::TransformType::SCALE_X, "scaleX", Actor::Property::SCALE_X},
+    {MotionTransformIndex::TransformType::SCALE_Y, "scaleY", Actor::Property::SCALE_Y},
+    {MotionTransformIndex::TransformType::SCALE_Z, "scaleZ", Actor::Property::SCALE_Z},
+};
+} // namespace
+
+// Positive test case for a method
+int UtcDaliMotionTransformIndexNew(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionTransformIndexNew");
+
+  MotionTransformIndex motionTransformIndex = MotionTransformIndex::New();
+  DALI_TEST_CHECK(motionTransformIndex);
+  DALI_TEST_EQUALS(motionTransformIndex.GetModelNodeId().stringKey, "", TEST_LOCATION);
+  DALI_TEST_EQUALS(motionTransformIndex.GetTransformType(), MotionTransformIndex::TransformType::INVALID, TEST_LOCATION);
+
+  motionTransformIndex = MotionTransformIndex::New("dummy", MotionTransformIndex::TransformType::SCALE);
+  DALI_TEST_CHECK(motionTransformIndex);
+  DALI_TEST_EQUALS(motionTransformIndex.GetModelNodeId().stringKey, "dummy", TEST_LOCATION);
+  DALI_TEST_EQUALS(motionTransformIndex.GetTransformType(), MotionTransformIndex::TransformType::SCALE, TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliMotionTransformIndexDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionTransformIndexDownCast");
+
+  MotionTransformIndex motionTransformIndex = MotionTransformIndex::New();
+  BaseHandle           handle(motionTransformIndex);
+
+  MotionTransformIndex motionTransformIndex2 = MotionTransformIndex::DownCast(handle);
+  DALI_TEST_CHECK(motionTransformIndex);
+  DALI_TEST_CHECK(motionTransformIndex2);
+  DALI_TEST_CHECK(motionTransformIndex2 == motionTransformIndex);
+  END_TEST;
+}
+
+int UtcDaliMotionTransformIndexTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK(typeRegistry);
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo("MotionTransformIndex");
+  DALI_TEST_CHECK(typeInfo);
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK(handle);
+
+  MotionTransformIndex motionTransformIndex = MotionTransformIndex::DownCast(handle);
+  DALI_TEST_CHECK(motionTransformIndex);
+
+  END_TEST;
+}
+
+int UtcDaliMotionTransformIndexCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionTransformIndex motionTransformIndex = MotionTransformIndex::New();
+  DALI_TEST_CHECK(motionTransformIndex);
+
+  MotionTransformIndex copy(motionTransformIndex);
+  DALI_TEST_CHECK(motionTransformIndex == copy);
+
+  MotionTransformIndex assign;
+  DALI_TEST_CHECK(!assign);
+
+  assign = copy;
+  DALI_TEST_CHECK(assign == motionTransformIndex);
+
+  END_TEST;
+}
+
+int UtcDaliMotionTransformIndexMoveConstructor(void)
+{
+  ToolkitTestApplication application;
+
+  MotionTransformIndex motionTransformIndex = MotionTransformIndex::New();
+  DALI_TEST_EQUALS(1, motionTransformIndex.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  MotionTransformIndex moved = std::move(motionTransformIndex);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(!motionTransformIndex);
+
+  END_TEST;
+}
+
+int UtcDaliMotionTransformIndexMoveAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionTransformIndex motionTransformIndex = MotionTransformIndex::New();
+  DALI_TEST_EQUALS(1, motionTransformIndex.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  MotionTransformIndex moved;
+  moved = std::move(motionTransformIndex);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+// Method test
+
+int UtcDaliMotionTransformIndexGetPropertyNameAndIndex(void)
+{
+  auto transfromTypeCount = sizeof(PROPERTY_TABLE) / sizeof(PROPERTY_TABLE[0]);
+  for(auto i = 0u; i < transfromTypeCount; i++)
+  {
+    auto type = PROPERTY_TABLE[i].type;
+
+    std::string     expectPropertyName  = PROPERTY_TABLE[i].name;
+    Property::Index expectPropertyIndex = PROPERTY_TABLE[i].index;
+
+    MotionIndex index = MotionTransformIndex::New("", type);
+
+    DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyName(), TEST_LOCATION);
+    DALI_TEST_EQUALS(expectPropertyIndex, index.GetPropertyIndex(), TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliMotionTransformIndexGetPropertyInvalid(void)
+{
+  std::string     expectPropertyName  = "";
+  Property::Index expectPropertyIndex = Property::INVALID_INDEX;
+
+  MotionIndex index = MotionTransformIndex::New();
+
+  // Invalid motion index return empty string, invalid index
+  DALI_TEST_EQUALS(expectPropertyName, index.GetPropertyName(), TEST_LOCATION);
+  DALI_TEST_EQUALS(expectPropertyIndex, index.GetPropertyIndex(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliMotionTransformIndexSetGetPropertType(void)
+{
+  auto                 expectType = MotionTransformIndex::TransformType::POSITION;
+  MotionTransformIndex index      = MotionTransformIndex::New("", expectType);
+
+  // Invalid motion index return empty string, invalid index
+  DALI_TEST_EQUALS(expectType, index.GetTransformType(), TEST_LOCATION);
+
+  expectType = MotionTransformIndex::TransformType::ORIENTATION;
+  index.SetTransformType(expectType);
+  DALI_TEST_EQUALS(expectType, index.GetTransformType(), TEST_LOCATION);
+
+  END_TEST;
+}
\ No newline at end of file
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-MotionValue.cpp b/automated-tests/src/dali-scene3d/utc-Dali-MotionValue.cpp
new file mode 100644 (file)
index 0000000..1ac4255
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/public-api/model-motion/motion-value.h>
+#include <dali/devel-api/animation/key-frames-devel.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+using namespace Dali::Scene3D;
+
+void model_motion_motion_value_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void model_motion_motion_value_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+} // namespace
+
+// Positive test case for a method
+int UtcDaliMotionValueNew(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionValueNew");
+
+  MotionValue motionValue = MotionValue::New();
+  DALI_TEST_CHECK(motionValue);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliMotionValueDownCast(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliMotionValueDownCast");
+
+  MotionValue motionValue = MotionValue::New();
+  BaseHandle  handle(motionValue);
+
+  MotionValue motionValue2 = MotionValue::DownCast(handle);
+  DALI_TEST_CHECK(motionValue);
+  DALI_TEST_CHECK(motionValue2);
+  DALI_TEST_CHECK(motionValue2 == motionValue);
+  END_TEST;
+}
+
+int UtcDaliMotionValueTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK(typeRegistry);
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo("MotionValue");
+  DALI_TEST_CHECK(typeInfo);
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK(handle);
+
+  MotionValue motionValue = MotionValue::DownCast(handle);
+  DALI_TEST_CHECK(motionValue);
+
+  END_TEST;
+}
+
+int UtcDaliMotionValueCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionValue motionValue = MotionValue::New(1);
+  DALI_TEST_CHECK(motionValue);
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::PROPERTY_VALUE);
+
+  MotionValue copy(motionValue);
+  DALI_TEST_CHECK(motionValue == copy);
+  DALI_TEST_CHECK(copy.GetValueType() == MotionValue::ValueType::PROPERTY_VALUE);
+
+  MotionValue assign;
+  DALI_TEST_CHECK(!assign);
+
+  assign = copy;
+  DALI_TEST_CHECK(assign == motionValue);
+  DALI_TEST_CHECK(assign.GetValueType() == MotionValue::ValueType::PROPERTY_VALUE);
+
+  END_TEST;
+}
+
+int UtcDaliMotionValueMoveConstructor(void)
+{
+  ToolkitTestApplication application;
+
+  MotionValue motionValue = MotionValue::New(3.0f);
+  DALI_TEST_EQUALS(1, motionValue.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::PROPERTY_VALUE);
+
+  MotionValue moved = std::move(motionValue);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(moved.GetValueType() == MotionValue::ValueType::PROPERTY_VALUE);
+  DALI_TEST_CHECK(!motionValue);
+
+  END_TEST;
+}
+
+int UtcDaliMotionValueMoveAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  MotionValue motionValue = MotionValue::New(KeyFrames::New());
+  DALI_TEST_EQUALS(1, motionValue.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::KEY_FRAMES);
+
+  MotionValue moved;
+  moved = std::move(motionValue);
+  DALI_TEST_CHECK(moved);
+  DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(moved.GetValueType() == MotionValue::ValueType::KEY_FRAMES);
+
+  END_TEST;
+}
+
+// Method test
+
+int UtcDaliMotionValueGetSetValue(void)
+{
+  ToolkitTestApplication application;
+
+  MotionValue motionValue = MotionValue::New();
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::INVALID);
+  DALI_TEST_CHECK(motionValue.GetPropertyValue().GetType() == Property::Type::NONE);
+  DALI_TEST_CHECK(!motionValue.GetKeyFrames());
+
+  float expectValue = 3.0f;
+  motionValue.SetValue(expectValue);
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::PROPERTY_VALUE);
+  DALI_TEST_CHECK(motionValue.GetPropertyValue().GetType() == Property::Type::FLOAT);
+  DALI_TEST_CHECK(motionValue.GetPropertyValue().Get<float>() == expectValue);
+
+  // Check the converted KeyFrames
+  auto convertedKeyFrames = motionValue.GetKeyFrames();
+  DALI_TEST_CHECK(convertedKeyFrames);
+  auto convertedKeyFrameCount = DevelKeyFrames::GetKeyFrameCount(convertedKeyFrames);
+  for(auto i = 0u; i < convertedKeyFrameCount; ++i)
+  {
+    float           progress;
+    Property::Value value;
+    DevelKeyFrames::GetKeyFrame(convertedKeyFrames, i, progress, value);
+
+    // Check all value has same as expect property.
+    DALI_TEST_EQUALS(value.Get<float>(), expectValue, TEST_LOCATION);
+  }
+
+  KeyFrames expectKeyFrames = KeyFrames::New();
+  expectValue               = 2.0f;
+  expectKeyFrames.Add(0.0f, expectValue - 1.0f);
+  expectKeyFrames.Add(1.0f, expectValue);
+  motionValue.SetValue(expectKeyFrames);
+
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::KEY_FRAMES);
+  DALI_TEST_CHECK(motionValue.GetKeyFrames() == expectKeyFrames);
+
+  // Check property value return last frame value.
+  DALI_TEST_CHECK(motionValue.GetPropertyValue().GetType() == Property::Type::FLOAT);
+  DALI_TEST_EQUALS(motionValue.GetPropertyValue().Get<float>(), expectValue, TEST_LOCATION);
+
+  // Check invalidate value.
+  motionValue.Invalidate();
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::INVALID);
+  DALI_TEST_CHECK(motionValue.GetPropertyValue().GetType() == Property::Type::NONE);
+  DALI_TEST_CHECK(!motionValue.GetKeyFrames());
+  
+  motionValue.SetValue(expectKeyFrames);
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::KEY_FRAMES);
+  DALI_TEST_CHECK(motionValue.GetKeyFrames() == expectKeyFrames);
+
+  // Check invalidate value by Clear().
+  motionValue.Clear();
+  DALI_TEST_CHECK(motionValue.GetValueType() == MotionValue::ValueType::INVALID);
+  DALI_TEST_CHECK(motionValue.GetPropertyValue().GetType() == Property::Type::NONE);
+  DALI_TEST_CHECK(!motionValue.GetKeyFrames());
+
+  END_TEST;
+}
\ No newline at end of file
index 2d3bad9..eb7c60a 100644 (file)
 #include <dali-scene3d/public-api/model-components/model-node.h>
 #include <dali-scene3d/public-api/model-components/model-primitive.h>
 
+#include <dali-scene3d/public-api/model-motion/motion-data.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-value.h>
+
 #endif // DALI_SCENE3D_H
\ No newline at end of file
index 5e0ad30..7c82d4b 100644 (file)
@@ -43,6 +43,7 @@
 #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;
 
@@ -558,6 +559,207 @@ void Model::RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName,
   }
 }
 
+Dali::Animation Model::GenerateMotionDataAnimation(Scene3D::MotionData motionData)
+{
+  Dali::Animation animation;
+
+  // TODO : Need to collect duplicated codes with SetMotionData()
+
+  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 : Need to collect duplicated codes with GenerateMotionDataAnimation()
+
+  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
index 4dcd5c8..f383aff 100644 (file)
@@ -156,6 +156,16 @@ public:
    */
   void RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector<Scene3D::ModelNode>& modelNodes) const;
 
+  /**
+   * @copydoc Model::GenerateMotionDataAnimation()
+   */
+  Dali::Animation GenerateMotionDataAnimation(Scene3D::MotionData motionData);
+
+  /**
+   * @copydoc Model::SetMotionData()
+   */
+  void SetMotionData(Scene3D::MotionData motionData);
+
 protected:
   /**
    * @brief Constructs a new Model.
index 56200d2..9ea43a8 100644 (file)
@@ -22,4 +22,11 @@ set(scene3d_src_files ${scene3d_src_files}
        ${scene3d_internal_dir}/model-components/material-impl.cpp
        ${scene3d_internal_dir}/model-components/model-node-impl.cpp
        ${scene3d_internal_dir}/model-components/model-primitive-impl.cpp
+       ${scene3d_internal_dir}/model-motion/motion-data-impl.cpp
+       ${scene3d_internal_dir}/model-motion/motion-data-load-task.cpp
+       ${scene3d_internal_dir}/model-motion/motion-index/blend-shape-index-impl.cpp
+       ${scene3d_internal_dir}/model-motion/motion-index/motion-index-impl.cpp
+       ${scene3d_internal_dir}/model-motion/motion-index/motion-property-index-impl.cpp
+       ${scene3d_internal_dir}/model-motion/motion-index/motion-transform-index-impl.cpp
+       ${scene3d_internal_dir}/model-motion/motion-value-impl.cpp
 )
diff --git a/dali-scene3d/internal/model-motion/motion-data-impl.cpp b/dali-scene3d/internal/model-motion/motion-data-impl.cpp
new file mode 100644 (file)
index 0000000..bb3f1cc
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * 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-motion/motion-data-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Creates control through type registry
+ */
+BaseHandle Create()
+{
+  return Scene3D::MotionData::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::MotionData, Dali::BaseHandle, Create);
+DALI_TYPE_REGISTRATION_END()
+
+} // unnamed namespace
+
+MotionDataPtr MotionData::New()
+{
+  MotionDataPtr motionData = new MotionData();
+
+  motionData->Initialize();
+
+  return motionData;
+}
+
+MotionData::MotionData()
+{
+}
+
+MotionData::~MotionData()
+{
+  if(Dali::Adaptor::IsAvailable())
+  {
+    CancelMotionDataLoad();
+  }
+}
+
+void MotionData::Initialize()
+{
+}
+
+uint32_t MotionData::GetMotionCount() const
+{
+  return static_cast<uint32_t>(mMotions.size());
+}
+
+Scene3D::MotionIndex MotionData::GetIndex(uint32_t index) const
+{
+  if(index < mMotions.size())
+  {
+    return mMotions[index].first;
+  }
+  return Scene3D::MotionIndex();
+}
+
+Scene3D::MotionValue MotionData::GetValue(uint32_t index) const
+{
+  if(index < mMotions.size())
+  {
+    return mMotions[index].second;
+  }
+  return Scene3D::MotionValue();
+}
+
+void MotionData::Add(Scene3D::MotionIndex index, Scene3D::MotionValue value)
+{
+  mMotions.emplace_back(index, value);
+}
+
+void MotionData::Clear()
+{
+  mMotions.clear();
+}
+
+void MotionData::SetDuration(float durationSeconds)
+{
+  mDurationSeconds = durationSeconds;
+}
+
+float MotionData::GetDuration() const
+{
+  return mDurationSeconds;
+}
+
+void MotionData::LoadBvh(const std::string& path, const Vector3& scale, bool synchronousLoad)
+{
+  CancelMotionDataLoad();
+  mMotionDataLoadTask = new MotionDataLoadTask(path, scale, MakeCallback(this, &MotionData::OnLoadCompleted));
+  RequestMotionDataLoad(synchronousLoad);
+}
+
+void MotionData::LoadBvhFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, const Vector3& scale, bool synchronousLoad)
+{
+  CancelMotionDataLoad();
+  mMotionDataLoadTask = new MotionDataLoadTask(rawBuffer, rawBufferLength, scale, MakeCallback(this, &MotionData::OnLoadCompleted));
+  RequestMotionDataLoad(synchronousLoad);
+}
+
+void MotionData::LoadFacialAnimation(const std::string& url, bool synchronousLoad)
+{
+  CancelMotionDataLoad();
+  mMotionDataLoadTask = new MotionDataLoadTask(url, MakeCallback(this, &MotionData::OnLoadCompleted));
+  RequestMotionDataLoad(synchronousLoad);
+}
+
+void MotionData::LoadFacialAnimationFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, bool synchronousLoad)
+{
+  CancelMotionDataLoad();
+  mMotionDataLoadTask = new MotionDataLoadTask(rawBuffer, rawBufferLength, MakeCallback(this, &MotionData::OnLoadCompleted));
+  RequestMotionDataLoad(synchronousLoad);
+}
+
+// Private method
+void MotionData::RequestMotionDataLoad(bool synchronousLoad)
+{
+  if(mMotionDataLoadTask)
+  {
+    if(synchronousLoad)
+    {
+      mMotionDataLoadTask->Process();
+      OnLoadCompleted(mMotionDataLoadTask);
+    }
+    else
+    {
+      Dali::AsyncTaskManager::Get().AddTask(mMotionDataLoadTask);
+    }
+  }
+}
+
+void MotionData::CancelMotionDataLoad()
+{
+  if(mMotionDataLoadTask)
+  {
+    Dali::AsyncTaskManager::Get().RemoveTask(mMotionDataLoadTask);
+    mMotionDataLoadTask.Reset();
+  }
+}
+
+// Called from MotionDataLoadTask
+void MotionData::OnLoadCompleted(MotionDataLoadTaskPtr task)
+{
+  if(mMotionDataLoadTask == task)
+  {
+    const Scene3D::Loader::AnimationDefinition& animationDefinition = mMotionDataLoadTask->GetAnimationDefinition();
+
+    mDurationSeconds = animationDefinition.GetDuration();
+
+    auto animatedPropertyCount = animationDefinition.GetPropertyCount();
+
+    mMotions.clear();
+    mMotions.reserve(animatedPropertyCount);
+
+    for(uint32_t i = 0u; i < animatedPropertyCount; ++i)
+    {
+      const auto& animatedProperty = animationDefinition.GetPropertyAt(i);
+
+      // TODO : Currently, we only support KeyFrames without alpha function and time period now.
+      if(animatedProperty.mKeyFrames)
+      {
+        Add(Scene3D::MotionPropertyIndex::New(animatedProperty.mNodeName, animatedProperty.mPropertyName), Scene3D::MotionValue::New(animatedProperty.mKeyFrames));
+      }
+    }
+
+    // Reset task before emit load competed signal.
+    mMotionDataLoadTask.Reset();
+    {
+      Scene3D::MotionData handle(this); ///< Keep handle for lifecycle.
+      LoadCompletedSignal().Emit(handle);
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-data-impl.h b/dali-scene3d/internal/model-motion/motion-data-impl.h
new file mode 100644 (file)
index 0000000..7b5316a
--- /dev/null
@@ -0,0 +1,192 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_DATA_IMPL_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_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/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+#include <dali/public-api/common/vector-wrapper.h>
+#include <utility> ///< for std::pair
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-data-load-task.h>
+#include <dali-scene3d/public-api/loader/animation-definition.h>
+#include <dali-scene3d/public-api/model-motion/motion-data.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+using MotionDataPtr = IntrusivePtr<MotionData>;
+
+/**
+ * @brief Internal data for Scene3D::MotionData.
+ */
+class MotionData : public BaseObject
+{
+public: // Creation & Destruction
+  /**
+   * @brief Create a new MotionData object.
+   * @return A smart-pointer to the newly allocated MotionData.
+   */
+  static MotionDataPtr New();
+
+protected:
+  /**
+   * @brief Construct a new MotionData.
+   */
+  MotionData();
+
+  /**
+   * @brief Second-phase constructor.
+   */
+  void Initialize();
+
+  /**
+   * @brief Virtual destructor.
+   */
+  virtual ~MotionData();
+
+public: // Public Method
+  /**
+   * @copydoc Dali::Scene3D::MotionData::GetMotionCount()
+   */
+  uint32_t GetMotionCount() const;
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::GetIndex()
+   */
+  Scene3D::MotionIndex GetIndex(uint32_t index) const;
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::GetValue()
+   */
+  Scene3D::MotionValue GetValue(uint32_t index) const;
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::Add()
+   */
+  void Add(Scene3D::MotionIndex index, Scene3D::MotionValue value);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::Clear()
+   */
+  void Clear();
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::SetDuration()
+   */
+  void SetDuration(float durationSeconds);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::GetDuration()
+   */
+  float GetDuration() const;
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::LoadBvh()
+   */
+  void LoadBvh(const std::string& path, const Vector3& scale = Vector3::ONE, bool synchronousLoad = false);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::LoadBvhFromBuffer()
+   */
+  void LoadBvhFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, const Vector3& scale = Vector3::ONE, bool synchronousLoad = false);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::LoadFacialAnimation()
+   */
+  void LoadFacialAnimation(const std::string& url, bool synchronousLoad = false);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionData::LoadFacialAnimationFromBuffer()
+   */
+  void LoadFacialAnimationFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, bool synchronousLoad = false);
+
+public:
+  /**
+   * @copydoc Dali::Scene3D::MotionData::LoadCompletedSignal()
+   */
+  Scene3D::MotionData::LoadCompletedSignalType& LoadCompletedSignal()
+  {
+    return mLoadCompletedSignal;
+  }
+
+private:
+  /**
+   * @brief Request motion data load task process.
+   *
+   * @param[in] synchronousLoad True if we want to load result synchronously.
+   */
+  void RequestMotionDataLoad(bool synchronousLoad);
+
+  /**
+   * @brief Cancel requested motion data load task process.
+   */
+  void CancelMotionDataLoad();
+
+private:
+  /**
+   * @brief Called when async load task completed.
+   *
+   * @param[in] task Completed tasks
+   */
+  void OnLoadCompleted(MotionDataLoadTaskPtr task);
+
+private:
+  // Asynchronous loading variable
+  MotionDataLoadTaskPtr                        mMotionDataLoadTask{nullptr};
+  Scene3D::MotionData::LoadCompletedSignalType mLoadCompletedSignal;
+
+  std::vector<std::pair<Scene3D::MotionIndex, Scene3D::MotionValue>> mMotions{};
+
+  float mDurationSeconds{0.0f}; ///< Duration of animation if we generate this motion data as Dali::Animation.
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::MotionData& GetImplementation(Dali::Scene3D::MotionData& motionData)
+{
+  DALI_ASSERT_ALWAYS(motionData && "MotionData handle is empty");
+
+  BaseObject& handle = motionData.GetBaseObject();
+
+  return static_cast<Internal::MotionData&>(handle);
+}
+
+inline const Internal::MotionData& GetImplementation(const Dali::Scene3D::MotionData& motionData)
+{
+  DALI_ASSERT_ALWAYS(motionData && "MotionData handle is empty");
+
+  const BaseObject& handle = motionData.GetBaseObject();
+
+  return static_cast<const Internal::MotionData&>(handle);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_DATA_IMPL_H
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-data-load-task.cpp b/dali-scene3d/internal/model-motion/motion-data-load-task.cpp
new file mode 100644 (file)
index 0000000..7c6d95e
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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-motion/motion-data-load-task.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/bvh-loader.h>
+#include <dali-scene3d/public-api/loader/facial-animation-loader.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+MotionDataLoadTask::MotionDataLoadTask(const std::string& path, const Vector3& scale, CallbackBase* callback)
+: AsyncTask(callback),
+  mFileUrl(path),
+  mRawBuffer(nullptr),
+  mRawBufferLength(0),
+  mScale(scale),
+  mAnimationDefinition{},
+  mLoadMethod(MotionDataLoadTask::LoadMethod::BVH_FILE)
+{
+}
+
+MotionDataLoadTask::MotionDataLoadTask(const uint8_t* rawBuffer, int rawBufferLength, const Vector3& scale, CallbackBase* callback)
+: AsyncTask(callback),
+  mFileUrl(),
+  mRawBuffer(nullptr),
+  mRawBufferLength(rawBufferLength),
+  mScale(scale),
+  mAnimationDefinition{},
+  mLoadMethod(MotionDataLoadTask::LoadMethod::BVH_BUFFER)
+{
+  // To keep life of raw buffer, let us copy data now.
+  mRawBuffer = new uint8_t[mRawBufferLength];
+  memcpy(mRawBuffer, rawBuffer, sizeof(uint8_t) * mRawBufferLength);
+}
+
+MotionDataLoadTask::MotionDataLoadTask(const std::string& url, CallbackBase* callback)
+: AsyncTask(callback),
+  mFileUrl(url),
+  mRawBuffer(nullptr),
+  mRawBufferLength(0),
+  mScale(),
+  mAnimationDefinition{},
+  mLoadMethod(MotionDataLoadTask::LoadMethod::FACIAL_FILE)
+{
+}
+
+MotionDataLoadTask::MotionDataLoadTask(const uint8_t* rawBuffer, int rawBufferLength, CallbackBase* callback)
+: AsyncTask(callback),
+  mFileUrl(),
+  mRawBuffer(nullptr),
+  mRawBufferLength(rawBufferLength),
+  mScale(),
+  mAnimationDefinition{},
+  mLoadMethod(MotionDataLoadTask::LoadMethod::FACIAL_BUFFER)
+{
+  // To keep life of raw buffer, let us copy data now.
+  mRawBuffer = new uint8_t[mRawBufferLength];
+  memcpy(mRawBuffer, rawBuffer, sizeof(uint8_t) * mRawBufferLength);
+}
+
+MotionDataLoadTask::~MotionDataLoadTask()
+{
+  if(mRawBuffer)
+  {
+    delete[] mRawBuffer;
+  }
+}
+
+void MotionDataLoadTask::Process()
+{
+  switch(mLoadMethod)
+  {
+    case LoadMethod::BVH_FILE:
+    {
+      mAnimationDefinition = std::move(Loader::LoadBvh(mFileUrl, "LoadedBvhMotionData", mScale));
+      break;
+    }
+    case LoadMethod::BVH_BUFFER:
+    {
+      mAnimationDefinition = std::move(Loader::LoadBvhFromBuffer(mRawBuffer, mRawBufferLength, "LoadedBvhMotionData", mScale));
+      break;
+    }
+    case LoadMethod::FACIAL_FILE:
+    {
+      mAnimationDefinition = std::move(Loader::LoadFacialAnimation(mFileUrl));
+      break;
+    }
+    case LoadMethod::FACIAL_BUFFER:
+    {
+      mAnimationDefinition = std::move(Loader::LoadFacialAnimationFromBuffer(mRawBuffer, mRawBufferLength));
+      break;
+    }
+  }
+}
+
+bool MotionDataLoadTask::IsReady()
+{
+  return true;
+}
+
+const Scene3D::Loader::AnimationDefinition& MotionDataLoadTask::GetAnimationDefinition() const
+{
+  return mAnimationDefinition;
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-data-load-task.h b/dali-scene3d/internal/model-motion/motion-data-load-task.h
new file mode 100644 (file)
index 0000000..89e9f21
--- /dev/null
@@ -0,0 +1,115 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_DATA_LOAD_TASK_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_DATA_LOAD_TASK_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/adaptor-framework/async-task-manager.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/animation-definition.h>
+#include <dali-scene3d/public-api/model-motion/motion-data.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+class MotionDataLoadTask;
+typedef IntrusivePtr<MotionDataLoadTask> MotionDataLoadTaskPtr;
+
+/**
+ * @brief AsyncTask for load MotionData from various type.
+ * After load finished, it will keep result as Loader::AnimationDefinition.
+ */
+class MotionDataLoadTask : public AsyncTask
+{
+public:
+  enum class LoadMethod
+  {
+    BVH_FILE,
+    BVH_BUFFER,
+    FACIAL_FILE,
+    FACIAL_BUFFER,
+  };
+
+public:
+  /**
+   * Constructor for load bvh from file.
+   */
+  MotionDataLoadTask(const std::string& path, const Vector3& scale, CallbackBase* callback);
+
+  /**
+   * Constructor for load bvh from buffer.
+   */
+  MotionDataLoadTask(const uint8_t* rawBuffer, int rawBufferLength, const Vector3& scale, CallbackBase* callback);
+
+  /**
+   * Constructor for load facial from file.
+   */
+  MotionDataLoadTask(const std::string& url, CallbackBase* callback);
+
+  /**
+   * Constructor for load facial from buffer.
+   */
+  MotionDataLoadTask(const uint8_t* rawBuffer, int rawBufferLength, CallbackBase* callback);
+
+  /**
+   * Destructor.
+   */
+  ~MotionDataLoadTask();
+
+  /**
+   * Process the task
+   */
+  void Process() override;
+
+  /**
+   * Whether the task is ready to process.
+   * @return True if the task is ready to process.
+   */
+  bool IsReady() override;
+
+public:
+  const Scene3D::Loader::AnimationDefinition& GetAnimationDefinition() const;
+
+private:
+  // Undefined
+  MotionDataLoadTask(const MotionDataLoadTask& task) = delete;
+
+  // Undefined
+  MotionDataLoadTask& operator=(const MotionDataLoadTask& task) = delete;
+
+private:
+  std::string mFileUrl;
+  uint8_t*    mRawBuffer;
+  int         mRawBufferLength;
+  Vector3     mScale;
+
+  Scene3D::Loader::AnimationDefinition mAnimationDefinition;
+  LoadMethod                           mLoadMethod;
+};
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_DATA_LOAD_TASK_H
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.cpp b/dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.cpp
new file mode 100644 (file)
index 0000000..3848d04
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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-motion/motion-index/blend-shape-index-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/blend-shape-details.h> ///< For BlendShapes::WEIGHTS_UNIFORM
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Creates control through type registry
+ */
+BaseHandle Create()
+{
+  return Scene3D::BlendShapeIndex::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::BlendShapeIndex, Dali::BaseHandle, Create);
+DALI_TYPE_REGISTRATION_END()
+
+std::string GetBlendShapePropertyNameFromIndex(int index)
+{
+  if(index >= 0)
+  {
+    char weightNameBuffer[32];
+
+    // Get return value of snprintf to avoid SVACE.
+    [[maybe_unused]] auto prefixSize = snprintf(weightNameBuffer, sizeof(weightNameBuffer), "%s[%d]", Loader::BlendShapes::WEIGHTS_UNIFORM, index);
+
+    return weightNameBuffer;
+  }
+  return "";
+}
+
+} // namespace
+
+BlendShapeIndexPtr BlendShapeIndex::New()
+{
+  BlendShapeIndexPtr blendShapeIndex = new BlendShapeIndex();
+
+  blendShapeIndex->Initialize();
+
+  return blendShapeIndex;
+}
+
+BlendShapeIndex::BlendShapeIndex()
+{
+}
+
+BlendShapeIndex::~BlendShapeIndex()
+{
+}
+
+void BlendShapeIndex::Initialize()
+{
+}
+
+void BlendShapeIndex::SetBlendShapeId(Property::Key blendShapeId)
+{
+  mBlendShapeId = blendShapeId;
+}
+
+Property::Key BlendShapeIndex::GetBlendShapeId() const
+{
+  return mBlendShapeId;
+}
+
+std::string BlendShapeIndex::GetPropertyName(Scene3D::ModelNode node)
+{
+  if(mBlendShapeId.type == Property::Key::Type::INDEX)
+  {
+    if(mBlendShapeId.indexKey != Property::INVALID_INDEX)
+    {
+      return GetBlendShapePropertyNameFromIndex(mBlendShapeId.indexKey);
+    }
+  }
+  else if(mBlendShapeId.type == Property::Key::Type::STRING)
+  {
+    if(node)
+    {
+      auto index = node.GetBlendShapeIndexByName(mBlendShapeId.stringKey);
+      if(index != Scene3D::Loader::BlendShapes::INVALID_INDEX)
+      {
+        return GetBlendShapePropertyNameFromIndex(index);
+      }
+    }
+  }
+  return "";
+}
+
+Property::Index BlendShapeIndex::GetPropertyIndex(Scene3D::ModelNode node)
+{
+  // Not surport now
+  return Property::INVALID_INDEX;
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.h b/dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.h
new file mode 100644 (file)
index 0000000..42a3b35
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_BLEND_SHAPE_INDEX_IMPL_H
+#define DALI_SCENE3D_MODEL_MOTION_BLEND_SHAPE_INDEX_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/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+using BlendShapeIndexPtr = IntrusivePtr<BlendShapeIndex>;
+
+/**
+ * @brief Internal data for Scene3D::BlendShapeIndex.
+ */
+class BlendShapeIndex : public MotionIndex
+{
+public: // Creation & Destruction
+  /**
+   * @brief Create a new BlendShapeIndex object.
+   * @return A smart-pointer to the newly allocated BlendShapeIndex.
+   */
+  static BlendShapeIndexPtr New();
+
+protected:
+  /**
+   * @brief Construct a new BlendShapeIndex.
+   */
+  BlendShapeIndex();
+
+  /**
+   * @brief Second-phase constructor.
+   */
+  void Initialize();
+
+  /**
+   * @brief Virtual destructor.
+   */
+  virtual ~BlendShapeIndex();
+
+public: // Public Method
+  /**
+   * @copydoc Dali::Scene3D::BlendShapeIndex::SetBlendShapeId()
+   */
+  void SetBlendShapeId(Property::Key blendShapeId);
+
+  /**
+   * @copydoc Dali::Scene3D::BlendShapeIndex::GetBlendShapeId()
+   */
+  Property::Key GetBlendShapeId() const;
+
+public: // MotionIndex Override Method
+  /**
+   * @copydoc Dali::Scene3D::Internal::MotionIndex::GetPropertyName()
+   */
+  std::string GetPropertyName(Scene3D::ModelNode node = Scene3D::ModelNode()) override;
+
+  /**
+   * @copydoc Dali::Scene3D::Internal::MotionIndex::GetPropertyIndex()
+   */
+  Property::Index GetPropertyIndex(Scene3D::ModelNode node = Scene3D::ModelNode()) override;
+
+protected:
+  Property::Key mBlendShapeId{Property::INVALID_KEY}; ///< The id of blend shape
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::BlendShapeIndex& GetImplementation(Dali::Scene3D::BlendShapeIndex& blendShapeIndex)
+{
+  DALI_ASSERT_ALWAYS(blendShapeIndex && "BlendShapeIndex handle is empty");
+
+  BaseObject& handle = blendShapeIndex.GetBaseObject();
+
+  return static_cast<Internal::BlendShapeIndex&>(handle);
+}
+
+inline const Internal::BlendShapeIndex& GetImplementation(const Dali::Scene3D::BlendShapeIndex& blendShapeIndex)
+{
+  DALI_ASSERT_ALWAYS(blendShapeIndex && "BlendShapeIndex handle is empty");
+
+  const BaseObject& handle = blendShapeIndex.GetBaseObject();
+
+  return static_cast<const Internal::BlendShapeIndex&>(handle);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_BLEND_SHAPE_INDEX_IMPL_H
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-index/motion-index-impl.cpp b/dali-scene3d/internal/model-motion/motion-index/motion-index-impl.cpp
new file mode 100644 (file)
index 0000000..2482c30
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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-motion/motion-index/motion-index-impl.h>
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+} // unnamed namespace
+
+MotionIndex::MotionIndex()
+{
+}
+
+MotionIndex::~MotionIndex()
+{
+}
+
+void MotionIndex::SetModelNodeId(Property::Key modelNodeId)
+{
+  mModelNodeId = modelNodeId;
+}
+
+Property::Key MotionIndex::GetModelNodeId() const
+{
+  return mModelNodeId;
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h b/dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h
new file mode 100644 (file)
index 0000000..8ca93a6
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_INDEX_IMPL_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_INDEX_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/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+using MotionIndexPtr = IntrusivePtr<MotionIndex>;
+
+/**
+ * @brief Internal abstract data for Scene3D::MotionIndex.
+ * The drived class can implemet there own GetPropertyIndex() and GetPropertyName() API.
+ */
+class MotionIndex : public BaseObject
+{
+protected:
+  /**
+   * @brief Construct a new MotionIndex.
+   */
+  MotionIndex();
+
+  /**
+   * @brief Virtual destructor.
+   */
+  virtual ~MotionIndex();
+
+public: // Public Method
+  /**
+   * @copydoc Dali::Scene3D::MotionIndex::SetModelNodeId()
+   */
+  void SetModelNodeId(Property::Key modelNodeId);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionIndex::GetModelNodeId()
+   */
+  Property::Key GetModelNodeId() const;
+
+public: // Virtual Method
+  /**
+   * @copydoc Dali::Scene3D::MotionIndex::GetPropertyName()
+   */
+  virtual std::string GetPropertyName(Scene3D::ModelNode node = Scene3D::ModelNode()) = 0;
+
+  /**
+   * @copydoc Dali::Scene3D::MotionIndex::GetPropertyIndex()
+   */
+  virtual Property::Index GetPropertyIndex(Scene3D::ModelNode node = Scene3D::ModelNode()) = 0;
+
+protected:
+  Property::Key mModelNodeId{Property::INVALID_KEY}; ///< The id of model node
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::MotionIndex& GetImplementation(Dali::Scene3D::MotionIndex& motionIndex)
+{
+  DALI_ASSERT_ALWAYS(motionIndex && "MotionIndex handle is empty");
+
+  BaseObject& handle = motionIndex.GetBaseObject();
+
+  return static_cast<Internal::MotionIndex&>(handle);
+}
+
+inline const Internal::MotionIndex& GetImplementation(const Dali::Scene3D::MotionIndex& motionIndex)
+{
+  DALI_ASSERT_ALWAYS(motionIndex && "MotionIndex handle is empty");
+
+  const BaseObject& handle = motionIndex.GetBaseObject();
+
+  return static_cast<const Internal::MotionIndex&>(handle);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_INDEX_IMPL_H
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.cpp b/dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.cpp
new file mode 100644 (file)
index 0000000..3bfe3a5
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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-motion/motion-index/motion-property-index-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Creates control through type registry
+ */
+BaseHandle Create()
+{
+  return Scene3D::MotionPropertyIndex::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::MotionPropertyIndex, Dali::BaseHandle, Create);
+DALI_TYPE_REGISTRATION_END()
+
+} // namespace
+
+MotionPropertyIndexPtr MotionPropertyIndex::New()
+{
+  MotionPropertyIndexPtr motionPropertyIndex = new MotionPropertyIndex();
+
+  motionPropertyIndex->Initialize();
+
+  return motionPropertyIndex;
+}
+
+MotionPropertyIndex::MotionPropertyIndex()
+{
+}
+
+MotionPropertyIndex::~MotionPropertyIndex()
+{
+}
+
+void MotionPropertyIndex::Initialize()
+{
+}
+
+void MotionPropertyIndex::SetPropertyId(Property::Key propertyId)
+{
+  mPropertyId = propertyId;
+}
+
+Property::Key MotionPropertyIndex::GetPropertyId() const
+{
+  return mPropertyId;
+}
+
+std::string MotionPropertyIndex::GetPropertyName(Scene3D::ModelNode node)
+{
+  if(mPropertyId.type == Property::Key::Type::STRING)
+  {
+    return mPropertyId.stringKey;
+  }
+  return "";
+}
+
+Property::Index MotionPropertyIndex::GetPropertyIndex(Scene3D::ModelNode node)
+{
+  if(mPropertyId.type == Property::Key::Type::INDEX)
+  {
+    return mPropertyId.indexKey;
+  }
+  return Property::INVALID_INDEX;
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.h b/dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.h
new file mode 100644 (file)
index 0000000..081dd97
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_PROPERTY_INDEX_IMPL_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_PROPERTY_INDEX_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/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+using MotionPropertyIndexPtr = IntrusivePtr<MotionPropertyIndex>;
+
+/**
+ * @brief Internal data for Scene3D::MotionPropertyIndex.
+ */
+class MotionPropertyIndex : public MotionIndex
+{
+public: // Creation & Destruction
+  /**
+   * @brief Create a new MotionPropertyIndex object.
+   * @return A smart-pointer to the newly allocated MotionPropertyIndex.
+   */
+  static MotionPropertyIndexPtr New();
+
+protected:
+  /**
+   * @brief Construct a new MotionPropertyIndex.
+   */
+  MotionPropertyIndex();
+
+  /**
+   * @brief Second-phase constructor.
+   */
+  void Initialize();
+
+  /**
+   * @brief Virtual destructor.
+   */
+  virtual ~MotionPropertyIndex();
+
+public: // Public Method
+  /**
+   * @copydoc Dali::Scene3D::MotionPropertyIndex::SetPropertyId()
+   */
+  void SetPropertyId(Property::Key propertyId);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionPropertyIndex::GetPropertyId()
+   */
+  Property::Key GetPropertyId() const;
+
+public: // MotionIndex Override Method
+  /**
+   * @copydoc Dali::Scene3D::Internal::MotionIndex::GetPropertyName()
+   */
+  std::string GetPropertyName(Scene3D::ModelNode node = Scene3D::ModelNode()) override;
+
+  /**
+   * @copydoc Dali::Scene3D::Internal::MotionIndex::GetPropertyIndex()
+   */
+  Property::Index GetPropertyIndex(Scene3D::ModelNode node = Scene3D::ModelNode()) override;
+
+protected:
+  Property::Key mPropertyId{Property::INVALID_KEY}; ///< The id of blend shape
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::MotionPropertyIndex& GetImplementation(Dali::Scene3D::MotionPropertyIndex& motionPropertyIndex)
+{
+  DALI_ASSERT_ALWAYS(motionPropertyIndex && "MotionPropertyIndex handle is empty");
+
+  BaseObject& handle = motionPropertyIndex.GetBaseObject();
+
+  return static_cast<Internal::MotionPropertyIndex&>(handle);
+}
+
+inline const Internal::MotionPropertyIndex& GetImplementation(const Dali::Scene3D::MotionPropertyIndex& motionPropertyIndex)
+{
+  DALI_ASSERT_ALWAYS(motionPropertyIndex && "MotionPropertyIndex handle is empty");
+
+  const BaseObject& handle = motionPropertyIndex.GetBaseObject();
+
+  return static_cast<const Internal::MotionPropertyIndex&>(handle);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_PROPERTY_INDEX_IMPL_H
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.cpp b/dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.cpp
new file mode 100644 (file)
index 0000000..e3babc8
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * 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-motion/motion-index/motion-transform-index-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
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Creates control through type registry
+ */
+BaseHandle Create()
+{
+  return Scene3D::MotionTransformIndex::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::MotionTransformIndex, Dali::BaseHandle, Create);
+DALI_TYPE_REGISTRATION_END()
+} // namespace
+
+MotionTransformIndexPtr MotionTransformIndex::New()
+{
+  MotionTransformIndexPtr motionTransformIndex = new MotionTransformIndex();
+
+  motionTransformIndex->Initialize();
+
+  return motionTransformIndex;
+}
+
+MotionTransformIndex::MotionTransformIndex()
+{
+}
+
+MotionTransformIndex::~MotionTransformIndex()
+{
+}
+
+void MotionTransformIndex::Initialize()
+{
+}
+
+void MotionTransformIndex::SetTransformType(Scene3D::MotionTransformIndex::TransformType type)
+{
+  mTransformType = type;
+}
+
+Scene3D::MotionTransformIndex::TransformType MotionTransformIndex::GetTransformType() const
+{
+  return mTransformType;
+}
+
+std::string MotionTransformIndex::GetPropertyName(Scene3D::ModelNode node)
+{
+  using TransformType = Scene3D::MotionTransformIndex::TransformType;
+
+  switch(mTransformType)
+  {
+    case TransformType::POSITION:
+    {
+      return "position";
+    }
+    case TransformType::POSITION_X:
+    {
+      return "positionX";
+    }
+    case TransformType::POSITION_Y:
+    {
+      return "positionY";
+    }
+    case TransformType::POSITION_Z:
+    {
+      return "positionZ";
+    }
+    case TransformType::ORIENTATION:
+    {
+      return "orientation";
+    }
+    case TransformType::SCALE:
+    {
+      return "scale";
+    }
+    case TransformType::SCALE_X:
+    {
+      return "scaleX";
+    }
+    case TransformType::SCALE_Y:
+    {
+      return "scaleY";
+    }
+    case TransformType::SCALE_Z:
+    {
+      return "scaleZ";
+    }
+    default:
+    {
+      DALI_LOG_ERROR("Invalid transform type used\n");
+      return "";
+    }
+  }
+}
+
+Property::Index MotionTransformIndex::GetPropertyIndex(Scene3D::ModelNode node)
+{
+  using TransformType = Scene3D::MotionTransformIndex::TransformType;
+
+  switch(mTransformType)
+  {
+    case TransformType::POSITION:
+    {
+      return Dali::Actor::Property::POSITION;
+    }
+    case TransformType::POSITION_X:
+    {
+      return Dali::Actor::Property::POSITION_X;
+    }
+    case TransformType::POSITION_Y:
+    {
+      return Dali::Actor::Property::POSITION_Y;
+    }
+    case TransformType::POSITION_Z:
+    {
+      return Dali::Actor::Property::POSITION_Z;
+    }
+    case TransformType::ORIENTATION:
+    {
+      return Dali::Actor::Property::ORIENTATION;
+    }
+    case TransformType::SCALE:
+    {
+      return Dali::Actor::Property::SCALE;
+    }
+    case TransformType::SCALE_X:
+    {
+      return Dali::Actor::Property::SCALE_X;
+    }
+    case TransformType::SCALE_Y:
+    {
+      return Dali::Actor::Property::SCALE_Y;
+    }
+    case TransformType::SCALE_Z:
+    {
+      return Dali::Actor::Property::SCALE_Z;
+    }
+    default:
+    {
+      DALI_LOG_ERROR("Invalid transform type used\n");
+      return Property::INVALID_INDEX;
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.h b/dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.h
new file mode 100644 (file)
index 0000000..72dc345
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_TRANSFORM_INDEX_IMPL_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_TRANSFORM_INDEX_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/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+using MotionTransformIndexPtr = IntrusivePtr<MotionTransformIndex>;
+
+/**
+ * @brief Internal data for Scene3D::MotionTransformIndex.
+ */
+class MotionTransformIndex : public MotionIndex
+{
+public: // Creation & Destruction
+  /**
+   * @brief Create a new MotionTransformIndex object.
+   * @return A smart-pointer to the newly allocated MotionTransformIndex.
+   */
+  static MotionTransformIndexPtr New();
+
+protected:
+  /**
+   * @brief Construct a new MotionTransformIndex.
+   */
+  MotionTransformIndex();
+
+  /**
+   * @brief Second-phase constructor.
+   */
+  void Initialize();
+
+  /**
+   * @brief Virtual destructor.
+   */
+  virtual ~MotionTransformIndex();
+
+public: // Public Method
+  /**
+   * @copydoc Dali::Scene3D::MotionTransformIndex::SetTransformType()
+   */
+  void SetTransformType(Scene3D::MotionTransformIndex::TransformType type);
+
+  /**
+   * @copydoc Dali::Scene3D::BlendShapeIndex::GetTransformType()
+   */
+  Scene3D::MotionTransformIndex::TransformType GetTransformType() const;
+
+public: // MotionIndex Override Method
+  /**
+   * @copydoc Dali::Scene3D::Internal::MotionIndex::GetPropertyName()
+   */
+  std::string GetPropertyName(Scene3D::ModelNode node = Scene3D::ModelNode()) override;
+
+  /**
+   * @copydoc Dali::Scene3D::Internal::MotionIndex::GetPropertyIndex()
+   */
+  Property::Index GetPropertyIndex(Scene3D::ModelNode node = Scene3D::ModelNode()) override;
+
+protected:
+  Scene3D::MotionTransformIndex::TransformType mTransformType{Scene3D::MotionTransformIndex::TransformType::INVALID}; ///< The type of transform
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::MotionTransformIndex& GetImplementation(Dali::Scene3D::MotionTransformIndex& motionTransformIndex)
+{
+  DALI_ASSERT_ALWAYS(motionTransformIndex && "MotionTransformIndex handle is empty");
+
+  BaseObject& handle = motionTransformIndex.GetBaseObject();
+
+  return static_cast<Internal::MotionTransformIndex&>(handle);
+}
+
+inline const Internal::MotionTransformIndex& GetImplementation(const Dali::Scene3D::MotionTransformIndex& motionTransformIndex)
+{
+  DALI_ASSERT_ALWAYS(motionTransformIndex && "MotionTransformIndex handle is empty");
+
+  const BaseObject& handle = motionTransformIndex.GetBaseObject();
+
+  return static_cast<const Internal::MotionTransformIndex&>(handle);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_TRANSFORM_INDEX_IMPL_H
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-value-impl.cpp b/dali-scene3d/internal/model-motion/motion-value-impl.cpp
new file mode 100644 (file)
index 0000000..d8189d1
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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-motion/motion-value-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/animation/key-frames-devel.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Creates control through type registry
+ */
+BaseHandle Create()
+{
+  return Scene3D::MotionValue::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::MotionValue, Dali::BaseHandle, Create);
+DALI_TYPE_REGISTRATION_END()
+
+} // unnamed namespace
+
+MotionValuePtr MotionValue::New()
+{
+  MotionValuePtr motionValue = new MotionValue();
+
+  motionValue->Initialize();
+
+  return motionValue;
+}
+
+MotionValue::MotionValue()
+{
+}
+
+MotionValue::~MotionValue()
+{
+}
+
+void MotionValue::Initialize()
+{
+}
+
+// Public Method
+
+Scene3D::MotionValue::ValueType MotionValue::GetValueType() const
+{
+  return mType;
+}
+
+void MotionValue::SetValue(Property::Value propertyValue)
+{
+  mType = Scene3D::MotionValue::ValueType::PROPERTY_VALUE;
+
+  mKeyFrames.Reset();
+  mPropertyValue = propertyValue;
+}
+
+void MotionValue::SetValue(Dali::KeyFrames keyFrames)
+{
+  mType = Scene3D::MotionValue::ValueType::KEY_FRAMES;
+
+  mKeyFrames     = keyFrames;
+  mPropertyValue = Property::Value();
+}
+
+void MotionValue::Clear()
+{
+  mType = Scene3D::MotionValue::ValueType::INVALID;
+
+  mKeyFrames.Reset();
+  mPropertyValue = Property::Value();
+}
+
+Property::Value MotionValue::GetPropertyValue() const
+{
+  if(mType == Scene3D::MotionValue::ValueType::PROPERTY_VALUE)
+  {
+    return mPropertyValue;
+  }
+  else if(mType == Scene3D::MotionValue::ValueType::KEY_FRAMES)
+  {
+    // Get last value of keyframes
+    auto keyFrameCount = DevelKeyFrames::GetKeyFrameCount(mKeyFrames);
+    if(keyFrameCount > 0u)
+    {
+      float           dummyProgress;
+      Property::Value propertyValue;
+      DevelKeyFrames::GetKeyFrame(mKeyFrames, keyFrameCount - 1u, dummyProgress, propertyValue);
+
+      return propertyValue;
+    }
+  }
+  return Property::Value();
+}
+
+KeyFrames MotionValue::GetKeyFrames() const
+{
+  if(mType == Scene3D::MotionValue::ValueType::KEY_FRAMES)
+  {
+    return mKeyFrames;
+  }
+  else if(mType == Scene3D::MotionValue::ValueType::PROPERTY_VALUE)
+  {
+    // Generate stable keyframe animation here.
+    // TODO : Should we check property value is animatable type or not?
+    KeyFrames keyFrames = KeyFrames::New();
+    keyFrames.Add(0.0f, mPropertyValue);
+    keyFrames.Add(1.0f, mPropertyValue);
+    return keyFrames;
+  }
+  return Dali::KeyFrames();
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/internal/model-motion/motion-value-impl.h b/dali-scene3d/internal/model-motion/motion-value-impl.h
new file mode 100644 (file)
index 0000000..b5bf343
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_VALUE_IMPL_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_VALUE_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/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-motion/motion-value.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+using MotionValuePtr = IntrusivePtr<MotionValue>;
+
+/**
+ * @brief Internal data for Scene3D::MotionValue.
+ */
+class MotionValue : public BaseObject
+{
+public: // Creation & Destruction
+  /**
+   * @brief Create a new MotionValue object.
+   * @return A smart-pointer to the newly allocated MotionValue.
+   */
+  static MotionValuePtr New();
+
+protected:
+  /**
+   * @brief Construct a new MotionValue.
+   */
+  MotionValue();
+
+  /**
+   * @brief Second-phase constructor.
+   */
+  void Initialize();
+
+  /**
+   * @brief Virtual destructor.
+   */
+  virtual ~MotionValue();
+
+public: // Public Method
+  /**
+   * @copydoc Dali::Scene3D::MotionValue::GetValueType()
+   */
+  Scene3D::MotionValue::ValueType GetValueType() const;
+
+  /**
+   * @copydoc Dali::Scene3D::MotionValue::SetValue()
+   */
+  void SetValue(Property::Value propertyValue);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionValue::SetValue()
+   */
+  void SetValue(Dali::KeyFrames keyFrames);
+
+  /**
+   * @copydoc Dali::Scene3D::MotionValue::Clear()
+   */
+  void Clear();
+
+  /**
+   * @copydoc Dali::Scene3D::MotionValue::GetPropertyValue()
+   */
+  Property::Value GetPropertyValue() const;
+
+  /**
+   * @copydoc Dali::Scene3D::MotionValue::GetKeyFrames()
+   */
+  KeyFrames GetKeyFrames() const;
+
+private:
+  Scene3D::MotionValue::ValueType mType{Scene3D::MotionValue::ValueType::INVALID};
+
+  Property::Value mPropertyValue{};
+  Dali::KeyFrames mKeyFrames{};
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::MotionValue& GetImplementation(Dali::Scene3D::MotionValue& motionValue)
+{
+  DALI_ASSERT_ALWAYS(motionValue && "MotionValue handle is empty");
+
+  BaseObject& handle = motionValue.GetBaseObject();
+
+  return static_cast<Internal::MotionValue&>(handle);
+}
+
+inline const Internal::MotionValue& GetImplementation(const Dali::Scene3D::MotionValue& motionValue)
+{
+  DALI_ASSERT_ALWAYS(motionValue && "MotionValue handle is empty");
+
+  const BaseObject& handle = motionValue.GetBaseObject();
+
+  return static_cast<const Internal::MotionValue&>(handle);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_VALUE_IMPL_H
\ No newline at end of file
index 5673d1a..a02e466 100644 (file)
@@ -158,6 +158,16 @@ void Model::RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName,
   GetImpl(*this).RetrieveModelNodesByBlendShapeName(blendShapeName, modelNodes);
 }
 
+Dali::Animation Model::GenerateMotionDataAnimation(MotionData motionData)
+{
+  return GetImpl(*this).GenerateMotionDataAnimation(motionData);
+}
+
+void Model::SetMotionData(MotionData motionData)
+{
+  GetImpl(*this).SetMotionData(motionData);
+}
+
 } // namespace Scene3D
 
 } // namespace Dali
index 75c3c7f..599eb91 100644 (file)
@@ -27,6 +27,7 @@
 // INTERNAL INCLUDES
 #include <dali-scene3d/public-api/api.h>
 #include <dali-scene3d/public-api/model-components/model-node.h>
+#include <dali-scene3d/public-api/model-motion/motion-data.h>
 
 namespace Dali
 {
@@ -345,6 +346,26 @@ public:
    */
   void RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector<ModelNode>& modelNodes) const;
 
+  /**
+   * @brief Generate specific animation of this Model by inputed MotionData.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionData the data of motion animation.
+   * @return Animation that be generated by MotionData. Or empty handle if there is no valid animation generated.
+   * @note This method should be called after Model load finished.
+   */
+  Dali::Animation GenerateMotionDataAnimation(MotionData motionData);
+
+  /**
+   * @brief Set specific values of this Model by inputed MotionData.
+   * @note If MotionValue's ValueType is ValueType::KEY_FRAMES, the last value will be set.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionData the data of motion to be set.
+   * @note This method should be called after Model load finished.
+   */
+  void SetMotionData(Scene3D::MotionData motionData);
+
 public: // Not intended for application developers
   /// @cond internal
   /**
index 43e992f..70c1f6c 100644 (file)
@@ -41,4 +41,10 @@ set(scene3d_src_files ${scene3d_src_files}
        ${scene3d_public_api_dir}/model-components/material.cpp
        ${scene3d_public_api_dir}/model-components/model-node.cpp
        ${scene3d_public_api_dir}/model-components/model-primitive.cpp
+       ${scene3d_public_api_dir}/model-motion/motion-data.cpp
+       ${scene3d_public_api_dir}/model-motion/motion-index/blend-shape-index.cpp
+       ${scene3d_public_api_dir}/model-motion/motion-index/motion-index.cpp
+       ${scene3d_public_api_dir}/model-motion/motion-index/motion-property-index.cpp
+       ${scene3d_public_api_dir}/model-motion/motion-index/motion-transform-index.cpp
+       ${scene3d_public_api_dir}/model-motion/motion-value.cpp
 )
\ No newline at end of file
index 15110c7..e357516 100644 (file)
@@ -20,7 +20,7 @@
 
 namespace Dali::Scene3D::Loader
 {
-void AnimatedProperty::Animate(Animation& anim, GetActor getActor)
+void AnimatedProperty::Animate(Animation& anim, GetActor getActor) const
 {
   if(Actor actor = getActor(*this))
   {
index 07b251f..90b8a02 100644 (file)
@@ -49,7 +49,7 @@ public: // METHODS
   /**
    * @return The Property object (of the given @a actor) whose value is being animated.
    */
-  Property GetProperty(Actor& actor)
+  Property GetProperty(Actor& actor) const
   {
     auto idx = actor.GetPropertyIndex(mPropertyName);
     return Property(actor, idx);
@@ -58,7 +58,7 @@ public: // METHODS
   /**
    * @brief The type of the Property (of the given @a actor) that is being animated.
    */
-  Property::Type GetPropertyType(Actor& actor)
+  Property::Type GetPropertyType(Actor& actor) const
   {
     auto idx = actor.GetPropertyIndex(mPropertyName);
     return actor.GetPropertyType(idx);
@@ -70,7 +70,7 @@ public: // METHODS
    *  Failing to find the actor purely means that this property will not be
    *  animated.
    */
-  void Animate(Animation& anim, GetActor getActor);
+  void Animate(Animation& anim, GetActor getActor) const;
 
 public: // DATA
   struct Value
index d35631d..d9ee5dd 100644 (file)
@@ -158,9 +158,9 @@ void AnimationDefinition::ReserveSize(uint32_t size)
   mProperties.reserve(size);
 }
 
-uint32_t AnimationDefinition::GetPropertyCount()
+uint32_t AnimationDefinition::GetPropertyCount() const
 {
-  return mProperties.size();
+  return static_cast<uint32_t>(mProperties.size());
 }
 
 void AnimationDefinition::SetProperty(uint32_t index, AnimatedProperty&& property)
@@ -177,4 +177,9 @@ AnimatedProperty& AnimationDefinition::GetPropertyAt(uint32_t index)
   return mProperties[index];
 }
 
+const AnimatedProperty& AnimationDefinition::GetPropertyAt(uint32_t index) const
+{
+  return mProperties[index];
+}
+
 } // namespace Dali::Scene3D::Loader
index 9b8393c..914dfa7 100644 (file)
@@ -173,7 +173,7 @@ public: // METHODS
    *
    * @return The count of animated properties.
    */
-  uint32_t GetPropertyCount();
+  uint32_t GetPropertyCount() const;
 
   /**
    * @brief Add a property that will be animated by this AnimationDefinition
@@ -190,6 +190,13 @@ public: // METHODS
    */
   AnimatedProperty& GetPropertyAt(uint32_t index);
 
+  /**
+   * @brief Retrieves animated property at the index
+   *
+   * @param[in] index The index of property to be retrieved.
+   */
+  const AnimatedProperty& GetPropertyAt(uint32_t index) const;
+
 private: // DATA
   std::string mName;
 
diff --git a/dali-scene3d/public-api/model-motion/motion-data.cpp b/dali-scene3d/public-api/model-motion/motion-data.cpp
new file mode 100644 (file)
index 0000000..f9418b5
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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/public-api/model-motion/motion-data.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-data-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+MotionData MotionData::New()
+{
+  Internal::MotionDataPtr internal = Internal::MotionData::New();
+
+  return MotionData(internal.Get());
+}
+
+MotionData MotionData::New(float durationSeconds)
+{
+  Internal::MotionDataPtr internal = Internal::MotionData::New();
+
+  internal->SetDuration(durationSeconds);
+
+  return MotionData(internal.Get());
+}
+
+MotionData::MotionData()
+{
+}
+
+MotionData::MotionData(const MotionData& motionData) = default;
+
+MotionData::MotionData(MotionData&& rhs) noexcept = default;
+
+MotionData::~MotionData()
+{
+}
+
+MotionData& MotionData::operator=(const MotionData& handle) = default;
+
+MotionData& MotionData::operator=(MotionData&& rhs) noexcept = default;
+
+MotionData MotionData::DownCast(BaseHandle handle)
+{
+  return MotionData(dynamic_cast<Dali::Scene3D::Internal::MotionData*>(handle.GetObjectPtr()));
+}
+
+MotionData::MotionData(Dali::Scene3D::Internal::MotionData* internal)
+: BaseHandle(internal)
+{
+}
+
+// Public Method
+
+uint32_t MotionData::GetMotionCount() const
+{
+  return GetImplementation(*this).GetMotionCount();
+}
+
+MotionIndex MotionData::GetIndex(uint32_t index) const
+{
+  return GetImplementation(*this).GetIndex(index);
+}
+
+MotionValue MotionData::GetValue(uint32_t index) const
+{
+  return GetImplementation(*this).GetValue(index);
+}
+
+void MotionData::Add(MotionIndex index, MotionValue value)
+{
+  GetImplementation(*this).Add(index, value);
+}
+
+void MotionData::Clear()
+{
+  GetImplementation(*this).Clear();
+}
+
+void MotionData::SetDuration(float durationSeconds)
+{
+  GetImplementation(*this).SetDuration(durationSeconds);
+}
+
+float MotionData::GetDuration() const
+{
+  return GetImplementation(*this).GetDuration();
+}
+
+void MotionData::LoadBvh(const std::string& path, const Vector3& scale, bool synchronousLoad)
+{
+  GetImplementation(*this).LoadBvh(path, scale, synchronousLoad);
+}
+
+void MotionData::LoadBvhFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, const Vector3& scale, bool synchronousLoad)
+{
+  GetImplementation(*this).LoadBvhFromBuffer(rawBuffer, rawBufferLength, scale, synchronousLoad);
+}
+
+void MotionData::LoadFacialAnimation(const std::string& url, bool synchronousLoad)
+{
+  GetImplementation(*this).LoadFacialAnimation(url, synchronousLoad);
+}
+
+void MotionData::LoadFacialAnimationFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, bool synchronousLoad)
+{
+  GetImplementation(*this).LoadFacialAnimationFromBuffer(rawBuffer, rawBufferLength, synchronousLoad);
+}
+
+MotionData::LoadCompletedSignalType& MotionData::LoadCompletedSignal()
+{
+  return GetImplementation(*this).LoadCompletedSignal();
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-data.h b/dali-scene3d/public-api/model-motion/motion-data.h
new file mode 100644 (file)
index 0000000..c3e3678
--- /dev/null
@@ -0,0 +1,331 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_DATA_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_DATA_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/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+#include <dali-scene3d/public-api/model-motion/motion-value.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+//Forward declarations.
+namespace Internal
+{
+class MotionData;
+} // namespace Internal
+
+/**
+ * @addtogroup dali_scene3d_model_motion_motion_data
+ * @{
+ */
+
+/**
+ * @brief List of model motion definitions.
+ * Each motion has pair of MotionIndex and MotionValue.
+ * MotionIndex is abstract class that specify the target of motion.
+ * MotionValue is target value of motion. It can be KeyFrames.
+ *
+ * We can generate list of motions by MotionIndex and MotionValue classes.
+ *
+ * @code
+ *
+ * MotionData motionData = MotionData::New(3.0f);
+ *
+ * // Make MotionIndex with MotionPropertyIndex
+ * // Make MotionValue with Dali::Property::Value
+ * motionData.Add(MotionPropertyIndex::New("nodeName", "color"), MotionValue::New(Color::RED));
+ *
+ * // Make MotionIndex with MotionTransformIndex
+ * // Make MotionValue with Dali::KeyFrames
+ * KeyFrames keyFrames = KeyFrames::New();
+ * keyFrames.Add(0.0f, 0.0f);
+ * keyFrames.Add(0.0f, 1.0f);
+ * motionData.Add(MotionTransformIndex::New("nodeName", MotionTransformIndex::TransformType::POSITION_X), MotionValue::New(keyFrames));
+ *
+ * // Make MotionIndex with BlendShapeIndex
+ * motionData.Add(BlendShapeIndex::New("nodeName", 0u), motionData.GetValue(1u));
+ *
+ * @endcode
+ *
+ * We can request to load MotionData from file or buffer asynchronously.
+ * If load completed, LoadCompetedSignal will be emmited.
+ *
+ * @code
+ *
+ * MotionData motionData = MotionData::New();
+ * motionData.LoadCompletedSignal().Connect(&OnLoadCompleted);
+ * motionData.LoadBvh("bvhFilename.bvh", Vector3::ONE);
+ *
+ * @endcode
+ *
+ * We can generate animation of Scene3D::Model from MotionData class.
+ * Or, just set values.
+ *
+ * @code
+ *
+ * // Generate animation from loaded Model
+ * Dali::Animation animation = model.GenerateMotionDataAnimation(motionData);
+ * animation.Play();
+ *
+ * // Set values from loaded Model.
+ * model2.SetMotionData(motionData);
+ *
+ * @endcode
+ * @note We don't check duplicated MotionIndex internally.
+ * @SINCE_2_2.34
+ */
+class DALI_SCENE3D_API MotionData : public Dali::BaseHandle
+{
+public:
+  /// @brief LoadCompleted signal type. @SINCE_2_2.34
+  typedef Signal<void(MotionData)> LoadCompletedSignalType;
+
+public: // Creation & Destruction
+  /**
+   * @brief Create an initialized MotionData.
+   *
+   * @SINCE_2_2.34
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionData New();
+
+  /**
+   * @brief Create an initialized MotionData with duration.
+   *
+   * @SINCE_2_2.34
+   * @param[in] durationSeconds Duration of animation as seconds.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionData New(float durationSeconds);
+
+  /**
+   * @brief Creates an uninitialized MotionData.
+   *
+   * Only derived versions can be instantiated. Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   *
+   * @SINCE_2_2.34
+   */
+  MotionData();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   *
+   * @SINCE_2_2.34
+   */
+  ~MotionData();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionData Handle to an object
+   */
+  MotionData(const MotionData& motionData);
+
+  /**
+   * @brief Move constructor
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   */
+  MotionData(MotionData&& rhs) noexcept;
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionData Handle to an object
+   * @return reference to this
+   */
+  MotionData& operator=(const MotionData& motionData);
+
+  /**
+   * @brief Move assignment
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  MotionData& operator=(MotionData&& rhs) noexcept;
+
+  /**
+   * @brief Downcasts an Object handle to MotionData.
+   *
+   * If handle points to a MotionData, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @SINCE_2_2.34
+   * @param[in] handle Handle to an object
+   * @return Handle to a MotionData or an uninitialized handle
+   */
+  static MotionData DownCast(BaseHandle handle);
+
+public: // Public Method
+  /**
+   * @brief Get the number of motions what we added
+   *
+   * @SINCE_2_2.34
+   * @return The number of motions
+   */
+  uint32_t GetMotionCount() const;
+
+  /**
+   * @brief Get MotionIndex from given index'th.
+   *
+   * @SINCE_2_2.34
+   * @param[in] index The index of motion list.
+   * @return Index of motion, or empty handle if invalid index inputed.
+   */
+  MotionIndex GetIndex(uint32_t index) const;
+
+  /**
+   * @brief Get MotionValue from given index'th.
+   *
+   * @SINCE_2_2.34
+   * @param[in] index The index of motion list.
+   * @return Value of motion, or empty handle if invalid index inputed.
+   */
+  MotionValue GetValue(uint32_t index) const;
+
+  /**
+   * @brief Append new motion.
+   * @note We don't check duplicated MotionIndex internally.
+   *
+   * @SINCE_2_2.34
+   * @param[in] index index of motion.
+   * @param[in] value value of motion.
+   */
+  void Add(MotionIndex index, MotionValue value);
+
+  /**
+   * @brief Clear all stored motion data.
+   *
+   * @SINCE_2_2.34
+   */
+  void Clear();
+
+  /**
+   * @brief Set the duration of this motion data if it be generated as Dali::Animation.
+   *
+   * @SINCE_2_2.34
+   * @param[in] durationSeconds Duration of animation as seconds.
+   */
+  void SetDuration(float durationSeconds);
+
+  /**
+   * @brief Get the duration of this motion data if it be generated as Dali::Animation.
+   *
+   * @SINCE_2_2.34
+   * @return The duration of this motion data seconds. Default is 0.0f
+   */
+  float GetDuration() const;
+
+  /**
+   * @brief Load MotionData from bvh file.
+   * It will use Dali::Scene3D::Loader::LoadBvh() internally.
+   * LoadCompleteSignal() will be emitted after load completed.
+   *
+   * @SINCE_2_2.34
+   * @param[in] path The file path.
+   * @param[in] scale The scale factor to set on the position property manually.
+   * @param[in] synchronousLoad True if we want to load result synchronously. Default is false.
+   */
+  void LoadBvh(const std::string& path, const Vector3& scale = Vector3::ONE, bool synchronousLoad = false);
+
+  /**
+   * @brief Load MotionData from bvh buffer.
+   * It will use Dali::Scene3D::Loader::LoadBvhFromBuffer() internally.
+   * LoadCompleteSignal() will be emitted after load completed.
+   *
+   * @SINCE_2_2.34
+   * @param[in] rawBuffer The bvh buffer containing the facial animation as bvh format string.
+   * @param[in] rawBufferLength The length of buffer.
+   * @param[in] scale The scale factor to set on the position property manually.
+   * @param[in] synchronousLoad True if we want to load result synchronously. Default is false.
+   */
+  void LoadBvhFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, const Vector3& scale = Vector3::ONE, bool synchronousLoad = false);
+
+  /**
+   * @brief Load MotionData from facial defined json file.
+   * It will use Dali::Scene3D::Loader::LoadFacialAnimation() internally.
+   * LoadCompleteSignal() will be emitted after load completed.
+   *
+   * @SINCE_2_2.34
+   * @param[in] url The file path.
+   * @param[in] synchronousLoad True if we want to load result synchronously. Default is false.
+   */
+  void LoadFacialAnimation(const std::string& url, bool synchronousLoad = false);
+
+  /**
+   * @brief Load MotionData from facial defined json file.
+   * It will use Dali::Scene3D::Loader::LoadFacialAnimationFromBuffer() internally.
+   * LoadCompleteSignal() will be emitted after load completed.
+   *
+   * @SINCE_2_2.34
+   * @param[in] rawBuffer The raw buffer containing the facial animation as json format string.
+   * @param[in] rawBufferLength The length of raw buffer.
+   * @param[in] synchronousLoad True if we want to load result synchronously. Default is false.
+   */
+  void LoadFacialAnimationFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, bool synchronousLoad = false);
+
+public:
+  /**
+   * @brief This signal is emitted after motion data are loaded completed.
+   * @note Signal will be emitted even if we request load synchronously.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName(MotionData motionData);
+   * @endcode
+   *
+   * @SINCE_2_2.34
+   * @return The signal to connect to.
+   */
+  LoadCompletedSignalType& LoadCompletedSignal();
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief Creates a handle using the Scene3D::Internal implementation.
+   *
+   * @param[in] implementation The MotionData implementation
+   */
+  DALI_INTERNAL MotionData(Dali::Scene3D::Internal::MotionData* implementation);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_DATA_H
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.cpp b/dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.cpp
new file mode 100644 (file)
index 0000000..549c80a
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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/public-api/model-motion/motion-index/blend-shape-index.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+BlendShapeIndex BlendShapeIndex::New()
+{
+  Internal::BlendShapeIndexPtr internal = Internal::BlendShapeIndex::New();
+
+  return BlendShapeIndex(internal.Get());
+}
+
+BlendShapeIndex BlendShapeIndex::New(Property::Key blendShapeId)
+{
+  Internal::BlendShapeIndexPtr internal = Internal::BlendShapeIndex::New();
+
+  internal->SetBlendShapeId(blendShapeId);
+
+  return BlendShapeIndex(internal.Get());
+}
+
+BlendShapeIndex BlendShapeIndex::New(Property::Key modelNodeId, Property::Key blendShapeId)
+{
+  Internal::BlendShapeIndexPtr internal = Internal::BlendShapeIndex::New();
+
+  internal->SetModelNodeId(modelNodeId);
+  internal->SetBlendShapeId(blendShapeId);
+
+  return BlendShapeIndex(internal.Get());
+}
+
+BlendShapeIndex::BlendShapeIndex()
+{
+}
+
+BlendShapeIndex::BlendShapeIndex(const BlendShapeIndex& blendShapeIndex) = default;
+
+BlendShapeIndex::BlendShapeIndex(BlendShapeIndex&& rhs) noexcept = default;
+
+BlendShapeIndex::~BlendShapeIndex()
+{
+}
+
+BlendShapeIndex& BlendShapeIndex::operator=(const BlendShapeIndex& handle) = default;
+
+BlendShapeIndex& BlendShapeIndex::operator=(BlendShapeIndex&& rhs) noexcept = default;
+
+BlendShapeIndex BlendShapeIndex::DownCast(BaseHandle handle)
+{
+  return BlendShapeIndex(dynamic_cast<Dali::Scene3D::Internal::BlendShapeIndex*>(handle.GetObjectPtr()));
+}
+
+BlendShapeIndex::BlendShapeIndex(Dali::Scene3D::Internal::BlendShapeIndex* internal)
+: MotionIndex(internal)
+{
+}
+
+// Public Method
+
+void BlendShapeIndex::SetBlendShapeId(Property::Key blendShapeId)
+{
+  GetImplementation(*this).SetBlendShapeId(blendShapeId);
+}
+
+Property::Key BlendShapeIndex::GetBlendShapeId() const
+{
+  return GetImplementation(*this).GetBlendShapeId();
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h b/dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h
new file mode 100644 (file)
index 0000000..f633a42
--- /dev/null
@@ -0,0 +1,205 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_BLEND_SHAPE_INDEX_H
+#define DALI_SCENE3D_MODEL_MOTION_BLEND_SHAPE_INDEX_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
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+//Forward declarations.
+namespace Internal
+{
+class BlendShapeIndex;
+} // namespace Internal
+
+/**
+ * @addtogroup dali_scene3d_model_motion_blend_shape_index
+ * @{
+ */
+
+/**
+ * @brief Specialized MotionIndex to control blend shape.
+ * We can control the blend shape by index (when we set BlendShapeId as IndexKey)
+ * or by name (when we set BlendShapeId as StringKey)
+ *
+ * @code
+ *
+ * BlendShapeIndex blendShapeIndex0 = BlendShapeIndex::New("nodeName", 0u);
+ * BlendShapeIndex blendShapeIndex1 = BlendShapeIndex::New("nodeName", "Target_1");
+ *
+ * // We can change the property later.
+ * BlendShapeIndex blendShapeIndex2 = BlendShapeIndex::New();
+ * blendShapeIndex2.SetModelNodeId("nodeName");
+ * blendShapeIndex2.SetBlendShapeId("Target_2");
+ *
+ * @endcode
+ *
+ * Specially, if ModelNodeId is Property::INVALID_KEY and BlendShapeId is StringKey,
+ * It will control all ModelNode that has the inputed BlendShape name.
+ *
+ * @code
+ *
+ * // If "node0" and "node1" has same BlendShape named "Smile",
+ * // blendShapeIndexAll will control both nodes.
+ * BlendShapeIndex blendShapeIndexAll = BlendShapeIndex::New("Smile");
+ *
+ * BlendShapeIndex blendShapeIndex0 = BlendShapeIndex::New("node0", "Smile");
+ * BlendShapeIndex blendShapeIndex1 = BlendShapeIndex::New("node1", "Smile");
+ *
+ * @endcode
+ *
+ * @SINCE_2_2.34
+ */
+class DALI_SCENE3D_API BlendShapeIndex : public MotionIndex
+{
+public: // Creation & Destruction
+  /**
+   * @brief Create an initialized BlendShapeIndex.
+   *
+   * @SINCE_2_2.34
+   * @return A handle to a newly allocated Dali resource
+   */
+  static BlendShapeIndex New();
+
+  /**
+   * @brief Create an initialized BlendShapeIndex with values. It will hold invalid ModelNodeId.
+   *
+   * @SINCE_2_2.34
+   * @param[in] blendShapeId The id of blend shape what this motion index looks.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static BlendShapeIndex New(Property::Key blendShapeId);
+
+  /**
+   * @brief Create an initialized BlendShapeIndex with values.
+   *
+   * @SINCE_2_2.34
+   * @param[in] modelNodeId The id of model node what this motion index looks.
+   * @param[in] blendShapeId The id of blend shape what this motion index looks.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static BlendShapeIndex New(Property::Key modelNodeId, Property::Key blendShapeId);
+
+  /**
+   * @brief Creates an uninitialized BlendShapeIndex.
+   *
+   * Only derived versions can be instantiated. Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   *
+   * @SINCE_2_2.34
+   */
+  BlendShapeIndex();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   *
+   * @SINCE_2_2.34
+   */
+  ~BlendShapeIndex();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @SINCE_2_2.34
+   * @param[in] blendShapeIndex Handle to an object
+   */
+  BlendShapeIndex(const BlendShapeIndex& blendShapeIndex);
+
+  /**
+   * @brief Move constructor
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   */
+  BlendShapeIndex(BlendShapeIndex&& rhs) noexcept;
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @SINCE_2_2.34
+   * @param[in] blendShapeIndex Handle to an object
+   * @return reference to this
+   */
+  BlendShapeIndex& operator=(const BlendShapeIndex& blendShapeIndex);
+
+  /**
+   * @brief Move assignment
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  BlendShapeIndex& operator=(BlendShapeIndex&& rhs) noexcept;
+
+  /**
+   * @brief Downcasts an Object handle to BlendShapeIndex.
+   *
+   * If handle points to a BlendShapeIndex, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @SINCE_2_2.34
+   * @param[in] handle Handle to an object
+   * @return Handle to a BlendShapeIndex or an uninitialized handle
+   */
+  static BlendShapeIndex DownCast(BaseHandle handle);
+
+public: // Public Method
+  /**
+   * @brief Set the id of BlendShape what this motion index looks.
+   *
+   * @SINCE_2_2.34
+   * @param[in] blendShapeId The blend shape id.
+   */
+  void SetBlendShapeId(Property::Key blendShapeId);
+
+  /**
+   * @brief Get the id of BlendShape what this motion index looks.
+   *
+   * @SINCE_2_2.34
+   * @return The blend shape id.
+   */
+  Property::Key GetBlendShapeId() const;
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief Creates a handle using the Scene3D::Internal implementation.
+   *
+   * @param[in] implementation The BlendShapeIndex implementation
+   */
+  DALI_INTERNAL BlendShapeIndex(Dali::Scene3D::Internal::BlendShapeIndex* implementation);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_BLEND_SHAPE_INDEX_H
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-index/motion-index.cpp b/dali-scene3d/public-api/model-motion/motion-index/motion-index.cpp
new file mode 100644 (file)
index 0000000..eaa3ad9
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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/public-api/model-motion/motion-index/motion-index.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+MotionIndex::MotionIndex()
+{
+}
+
+MotionIndex::MotionIndex(const MotionIndex& motionIndex) = default;
+
+MotionIndex::MotionIndex(MotionIndex&& rhs) noexcept = default;
+
+MotionIndex::~MotionIndex()
+{
+}
+
+MotionIndex& MotionIndex::operator=(const MotionIndex& handle) = default;
+
+MotionIndex& MotionIndex::operator=(MotionIndex&& rhs) noexcept = default;
+
+MotionIndex MotionIndex::DownCast(BaseHandle handle)
+{
+  return MotionIndex(dynamic_cast<Dali::Scene3D::Internal::MotionIndex*>(handle.GetObjectPtr()));
+}
+
+MotionIndex::MotionIndex(Dali::Scene3D::Internal::MotionIndex* internal)
+: BaseHandle(internal)
+{
+}
+
+// Public Method
+
+void MotionIndex::SetModelNodeId(Property::Key modelNodeId)
+{
+  GetImplementation(*this).SetModelNodeId(modelNodeId);
+}
+
+Property::Key MotionIndex::GetModelNodeId() const
+{
+  return GetImplementation(*this).GetModelNodeId();
+}
+
+std::string MotionIndex::GetPropertyName(ModelNode node)
+{
+  return GetImplementation(*this).GetPropertyName(node);
+}
+
+Property::Index MotionIndex::GetPropertyIndex(ModelNode node)
+{
+  return GetImplementation(*this).GetPropertyIndex(node);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-index/motion-index.h b/dali-scene3d/public-api/model-motion/motion-index/motion-index.h
new file mode 100644 (file)
index 0000000..207fe9f
--- /dev/null
@@ -0,0 +1,176 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_INDEX_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_INDEX_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/object/property-key.h>
+#include <dali/public-api/object/property.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-components/model-node.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+//Forward declarations.
+namespace Internal
+{
+class MotionIndex;
+} // namespace Internal
+
+/**
+ * @addtogroup dali_scene3d_model_motion_motion_index
+ * @{
+ */
+
+/**
+ * @brief Key of motion data to specify what ModelNode's property will be moved.
+ * MotionIndex itself is abstract classes. We need to create New from one of below classes.
+ * - BlendShapeIndex : To control blendshape.
+ * - MotionPropertyIndex : To control the property by Dali::Property.
+ * - MotionTransfromIndex : To control the transform property. Usually be used on CSharp binded API who cannot use Dali::Property directly.
+ * @todo Need to implement ModelNodeId as IndexKey. Currently, StringKey only works well.
+ *
+ * @SINCE_2_2.34
+ */
+class DALI_SCENE3D_API MotionIndex : public Dali::BaseHandle
+{
+public: // Creation & Destruction
+  /**
+   * @brief Creates an uninitialized MotionIndex.
+   *
+   * Only derived versions can be instantiated. Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   *
+   * @SINCE_2_2.34
+   */
+  MotionIndex();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   *
+   * @SINCE_2_2.34
+   */
+  ~MotionIndex();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionIndex Handle to an object
+   */
+  MotionIndex(const MotionIndex& motionIndex);
+
+  /**
+   * @brief Move constructor
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   */
+  MotionIndex(MotionIndex&& rhs) noexcept;
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionIndex Handle to an object
+   * @return reference to this
+   */
+  MotionIndex& operator=(const MotionIndex& motionIndex);
+
+  /**
+   * @brief Move assignment
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  MotionIndex& operator=(MotionIndex&& rhs) noexcept;
+
+  /**
+   * @brief Downcasts an Object handle to MotionIndex.
+   *
+   * If handle points to a MotionIndex, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @SINCE_2_2.34
+   * @param[in] handle Handle to an object
+   * @return Handle to a MotionIndex or an uninitialized handle
+   */
+  static MotionIndex DownCast(BaseHandle handle);
+
+public: // Public Method
+  /**
+   * @brief Set the id of ModelNode what this motion index looks.
+   *
+   * @SINCE_2_2.34
+   * @param[in] modelNodeId The model node id.
+   */
+  void SetModelNodeId(Property::Key modelNodeId);
+
+  /**
+   * @brief Get the id of ModelNode what this motion index looks.
+   *
+   * @SINCE_2_2.34
+   * @return The model node id.
+   */
+  Property::Key GetModelNodeId() const;
+
+  /**
+   * @brief Get the property name of this MotionIndex from given ModelNode.
+   *
+   * @SINCE_2_2.34
+   * @param[in] node The model node to get the property name.
+   * @return The name of current property.
+   */
+  std::string GetPropertyName(ModelNode node = ModelNode());
+
+  /**
+   * @brief Get the property index of this MotionIndex from given ModelNode.
+   *
+   * @SINCE_2_2.34
+   * @param[in] node The model node to get the property index.
+   * @return The index of current property.
+   */
+  Property::Index GetPropertyIndex(ModelNode node = ModelNode());
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief Creates a handle using the Scene3D::Internal implementation.
+   *
+   * @param[in] implementation The MotionIndex implementation
+   */
+  DALI_INTERNAL MotionIndex(Dali::Scene3D::Internal::MotionIndex* implementation);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_INDEX_H
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-index/motion-property-index.cpp b/dali-scene3d/public-api/model-motion/motion-index/motion-property-index.cpp
new file mode 100644 (file)
index 0000000..3dc7d76
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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/public-api/model-motion/motion-index/motion-property-index.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+MotionPropertyIndex MotionPropertyIndex::New()
+{
+  Internal::MotionPropertyIndexPtr internal = Internal::MotionPropertyIndex::New();
+
+  return MotionPropertyIndex(internal.Get());
+}
+
+MotionPropertyIndex MotionPropertyIndex::New(Property::Key modelNodeId, Property::Key propertyId)
+{
+  Internal::MotionPropertyIndexPtr internal = Internal::MotionPropertyIndex::New();
+
+  internal->SetModelNodeId(modelNodeId);
+  internal->SetPropertyId(propertyId);
+
+  return MotionPropertyIndex(internal.Get());
+}
+
+MotionPropertyIndex::MotionPropertyIndex()
+{
+}
+
+MotionPropertyIndex::MotionPropertyIndex(const MotionPropertyIndex& motionPropertyIndex) = default;
+
+MotionPropertyIndex::MotionPropertyIndex(MotionPropertyIndex&& rhs) noexcept = default;
+
+MotionPropertyIndex::~MotionPropertyIndex()
+{
+}
+
+MotionPropertyIndex& MotionPropertyIndex::operator=(const MotionPropertyIndex& handle) = default;
+
+MotionPropertyIndex& MotionPropertyIndex::operator=(MotionPropertyIndex&& rhs) noexcept = default;
+
+MotionPropertyIndex MotionPropertyIndex::DownCast(BaseHandle handle)
+{
+  return MotionPropertyIndex(dynamic_cast<Dali::Scene3D::Internal::MotionPropertyIndex*>(handle.GetObjectPtr()));
+}
+
+MotionPropertyIndex::MotionPropertyIndex(Dali::Scene3D::Internal::MotionPropertyIndex* internal)
+: MotionIndex(internal)
+{
+}
+
+// Public Method
+
+void MotionPropertyIndex::SetPropertyId(Property::Key blendShapeId)
+{
+  GetImplementation(*this).SetPropertyId(blendShapeId);
+}
+
+Property::Key MotionPropertyIndex::GetPropertyId() const
+{
+  return GetImplementation(*this).GetPropertyId();
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h b/dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h
new file mode 100644 (file)
index 0000000..8601a9c
--- /dev/null
@@ -0,0 +1,185 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_PROPERTY_INDEX_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_PROPERTY_INDEX_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
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+//Forward declarations.
+namespace Internal
+{
+class MotionPropertyIndex;
+} // namespace Internal
+
+/**
+ * @addtogroup dali_scene3d_model_motion_motion_property_index
+ * @{
+ */
+
+/**
+ * @brief Basic MotionIndex to control Dali::Property.
+ * It can control more general case.
+ *
+ * @code
+ *
+ * MotionPropertyIndex color = MotionPropertyIndex::New("nodeName", Dali::Actor::Property::COLOR);
+ *
+ * // We can change the property later.
+ * MotionPropertyIndex custom = MotionPropertyIndex::New();
+ * orientation.SetModelNodeId("nodeName");
+ * orientation.SetPropertyId("some_custom_property");
+ *
+ * // Note that all cases of MotionTransformIndex can be controled by MotionPropertyIndex
+ * // Both position0 and position1 can control the node's Position.
+ * MotionTransformIndex position0 = MotionTransformIndex::New("nodeName", MotionTransformIndex::TransformType::POSITION);
+ * MotionPropertyIndex  position1 = MotionPropertyIndex::New("nodeName", Dali::Actor::Property::POSITION);
+ *
+ * @endcode
+ *
+ * @SINCE_2_2.34
+ */
+class DALI_SCENE3D_API MotionPropertyIndex : public MotionIndex
+{
+public: // Creation & Destruction
+  /**
+   * @brief Create an initialized MotionPropertyIndex.
+   *
+   * @SINCE_2_2.34
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionPropertyIndex New();
+
+  /**
+   * @brief Create an initialized MotionPropertyIndex with values.
+   *
+   * @SINCE_2_2.34
+   * @param[in] modelNodeId The id of model node what this motion index looks.
+   * @param[in] propertyId The id of property what this motion index looks.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionPropertyIndex New(Property::Key modelNodeId, Property::Key propertyId);
+
+  /**
+   * @brief Creates an uninitialized MotionPropertyIndex.
+   *
+   * Only derived versions can be instantiated. Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   *
+   * @SINCE_2_2.34
+   */
+  MotionPropertyIndex();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   *
+   * @SINCE_2_2.34
+   */
+  ~MotionPropertyIndex();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionPropertyIndex Handle to an object
+   */
+  MotionPropertyIndex(const MotionPropertyIndex& motionPropertyIndex);
+
+  /**
+   * @brief Move constructor
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   */
+  MotionPropertyIndex(MotionPropertyIndex&& rhs) noexcept;
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionPropertyIndex Handle to an object
+   * @return reference to this
+   */
+  MotionPropertyIndex& operator=(const MotionPropertyIndex& motionPropertyIndex);
+
+  /**
+   * @brief Move assignment
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  MotionPropertyIndex& operator=(MotionPropertyIndex&& rhs) noexcept;
+
+  /**
+   * @brief Downcasts an Object handle to MotionPropertyIndex.
+   *
+   * If handle points to a MotionPropertyIndex, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @SINCE_2_2.34
+   * @param[in] handle Handle to an object
+   * @return Handle to a MotionPropertyIndex or an uninitialized handle
+   */
+  static MotionPropertyIndex DownCast(BaseHandle handle);
+
+public: // Public Method
+  /**
+   * @brief Set the id of property what this motion index looks.
+   *
+   * @SINCE_2_2.34
+   * @param[in] propertyId The property id.
+   */
+  void SetPropertyId(Property::Key propertyId);
+
+  /**
+   * @brief Get the id of property what this motion index looks.
+   *
+   * @SINCE_2_2.34
+   * @return The blend shape id.
+   */
+  Property::Key GetPropertyId() const;
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief Creates a handle using the Scene3D::Internal implementation.
+   *
+   * @param[in] implementation The MotionPropertyIndex implementation
+   */
+  DALI_INTERNAL MotionPropertyIndex(Dali::Scene3D::Internal::MotionPropertyIndex* implementation);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_PROPERTY_INDEX_H
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.cpp b/dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.cpp
new file mode 100644 (file)
index 0000000..5ea483f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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/public-api/model-motion/motion-index/motion-transform-index.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+MotionTransformIndex MotionTransformIndex::New()
+{
+  Internal::MotionTransformIndexPtr internal = Internal::MotionTransformIndex::New();
+
+  return MotionTransformIndex(internal.Get());
+}
+
+MotionTransformIndex MotionTransformIndex::New(Property::Key modelNodeId, TransformType type)
+{
+  Internal::MotionTransformIndexPtr internal = Internal::MotionTransformIndex::New();
+
+  internal->SetModelNodeId(modelNodeId);
+  internal->SetTransformType(type);
+
+  return MotionTransformIndex(internal.Get());
+}
+
+MotionTransformIndex::MotionTransformIndex()
+{
+}
+
+MotionTransformIndex::MotionTransformIndex(const MotionTransformIndex& motionTransformIndex) = default;
+
+MotionTransformIndex::MotionTransformIndex(MotionTransformIndex&& rhs) noexcept = default;
+
+MotionTransformIndex::~MotionTransformIndex()
+{
+}
+
+MotionTransformIndex& MotionTransformIndex::operator=(const MotionTransformIndex& handle) = default;
+
+MotionTransformIndex& MotionTransformIndex::operator=(MotionTransformIndex&& rhs) noexcept = default;
+
+MotionTransformIndex MotionTransformIndex::DownCast(BaseHandle handle)
+{
+  return MotionTransformIndex(dynamic_cast<Dali::Scene3D::Internal::MotionTransformIndex*>(handle.GetObjectPtr()));
+}
+
+MotionTransformIndex::MotionTransformIndex(Dali::Scene3D::Internal::MotionTransformIndex* internal)
+: MotionIndex(internal)
+{
+}
+
+// Public Method
+
+void MotionTransformIndex::SetTransformType(MotionTransformIndex::TransformType type)
+{
+  GetImplementation(*this).SetTransformType(type);
+}
+
+MotionTransformIndex::TransformType MotionTransformIndex::GetTransformType() const
+{
+  return GetImplementation(*this).GetTransformType();
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h b/dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h
new file mode 100644 (file)
index 0000000..c3723a9
--- /dev/null
@@ -0,0 +1,203 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_TRANSFORM_INDEX_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_TRANSFORM_INDEX_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
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-motion/motion-index/motion-index.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+//Forward declarations.
+namespace Internal
+{
+class MotionTransformIndex;
+} // namespace Internal
+
+/**
+ * @addtogroup dali_scene3d_model_motion_motion_transform_index
+ * @{
+ */
+
+/**
+ * @brief Specialized MotionIndex to control transform.
+ * It will be used when app developer don't care about Dali::Actor::Property list,
+ * but want to change the transform properties anyway fast enough.
+ *
+ * @code
+ *
+ * MotionTransformIndex position = MotionTransformIndex::New("nodeName", MotionTransformIndex::TransformType::POSITION);
+ *
+ * // We can change the property later.
+ * MotionTransformIndex orientation = MotionTransformIndex::New();
+ * orientation.SetModelNodeId("nodeName");
+ * orientation.SetTransformType(MotionTransformIndex::TransformType::ORIENTATION);
+ *
+ * @endcode
+ *
+ * @SINCE_2_2.34
+ */
+class DALI_SCENE3D_API MotionTransformIndex : public MotionIndex
+{
+public:
+  /**
+   * @brief The type of Transform
+   * @SINCE_2_2.34
+   */
+  enum class TransformType
+  {
+    INVALID = -1,
+
+    POSITION = 0, ///< The position of ModelNode. MotionValue should be Vector3.
+    POSITION_X,   ///< The x position of ModelNode. MotionValue should be float.
+    POSITION_Y,   ///< The y position of ModelNode. MotionValue should be float.
+    POSITION_Z,   ///< The z position of ModelNode. MotionValue should be float.
+
+    ORIENTATION, ///< The orientation of ModelNode. MotionValue should be Quaternion.
+
+    SCALE,   ///< The scale of ModelNode. MotionValue should be Vector3.
+    SCALE_X, ///< The x scale of ModelNode. MotionValue should be float.
+    SCALE_Y, ///< The y scale of ModelNode. MotionValue should be float.
+    SCALE_Z, ///< The z scale of ModelNode. MotionValue should be float.
+  };
+
+public: // Creation & Destruction
+  /**
+   * @brief Create an initialized MotionTransformIndex.
+   *
+   * @SINCE_2_2.34
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionTransformIndex New();
+
+  /**
+   * @brief Create an initialized MotionTransformIndex with values.
+   *
+   * @SINCE_2_2.34
+   * @param[in] modelNodeId The id of model node what this motion index looks.
+   * @param[in] type The type of transform what this motion index looks.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionTransformIndex New(Property::Key modelNodeId, TransformType type);
+
+  /**
+   * @brief Creates an uninitialized MotionTransformIndex.
+   *
+   * Only derived versions can be instantiated. Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   *
+   * @SINCE_2_2.34
+   */
+  MotionTransformIndex();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   *
+   * @SINCE_2_2.34
+   */
+  ~MotionTransformIndex();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionTransformIndex Handle to an object
+   */
+  MotionTransformIndex(const MotionTransformIndex& motionTransformIndex);
+
+  /**
+   * @brief Move constructor
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   */
+  MotionTransformIndex(MotionTransformIndex&& rhs) noexcept;
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionTransformIndex Handle to an object
+   * @return reference to this
+   */
+  MotionTransformIndex& operator=(const MotionTransformIndex& motionTransformIndex);
+
+  /**
+   * @brief Move assignment
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  MotionTransformIndex& operator=(MotionTransformIndex&& rhs) noexcept;
+
+  /**
+   * @brief Downcasts an Object handle to MotionTransformIndex.
+   *
+   * If handle points to a MotionTransformIndex, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @SINCE_2_2.34
+   * @param[in] handle Handle to an object
+   * @return Handle to a MotionTransformIndex or an uninitialized handle
+   */
+  static MotionTransformIndex DownCast(BaseHandle handle);
+
+public: // Public Method
+  /**
+   * @brief Set the type of transform what this motion index looks.
+   *
+   * @SINCE_2_2.34
+   * @param[in] type The type of transform.
+   */
+  void SetTransformType(TransformType type);
+
+  /**
+   * @brief Get the type of transform what this motion index looks.
+   *
+   * @SINCE_2_2.34
+   * @return The type of transform.
+   */
+  TransformType GetTransformType() const;
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief Creates a handle using the Scene3D::Internal implementation.
+   *
+   * @param[in] implementation The MotionTransformIndex implementation
+   */
+  DALI_INTERNAL MotionTransformIndex(Dali::Scene3D::Internal::MotionTransformIndex* implementation);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_TRANSFORM_INDEX_H
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-value.cpp b/dali-scene3d/public-api/model-motion/motion-value.cpp
new file mode 100644 (file)
index 0000000..4641a9c
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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/public-api/model-motion/motion-value.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-motion/motion-value-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+MotionValue MotionValue::New()
+{
+  Internal::MotionValuePtr internal = Internal::MotionValue::New();
+
+  return MotionValue(internal.Get());
+}
+
+MotionValue MotionValue::New(Property::Value propertyValue)
+{
+  Internal::MotionValuePtr internal = Internal::MotionValue::New();
+
+  internal->SetValue(propertyValue);
+
+  return MotionValue(internal.Get());
+}
+
+MotionValue MotionValue::New(KeyFrames keyFrames)
+{
+  Internal::MotionValuePtr internal = Internal::MotionValue::New();
+
+  internal->SetValue(keyFrames);
+
+  return MotionValue(internal.Get());
+}
+
+MotionValue::MotionValue()
+{
+}
+
+MotionValue::MotionValue(const MotionValue& motionValue) = default;
+
+MotionValue::MotionValue(MotionValue&& rhs) noexcept = default;
+
+MotionValue::~MotionValue()
+{
+}
+
+MotionValue& MotionValue::operator=(const MotionValue& handle) = default;
+
+MotionValue& MotionValue::operator=(MotionValue&& rhs) noexcept = default;
+
+MotionValue MotionValue::DownCast(BaseHandle handle)
+{
+  return MotionValue(dynamic_cast<Dali::Scene3D::Internal::MotionValue*>(handle.GetObjectPtr()));
+}
+
+MotionValue::MotionValue(Dali::Scene3D::Internal::MotionValue* internal)
+: BaseHandle(internal)
+{
+}
+
+// Public Method
+
+MotionValue::ValueType MotionValue::GetValueType() const
+{
+  return GetImplementation(*this).GetValueType();
+}
+
+void MotionValue::SetValue(Property::Value propertyValue)
+{
+  GetImplementation(*this).SetValue(propertyValue);
+}
+
+void MotionValue::SetValue(KeyFrames keyFrames)
+{
+  GetImplementation(*this).SetValue(keyFrames);
+}
+
+void MotionValue::Invalidate()
+{
+  Clear();
+}
+
+void MotionValue::Clear()
+{
+  GetImplementation(*this).Clear();
+}
+
+Property::Value MotionValue::GetPropertyValue() const
+{
+  return GetImplementation(*this).GetPropertyValue();
+}
+
+KeyFrames MotionValue::GetKeyFrames() const
+{
+  return GetImplementation(*this).GetKeyFrames();
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-scene3d/public-api/model-motion/motion-value.h b/dali-scene3d/public-api/model-motion/motion-value.h
new file mode 100644 (file)
index 0000000..39ccbd7
--- /dev/null
@@ -0,0 +1,240 @@
+#ifndef DALI_SCENE3D_MODEL_MOTION_MOTION_VALUE_H
+#define DALI_SCENE3D_MODEL_MOTION_MOTION_VALUE_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/key-frames.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property-value.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/api.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+//Forward declarations.
+namespace Internal
+{
+class MotionValue;
+} // namespace Internal
+
+/**
+ * @addtogroup dali_scene3d_model_motion_motion_value
+ * @{
+ */
+
+/**
+ * @brief This MotionValue be used for target value of each MotionIndex.
+ * We can get and set MotionValue as 2 types : Property::Value and KeyFrames.
+ *
+ * Each types will be cross-converted internally.
+ * For example, when we set Property::Value, we can get KeyFrames with 2 frames, and target value is setted.
+ *
+ * @note The type of property should be matched with MotionIndex required.
+ * @SINCE_2_2.34
+ */
+class DALI_SCENE3D_API MotionValue : public Dali::BaseHandle
+{
+public:
+  /**
+   * @brief Determine whether current stored value is PropertyValue, or KeyFrames.
+   * @SINCE_2_2.34
+   */
+  enum class ValueType
+  {
+    INVALID = -1, ///< Value is null, or invalid.
+
+    PROPERTY_VALUE = 0, ///< Value is PropertyValue.
+    KEY_FRAMES,         ///< Value is KeyFrames.
+  };
+
+public: // Creation & Destruction
+  /**
+   * @brief Create an initialized MotionValue.
+   *
+   * @SINCE_2_2.34
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionValue New();
+
+  /**
+   * @brief Create an initialized MotionValue with Property::Value.
+   *
+   * @SINCE_2_2.34
+   * @param[in] propertyValue The static value.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionValue New(Property::Value propertyValue);
+
+  /**
+   * @brief Create an initialized MotionValue with KeyFrames.
+   *
+   * @SINCE_2_2.34
+   * @param[in] keyFrames The keyframes value.
+   * @return A handle to a newly allocated Dali resource
+   */
+  static MotionValue New(KeyFrames keyFrames);
+
+  /**
+   * @brief Creates an uninitialized MotionValue.
+   *
+   * Only derived versions can be instantiated. Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   *
+   * @SINCE_2_2.34
+   */
+  MotionValue();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   *
+   * @SINCE_2_2.34
+   */
+  ~MotionValue();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionValue Handle to an object
+   */
+  MotionValue(const MotionValue& motionValue);
+
+  /**
+   * @brief Move constructor
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   */
+  MotionValue(MotionValue&& rhs) noexcept;
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @SINCE_2_2.34
+   * @param[in] motionValue Handle to an object
+   * @return reference to this
+   */
+  MotionValue& operator=(const MotionValue& motionValue);
+
+  /**
+   * @brief Move assignment
+   *
+   * @SINCE_2_2.34
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this
+   */
+  MotionValue& operator=(MotionValue&& rhs) noexcept;
+
+  /**
+   * @brief Downcasts an Object handle to MotionValue.
+   *
+   * If handle points to a MotionValue, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @SINCE_2_2.34
+   * @param[in] handle Handle to an object
+   * @return Handle to a MotionValue or an uninitialized handle
+   */
+  static MotionValue DownCast(BaseHandle handle);
+
+public: // Public Method
+  /**
+   * @brief Get the type of value this MotionValue hold.
+   * The type of value will be changed what we set.
+   *
+   * @SINCE_2_2.34
+   * @return Type of value.
+   */
+  ValueType GetValueType() const;
+
+  /**
+   * @brief Set the value as Property::Value type.
+   *
+   * @SINCE_2_2.34
+   * @param[in] propertyValue The static value.
+   */
+  void SetValue(Property::Value propertyValue);
+
+  /**
+   * @brief Set the value as KeyFrames type.
+   *
+   * @SINCE_2_2.34
+   * @param[in] keyFrames The keyframes value.
+   */
+  void SetValue(KeyFrames keyFrames);
+
+  /**
+   * @brief Make value as Invalid type.
+   *
+   * @SINCE_2_2.34
+   */
+  void Invalidate();
+
+  /**
+   * @brief Make value as Invalid type.
+   * @see Dali::Scene3D::MotionValue::Invalidate()
+   *
+   * @SINCE_2_2.34
+   */
+  void Clear();
+
+  /**
+   * @brief Get the value as Property::Value.
+   * If ValueType is KEY_FRAMES, it will return last value of stored KeyFrames.
+   *
+   * @SINCE_2_2.34
+   * @return Property value, or empty if it is invalid.
+   */
+  Property::Value GetPropertyValue() const;
+
+  /**
+   * @brief Get the value as KeyFrames
+   * If ValueType is PROPERTY_VALUE, it will create new KeyFrames by stored Property::Value.
+   *
+   * @SINCE_2_2.34
+   * @return Keyframes handle, or empty if it is invalid.
+   */
+  KeyFrames GetKeyFrames() const;
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief Creates a handle using the Scene3D::Internal implementation.
+   *
+   * @param[in] implementation The MotionValue implementation
+   */
+  DALI_INTERNAL MotionValue(Dali::Scene3D::Internal::MotionValue* implementation);
+  /// @endcond
+};
+
+/**
+ * @}
+ */
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_VALUE_H
\ No newline at end of file