From 2116ad7b1ce51093a891ca6b3e83419b0b5b79dd Mon Sep 17 00:00:00 2001 From: "EverLEEst(SangHyeon Lee)" Date: Wed, 28 Jun 2023 14:39:34 +0900 Subject: [PATCH] [Tizen] Add MotionData class and generate Animation by this This reverts commit 469fdeab34b1f319e0d9a73a799f1a48732a0410. --- .../AnimatedMorphCubeAnimateNonZeroFrame.gltf | 6 + automated-tests/resources/MorphPrimitivesTest.gltf | 10 +- automated-tests/src/dali-scene3d/CMakeLists.txt | 6 + .../src/dali-scene3d/utc-Dali-BlendShapeIndex.cpp | 215 +++++++++++ .../src/dali-scene3d/utc-Dali-Model.cpp | 203 ++++++++++- .../src/dali-scene3d/utc-Dali-MotionData.cpp | 400 +++++++++++++++++++++ .../src/dali-scene3d/utc-Dali-MotionIndex.cpp | 161 +++++++++ .../dali-scene3d/utc-Dali-MotionPropertyIndex.cpp | 195 ++++++++++ .../dali-scene3d/utc-Dali-MotionTransformIndex.cpp | 212 +++++++++++ .../src/dali-scene3d/utc-Dali-MotionValue.cpp | 196 ++++++++++ dali-scene3d/dali-scene3d.h | 7 + .../internal/controls/model/model-impl.cpp | 272 +++++++++++++- dali-scene3d/internal/controls/model/model-impl.h | 34 +- dali-scene3d/internal/file.list | 7 + dali-scene3d/internal/loader/gltf2-asset.h | 19 +- dali-scene3d/internal/loader/gltf2-util.cpp | 66 +++- dali-scene3d/internal/loader/json-reader.h | 7 +- .../internal/model-components/model-node-impl.cpp | 36 +- .../internal/model-components/model-node-impl.h | 20 +- .../internal/model-motion/motion-data-impl.cpp | 212 +++++++++++ .../internal/model-motion/motion-data-impl.h | 192 ++++++++++ .../model-motion/motion-data-load-task.cpp | 133 +++++++ .../internal/model-motion/motion-data-load-task.h | 115 ++++++ .../motion-index/blend-shape-index-impl.cpp | 128 +++++++ .../motion-index/blend-shape-index-impl.h | 118 ++++++ .../motion-index/motion-index-impl.cpp | 57 +++ .../model-motion/motion-index/motion-index-impl.h | 106 ++++++ .../motion-index/motion-property-index-impl.cpp | 102 ++++++ .../motion-index/motion-property-index-impl.h | 118 ++++++ .../motion-index/motion-transform-index-impl.cpp | 184 ++++++++++ .../motion-index/motion-transform-index-impl.h | 118 ++++++ .../internal/model-motion/motion-value-impl.cpp | 146 ++++++++ .../internal/model-motion/motion-value-impl.h | 129 +++++++ dali-scene3d/public-api/controls/model/model.cpp | 20 ++ dali-scene3d/public-api/controls/model/model.h | 42 +++ dali-scene3d/public-api/file.list | 6 + .../public-api/loader/animated-property.cpp | 2 +- dali-scene3d/public-api/loader/animated-property.h | 6 +- .../public-api/loader/animation-definition.cpp | 9 +- .../public-api/loader/animation-definition.h | 9 +- .../public-api/loader/blend-shape-details.h | 17 +- .../public-api/loader/scene-definition.cpp | 1 + .../public-api/model-components/model-node.cpp | 10 + .../public-api/model-components/model-node.h | 18 +- .../public-api/model-motion/motion-data.cpp | 134 +++++++ dali-scene3d/public-api/model-motion/motion-data.h | 331 +++++++++++++++++ .../motion-index/blend-shape-index.cpp | 94 +++++ .../model-motion/motion-index/blend-shape-index.h | 179 +++++++++ .../model-motion/motion-index/motion-index.cpp | 78 ++++ .../model-motion/motion-index/motion-index.h | 176 +++++++++ .../motion-index/motion-property-index.cpp | 85 +++++ .../motion-index/motion-property-index.h | 168 +++++++++ .../motion-index/motion-transform-index.cpp | 85 +++++ .../motion-index/motion-transform-index.h | 190 ++++++++++ .../public-api/model-motion/motion-value.cpp | 113 ++++++ .../public-api/model-motion/motion-value.h | 232 ++++++++++++ 56 files changed, 5892 insertions(+), 43 deletions(-) create mode 100644 automated-tests/src/dali-scene3d/utc-Dali-BlendShapeIndex.cpp create mode 100644 automated-tests/src/dali-scene3d/utc-Dali-MotionData.cpp create mode 100644 automated-tests/src/dali-scene3d/utc-Dali-MotionIndex.cpp create mode 100644 automated-tests/src/dali-scene3d/utc-Dali-MotionPropertyIndex.cpp create mode 100644 automated-tests/src/dali-scene3d/utc-Dali-MotionTransformIndex.cpp create mode 100644 automated-tests/src/dali-scene3d/utc-Dali-MotionValue.cpp create mode 100644 dali-scene3d/internal/model-motion/motion-data-impl.cpp create mode 100644 dali-scene3d/internal/model-motion/motion-data-impl.h create mode 100644 dali-scene3d/internal/model-motion/motion-data-load-task.cpp create mode 100644 dali-scene3d/internal/model-motion/motion-data-load-task.h create mode 100644 dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.cpp create mode 100644 dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.h create mode 100644 dali-scene3d/internal/model-motion/motion-index/motion-index-impl.cpp create mode 100644 dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h create mode 100644 dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.cpp create mode 100644 dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.h create mode 100644 dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.cpp create mode 100644 dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.h create mode 100644 dali-scene3d/internal/model-motion/motion-value-impl.cpp create mode 100644 dali-scene3d/internal/model-motion/motion-value-impl.h create mode 100644 dali-scene3d/public-api/model-motion/motion-data.cpp create mode 100644 dali-scene3d/public-api/model-motion/motion-data.h create mode 100644 dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.cpp create mode 100644 dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h create mode 100644 dali-scene3d/public-api/model-motion/motion-index/motion-index.cpp create mode 100644 dali-scene3d/public-api/model-motion/motion-index/motion-index.h create mode 100644 dali-scene3d/public-api/model-motion/motion-index/motion-property-index.cpp create mode 100644 dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h create mode 100644 dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.cpp create mode 100644 dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h create mode 100644 dali-scene3d/public-api/model-motion/motion-value.cpp create mode 100644 dali-scene3d/public-api/model-motion/motion-value.h diff --git a/automated-tests/resources/AnimatedMorphCubeAnimateNonZeroFrame.gltf b/automated-tests/resources/AnimatedMorphCubeAnimateNonZeroFrame.gltf index 08c8daf..48a9d20 100644 --- a/automated-tests/resources/AnimatedMorphCubeAnimateNonZeroFrame.gltf +++ b/automated-tests/resources/AnimatedMorphCubeAnimateNonZeroFrame.gltf @@ -209,6 +209,12 @@ ], "meshes": [ { + "extras": { + "targetNames": [ + "Target_0", + "Target_1" + ] + }, "primitives": [ { "attributes": { diff --git a/automated-tests/resources/MorphPrimitivesTest.gltf b/automated-tests/resources/MorphPrimitivesTest.gltf index a987f2d..10fb1e7 100644 --- a/automated-tests/resources/MorphPrimitivesTest.gltf +++ b/automated-tests/resources/MorphPrimitivesTest.gltf @@ -291,7 +291,15 @@ ], "mode": 4 } - ] + ], + "extensions": { + "SXR_targets_names": { + "Target_0": 0 + }, + "avatar_shape_names": { + "Target_0": 0 + } + } } ], "nodes": [ diff --git a/automated-tests/src/dali-scene3d/CMakeLists.txt b/automated-tests/src/dali-scene3d/CMakeLists.txt index 4dff80c..1eed33c 100755 --- a/automated-tests/src/dali-scene3d/CMakeLists.txt +++ b/automated-tests/src/dali-scene3d/CMakeLists.txt @@ -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 index 0000000..b7c34ff --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-BlendShapeIndex.cpp @@ -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 +#include +#include +#include + +#include +#include + +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 diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp index c219f93..30b755d 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -27,6 +28,10 @@ #include #include +#include +#include +#include + #include using namespace Dali; @@ -53,7 +58,9 @@ const bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false; */ const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf"; 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"; @@ -1135,8 +1142,7 @@ int UtcDaliModelCameraGenerate02(void) CameraActor appliedCamera; DALI_TEST_EQUALS(model.ApplyCamera(0u, appliedCamera), false, TEST_LOCATION); // Cannot apply into empty camera. - auto CompareCameraProperties = [](CameraActor lhs, CameraActor rhs, const char* location) - { + auto CompareCameraProperties = [](CameraActor lhs, CameraActor rhs, const char* location) { DALI_TEST_EQUALS(lhs.GetProperty(Dali::CameraActor::Property::PROJECTION_MODE), rhs.GetProperty(Dali::CameraActor::Property::PROJECTION_MODE), TEST_LOCATION); DALI_TEST_EQUALS(lhs.GetProperty(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE), rhs.GetProperty(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE), TEST_LOCATION); @@ -1488,3 +1494,196 @@ int UtcDaliModelSizeChange2(void) END_TEST; } + +int UtcDaliModelRetrieveBlendShapeNames(void) +{ + tet_infoline(" UtcDaliModelRetrieveBlendShapeByName."); + + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_EXTRAS_FILE_NAME); + model.SetProperty(Dali::Actor::Property::SIZE, Vector3(300, 300, 300)); + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(model.GetChildCount(), 1u, TEST_LOCATION); + + // Get target ModelNode that has extras + Scene3D::ModelNode expectNode = model.FindChildModelNodeByName("AnimatedMorphCube"); + + // Pair of expected blend shape index from expectNode. + std::map expectBlendShapeNames = { + {"Target_0", 0u}, + {"Target_1", 1u}, + }; + + std::vector blendShapeNameList; + model.RetrieveBlendShapeNames(blendShapeNameList); + + DALI_TEST_EQUALS(blendShapeNameList.size(), expectBlendShapeNames.size(), TEST_LOCATION); + for(auto i = 0u; i < blendShapeNameList.size(); ++i) + { + const auto& name = blendShapeNameList[i]; + tet_printf("Check retrieved blendshape name : %s\n", name.c_str()); + + const auto& iter = expectBlendShapeNames.find(name); + DALI_TEST_CHECK(iter != expectBlendShapeNames.end()); + + std::vector nodeList; + model.RetrieveModelNodesByBlendShapeName(name, nodeList); + DALI_TEST_EQUALS(nodeList.size(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(nodeList[0], expectNode, TEST_LOCATION); + DALI_TEST_EQUALS(nodeList[0].GetBlendShapeIndexByName(name), iter->second, TEST_LOCATION); + } + + 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(Actor::Property::SCALE_X); + + model.SetMotionData(motionData); + + DALI_TEST_EQUALS(cubeModelNode.GetProperty(Actor::Property::SCALE_X), expectScaleX, TEST_LOCATION); + DALI_TEST_EQUALS(cubeModelNode.GetProperty(Actor::Property::SCALE_Y), 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(cubeModelNode.GetProperty(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(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(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 index 0000000..54fc168 --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-MotionData.cpp @@ -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 +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +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(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(rawString.data()), static_cast(rawString.length())); + break; + } + case 3: + { + std::string rawString = ReadBufferFromFile(TEST_FACIAL_FILE_NAME); + motionData.LoadFacialAnimationFromBuffer(reinterpret_cast(rawString.data()), static_cast(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(rawString.data()), static_cast(rawString.length()), Vector3::ONE, true); + break; + } + case 3: + { + std::string rawString = ReadBufferFromFile(TEST_FACIAL_FILE_NAME); + motionData.LoadFacialAnimationFromBuffer(reinterpret_cast(rawString.data()), static_cast(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 index 0000000..1e28a46 --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-MotionIndex.cpp @@ -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 +#include +#include +#include + +#include +#include +#include +#include + +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 index 0000000..d0aa20d --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-MotionPropertyIndex.cpp @@ -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 +#include +#include +#include + +#include +#include + +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 index 0000000..0dd0814 --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-MotionTransformIndex.cpp @@ -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 +#include +#include +#include + +#include +#include + +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 index 0000000..103b533 --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-MotionValue.cpp @@ -0,0 +1,196 @@ +/* + * 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 +#include +#include +#include + +#include +#include + +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() == 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(), 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(), expectValue, TEST_LOCATION); + + 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 diff --git a/dali-scene3d/dali-scene3d.h b/dali-scene3d/dali-scene3d.h index 2d3bad9..eb7c60a 100644 --- a/dali-scene3d/dali-scene3d.h +++ b/dali-scene3d/dali-scene3d.h @@ -71,4 +71,11 @@ #include #include +#include +#include +#include +#include +#include +#include + #endif // DALI_SCENE3D_H \ No newline at end of file diff --git a/dali-scene3d/internal/controls/model/model-impl.cpp b/dali-scene3d/internal/controls/model/model-impl.cpp index 73823d5..acaccbf 100644 --- a/dali-scene3d/internal/controls/model/model-impl.cpp +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -43,6 +43,7 @@ #include #include #include +#include using namespace Dali; @@ -118,8 +119,7 @@ void ConfigureBlendShapeShaders( Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector&& requests) { std::vector errors; - auto onError = [&errors](const std::string& msg) - { errors.push_back(msg); }; + auto onError = [&errors](const std::string& msg) { errors.push_back(msg); }; if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError)) { Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION); @@ -178,7 +178,6 @@ void AddLightRecursively(Scene3D::ModelNode node, Scene3D::Light light, uint32_t { return; } - GetImplementation(node).AddLight(light, lightIndex); uint32_t childrenCount = node.GetChildCount(); @@ -212,6 +211,27 @@ void RemoveLightRecursively(Scene3D::ModelNode node, uint32_t lightIndex) } } +void UpdateBlendShapeNodeMapRecursively(Model::BlendShapeModelNodeMap& resultMap, const Scene3D::ModelNode& node) +{ + if(!node) + { + return; + } + const auto childCount = node.GetChildCount(); + for(auto i = 0u; i < childCount; ++i) + { + UpdateBlendShapeNodeMapRecursively(resultMap, Scene3D::ModelNode::DownCast(node.GetChildAt(i))); + } + + std::vector blendShapeNames; + node.RetrieveBlendShapeNames(blendShapeNames); + for(const auto& iter : blendShapeNames) + { + // Append or create new list. + resultMap[iter].push_back(node); + } +} + } // anonymous namespace Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl) @@ -516,6 +536,229 @@ Scene3D::ModelNode Model::FindChildModelNodeByName(std::string_view nodeName) return Scene3D::ModelNode::DownCast(childActor); } +void Model::RetrieveBlendShapeNames(std::vector& blendShapeNames) const +{ + blendShapeNames.reserve(blendShapeNames.size() + mBlendShapeModelNodeMap.size()); + for(const auto& iter : mBlendShapeModelNodeMap) + { + blendShapeNames.push_back(iter.first); + } +} + +void Model::RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector& modelNodes) const +{ + auto iter = mBlendShapeModelNodeMap.find(std::string(blendShapeName)); + if(iter != mBlendShapeModelNodeMap.end()) + { + const auto& modelNodeList = iter->second; + modelNodes.reserve(modelNodes.size() + modelNodeList.size()); + for(const auto& nodeIter : modelNodeList) + { + modelNodes.push_back(nodeIter); + } + } +} + +Dali::Animation Model::GenerateMotionDataAnimation(Scene3D::MotionData motionData) +{ + Dali::Animation animation; + + // TODO : Collect duplicated codes. + + if(motionData) + { + const uint32_t motionCount = motionData.GetMotionCount(); + for(uint32_t i = 0u; i < motionCount; ++i) + { + auto motionIndex = motionData.GetIndex(i); + auto motionValue = motionData.GetValue(i); + if(motionIndex && motionValue) + { + if(motionIndex.GetModelNodeId() != Property::INVALID_KEY) + { + Scene3D::ModelNode modelNode; + if(motionIndex.GetModelNodeId().type == Property::Key::Type::STRING) + { + modelNode = FindChildModelNodeByName(motionIndex.GetModelNodeId().stringKey); + } + else if(motionIndex.GetModelNodeId().type == Property::Key::Type::INDEX) + { + // TODO : Not implement yet. + } + + if(modelNode) + { + KeyFrames keyFrames = motionValue.GetKeyFrames(); + + if(keyFrames) + { + // Try to use index first. If failed, try to use name + Property::Index animatedPropertyIndex = motionIndex.GetPropertyIndex(modelNode); + if(animatedPropertyIndex != Property::INVALID_INDEX) + { + if(DALI_UNLIKELY(!animation)) + { + animation = Animation::New(motionData.GetDuration()); + } + animation.AnimateBetween(Dali::Property(modelNode, animatedPropertyIndex), keyFrames); + } + else + { + std::string animatedPropertyName = motionIndex.GetPropertyName(modelNode); + Dali::Property property(modelNode, animatedPropertyName); + if(property.propertyIndex != Property::INVALID_INDEX) + { + if(DALI_UNLIKELY(!animation)) + { + animation = Animation::New(motionData.GetDuration()); + } + animation.AnimateBetween(property, keyFrames); + } + } + } + } + } + else + { + Scene3D::BlendShapeIndex blendShapeIndex = Scene3D::BlendShapeIndex::DownCast(motionIndex); + if(blendShapeIndex && blendShapeIndex.GetBlendShapeId().type == Property::Key::Type::STRING) + { + // Special case : For BlendShapeIndex that doesn't have ModelNodeId and has string BlendShapeId, + // we need to animate all kind of blendshapes + + KeyFrames keyFrames = motionValue.GetKeyFrames(); + + if(keyFrames) + { + std::vector modelNodes; + RetrieveModelNodesByBlendShapeName(blendShapeIndex.GetBlendShapeId().stringKey, modelNodes); + + for(auto& modelNode : modelNodes) + { + // Try to use index first. If failed, try to use name + Property::Index animatedPropertyIndex = motionIndex.GetPropertyIndex(modelNode); + if(animatedPropertyIndex != Property::INVALID_INDEX) + { + if(DALI_UNLIKELY(!animation)) + { + animation = Animation::New(motionData.GetDuration()); + } + animation.AnimateBetween(Dali::Property(modelNode, animatedPropertyIndex), keyFrames); + } + else + { + std::string animatedPropertyName = motionIndex.GetPropertyName(modelNode); + Dali::Property property(modelNode, animatedPropertyName); + + if(property.propertyIndex != Property::INVALID_INDEX) + { + if(DALI_UNLIKELY(!animation)) + { + animation = Animation::New(motionData.GetDuration()); + } + animation.AnimateBetween(property, keyFrames); + } + } + } + } + } + } + } + } + } + + return animation; +} + +void Model::SetMotionData(Scene3D::MotionData motionData) +{ + // TODO : Collect duplicated codes. + if(motionData) + { + const uint32_t motionCount = motionData.GetMotionCount(); + for(uint32_t i = 0u; i < motionCount; ++i) + { + auto motionIndex = motionData.GetIndex(i); + auto motionValue = motionData.GetValue(i); + if(motionIndex && motionValue) + { + if(motionIndex.GetModelNodeId() != Property::INVALID_KEY) + { + Scene3D::ModelNode modelNode; + if(motionIndex.GetModelNodeId().type == Property::Key::Type::STRING) + { + modelNode = FindChildModelNodeByName(motionIndex.GetModelNodeId().stringKey); + } + else if(motionIndex.GetModelNodeId().type == Property::Key::Type::INDEX) + { + // TODO : Not implement yet. + } + + if(modelNode) + { + Property::Value value = motionValue.GetPropertyValue(); + + if(value.GetType() != Property::Type::NONE) + { + // Try to use index first. If failed, try to use name + Property::Index propertyIndex = motionIndex.GetPropertyIndex(modelNode); + if(propertyIndex != Property::INVALID_INDEX) + { + modelNode.SetProperty(propertyIndex, value); + } + else + { + std::string propertyName = motionIndex.GetPropertyName(modelNode); + Dali::Property property(modelNode, propertyName); + if(property.propertyIndex != Property::INVALID_INDEX) + { + modelNode.SetProperty(property.propertyIndex, value); + } + } + } + } + } + else + { + Scene3D::BlendShapeIndex blendShapeIndex = Scene3D::BlendShapeIndex::DownCast(motionIndex); + if(blendShapeIndex && blendShapeIndex.GetBlendShapeId().type == Property::Key::Type::STRING) + { + // Special case : For BlendShapeIndex that doesn't have ModelNodeId and has string BlendShapeId, + // we need to animate all kind of blendshapes + + Property::Value value = motionValue.GetPropertyValue(); + + if(value.GetType() != Property::Type::NONE) + { + std::vector 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 @@ -941,19 +1184,21 @@ void Model::CreateModel() resources.GenerateResources(); for(auto iRoot : scene.GetRoots()) { - if(auto actor = scene.CreateNodes(iRoot, resourceChoices, nodeParams)) + if(auto modelNode = scene.CreateNodes(iRoot, resourceChoices, nodeParams)) { - scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); - ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); + scene.ConfigureSkinningShaders(resources, modelNode, std::move(nodeParams.mSkinnables)); + ConfigureBlendShapeShaders(resources, scene, modelNode, std::move(nodeParams.mBlendshapeRequests)); - scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); + scene.ApplyConstraints(modelNode, std::move(nodeParams.mConstrainables)); - mModelRoot.Add(actor); + mModelRoot.Add(modelNode); } AddModelTreeToAABB(AABB, scene, resourceChoices, iRoot, nodeParams, Matrix::IDENTITY); } + UpdateBlendShapeNodeMap(); + mNaturalSize = AABB.CalculateSize(); mModelPivot = AABB.CalculatePivot(); mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); @@ -971,8 +1216,7 @@ void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene) mAnimations.clear(); if(!mModelLoadTask->GetAnimations().empty()) { - auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) - { + auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) { if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX) { return mModelRoot.FindChildByName(property.mNodeName); @@ -1003,6 +1247,14 @@ void Model::ResetCameraParameters() } } +void Model::UpdateBlendShapeNodeMap() +{ + // Remove privous node map + mBlendShapeModelNodeMap.clear(); + + UpdateBlendShapeNodeMapRecursively(mBlendShapeModelNodeMap, mModelRoot); +} + } // namespace Internal } // namespace Scene3D } // namespace Dali diff --git a/dali-scene3d/internal/controls/model/model-impl.h b/dali-scene3d/internal/controls/model/model-impl.h index 52aed7d5..f383aff 100644 --- a/dali-scene3d/internal/controls/model/model-impl.h +++ b/dali-scene3d/internal/controls/model/model-impl.h @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include #include #include #include @@ -51,8 +52,9 @@ namespace Internal class Model : public Dali::Toolkit::Internal::Control, public LightObserver { public: - using AnimationData = std::pair; - using CameraData = Loader::CameraParameters; + using AnimationData = std::pair; + using CameraData = Loader::CameraParameters; + using BlendShapeModelNodeMap = std::map>; /** * @copydoc Model::New() @@ -144,6 +146,26 @@ public: */ Scene3D::ModelNode FindChildModelNodeByName(std::string_view nodeName); + /** + * @copydoc Model::RetrieveBlendShapeNames() + */ + void RetrieveBlendShapeNames(std::vector& blendShapeNames) const; + + /** + * @copydoc Model::RetrieveModelNodesByBlendShapeName() + */ + void RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector& 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. @@ -325,6 +347,11 @@ private: */ void ResetCameraParameters(); + /** + * @brief Collect ModelNode list by blendshape name + */ + void UpdateBlendShapeNodeMap(); + private: std::string mModelUrl; std::string mResourceDirectoryUrl; @@ -337,6 +364,9 @@ private: // Light std::vector mLights; + // List of ModelNode for name of blend shape. + BlendShapeModelNodeMap mBlendShapeModelNodeMap; + // Asynchronous loading variable ModelLoadTaskPtr mModelLoadTask; EnvironmentMapLoadTaskPtr mIblDiffuseLoadTask; diff --git a/dali-scene3d/internal/file.list b/dali-scene3d/internal/file.list index 56200d2..9ea43a8 100644 --- a/dali-scene3d/internal/file.list +++ b/dali-scene3d/internal/file.list @@ -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/loader/gltf2-asset.h b/dali-scene3d/internal/loader/gltf2-asset.h index 7a8af2b..7d2c332 100644 --- a/dali-scene3d/internal/loader/gltf2-asset.h +++ b/dali-scene3d/internal/loader/gltf2-asset.h @@ -426,10 +426,25 @@ struct Mesh : Named //TODO: extensions }; + struct Extras + { + std::vector mTargetNames; + + //TODO: extras + }; + + struct Extensions + { + std::vector mSXRTargetsNames; + std::vector mAvatarShapeNames; + + //TODO: extensions + }; + std::vector mPrimitives; std::vector mWeights; - //TODO: extras - //TODO: extensions + Extras mExtras; + Extensions mExtensions; }; struct Node; diff --git a/dali-scene3d/internal/loader/gltf2-util.cpp b/dali-scene3d/internal/loader/gltf2-util.cpp index 219f207..90deac9 100644 --- a/dali-scene3d/internal/loader/gltf2-util.cpp +++ b/dali-scene3d/internal/loader/gltf2-util.cpp @@ -281,6 +281,44 @@ const json::Reader& GetMeshPrimitiveReader() return MESH_PRIMITIVE_READER; } +const json::Reader& GetMeshExtrasReader() +{ + static const auto MESH_EXTRAS_READER = std::move(json::Reader() + .Register(*json::MakeProperty("targetNames", json::Read::Array, &gltf2::Mesh::Extras::mTargetNames))); + return MESH_EXTRAS_READER; +} + +std::vector ReadMeshExtensionsTargetsName(const json_value_s& j) +{ + auto& jsonObject = json::Cast(j); + std::vector result; + + auto element = jsonObject.start; + while(element) + { + auto jsonString = *element->name; + uint32_t index = json::Read::Number(*element->value); + + if(result.size() <= index) + { + result.resize(index + 1u); + } + + result[index] = json::Read::StringView(jsonString); + + element = element->next; + } + return result; +} + +const json::Reader& GetMeshExtensionsReader() +{ + static const auto MESH_EXTENSIONS_READER = std::move(json::Reader() + .Register(*json::MakeProperty("SXR_targets_names", ReadMeshExtensionsTargetsName, &gltf2::Mesh::Extensions::mSXRTargetsNames)) + .Register(*json::MakeProperty("avatar_shape_names", ReadMeshExtensionsTargetsName, &gltf2::Mesh::Extensions::mAvatarShapeNames))); + return MESH_EXTENSIONS_READER; +} + const json::Reader& GetMeshReader() { static const auto MESH_READER = std::move(json::Reader() @@ -288,7 +326,9 @@ const json::Reader& GetMeshReader() .Register(*json::MakeProperty("primitives", json::Read::Array::Read>, &gltf2::Mesh::mPrimitives)) - .Register(*json::MakeProperty("weights", json::Read::Array, &gltf2::Mesh::mWeights))); + .Register(*json::MakeProperty("weights", json::Read::Array, &gltf2::Mesh::mWeights)) + .Register(*json::MakeProperty("extras", json::ObjectReader::Read, &gltf2::Mesh::mExtras)) + .Register(*json::MakeProperty("extensions", json::ObjectReader::Read, &gltf2::Mesh::mExtensions))); return MESH_READER; } @@ -541,8 +581,7 @@ void AddTextureStage(uint32_t semantic, MaterialDefinition& materialDefinition, void ConvertMaterial(const gltf2::Material& material, const std::unordered_map& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials, ConversionContext& context) { - auto getTextureMetaData = [](const std::unordered_map& metaData, const gltf2::TextureInfo& info) - { + auto getTextureMetaData = [](const std::unordered_map& metaData, const gltf2::TextureInfo& info) { if(!info.mTexture->mSource->mUri.empty()) { if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end()) @@ -796,6 +835,7 @@ void ConvertMeshes(const gltf2::Document& document, ConversionContext& context) { meshDefinition.mBlendShapes.reserve(primitive.mTargets.size()); meshDefinition.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0; + uint32_t blendShapeIndex = 0u; for(const auto& target : primitive.mTargets) { MeshDefinition::BlendShape blendShape; @@ -822,7 +862,22 @@ void ConvertMeshes(const gltf2::Document& document, ConversionContext& context) blendShape.weight = mesh.mWeights[meshDefinition.mBlendShapes.size()]; } + // Get blendshape name from extras / SXR_targets_names / avatar_shape_names. + if(blendShapeIndex < mesh.mExtras.mTargetNames.size()) + { + blendShape.name = mesh.mExtras.mTargetNames[blendShapeIndex]; + } + else if(blendShapeIndex < mesh.mExtensions.mSXRTargetsNames.size()) + { + blendShape.name = mesh.mExtensions.mSXRTargetsNames[blendShapeIndex]; + } + else if(blendShapeIndex < mesh.mExtensions.mAvatarShapeNames.size()) + { + blendShape.name = mesh.mExtensions.mAvatarShapeNames[blendShapeIndex]; + } + meshDefinition.mBlendShapes.push_back(std::move(blendShape)); + ++blendShapeIndex; } } @@ -900,8 +955,7 @@ void ConvertNode(gltf2::Node const& node, const Index gltfIndex, Index parentInd auto& resources = output.mResources; const auto index = scene.GetNodeCount(); - auto weakNode = scene.AddNode([&]() - { + auto weakNode = scene.AddNode([&]() { std::unique_ptr nodeDefinition{new NodeDefinition()}; nodeDefinition->mParentIdx = parentIndex; @@ -1333,6 +1387,8 @@ void SetObjectReaders() json::SetObjectReader(GetMaterialExtensionsReader()); json::SetObjectReader(GetMaterialReader()); json::SetObjectReader(GetMeshPrimitiveReader()); + json::SetObjectReader(GetMeshExtrasReader()); + json::SetObjectReader(GetMeshExtensionsReader()); json::SetObjectReader(GetMeshReader()); json::SetObjectReader(GetSkinReader()); json::SetObjectReader(GetCameraPerspectiveReader()); diff --git a/dali-scene3d/internal/loader/json-reader.h b/dali-scene3d/internal/loader/json-reader.h index 100472a..45e4e42 100644 --- a/dali-scene3d/internal/loader/json-reader.h +++ b/dali-scene3d/internal/loader/json-reader.h @@ -170,10 +170,15 @@ struct Read return static_cast(number); } + static std::string_view StringView(const json_string_s& js) + { + return std::string_view(js.string, js.string_size); + } + static std::string_view StringView(const json_value_s& j) { auto& js = Cast(j); - return std::string_view(js.string, js.string_size); + return StringView(js); } static std::string String(const json_value_s& j) diff --git a/dali-scene3d/internal/model-components/model-node-impl.cpp b/dali-scene3d/internal/model-components/model-node-impl.cpp index 64b3ec2..a37d4a8 100644 --- a/dali-scene3d/internal/model-components/model-node-impl.cpp +++ b/dali-scene3d/internal/model-components/model-node-impl.cpp @@ -24,8 +24,8 @@ #include // INTERNAL INCLUDES -#include #include +#include namespace Dali { @@ -280,6 +280,25 @@ Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName return Scene3D::ModelNode::DownCast(childActor); } +void ModelNode::RetrieveBlendShapeNames(std::vector& blendShapeNames) const +{ + blendShapeNames.reserve(blendShapeNames.size() + mBlendShapeIndexMap.size()); + for(const auto& iter : mBlendShapeIndexMap) + { + blendShapeNames.push_back(iter.first); + } +} + +Loader::BlendShapes::Index ModelNode::GetBlendShapeIndexByName(std::string_view blendShapeName) const +{ + auto iter = mBlendShapeIndexMap.find(std::string(blendShapeName)); + if(iter != mBlendShapeIndexMap.end()) + { + return iter->second; + } + return Loader::BlendShapes::INVALID_INDEX; +} + void ModelNode::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels) { mDiffuseTexture = diffuseTexture; @@ -321,6 +340,18 @@ void ModelNode::RemoveLight(uint32_t lightIndex) void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive) { + // Update mBlendShapeIndexMap + mBlendShapeIndexMap.clear(); + const auto blendShapeCount = data.names.size(); + for(Loader::BlendShapes::Index index = 0u; index < blendShapeCount; ++index) + { + auto& name = data.names[index]; + if(!name.empty()) + { + mBlendShapeIndexMap[name] = index; + } + } + GetImplementation(primitive).SetBlendShapeData(data); } @@ -372,8 +403,7 @@ void ModelNode::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive) Matrix inverseMatrix = boneData.inverseMatrix; // Constrain bone matrix to joint transform. - boneData.constraint = Constraint::New(renderer, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs) - { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); }); + boneData.constraint = Constraint::New(renderer, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs) { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); }); Actor joint = Self(); boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX}); diff --git a/dali-scene3d/internal/model-components/model-node-impl.h b/dali-scene3d/internal/model-components/model-node-impl.h index 4b9a66d..8a06116 100644 --- a/dali-scene3d/internal/model-components/model-node-impl.h +++ b/dali-scene3d/internal/model-components/model-node-impl.h @@ -19,9 +19,11 @@ */ // EXTERNAL INCLUDES +#include #include #include #include // for std::unique_ptr +#include // INTERNAL INCLUDES #include @@ -52,6 +54,7 @@ class DALI_SCENE3D_API ModelNode : public CustomActorImpl, public ModelPrimitive public: using ModelPrimitiveContainer = std::vector; using BoneDataContainer = std::vector; + using BlendShapeIndexMap = std::map; // Creation & Destruction /** @@ -217,6 +220,16 @@ public: // Public Method Scene3D::ModelNode FindChildModelNodeByName(std::string_view nodeName); /** + * @copydoc Dali::Scene3D::ModelNode::RetrieveBlendShapeNames() + */ + void RetrieveBlendShapeNames(std::vector& blendShapeNames) const; + + /** + * @copydoc Dali::Scene3D::ModelNode::GetBlendShapeIndexByName() + */ + Loader::BlendShapes::Index GetBlendShapeIndexByName(std::string_view blendShapeName) const; + + /** * @brief Sets the diffuse and specular image-based lighting textures for a ModelPrimitive. * * @param[in] diffuseTexture The diffuse texture. @@ -272,14 +285,15 @@ private: /// @cond internal // Not copyable or movable - DALI_INTERNAL ModelNode(const ModelNode&) = delete; ///< Deleted copy constructor. - DALI_INTERNAL ModelNode(ModelNode&&) = delete; ///< Deleted move constructor. + DALI_INTERNAL ModelNode(const ModelNode&) = delete; ///< Deleted copy constructor. + DALI_INTERNAL ModelNode(ModelNode&&) = delete; ///< Deleted move constructor. DALI_INTERNAL ModelNode& operator=(const ModelNode&) = delete; ///< Deleted copy assignment operator. - DALI_INTERNAL ModelNode& operator=(ModelNode&&) = delete; ///< Deleted move assignment operator. + DALI_INTERNAL ModelNode& operator=(ModelNode&&) = delete; ///< Deleted move assignment operator. private: ModelPrimitiveContainer mModelPrimitiveContainer; ///< List of model primitives BoneDataContainer mBoneDataContainer; + BlendShapeIndexMap mBlendShapeIndexMap; ///< Index of blend shape by name Dali::Texture mSpecularTexture; Dali::Texture mDiffuseTexture; float mIblScaleFactor{1.0f}; 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 index 0000000..bb3f1cc --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-data-impl.cpp @@ -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 + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +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(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 index 0000000..7b5316a --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-data-impl.h @@ -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 +#include +#include + +#include +#include ///< for std::pair + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +using MotionDataPtr = IntrusivePtr; + +/** + * @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> 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(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(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 index 0000000..89bcf33 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-data-load-task.cpp @@ -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 + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include + +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 we 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 we 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 index 0000000..89e9f21 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-data-load-task.h @@ -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 + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +class MotionDataLoadTask; +typedef IntrusivePtr 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 index 0000000..3848d04 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.cpp @@ -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 + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include ///< 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 index 0000000..42a3b35 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-index/blend-shape-index-impl.h @@ -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 +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +using BlendShapeIndexPtr = IntrusivePtr; + +/** + * @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(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(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 index 0000000..2482c30 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-index/motion-index-impl.cpp @@ -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 + +// 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 index 0000000..8ca93a6 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-index/motion-index-impl.h @@ -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 +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +using MotionIndexPtr = IntrusivePtr; + +/** + * @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(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(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 index 0000000..3bfe3a5 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.cpp @@ -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 + +// EXTERNAL INCLUDES +#include +#include + +// 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 index 0000000..081dd97 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-index/motion-property-index-impl.h @@ -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 +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +using MotionPropertyIndexPtr = IntrusivePtr; + +/** + * @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(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(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 index 0000000..e3babc8 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.cpp @@ -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 + +// EXTERNAL INCLUDES +#include +#include +#include + +// 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 index 0000000..72dc345 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-index/motion-transform-index-impl.h @@ -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 +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +using MotionTransformIndexPtr = IntrusivePtr; + +/** + * @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(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(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 index 0000000..d8189d1 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-value-impl.cpp @@ -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 + +// EXTERNAL INCLUDES +#include +#include +#include + +// 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 index 0000000..b5bf343 --- /dev/null +++ b/dali-scene3d/internal/model-motion/motion-value-impl.h @@ -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 +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +using MotionValuePtr = IntrusivePtr; + +/** + * @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(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(handle); +} + +} // namespace Scene3D + +} // namespace Dali + +#endif // DALI_SCENE3D_MODEL_MOTION_MOTION_VALUE_IMPL_H \ No newline at end of file diff --git a/dali-scene3d/public-api/controls/model/model.cpp b/dali-scene3d/public-api/controls/model/model.cpp index 0df438c..a02e466 100644 --- a/dali-scene3d/public-api/controls/model/model.cpp +++ b/dali-scene3d/public-api/controls/model/model.cpp @@ -148,6 +148,26 @@ ModelNode Model::FindChildModelNodeByName(std::string_view nodeName) return GetImpl(*this).FindChildModelNodeByName(nodeName); } +void Model::RetrieveBlendShapeNames(std::vector& blendShapeNames) const +{ + GetImpl(*this).RetrieveBlendShapeNames(blendShapeNames); +} + +void Model::RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector& modelNodes) const +{ + 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 diff --git a/dali-scene3d/public-api/controls/model/model.h b/dali-scene3d/public-api/controls/model/model.h index 8025c64..bbb2a6d 100644 --- a/dali-scene3d/public-api/controls/model/model.h +++ b/dali-scene3d/public-api/controls/model/model.h @@ -27,6 +27,7 @@ // INTERNAL INCLUDES #include #include +#include namespace Dali { @@ -323,6 +324,47 @@ public: */ ModelNode FindChildModelNodeByName(std::string_view nodeName); + /** + * @brief Retrieve the list of blendshape name that current Model hold. + * The name will be appended end of input list. + * + * @SINCE_2_2.99 + * @param[in, out] blendShapeNames The name of blendShape list collected. + * @note This method should be called after Model load finished. + */ + void RetrieveBlendShapeNames(std::vector& blendShapeNames) const; + + /** + * @brief Retrieve the list of ModelNode that contains given blend shape name. + * The ModelNode will be appended end of input list. + * + * @SINCE_2_2.99 + * @param[in] blendShapeName The name of blendShape that want to collect. + * @param[in, out] modelNodes The ModelNode list collected. + * @note This method should be called after Model load finished. + */ + void RetrieveModelNodesByBlendShapeName(std::string_view blendShapeName, std::vector& modelNodes) const; + + /** + * @brief Generate specific animation of this Model by inputed MotionData. + * + * @SINCE_2_2.99 + * @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 setted. + * + * @SINCE_2_2.99 + * @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 /** diff --git a/dali-scene3d/public-api/file.list b/dali-scene3d/public-api/file.list index 43e992f..70c1f6c 100644 --- a/dali-scene3d/public-api/file.list +++ b/dali-scene3d/public-api/file.list @@ -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 diff --git a/dali-scene3d/public-api/loader/animated-property.cpp b/dali-scene3d/public-api/loader/animated-property.cpp index 15110c7..e357516 100644 --- a/dali-scene3d/public-api/loader/animated-property.cpp +++ b/dali-scene3d/public-api/loader/animated-property.cpp @@ -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)) { diff --git a/dali-scene3d/public-api/loader/animated-property.h b/dali-scene3d/public-api/loader/animated-property.h index 07b251f..90b8a02 100644 --- a/dali-scene3d/public-api/loader/animated-property.h +++ b/dali-scene3d/public-api/loader/animated-property.h @@ -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 diff --git a/dali-scene3d/public-api/loader/animation-definition.cpp b/dali-scene3d/public-api/loader/animation-definition.cpp index d35631d..d9ee5dd 100644 --- a/dali-scene3d/public-api/loader/animation-definition.cpp +++ b/dali-scene3d/public-api/loader/animation-definition.cpp @@ -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(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 diff --git a/dali-scene3d/public-api/loader/animation-definition.h b/dali-scene3d/public-api/loader/animation-definition.h index 9b8393c..914dfa7 100644 --- a/dali-scene3d/public-api/loader/animation-definition.h +++ b/dali-scene3d/public-api/loader/animation-definition.h @@ -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/loader/blend-shape-details.h b/dali-scene3d/public-api/loader/blend-shape-details.h index e7d2eb4..d7d6325 100644 --- a/dali-scene3d/public-api/loader/blend-shape-details.h +++ b/dali-scene3d/public-api/loader/blend-shape-details.h @@ -22,6 +22,7 @@ #include #include #include +#include ///< for std::numeric_limits #include // INTERNAL INCLUDES @@ -34,6 +35,9 @@ struct MeshGeometry; struct DALI_SCENE3D_API BlendShapes { + using Index = uint32_t; + static constexpr Index INVALID_INDEX = std::numeric_limits::max(); + enum class Version { VERSION_1_0, @@ -53,12 +57,13 @@ struct DALI_SCENE3D_API BlendShapes struct BlendShapeData { - std::vector weights; - std::vector unnormalizeFactors; - Version version{Scene3D::Loader::BlendShapes::Version::INVALID}; - uint32_t bufferOffset{0}; - int32_t components{0x0}; - Dali::WeakHandle mActor; + std::vector names; + std::vector weights; + std::vector unnormalizeFactors; + Version version{Scene3D::Loader::BlendShapes::Version::INVALID}; + uint32_t bufferOffset{0}; + int32_t components{0x0}; + Dali::WeakHandle mActor; }; // shader properties - animatable (uniforms) diff --git a/dali-scene3d/public-api/loader/scene-definition.cpp b/dali-scene3d/public-api/loader/scene-definition.cpp index 10f6866..cf5aa61 100644 --- a/dali-scene3d/public-api/loader/scene-definition.cpp +++ b/dali-scene3d/public-api/loader/scene-definition.cpp @@ -860,6 +860,7 @@ bool SceneDefinition::ConfigureBlendshapeShaders(const ResourceBundle& data.components = 0x0; for(auto&& blendShape : mesh.first.mBlendShapes) { + data.names.push_back(blendShape.name); data.weights.push_back(blendShape.weight); data.components |= (blendShape.deltas.IsDefined() * BlendShapes::Component::POSITIONS) | (blendShape.normals.IsDefined() * BlendShapes::Component::NORMALS) | (blendShape.tangents.IsDefined() * BlendShapes::Component::TANGENTS); diff --git a/dali-scene3d/public-api/model-components/model-node.cpp b/dali-scene3d/public-api/model-components/model-node.cpp index 583cdd0..a664eeb 100644 --- a/dali-scene3d/public-api/model-components/model-node.cpp +++ b/dali-scene3d/public-api/model-components/model-node.cpp @@ -118,6 +118,16 @@ ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName) return Internal::GetImplementation(*this).FindChildModelNodeByName(nodeName); } +void ModelNode::RetrieveBlendShapeNames(std::vector& blendShapeNames) const +{ + return Internal::GetImplementation(*this).RetrieveBlendShapeNames(blendShapeNames); +} + +Loader::BlendShapes::Index ModelNode::GetBlendShapeIndexByName(std::string_view blendShapeName) const +{ + return Internal::GetImplementation(*this).GetBlendShapeIndexByName(blendShapeName); +} + } // namespace Scene3D } // namespace Dali diff --git a/dali-scene3d/public-api/model-components/model-node.h b/dali-scene3d/public-api/model-components/model-node.h index dc3e717..ffd469d 100644 --- a/dali-scene3d/public-api/model-components/model-node.h +++ b/dali-scene3d/public-api/model-components/model-node.h @@ -24,6 +24,7 @@ // INTERNAL INCLUDES #include +#include ///< For Loader::BlendShapes::Index #include namespace Dali @@ -136,7 +137,6 @@ public: static ModelNode DownCast(BaseHandle handle); public: // Public Method - /** * @brief Gets the number of ModelPrimitives this node has. * @@ -186,6 +186,22 @@ public: // Public Method */ ModelNode FindChildModelNodeByName(std::string_view nodeName); + /** + * @brief Retrieve the list of blendshape name that current ModelNode hold. + * The name will be appended end of input list. + * + * @param[in, out] blendShapeNames The name of blendShape list collected. + */ + void RetrieveBlendShapeNames(std::vector& blendShapeNames) const; + + /** + * @brief Get the index of blend shape by given name. + * + * @param[in] blendShapeName The name of blendshape that is not empty. + * @return Index of blendshape, or return invalid if there is no blendshape with given name. + */ + Loader::BlendShapes::Index GetBlendShapeIndexByName(std::string_view blendShapeName) const; + public: // Not intended for application developers /// @cond internal /** 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 index 0000000..f9418b5 --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-data.cpp @@ -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 + +// INTERNAL INCLUDES +#include + +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(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 index 0000000..438e6af --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-data.h @@ -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 +#include + +// INTERNAL INCLUDES +#include +#include +#include + +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.99 + */ +class DALI_SCENE3D_API MotionData : public Dali::BaseHandle +{ +public: + /// @brief LoadCompleted signal type. @SINCE_2_2.99 + typedef Signal LoadCompletedSignalType; + +public: // Creation & Destruction + /** + * @brief Create an initialized MotionData. + * + * @SINCE_2_2.99 + * @return A handle to a newly allocated Dali resource + */ + static MotionData New(); + + /** + * @brief Create an initialized MotionData with duration. + * + * @SINCE_2_2.99 + * @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.99 + */ + MotionData(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + * + * @SINCE_2_2.99 + */ + ~MotionData(); + + /** + * @brief Copy constructor. + * + * @SINCE_2_2.99 + * @param[in] motionData Handle to an object + */ + MotionData(const MotionData& motionData); + + /** + * @brief Move constructor + * + * @SINCE_2_2.99 + * @param[in] rhs A reference to the moved handle + */ + MotionData(MotionData&& rhs) noexcept; + + /** + * @brief Assignment operator. + * + * @SINCE_2_2.99 + * @param[in] motionData Handle to an object + * @return reference to this + */ + MotionData& operator=(const MotionData& motionData); + + /** + * @brief Move assignment + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + * @return The number of motions + */ + uint32_t GetMotionCount() const; + + /** + * @brief Get MotionIndex from given index'th. + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + * @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.99 + */ + void Clear(); + + /** + * @brief Set the duration of this motion data if it be generated as Dali::Animation. + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + * @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.99 + * @param[in] rawBuffer The bvh buffer. + * @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 facail defined json file. + * It will use Dali::Scene3D::Loader::LoadFacialAnimation() internally. + * LoadCompleteSignal() will be emitted after load completed. + * + * @SINCE_2_2.99 + * @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 facail defined json file. + * It will use Dali::Scene3D::Loader::LoadFacialAnimationFromBuffer() internally. + * LoadCompleteSignal() will be emitted after load completed. + * + * @SINCE_2_2.99 + * @param[in] rawBuffer The raw buffer containing the facial animation. + * @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.99 + * @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 index 0000000..549c80a --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.cpp @@ -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 + +// INTERNAL INCLUDES +#include + +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(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 index 0000000..901f37d --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h @@ -0,0 +1,179 @@ +#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 + +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 blendshape. + * Specially, if ModelNodeId is Property::INVALID_KEY and BlendShapeId is StringKey, + * It will control all ModelNode that has the inputed BlendShape name. + * + * @SINCE_2_2.99 + */ +class DALI_SCENE3D_API BlendShapeIndex : public MotionIndex +{ +public: // Creation & Destruction + /** + * @brief Create an initialized BlendShapeIndex. + * + * @SINCE_2_2.99 + * @return A handle to a newly allocated Dali resource + */ + static BlendShapeIndex New(); + + /** + * @brief Create an initialized BlendShapeIndex with values. + * + * @SINCE_2_2.99 + * @param[in] blendShapeId The id of blendshape 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.99 + * @param[in] modelNodeId The id of model node what this motion index looks. + * @param[in] blendShapeId The id of blendshape 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.99 + */ + BlendShapeIndex(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + * + * @SINCE_2_2.99 + */ + ~BlendShapeIndex(); + + /** + * @brief Copy constructor. + * + * @SINCE_2_2.99 + * @param[in] blendShapeIndex Handle to an object + */ + BlendShapeIndex(const BlendShapeIndex& blendShapeIndex); + + /** + * @brief Move constructor + * + * @SINCE_2_2.99 + * @param[in] rhs A reference to the moved handle + */ + BlendShapeIndex(BlendShapeIndex&& rhs) noexcept; + + /** + * @brief Assignment operator. + * + * @SINCE_2_2.99 + * @param[in] blendShapeIndex Handle to an object + * @return reference to this + */ + BlendShapeIndex& operator=(const BlendShapeIndex& blendShapeIndex); + + /** + * @brief Move assignment + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + * @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.99 + * @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 index 0000000..eaa3ad9 --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-index/motion-index.cpp @@ -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 + +// INTERNAL INCLUDES +#include + +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(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 index 0000000..4355b99 --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-index/motion-index.h @@ -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 +#include +#include + +// INTERNAL INCLUDES +#include + +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.99 + */ +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.99 + */ + MotionIndex(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + * + * @SINCE_2_2.99 + */ + ~MotionIndex(); + + /** + * @brief Copy constructor. + * + * @SINCE_2_2.99 + * @param[in] motionIndex Handle to an object + */ + MotionIndex(const MotionIndex& motionIndex); + + /** + * @brief Move constructor + * + * @SINCE_2_2.99 + * @param[in] rhs A reference to the moved handle + */ + MotionIndex(MotionIndex&& rhs) noexcept; + + /** + * @brief Assignment operator. + * + * @SINCE_2_2.99 + * @param[in] motionIndex Handle to an object + * @return reference to this + */ + MotionIndex& operator=(const MotionIndex& motionIndex); + + /** + * @brief Move assignment + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + * @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.99 + * @return The model node id. + */ + Property::Key GetModelNodeId() const; + + /** + * @brief Get the property name of this MotionIndex from given ModelNode. + * + * @SINCE_2_2.99 + * @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.99 + * @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 index 0000000..3dc7d76 --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-index/motion-property-index.cpp @@ -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 + +// INTERNAL INCLUDES +#include + +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(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 index 0000000..335fb41 --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-index/motion-property-index.h @@ -0,0 +1,168 @@ +#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 + +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. + * + * @SINCE_2_2.99 + */ +class DALI_SCENE3D_API MotionPropertyIndex : public MotionIndex +{ +public: // Creation & Destruction + /** + * @brief Create an initialized MotionPropertyIndex. + * + * @SINCE_2_2.99 + * @return A handle to a newly allocated Dali resource + */ + static MotionPropertyIndex New(); + + /** + * @brief Create an initialized MotionPropertyIndex with values. + * + * @SINCE_2_2.99 + * @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.99 + */ + MotionPropertyIndex(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + * + * @SINCE_2_2.99 + */ + ~MotionPropertyIndex(); + + /** + * @brief Copy constructor. + * + * @SINCE_2_2.99 + * @param[in] motionPropertyIndex Handle to an object + */ + MotionPropertyIndex(const MotionPropertyIndex& motionPropertyIndex); + + /** + * @brief Move constructor + * + * @SINCE_2_2.99 + * @param[in] rhs A reference to the moved handle + */ + MotionPropertyIndex(MotionPropertyIndex&& rhs) noexcept; + + /** + * @brief Assignment operator. + * + * @SINCE_2_2.99 + * @param[in] motionPropertyIndex Handle to an object + * @return reference to this + */ + MotionPropertyIndex& operator=(const MotionPropertyIndex& motionPropertyIndex); + + /** + * @brief Move assignment + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + * @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.99 + * @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 index 0000000..5ea483f --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.cpp @@ -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 + +// INTERNAL INCLUDES +#include + +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(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 index 0000000..d90f546 --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h @@ -0,0 +1,190 @@ +#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 + +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. + * + * @SINCE_2_2.99 + */ +class DALI_SCENE3D_API MotionTransformIndex : public MotionIndex +{ +public: + /** + * @brief The type of Transform + * @SINCE_2_2.99 + */ + 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.99 + * @return A handle to a newly allocated Dali resource + */ + static MotionTransformIndex New(); + + /** + * @brief Create an initialized MotionTransformIndex with values. + * + * @SINCE_2_2.99 + * @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.99 + */ + MotionTransformIndex(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + * + * @SINCE_2_2.99 + */ + ~MotionTransformIndex(); + + /** + * @brief Copy constructor. + * + * @SINCE_2_2.99 + * @param[in] motionTransformIndex Handle to an object + */ + MotionTransformIndex(const MotionTransformIndex& motionTransformIndex); + + /** + * @brief Move constructor + * + * @SINCE_2_2.99 + * @param[in] rhs A reference to the moved handle + */ + MotionTransformIndex(MotionTransformIndex&& rhs) noexcept; + + /** + * @brief Assignment operator. + * + * @SINCE_2_2.99 + * @param[in] motionTransformIndex Handle to an object + * @return reference to this + */ + MotionTransformIndex& operator=(const MotionTransformIndex& motionTransformIndex); + + /** + * @brief Move assignment + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + * @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.99 + * @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 index 0000000..dd5b00a --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-value.cpp @@ -0,0 +1,113 @@ +/* + * 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 + +// INTERNAL INCLUDES +#include + +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(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::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 index 0000000..96bdb5e7 --- /dev/null +++ b/dali-scene3d/public-api/model-motion/motion-value.h @@ -0,0 +1,232 @@ +#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 +#include +#include +#include + +// INTERNAL INCLUDES +#include + +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.99 + */ +class DALI_SCENE3D_API MotionValue : public Dali::BaseHandle +{ +public: + /** + * @brief Determine whether current stored value is PropertyValue, or KeyFrames. + * @SINCE_2_2.99 + */ + 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.99 + * @return A handle to a newly allocated Dali resource + */ + static MotionValue New(); + + /** + * @brief Create an initialized MotionValue with Property::Value. + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + */ + MotionValue(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + * + * @SINCE_2_2.99 + */ + ~MotionValue(); + + /** + * @brief Copy constructor. + * + * @SINCE_2_2.99 + * @param[in] motionValue Handle to an object + */ + MotionValue(const MotionValue& motionValue); + + /** + * @brief Move constructor + * + * @SINCE_2_2.99 + * @param[in] rhs A reference to the moved handle + */ + MotionValue(MotionValue&& rhs) noexcept; + + /** + * @brief Assignment operator. + * + * @SINCE_2_2.99 + * @param[in] motionValue Handle to an object + * @return reference to this + */ + MotionValue& operator=(const MotionValue& motionValue); + + /** + * @brief Move assignment + * + * @SINCE_2_2.99 + * @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.99 + * @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.99 + * @return Type of value. + */ + ValueType GetValueType() const; + + /** + * @brief Set the value as Property::Value type. + * + * @SINCE_2_2.99 + * @param[in] propertyValue The static value. + */ + void SetValue(Property::Value propertyValue); + + /** + * @brief Set the value as KeyFrames type. + * + * @SINCE_2_2.99 + * @param[in] keyFrames The keyframes value. + */ + void SetValue(KeyFrames keyFrames); + + /** + * @brief Make value as Invalid type. + * + * @SINCE_2_2.99 + */ + 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.99 + * @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.99 + * @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 -- 2.7.4