#include <dali/integration-api/debug.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <filesystem>
// INTERNAL INCLUDES
mModelUrl(modelUrl),
mResourceDirectoryUrl(resourceDirectoryUrl),
mModelRoot(),
+ mModelLoadedCallback(nullptr),
+ mIblLoadedCallback(nullptr),
mNaturalSize(Vector3::ZERO),
mModelPivot(AnchorPoint::CENTER),
mIblScaleFactor(1.0f),
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)
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);
}
}
mIblScaleFactor = scaleFactor;
UpdateImageBasedLightScaleFactor();
}
-
}
}
{
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();
{
if(!mModelRoot)
{
- LoadModel();
+ DALI_LOG_ERROR("Model is still not loaded.\n");
+ return Vector3::ZERO;
}
return mNaturalSize;
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()
}
}
+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
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();
*/
void UpdateImageBasedLightScaleFactor();
+ /**
+ * @brief Asynchronously loading finished.
+ */
+ void OnLoadComplete();
+
private:
std::string mModelUrl;
std::string mResourceDirectoryUrl;
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;
#include <dali/integration-api/debug.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
// INTERNAL INCLUDES
#include <dali-scene3d/internal/controls/model/model-impl.h>
} // anonymous namespace
SceneView::SceneView()
-: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT))
+: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
+ 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()
{
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)
}
}
+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
*/
void UpdateRenderTask();
+ /**
+ * @brief Loads image based light from file.
+ */
+ void LoadImageBasedLight();
+
+ /**
+ * @brief Asynchronously loading finished.
+ */
+ void OnLoadComplete();
+
private:
Toolkit::Visual::Base mVisual;
Dali::Texture mTexture;
Dali::RenderTask mRenderTask;
- Layer mRootLayer;
+ CallbackBase* mIblLoadedCallback;
+ std::string mDiffuseIblUrl;
+ std::string mSpecularIblUrl;
+ Layer mRootLayer;
Dali::Texture mSpecularTexture;
Dali::Texture mDiffuseTexture;
float mIblScaleFactor{1.0f};
{
namespace Scene3D
{
-Model::Model()
-{
-}
+Model::Model() = default;
Model::Model(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)
{
/**
* @brief Sets Image Based Light Texture.
+ * @note This method doesn't load texture from file, so this work is performed synchronously.
*
* @param[in] diffuseTexture cube map texture that can be used as a diffuse IBL source.
* @param[in] specularTexture cube map texture that can be used as a specular IBL source.