[dali_2.2.15] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / dli-loader.cpp
index ca28c83..8953f1a 100644 (file)
@@ -57,19 +57,18 @@ namespace rs = RendererState;
 
 namespace
 {
-const std::string NODES         = "nodes";
-const std::string SCENES        = "scenes";
-const std::string NODE          = "node";
-const std::string URI           = "uri";
-const std::string URL           = "url";
-const std::string CUSTOMIZATION = "customization";
-const std::string HINTS         = "hints";
-const std::string NAME("name");
-const std::string BLEND_SHAPE_HEADER("blendShapeHeader");
-const std::string BLEND_SHAPES("blendShapes");
-const std::string BLEND_SHAPE_VERSION_1_0("1.0");
-const std::string BLEND_SHAPE_VERSION_2_0("2.0");
-const std::string VERSION("version");
+const char* NODES         = "nodes";
+const char* SCENES        = "scenes";
+const char* NODE          = "node";
+const char* URI           = "uri";
+const char* URL           = "url";
+const char* HINTS         = "hints";
+const char* NAME("name");
+const char* BLEND_SHAPE_HEADER("blendShapeHeader");
+const char* BLEND_SHAPES("blendShapes");
+const char* BLEND_SHAPE_VERSION_1_0("1.0");
+const char* BLEND_SHAPE_VERSION_2_0("2.0");
+const char* VERSION("version");
 
 const char* const SHADOW_MAP_SIZE   = "shadowMapSize";
 const char* const ORTHOGRAPHIC_SIZE = "orthographicSize";
@@ -145,7 +144,7 @@ RendererState::Type ReadRendererState(const TreeNode& tnRendererState)
 }
 
 ///@brief Reads arc properties.
-void ReadArcField(const TreeNode* eArc, ArcNode& arc)
+void ReadArcField(const TreeNode* eArc, ArcRenderable& arc)
 {
   ReadBool(eArc->GetChild("antiAliasing"), arc.mAntiAliasing);
   ReadInt(eArc->GetChild("arcCaps"), arc.mArcCaps);
@@ -301,7 +300,7 @@ void ParseProperties(const Toolkit::TreeNode& node, Property::Array& array)
   }
 }
 
-} //namespace
+} // namespace
 
 struct DliLoader::Impl
 {
@@ -407,76 +406,78 @@ void DliLoader::Impl::ParseScene(LoadParams& params)
 
   // get index of root node.
   auto docRoot = mParser.GetRoot();
-
-  // Process resources first - these are shared
-  if(auto environments = docRoot->GetChild("environment"))
+  if(docRoot)
   {
-    ParseEnvironments(environments, output.mResources); // NOTE: must precede parsing of materials
-  }
+    // Process resources first - these are shared
+    if(auto environments = docRoot->GetChild("environment"))
+    {
+      ParseEnvironments(environments, output.mResources); // NOTE: must precede parsing of materials
+    }
 
-  if(auto meshes = docRoot->GetChild("meshes"))
-  {
-    ParseMeshes(meshes, output.mResources);
-  }
+    if(auto meshes = docRoot->GetChild("meshes"))
+    {
+      ParseMeshes(meshes, output.mResources);
+    }
 
-  if(auto shaders = docRoot->GetChild("shaders"))
-  {
-    ParseShaders(shaders, output.mResources);
-  }
+    if(auto shaders = docRoot->GetChild("shaders"))
+    {
+      ParseShaders(shaders, output.mResources);
+    }
 
-  if(auto materials = docRoot->GetChild("materials"))
-  {
-    ParseMaterials(materials, input.mConvertColorCode, output.mResources);
-  }
+    if(auto materials = docRoot->GetChild("materials"))
+    {
+      ParseMaterials(materials, input.mConvertColorCode, output.mResources);
+    }
 
-  for(auto& c : input.mPreNodeCategoryProcessors)
-  {
-    if(auto node = docRoot->GetChild(c.first))
+    for(auto& c : input.mPreNodeCategoryProcessors)
     {
-      Property::Array array;
-      ParseProperties(*node, array);
-      c.second(std::move(array), mOnError);
+      if(auto node = docRoot->GetChild(c.first))
+      {
+        Property::Array array;
+        ParseProperties(*node, array);
+        c.second(std::move(array), mOnError);
+      }
     }
-  }
 
-  // Process scenes
-  Index iScene = 0; // default scene
-  ReadIndex(docRoot->GetChild("scene"), iScene);
+    // Process scenes
+    Index iScene = 0; // default scene
+    ReadIndex(docRoot->GetChild("scene"), iScene);
 
-  auto tnScenes = RequireChild(docRoot, "scenes");
-  auto tnNodes  = RequireChild(docRoot, "nodes");
-  ParseSceneInternal(iScene, tnScenes, tnNodes, params);
+    auto tnScenes = RequireChild(docRoot, "scenes");
+    auto tnNodes  = RequireChild(docRoot, "nodes");
+    ParseSceneInternal(iScene, tnScenes, tnNodes, params);
 
-  ParseSkeletons(docRoot->GetChild("skeletons"), output.mScene, output.mResources);
+    ParseSkeletons(docRoot->GetChild("skeletons"), output.mScene, output.mResources);
 
-  output.mScene.EnsureUniqueSkinningShaderInstances(output.mResources);
-  output.mScene.EnsureUniqueBlendShapeShaderInstances(output.mResources);
+    output.mScene.EnsureUniqueSkinningShaderInstances(output.mResources);
+    output.mScene.EnsureUniqueBlendShapeShaderInstances(output.mResources);
 
-  // Ger cameras and lights
-  GetCameraParameters(output.mCameraParameters);
-  GetLightParameters(output.mLightParameters);
+    // Ger cameras and lights
+    GetCameraParameters(output.mCameraParameters);
+    GetLightParameters(output.mLightParameters);
 
-  // Post-node processors and animations last
-  for(auto& c : input.mPostNodeCategoryProcessors)
-  {
-    if(auto node = docRoot->GetChild(c.first))
+    // Post-node processors and animations last
+    for(auto& c : input.mPostNodeCategoryProcessors)
     {
-      Property::Array array;
-      ParseProperties(*node, array);
-      c.second(std::move(array), mOnError);
+      if(auto node = docRoot->GetChild(c.first))
+      {
+        Property::Array array;
+        ParseProperties(*node, array);
+        c.second(std::move(array), mOnError);
+      }
     }
-  }
 
-  if(auto animations = docRoot->GetChild("animations"))
-  {
-    ParseAnimations(animations, params);
-  }
+    if(auto animations = docRoot->GetChild("animations"))
+    {
+      ParseAnimations(animations, params);
+    }
 
-  if(!output.mAnimationDefinitions.empty())
-  {
-    if(auto animationGroups = docRoot->GetChild("animationGroups"))
+    if(!output.mAnimationDefinitions.empty())
     {
-      ParseAnimationGroups(animationGroups, params);
+      if(auto animationGroups = docRoot->GetChild("animationGroups"))
+      {
+        ParseAnimationGroups(animationGroups, params);
+      }
     }
   }
 }
@@ -737,9 +738,10 @@ void DliLoader::Impl::ParseShaders(const TreeNode* shaders, ResourceBundle& reso
 
             default:
               mOnError(FormatString(
-                "shader %d: Ignoring uniform '%s': failed to infer type from %d elements.",
+                "shader %u: Ignoring uniform '%s': failed to infer type from %zu elements.",
                 iShader,
-                key.c_str()));
+                key.c_str(),
+                size));
               break;
           }
 
@@ -932,7 +934,7 @@ void DliLoader::Impl::ParseMaterials(const TreeNode* materials, ConvertColorCode
       }
     }
 
-    //TODO : need to consider AGIF
+    // TODO : need to consider AGIF
     std::vector<std::string> texturePaths;
     std::string              texturePath;
     if(ReadString(node.GetChild("albedoMap"), texturePath))
@@ -1075,9 +1077,7 @@ void DliLoader::Impl::ParseNodes(const TreeNode* const nodes, Index index, LoadP
 
     virtual unsigned int Resolve(Index iDli) override
     {
-      auto iFind = std::lower_bound(mIndices.begin(), mIndices.end(), iDli, [](const Entry& idx, Index iDli) {
-        return idx.iDli < iDli;
-      });
+      auto iFind = std::lower_bound(mIndices.begin(), mIndices.end(), iDli, [](const Entry& idx, Index iDli) { return idx.iDli < iDli; });
       DALI_ASSERT_ALWAYS(iFind != mIndices.end());
       return iFind->iScene;
     }
@@ -1157,7 +1157,7 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde
     else // something renderable maybe
     {
       std::unique_ptr<NodeDefinition::Renderable> renderable;
-      ModelNode*                                  modelNode = nullptr; // no ownership, aliasing renderable for the right type.
+      ModelRenderable*                            modelRenderable = nullptr; // no ownership, aliasing renderable for the right type.
 
       const TreeNode* eRenderable = nullptr;
       if((eRenderable = node->GetChild("model")))
@@ -1169,10 +1169,10 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde
           ExceptionFlinger(ASSERT_LOCATION) << "node " << nodeDef.mName << ": Missing mesh definition.";
         }
 
-        modelNode = new ModelNode();
-        renderable.reset(modelNode);
+        modelRenderable = new ModelRenderable();
+        renderable.reset(modelRenderable);
 
-        resourceIds.push_back({ResourceType::Mesh, eMesh, modelNode->mMeshIdx});
+        resourceIds.push_back({ResourceType::Mesh, eMesh, modelRenderable->mMeshIdx});
       }
       else if((eRenderable = node->GetChild("arc")))
       {
@@ -1183,36 +1183,42 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde
           ExceptionFlinger(ASSERT_LOCATION) << "node " << nodeDef.mName << ": Missing mesh definition.";
         }
 
-        auto arcNode = new ArcNode;
-        renderable.reset(arcNode);
-        modelNode = arcNode;
+        auto arcRenderable = new ArcRenderable;
+        renderable.reset(arcRenderable);
+        modelRenderable = arcRenderable;
 
-        resourceIds.push_back({ResourceType::Mesh, eMesh, arcNode->mMeshIdx});
+        resourceIds.push_back({ResourceType::Mesh, eMesh, arcRenderable->mMeshIdx});
 
-        ReadArcField(eRenderable, *arcNode);
+        ReadArcField(eRenderable, *arcRenderable);
       }
 
-      if(renderable) // process common properties of all renderables + register payload
+      if(renderable && eRenderable != nullptr) // process common properties of all renderables + register payload
       {
         // shader
         renderable->mShaderIdx = 0;
         auto eShader           = eRenderable->GetChild("shader");
-        resourceIds.push_back({ResourceType::Shader, eShader, renderable->mShaderIdx});
+        if(eShader)
+        {
+          resourceIds.push_back({ResourceType::Shader, eShader, renderable->mShaderIdx});
+        }
 
         // color
-        if(modelNode)
+        if(modelRenderable)
         {
-          modelNode->mMaterialIdx = 0; // must offer default of 0
-          auto eMaterial          = eRenderable->GetChild("material");
-          resourceIds.push_back({ResourceType::Material, eMaterial, modelNode->mMaterialIdx});
+          modelRenderable->mMaterialIdx = 0; // must offer default of 0
+          auto eMaterial                = eRenderable->GetChild("material");
+          if(eMaterial)
+          {
+            resourceIds.push_back({ResourceType::Material, eMaterial, modelRenderable->mMaterialIdx});
+          }
 
-          if(!ReadColorCodeOrColor(eRenderable, modelNode->mColor, params.input.mConvertColorCode))
+          if(!ReadColorCodeOrColor(eRenderable, modelRenderable->mColor, params.input.mConvertColorCode))
           {
-            ReadColorCodeOrColor(node, modelNode->mColor, params.input.mConvertColorCode);
+            ReadColorCodeOrColor(node, modelRenderable->mColor, params.input.mConvertColorCode);
           }
         }
 
-        nodeDef.mRenderable = std::move(renderable);
+        nodeDef.mRenderables.push_back(std::move(renderable));
       }
     }
 
@@ -1347,7 +1353,7 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde
     const unsigned int myIndex = output.mScene.GetNodeCount();
     if(!mapper.Map(index, myIndex))
     {
-      mOnError(FormatString("node %d: error mapping dli index %d: node has multiple parents. Ignoring subtree."));
+      mOnError(FormatString("node %d: error mapping dli index %d: node has multiple parents. Ignoring subtree.", index, myIndex));
       return;
     }
 
@@ -1418,9 +1424,7 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams&
     AnimationDefinition animDef;
     ReadString(tnAnim.GetChild(NAME), animDef.mName);
 
-    auto       iFind     = std::lower_bound(definitions.begin(), definitions.end(), animDef, [](const AnimationDefinition& ad0, const AnimationDefinition& ad1) {
-      return ad0.mName < ad1.mName;
-    });
+    auto       iFind     = std::lower_bound(definitions.begin(), definitions.end(), animDef, [](const AnimationDefinition& ad0, const AnimationDefinition& ad1) { return ad0.mName < ad1.mName; });
     const bool overwrite = iFind != definitions.end() && iFind->mName == animDef.mName;
     if(overwrite)
     {
@@ -1548,10 +1552,10 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams&
 
           animProp.mKeyFrames = KeyFrames::New();
 
-          //In binary animation file only is saved the position, rotation, scale and blend shape weight keys.
-          //so, if it is vector3 we assume is position or scale keys, if it is vector4 we assume is rotation,
-          // otherwise are blend shape weight keys.
-          // TODO support for binary header with size information
+          // In binary animation file only is saved the position, rotation, scale and blend shape weight keys.
+          // so, if it is vector3 we assume is position or scale keys, if it is vector4 we assume is rotation,
+          //  otherwise are blend shape weight keys.
+          //  TODO support for binary header with size information
           Property::Type propType = Property::FLOAT; // assume blend shape weights
           if(animProp.mPropertyName == "orientation")
           {
@@ -1562,8 +1566,8 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams&
             propType = Property::VECTOR3;
           }
 
-          //alphafunction is reserved for future implementation
-          // NOTE: right now we're just using AlphaFunction::LINEAR.
+          // alphafunction is reserved for future implementation
+          //  NOTE: right now we're just using AlphaFunction::LINEAR.
           unsigned char dummyAlphaFunction;
 
           float           progress;
@@ -1686,9 +1690,7 @@ void DliLoader::Impl::ParseAnimationGroups(const Toolkit::TreeNode* tnAnimationG
       continue;
     }
 
-    auto iFind = std::lower_bound(animGroups.begin(), animGroups.end(), groupName, [](const AnimationGroupDefinition& group, const std::string& name) {
-      return group.mName < name;
-    });
+    auto iFind = std::lower_bound(animGroups.begin(), animGroups.end(), groupName, [](const AnimationGroupDefinition& group, const std::string& name) { return group.mName < name; });
     if(iFind != animGroups.end() && iFind->mName == groupName)
     {
       mOnError(FormatString("Animation group with name '%s' already exists; new entries will be merged.", groupName.c_str()));
@@ -1715,95 +1717,106 @@ void DliLoader::Impl::ParseAnimationGroups(const Toolkit::TreeNode* tnAnimationG
 
 void DliLoader::Impl::GetCameraParameters(std::vector<CameraParameters>& cameras) const
 {
-  if(const TreeNode* jsonCameras = mParser.GetRoot()->GetChild("cameras"))
+  if(mParser.GetRoot())
   {
-    cameras.resize(jsonCameras->Size());
-    auto iCamera = cameras.begin();
-    for(auto i0 = jsonCameras->CBegin(), i1 = jsonCameras->CEnd(); i0 != i1; ++i0)
+    if(const TreeNode* jsonCameras = mParser.GetRoot()->GetChild("cameras"))
     {
-      auto& jsonCamera = (*i0).second;
+      float dummyFloatArray[4];
 
-      ReadFloat(jsonCamera.GetChild("fov"), iCamera->yFov);
-      ReadFloat(jsonCamera.GetChild("near"), iCamera->zNear);
-      ReadFloat(jsonCamera.GetChild("far"), iCamera->zFar);
-      if(ReadVector(jsonCamera.GetChild("orthographic"), iCamera->orthographicSize.AsFloat(), 4u))
+      cameras.resize(jsonCameras->Size());
+      auto iCamera = cameras.begin();
+      for(auto i0 = jsonCameras->CBegin(), i1 = jsonCameras->CEnd(); i0 != i1; ++i0)
       {
-        iCamera->isPerspective = false;
-      }
+        auto& jsonCamera = (*i0).second;
 
-      if(auto jsonMatrix = jsonCamera.GetChild("matrix"))
-      {
-        ReadVector(jsonMatrix, iCamera->matrix.AsFloat(), 16u);
-      }
+        ReadFloat(jsonCamera.GetChild("fov"), iCamera->yFov);
+        ReadFloat(jsonCamera.GetChild("near"), iCamera->zNear);
+        ReadFloat(jsonCamera.GetChild("far"), iCamera->zFar);
+        if(ReadVector(jsonCamera.GetChild("orthographic"), dummyFloatArray, 4u))
+        {
+          iCamera->isPerspective = false;
+
+          iCamera->orthographicSize = dummyFloatArray[2] * 0.5f;
+          iCamera->aspectRatio      = dummyFloatArray[1] / dummyFloatArray[2];
+        }
+
+        if(auto jsonMatrix = jsonCamera.GetChild("matrix"))
+        {
+          ReadVector(jsonMatrix, iCamera->matrix.AsFloat(), 16u);
+        }
 
-      ++iCamera;
+        ++iCamera;
+      }
     }
   }
 }
 
 void DliLoader::Impl::GetLightParameters(std::vector<LightParameters>& lights) const
 {
-  if(const TreeNode* jsonLights = mParser.GetRoot()->GetChild("lights"))
+  if(mParser.GetRoot())
   {
-    lights.resize(jsonLights->Size());
-    auto iLight = lights.begin();
-    for(auto i0 = jsonLights->CBegin(), i1 = jsonLights->CEnd(); i0 != i1; ++i0)
+    if(const TreeNode* jsonLights = mParser.GetRoot()->GetChild("lights"))
     {
-      auto& jsonLight = (*i0).second;
-      if(!ReadVector(jsonLight.GetChild("matrix"), iLight->transform.AsFloat(), 16))
+      lights.resize(jsonLights->Size());
+      auto iLight = lights.begin();
+      for(auto i0 = jsonLights->CBegin(), i1 = jsonLights->CEnd(); i0 != i1; ++i0)
       {
-        mOnError(
-          FormatString("Failed to parse light %d - \"matrix\" child with 16 floats expected.\n",
-                       std::distance(jsonLights->CBegin(), i0)));
-        continue;
-      }
+        auto& jsonLight = (*i0).second;
+        if(!ReadVector(jsonLight.GetChild("matrix"), iLight->transform.AsFloat(), 16))
+        {
+          mOnError(
+            FormatString("Failed to parse light %d - \"matrix\" child with 16 floats expected.\n",
+                         std::distance(jsonLights->CBegin(), i0)));
+          continue;
+        }
 
-      int shadowMapSize = 0;
-      if(ReadInt(jsonLight.GetChild(SHADOW_MAP_SIZE), shadowMapSize) && shadowMapSize < 0)
-      {
-        mOnError(
-          FormatString("Failed to parse light %d - %s has an invalid value.",
-                       std::distance(jsonLights->CBegin(), i0),
-                       SHADOW_MAP_SIZE));
-        continue;
-      }
-      iLight->shadowMapSize = shadowMapSize;
+        int shadowMapSize = 0;
+        if(ReadInt(jsonLight.GetChild(SHADOW_MAP_SIZE), shadowMapSize) && shadowMapSize < 0)
+        {
+          mOnError(
+            FormatString("Failed to parse light %d - %s has an invalid value.",
+                         std::distance(jsonLights->CBegin(), i0),
+                         SHADOW_MAP_SIZE));
+          continue;
+        }
+        iLight->shadowMapSize = shadowMapSize;
 
-      float orthoSize = 0.f;
-      if(ReadFloat(jsonLight.GetChild(ORTHOGRAPHIC_SIZE), orthoSize) &&
-         (orthoSize < .0f || std::isnan(orthoSize) || std::isinf(orthoSize)))
-      {
-        mOnError(
-          FormatString("Failed to parse light %d - %s has an invalid value.",
-                       std::distance(jsonLights->CBegin(), i0),
-                       ORTHOGRAPHIC_SIZE));
-        continue;
-      }
-      iLight->orthographicSize = orthoSize;
+        float orthoSize = 0.f;
+        if(ReadFloat(jsonLight.GetChild(ORTHOGRAPHIC_SIZE), orthoSize) &&
+           (orthoSize < .0f || std::isnan(orthoSize) || std::isinf(orthoSize)))
+        {
+          mOnError(
+            FormatString("Failed to parse light %d - %s has an invalid value.",
+                         std::distance(jsonLights->CBegin(), i0),
+                         ORTHOGRAPHIC_SIZE));
+          continue;
+        }
+        iLight->orthographicSize = orthoSize;
 
-      if((iLight->shadowMapSize > 0) != (iLight->orthographicSize > .0f))
-      {
-        mOnError(FormatString(
-          "Light %d: Both shadow map size and orthographic size must be set for shadows to work.",
-          std::distance(jsonLights->CBegin(), i0)));
-      }
+        if((iLight->shadowMapSize > 0) != (iLight->orthographicSize > .0f))
+        {
+          mOnError(FormatString(
+            "Light %d: Both shadow map size and orthographic size must be set for shadows to work.",
+            std::distance(jsonLights->CBegin(), i0)));
+        }
 
-      if(!ReadVector(jsonLight.GetChild("color"), iLight->color.AsFloat(), 3)) // color is optional
-      {
-        iLight->color = Vector3::ONE; // default to white
-      }
+        if(!ReadVector(jsonLight.GetChild("color"), iLight->color.AsFloat(), 3)) // color is optional
+        {
+          iLight->color = Vector3::ONE; // default to white
+        }
 
-      if(!ReadFloat(jsonLight.GetChild("intensity"), iLight->intensity)) // intensity is optional
-      {
-        iLight->intensity = 1.0f; // default to 1.0
-      }
+        if(!ReadFloat(jsonLight.GetChild("intensity"), iLight->intensity)) // intensity is optional
+        {
+          iLight->intensity = 1.0f; // default to 1.0
+        }
 
-      if(!ReadFloat(jsonLight.GetChild("shadowIntensity"), iLight->shadowIntensity)) // intensity is optional
-      {
-        iLight->shadowIntensity = 1.0f; // default to 1.0
-      }
+        if(!ReadFloat(jsonLight.GetChild("shadowIntensity"), iLight->shadowIntensity)) // intensity is optional
+        {
+          iLight->shadowIntensity = 1.0f; // default to 1.0
+        }
 
-      ++iLight;
+        ++iLight;
+      }
     }
   }
 }