[dali_2.3.24] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / facial-animation-loader.cpp
index 26afb29..4f1d5e1 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.\r
  *\r
  * Licensed under the Apache License, Version 2.0 (the "License");\r
  * you may not use this file except in compliance with the License.\r
@@ -19,6 +19,7 @@
 #include <dali-scene3d/public-api/loader/facial-animation-loader.h>\r
 \r
 // EXTERNAL INCLUDES\r
+#include <dali/devel-api/animation/key-frames-devel.h>\r
 #include <sstream>\r
 \r
 // INTERNAL INCLUDES\r
@@ -74,48 +75,29 @@ std::vector<std::vector<float>> ReadBlendShapeKeys(const json_value_s& j)
 const js::Reader<BlendShape>& GetBlendShapeReader()\r
 {\r
   static const auto BLEND_SHAPE_READER = std::move(js::Reader<BlendShape>()\r
-                                                      .Register(*js::MakeProperty("key", ReadBlendShapeKeys, &BlendShape::mKeys))\r
-                                                      .Register(*new js::Property<BlendShape, std::string_view>("name", js::Read::StringView, &BlendShape::mNodeName))\r
-                                                      .Register(*js::MakeProperty("morphtarget", js::Read::Number<uint32_t>, &BlendShape::mNumberOfMorphTarget))\r
-                                                      .Register(*new js::Property<BlendShape, std::string_view>("blendShapeVersion", js::Read::StringView, &BlendShape::mVersion))\r
-                                                      .Register(*new js::Property<BlendShape, std::string_view>("fullName", js::Read::StringView, &BlendShape::mFullName))\r
-                                                      .Register(*js::MakeProperty("morphname", js::Read::Array<std::string_view, js::Read::StringView>, &BlendShape::mMorphNames)));\r
+                                                     .Register(*js::MakeProperty("key", ReadBlendShapeKeys, &BlendShape::mKeys))\r
+                                                     .Register(*new js::Property<BlendShape, std::string_view>("name", js::Read::StringView, &BlendShape::mNodeName))\r
+                                                     .Register(*js::MakeProperty("morphtarget", js::Read::Number<uint32_t>, &BlendShape::mNumberOfMorphTarget))\r
+                                                     .Register(*new js::Property<BlendShape, std::string_view>("blendShapeVersion", js::Read::StringView, &BlendShape::mVersion))\r
+                                                     .Register(*new js::Property<BlendShape, std::string_view>("fullName", js::Read::StringView, &BlendShape::mFullName))\r
+                                                     .Register(*js::MakeProperty("morphname", js::Read::Array<std::string_view, js::Read::StringView>, &BlendShape::mMorphNames)));\r
   return BLEND_SHAPE_READER;\r
 }\r
 \r
 const js::Reader<FacialAnimation>& GetFacialAnimationReader()\r
 {\r
   static const auto FACIAL_ANIMATION_READER = std::move(js::Reader<FacialAnimation>()\r
-                                                           .Register(*new js::Property<FacialAnimation, std::string_view>("name", js::Read::StringView, &FacialAnimation::mName))\r
-                                                           .Register(*js::MakeProperty("blendShapes", js::Read::Array<BlendShape, js::ObjectReader<BlendShape>::Read>, &FacialAnimation::mBlendShapes))\r
-                                                           .Register(*new js::Property<FacialAnimation, std::string_view>("version", js::Read::StringView, &FacialAnimation::mVersion))\r
-                                                           .Register(*js::MakeProperty("shapesAmount", js::Read::Number<uint32_t>, &FacialAnimation::mNumberOfShapes))\r
-                                                           .Register(*js::MakeProperty("time", js::Read::Array<uint32_t, js::Read::Number>, &FacialAnimation::mTime))\r
-                                                           .Register(*js::MakeProperty("frames", js::Read::Number<uint32_t>, &FacialAnimation::mNumberOfFrames)));\r
+                                                          .Register(*new js::Property<FacialAnimation, std::string_view>("name", js::Read::StringView, &FacialAnimation::mName))\r
+                                                          .Register(*js::MakeProperty("blendShapes", js::Read::Array<BlendShape, js::ObjectReader<BlendShape>::Read>, &FacialAnimation::mBlendShapes))\r
+                                                          .Register(*new js::Property<FacialAnimation, std::string_view>("version", js::Read::StringView, &FacialAnimation::mVersion))\r
+                                                          .Register(*js::MakeProperty("shapesAmount", js::Read::Number<uint32_t>, &FacialAnimation::mNumberOfShapes))\r
+                                                          .Register(*js::MakeProperty("time", js::Read::Array<uint32_t, js::Read::Number>, &FacialAnimation::mTime))\r
+                                                          .Register(*js::MakeProperty("frames", js::Read::Number<uint32_t>, &FacialAnimation::mNumberOfFrames)));\r
   return FACIAL_ANIMATION_READER;\r
 }\r
 \r
-} // unnamed namespace\r
-\r
-namespace Scene3D\r
-{\r
-namespace Loader\r
+Dali::Scene3D::Loader::AnimationDefinition LoadFacialAnimationInternal(json::unique_ptr& root)\r
 {\r
-AnimationDefinition LoadFacialAnimation(const std::string& url)\r
-{\r
-  bool failed = false;\r
-  auto js     = LoadTextFile(url.c_str(), &failed);\r
-  if(failed)\r
-  {\r
-    ExceptionFlinger(ASSERT_LOCATION) << "Failed to load " << url << ".";\r
-  }\r
-\r
-  json::unique_ptr root(json_parse(js.c_str(), js.size()));\r
-  if(!root)\r
-  {\r
-    ExceptionFlinger(ASSERT_LOCATION) << "Failed to parse " << url << ".";\r
-  }\r
-\r
   static bool setObjectReaders = true;\r
   if(setObjectReaders)\r
   {\r
@@ -129,7 +111,7 @@ AnimationDefinition LoadFacialAnimation(const std::string& url)
   FacialAnimation facialAnimation;\r
   GetFacialAnimationReader().Read(rootObj, facialAnimation);\r
 \r
-  AnimationDefinition animationDefinition;\r
+  Dali::Scene3D::Loader::AnimationDefinition animationDefinition;\r
   animationDefinition.SetName(facialAnimation.mName.data());\r
   animationDefinition.SetDuration(MILLISECONDS_TO_SECONDS * static_cast<float>(facialAnimation.mTime[facialAnimation.mNumberOfFrames - 1u]));\r
 \r
@@ -146,11 +128,11 @@ AnimationDefinition LoadFacialAnimation(const std::string& url)
   {\r
     for(uint32_t morphTargetIndex = 0u; morphTargetIndex < blendShape.mNumberOfMorphTarget; ++morphTargetIndex)\r
     {\r
-      AnimatedProperty animatedProperty;\r
+      Dali::Scene3D::Loader::AnimatedProperty animatedProperty;\r
       animatedProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());\r
-      animatedProperty.mNodeName = blendShape.mNodeName;\r
+      animatedProperty.mNodeName   = blendShape.mNodeName;\r
       std::stringstream weightPropertyStream;\r
-      weightPropertyStream << BlendShapes::WEIGHTS_UNIFORM << "[" << morphTargetIndex << "]";\r
+      weightPropertyStream << Dali::Scene3D::Loader::BlendShapes::WEIGHTS_UNIFORM << "[" << morphTargetIndex << "]";\r
       animatedProperty.mPropertyName = weightPropertyStream.str();\r
 \r
       animatedProperty.mKeyFrames = Dali::KeyFrames::New();\r
@@ -159,6 +141,8 @@ AnimationDefinition LoadFacialAnimation(const std::string& url)
         const float progress = MILLISECONDS_TO_SECONDS * static_cast<float>(facialAnimation.mTime[timeIndex]) / animationDefinition.GetDuration();\r
         animatedProperty.mKeyFrames.Add(progress, blendShape.mKeys[timeIndex][morphTargetIndex]);\r
       }\r
+      // Optimize keyframes, for heuristic!\r
+      DevelKeyFrames::OptimizeKeyFramesLinear(animatedProperty.mKeyFrames);\r
       animationDefinition.SetProperty(targets + morphTargetIndex, std::move(animatedProperty));\r
     }\r
 \r
@@ -167,7 +151,40 @@ AnimationDefinition LoadFacialAnimation(const std::string& url)
 \r
   return animationDefinition;\r
 }\r
+} // unnamed namespace\r
+\r
+namespace Scene3D\r
+{\r
+namespace Loader\r
+{\r
+AnimationDefinition LoadFacialAnimation(const std::string& url)\r
+{\r
+  bool failed   = false;\r
+  auto jsonData = LoadTextFile(url.c_str(), &failed);\r
+  if(failed)\r
+  {\r
+    ExceptionFlinger(ASSERT_LOCATION) << "Failed to load " << url << ".";\r
+  }\r
+\r
+  json::unique_ptr root(json_parse(jsonData.c_str(), jsonData.size()));\r
+  if(!root)\r
+  {\r
+    ExceptionFlinger(ASSERT_LOCATION) << "Failed to parse json " << url << ".";\r
+  }\r
+\r
+  return LoadFacialAnimationInternal(root);\r
+}\r
+\r
+AnimationDefinition LoadFacialAnimationFromBuffer(const uint8_t* rawBuffer, int rawBufferLength)\r
+{\r
+  json::unique_ptr root(json_parse(rawBuffer, static_cast<size_t>(static_cast<uint32_t>(rawBufferLength))));\r
+  if(!root)\r
+  {\r
+    ExceptionFlinger(ASSERT_LOCATION) << "Failed to parse json from buffer.";\r
+  }\r
 \r
+  return LoadFacialAnimationInternal(root);\r
+}\r
 } // namespace Loader\r
 } // namespace Scene3D\r
 } // namespace Dali\r