[Tizen] Add Asynchronous loading for Model and SceneView 62/283762/1
authorseungho <sbsh.baek@samsung.com>
Wed, 2 Nov 2022 09:56:33 +0000 (18:56 +0900)
committerseungho <sbsh.baek@samsung.com>
Wed, 2 Nov 2022 09:59:49 +0000 (18:59 +0900)
This reverts commit ee3275dfdf14134cd54631c39484e29d01a2fad7.

Change-Id: I06fa34335760826c1e1e4d2b5331db946d5aaf1c

dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/model/model-impl.h
dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp
dali-scene3d/internal/controls/scene-view/scene-view-impl.h
dali-scene3d/public-api/controls/model/model.cpp
dali-scene3d/public-api/controls/model/model.h

index 24e7af5..3a6b11d 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali/devel-api/actors/actor-devel.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
 #include <dali/integration-api/debug.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <dali/public-api/object/type-registry.h>
@@ -179,6 +180,8 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr
   mModelUrl(modelUrl),
   mResourceDirectoryUrl(resourceDirectoryUrl),
   mModelRoot(),
+  mModelLoadedCallback(nullptr),
+  mIblLoadedCallback(nullptr),
   mNaturalSize(Vector3::ZERO),
   mModelPivot(AnchorPoint::CENTER),
   mIblScaleFactor(1.0f),
@@ -190,6 +193,17 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr
 
 Model::~Model()
 {
+  if(mModelLoadedCallback && Adaptor::IsAvailable())
+  {
+    // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
+    Adaptor::Get().RemoveIdle(mModelLoadedCallback);
+  }
+
+  if(mIblLoadedCallback && Adaptor::IsAvailable())
+  {
+    // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
+    Adaptor::Get().RemoveIdle(mIblLoadedCallback);
+  }
 }
 
 Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
@@ -229,17 +243,16 @@ bool Model::GetChildrenSensitive() const
 
 void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
 {
-  mIBLResourceReady       = false;
-  Texture diffuseTexture  = Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl);
-  Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specularUrl);
-  SetImageBasedLightTexture(diffuseTexture, specularTexture, scaleFactor);
-  mIBLResourceReady = true;
-
-  // If Model resource is already ready, then set resource ready.
-  // If Model resource is still not ready, wait for model resource ready.
-  if(IsResourceReady())
+  // Request asynchronous model loading
+  if(!mIblLoadedCallback)
   {
-    SetResourceReady(false);
+    mIBLResourceReady = false;
+    mDiffuseIblUrl    = diffuseUrl;
+    mSpecularIblUrl   = specularUrl;
+    mIblScaleFactor   = scaleFactor;
+    // The callback manager takes the ownership of the callback object.
+    mIblLoadedCallback = MakeCallback(this, &Model::OnLoadComplete);
+    Adaptor::Get().AddIdle(mIblLoadedCallback, false);
   }
 }
 
@@ -316,7 +329,14 @@ void Model::OnSceneConnection(int depth)
 {
   if(!mModelRoot)
   {
-    LoadModel();
+    // Request asynchronous model loading
+    if(!mModelLoadedCallback)
+    {
+      mModelResourceReady = false;
+      // The callback manager takes the ownership of the callback object.
+      mModelLoadedCallback = MakeCallback(this, &Model::OnLoadComplete);
+      Adaptor::Get().AddIdle(mModelLoadedCallback, false);
+    }
   }
 
   Actor parent = Self().GetParent();
@@ -350,7 +370,8 @@ Vector3 Model::GetNaturalSize()
 {
   if(!mModelRoot)
   {
-    LoadModel();
+    DALI_LOG_ERROR("Model is still not loaded.\n");
+    return Vector3::ZERO;
   }
 
   return mNaturalSize;
@@ -509,10 +530,13 @@ void Model::LoadModel()
 
   Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
   Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
+}
 
-  mModelResourceReady = true;
-
-  Control::SetResourceReady(false);
+void Model::LoadImageBasedLight()
+{
+  Texture diffuseTexture  = Dali::Scene3D::Loader::LoadCubeMap(mDiffuseIblUrl);
+  Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(mSpecularIblUrl);
+  SetImageBasedLightTexture(diffuseTexture, specularTexture, mIblScaleFactor);
 }
 
 void Model::ScaleModel()
@@ -609,6 +633,37 @@ void Model::UpdateImageBasedLightScaleFactor()
   }
 }
 
+void Model::OnLoadComplete()
+{
+  // TODO: In this implementation, we cannot know which request occurs this OnLoadComplete Callback.
+  // Currently it is no problem because the all loading is processed in this method.
+
+  // Prevent to emit unnecessary resource ready signal.
+  if(IsResourceReady())
+  {
+    return;
+  }
+
+  if(!mIBLResourceReady)
+  {
+    LoadImageBasedLight();
+    mIBLResourceReady  = true;
+    mIblLoadedCallback = nullptr;
+  }
+
+  if(!mModelResourceReady)
+  {
+    LoadModel();
+    mModelResourceReady  = true;
+    mModelLoadedCallback = nullptr;
+  }
+
+  if(IsResourceReady())
+  {
+    Control::SetResourceReady(false);
+  }
+}
+
 } // namespace Internal
 } // namespace Scene3D
 } // namespace Dali
index 3db9c57..a037c93 100644 (file)
@@ -155,6 +155,11 @@ private:
   void LoadModel();
 
   /**
+   * @brief Loads image based light from file.
+   */
+  void LoadImageBasedLight();
+
+  /**
    * @brief Scales the model to fit the control or to return to original size.
    */
   void ScaleModel();
@@ -179,6 +184,11 @@ private:
    */
   void UpdateImageBasedLightScaleFactor();
 
+  /**
+   * @brief Asynchronously loading finished.
+   */
+  void OnLoadComplete();
+
 private:
   std::string                    mModelUrl;
   std::string                    mResourceDirectoryUrl;
@@ -187,6 +197,11 @@ private:
   std::vector<WeakHandle<Actor>> mRenderableActors;
   WeakHandle<Scene3D::SceneView> mParentSceneView;
 
+  CallbackBase* mModelLoadedCallback;
+  CallbackBase* mIblLoadedCallback;
+  std::string   mDiffuseIblUrl;
+  std::string   mSpecularIblUrl;
+
   Dali::Texture mSpecularTexture;
   Dali::Texture mDiffuseTexture;
   Vector3       mNaturalSize;
index 593daf0..a548b8f 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali/devel-api/actors/camera-actor-devel.h>
 #include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/common/stage.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
 #include <dali/integration-api/debug.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <dali/public-api/object/type-registry.h>
@@ -64,11 +65,19 @@ constexpr int32_t DEFAULT_ORIENTATION = 0;
 
 SceneView::SceneView()
 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
-  mWindowOrientation(DEFAULT_ORIENTATION)
+  mWindowOrientation(DEFAULT_ORIENTATION),
+  mIblLoadedCallback(nullptr)
 {
 }
 
-SceneView::~SceneView() = default;
+SceneView::~SceneView()
+{
+  if(mIblLoadedCallback && Adaptor::IsAvailable())
+  {
+    // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
+    Adaptor::Get().RemoveIdle(mIblLoadedCallback);
+  }
+}
 
 Dali::Scene3D::SceneView SceneView::New()
 {
@@ -192,28 +201,17 @@ void SceneView::UnregisterModel(Scene3D::Model model)
 
 void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
 {
-  mIBLResourceReady      = false;
-  Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl);
-  if(diffuseTexture)
+  // Request asynchronous model loading
+  if(!mIblLoadedCallback)
   {
-    Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specularUrl);
-    if(specularTexture)
-    {
-      mDiffuseTexture  = diffuseTexture;
-      mSpecularTexture = specularTexture;
-      mIblScaleFactor  = scaleFactor;
-
-      for(auto&& model : mModels)
-      {
-        if(model)
-        {
-          model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
-        }
-      }
-    }
+    mIBLResourceReady = false;
+    mDiffuseIblUrl    = diffuseUrl;
+    mSpecularIblUrl   = specularUrl;
+    mIblScaleFactor   = scaleFactor;
+    // The callback manager takes the ownership of the callback object.
+    mIblLoadedCallback = MakeCallback(this, &SceneView::OnLoadComplete);
+    Adaptor::Get().AddIdle(mIblLoadedCallback, false);
   }
-  mIBLResourceReady = true;
-  Control::SetResourceReady(false);
 }
 
 void SceneView::SetImageBasedLightScaleFactor(float scaleFactor)
@@ -456,6 +454,53 @@ void SceneView::RotateCamera()
   }
 }
 
+void SceneView::LoadImageBasedLight()
+{
+  Texture diffuseTexture  = Dali::Scene3D::Loader::LoadCubeMap(mDiffuseIblUrl);
+  Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(mSpecularIblUrl);
+
+  if(diffuseTexture)
+  {
+    if(specularTexture)
+    {
+      mDiffuseTexture  = diffuseTexture;
+      mSpecularTexture = specularTexture;
+
+      for(auto&& model : mModels)
+      {
+        if(model)
+        {
+          model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
+        }
+      }
+    }
+  }
+}
+
+void SceneView::OnLoadComplete()
+{
+  // TODO: In this implementation, we cannot know which request occurs this OnLoadComplete Callback.
+  // Currently it is no problem because the all loading is processed in this method.
+
+  // Prevent to emit unnecessary resource ready signal.
+  if(IsResourceReady())
+  {
+    return;
+  }
+
+  if(!mIBLResourceReady)
+  {
+    LoadImageBasedLight();
+    mIBLResourceReady  = true;
+    mIblLoadedCallback = nullptr;
+  }
+
+  if(IsResourceReady())
+  {
+    Control::SetResourceReady(false);
+  }
+}
+
 } // namespace Internal
 } // namespace Scene3D
 } // namespace Dali
index 548bfee..363449e 100644 (file)
@@ -215,6 +215,16 @@ private:
    */
   void RotateCamera();
 
+  /**
+   * @brief Loads image based light from file.
+   */
+  void LoadImageBasedLight();
+
+  /**
+   * @brief Asynchronously loading finished.
+   */
+  void OnLoadComplete();
+
 private:
   Toolkit::Visual::Base mVisual;
 
@@ -230,6 +240,11 @@ private:
   Layer                       mRootLayer;
   int32_t                     mWindowOrientation;
 
+  CallbackBase* mIblLoadedCallback;
+  std::string   mDiffuseIblUrl;
+  std::string   mSpecularIblUrl;
+
+  Layer         mRootLayer;
   Dali::Texture mSpecularTexture;
   Dali::Texture mDiffuseTexture;
   float         mIblScaleFactor{1.0f};
index 69029d9..41ecb92 100644 (file)
@@ -25,9 +25,7 @@ namespace Dali
 {
 namespace Scene3D
 {
-Model::Model()
-{
-}
+Model::Model() = default;
 
 Model::Model(const Model& model) = default;
 
@@ -37,9 +35,7 @@ Model& Model::operator=(const Model& model) = default;
 
 Model& Model::operator=(Model&& rhs) = default;
 
-Model::~Model()
-{
-}
+Model::~Model() = default;
 
 Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
 {
index 104e054..acdc447 100644 (file)
@@ -188,6 +188,7 @@ public:
 
   /**
    * @brief Sets Image Based Light Texture.
+   * @note This method doesn't load texture from file, so this work is performed synchronously.
    *
    * @SINCE_2_1.41
    * @param[in] diffuseTexture cube map texture that can be used as a diffuse IBL source.