/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <filesystem>
// INTERNAL INCLUDES
+#include <dali-scene3d/internal/common/image-resource-loader.h>
#include <dali-scene3d/internal/common/model-cache-manager.h>
#include <dali-scene3d/internal/controls/scene-view/scene-view-impl.h>
+#include <dali-scene3d/internal/event/collider-mesh-processor.h>
+#include <dali-scene3d/internal/light/light-impl.h>
#include <dali-scene3d/internal/model-components/model-node-impl.h>
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/loader/animation-definition.h>
#include <dali-scene3d/public-api/loader/load-result.h>
#include <dali-scene3d/public-api/loader/node-definition.h>
#include <dali-scene3d/public-api/loader/scene-definition.h>
-#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
-
+#include <dali-scene3d/public-api/loader/shader-manager.h>
+#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
using namespace Dali;
namespace Dali
DALI_TYPE_REGISTRATION_END()
static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f);
+static constexpr float SIZE_STEP_CONDITION = 0.1f;
static constexpr bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false;
static constexpr bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false;
Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector<Dali::Scene3D::Loader::BlendshapeShaderConfigurationRequest>&& requests)
{
std::vector<std::string> 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);
}
}
+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<std::string> blendShapeNames;
+ node.RetrieveBlendShapeNames(blendShapeNames);
+ for(const auto& iter : blendShapeNames)
+ {
+ // Append or create new list.
+ resultMap[iter].push_back(node);
+ }
+}
+
+void UpdateShaderRecursively(Scene3D::ModelNode node, Scene3D::Loader::ShaderManagerPtr shaderManager)
+{
+ if(!node)
+ {
+ return;
+ }
+
+ GetImplementation(node).UpdateShader(shaderManager);
+
+ uint32_t childrenCount = node.GetChildCount();
+ for(uint32_t i = 0; i < childrenCount; ++i)
+ {
+ Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+ if(childNode)
+ {
+ UpdateShaderRecursively(childNode, shaderManager);
+ }
+ }
+}
+
+void UpdateShadowMapTextureRecursively(Scene3D::ModelNode node, Dali::Texture shadowMapTexture)
+{
+ if(!node)
+ {
+ return;
+ }
+
+ GetImplementation(node).SetShadowMapTexture(shadowMapTexture);
+
+ uint32_t childrenCount = node.GetChildCount();
+ for(uint32_t i = 0; i < childrenCount; ++i)
+ {
+ Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+ if(childNode)
+ {
+ UpdateShadowMapTextureRecursively(childNode, shadowMapTexture);
+ }
+ }
+}
+
+void ResetResourceTask(IntrusivePtr<AsyncTask>&& asyncTask)
+{
+ if(!asyncTask)
+ {
+ return;
+ }
+ Dali::AsyncTaskManager::Get().RemoveTask(asyncTask);
+ asyncTask.Reset();
+}
+
} // anonymous namespace
Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
mModelUrl(modelUrl),
mResourceDirectoryUrl(resourceDirectoryUrl),
mModelRoot(),
+ mShaderManager(new Scene3D::Loader::ShaderManager()),
mNaturalSize(Vector3::ZERO),
mModelPivot(AnchorPoint::CENTER),
mSceneIblScaleFactor(1.0f),
mIblDiffuseResourceReady(true),
mIblSpecularResourceReady(true),
mIblDiffuseDirty(false),
- mIblSpecularDirty(false)
+ mIblSpecularDirty(false),
+ mIsShadowCasting(true),
+ mIsShadowReceiving(true)
{
}
Model::~Model()
{
+ ResetResourceTasks();
+
if(ModelCacheManager::Get() && !mModelUrl.empty())
{
ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
}
-
- ResetResourceTasks();
}
Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
mModelResourceReady = true;
}
+ UpdateShaderRecursively(modelNode, mShaderManager);
+
+ if(mShadowMapTexture)
+ {
+ UpdateShadowMapTextureRecursively(modelNode, mShadowMapTexture);
+ }
+
if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
{
UpdateImageBasedLightTexture();
UpdateImageBasedLightScaleFactor();
}
+ GetImplementation(modelNode).SetRootModel(this);
+
+ // If model has a collider mesh set, add it to the container
+ if(modelNode.HasColliderMesh())
+ {
+ RegisterColliderMesh(modelNode);
+ Scene3D::ColliderMeshProcessor::Get().ColliderMeshChanged(Scene3D::Model::DownCast(Self()));
+ }
+
if(Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
{
NotifyResourceReady();
}
}
+void Model::RegisterColliderMesh(Scene3D::ModelNode& modelNode)
+{
+ mColliderMeshes[modelNode.GetProperty<int>(Actor::Property::ID)] = modelNode;
+
+ // Add processor
+ Scene3D::ColliderMeshProcessor::Get().ColliderMeshChanged(Scene3D::Model::DownCast(Self()));
+}
+
+void Model::RemoveColliderMesh(Scene3D::ModelNode& node)
+{
+ auto id = node.GetProperty<int>(Actor::Property::ID);
+ auto iter = std::find_if(mColliderMeshes.begin(), mColliderMeshes.end(), [id](auto& item) {
+ return item.first == id;
+ });
+ if(iter != mColliderMeshes.end())
+ {
+ mColliderMeshes.erase(iter);
+ }
+}
+
void Model::RemoveModelNode(Scene3D::ModelNode modelNode)
{
+ // remove collider mesh from the list if node is being removed
+ if(modelNode.HasColliderMesh())
+ {
+ RemoveColliderMesh(modelNode);
+ GetImplementation(modelNode).SetRootModel(nullptr);
+ }
+
if(mModelRoot)
{
+ UpdateShaderRecursively(modelNode, nullptr);
mModelRoot.Remove(modelNode);
}
}
mDiffuseTexture.Reset();
mSpecularTexture.Reset();
UpdateImageBasedLightTexture();
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
else
{
mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblDiffuseLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
mIblDiffuseDirty = false;
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
if(isOnScene && mIblSpecularDirty)
mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &Model::OnIblSpecularLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
mIblSpecularDirty = false;
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
}
return Scene3D::ModelNode::DownCast(childActor);
}
+void Model::RetrieveBlendShapeNames(std::vector<std::string>& 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<Scene3D::ModelNode>& 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 : Need to collect duplicated codes with SetMotionData()
+
+ 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<Scene3D::ModelNode> 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 : Need to collect duplicated codes with GenerateMotionDataAnimation()
+
+ 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<Scene3D::ModelNode> 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);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void Model::CastShadow(bool castShadow)
+{
+ mIsShadowCasting = castShadow;
+ UpdateCastShadowRecursively(mModelRoot, mIsShadowCasting);
+}
+
+bool Model::IsShadowCasting() const
+{
+ return mIsShadowCasting;
+}
+
+void Model::ReceiveShadow(bool receiveShadow)
+{
+ mIsShadowReceiving = receiveShadow;
+ UpdateReceiveShadowRecursively(mModelRoot, mIsShadowReceiving);
+}
+
+bool Model::IsShadowReceiving() const
+{
+ return mIsShadowReceiving;
+}
+
+
///////////////////////////////////////////////////////////
//
// Private methods
{
// Make ParentOrigin as Center.
Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ mDefaultDiffuseTexture = ImageResourceLoader::GetEmptyTextureWhiteRGB();
+ mDefaultSpecularTexture = ImageResourceLoader::GetEmptyTextureWhiteRGB();
}
void Model::OnSceneConnection(int depth)
{
+ Actor parent = Self().GetParent();
+ while(parent)
+ {
+ // If this Model has parent SceneView and the its ShaderManager is same with privious ShaderManager,
+ // this Model don't need to update shader.
+ Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
+ if(sceneView)
+ {
+ mParentSceneView = sceneView;
+ GetImpl(sceneView).RegisterSceneItem(this);
+ Scene3D::Loader::ShaderManagerPtr shaderManager = GetImpl(sceneView).GetShaderManager();
+ if(mShaderManager != shaderManager)
+ {
+ mShaderManager = shaderManager;
+ UpdateShaderRecursively(mModelRoot, mShaderManager);
+ }
+ break;
+ }
+ parent = parent.GetParent();
+ }
+
+ // Model can be added on Dali::Scene directly without SceneView.
+ // So, Model's mShaderManager and shaders of child ModelNodes are needed to be reset when this Model has not parent SceneView.
+ Scene3D::SceneView parentSceneView = mParentSceneView.GetHandle();
+ if(!parentSceneView)
+ {
+ mShaderManager = new Dali::Scene3D::Loader::ShaderManager();
+ UpdateShaderRecursively(mModelRoot, mShaderManager);
+ }
+
if(!mModelLoadTask && !mModelResourceReady && !mModelUrl.empty())
{
// Request model load only if we setup url.
SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
}
- Actor parent = Self().GetParent();
- while(parent)
- {
- Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
- if(sceneView)
- {
- GetImpl(sceneView).RegisterSceneItem(this);
- mParentSceneView = sceneView;
- break;
- }
- parent = parent.GetParent();
- }
-
NotifyResourceReady();
+
+ mSizeNotification = Self().AddPropertyNotification(Actor::Property::SIZE, StepCondition(SIZE_STEP_CONDITION));
+ mSizeNotification.NotifySignal().Connect(this, &Model::OnSizeNotification);
Control::OnSceneConnection(depth);
}
void Model::OnSceneDisconnection()
{
+ // If mParentSceneView is still onScene, that means this model
+ // is disconnected from mParentSceneView's sub tree.
+ // So, Unregister this Model from SceneView.
Scene3D::SceneView sceneView = mParentSceneView.GetHandle();
- if(sceneView)
+ if(sceneView && sceneView.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
{
GetImpl(sceneView).UnregisterSceneItem(this);
mParentSceneView.Reset();
}
+
+ mSizeNotification.NotifySignal().Disconnect(this, &Model::OnSizeNotification);
+ Self().RemovePropertyNotification(mSizeNotification);
+ mSizeNotification.Reset();
+
Control::OnSceneDisconnection();
}
+void Model::OnSizeSet(const Vector3& size)
+{
+ ScaleModel(false);
+}
+
Vector3 Model::GetNaturalSize()
{
if(!mModelRoot)
void Model::OnRelayout(const Vector2& size, RelayoutContainer& container)
{
Control::OnRelayout(size, container);
- ScaleModel();
+ ScaleModel(false);
}
bool Model::IsResourceReady() const
Self().Add(mModelRoot);
}
-void Model::ScaleModel()
+void Model::ScaleModel(bool useCurrentSize)
{
if(!mModelRoot)
{
}
float scale = 1.0f;
- Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+ Vector3 size = (useCurrentSize) ? Self().GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE) : Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
if(size.x > 0.0f && size.y > 0.0f)
{
scale = MAXFLOAT;
mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
}
+void Model::UpdateCastShadowRecursively(Scene3D::ModelNode node, bool castShadow)
+{
+ if(!node)
+ {
+ return;
+ }
+
+ GetImplementation(node).CastShadow(castShadow);
+ uint32_t childrenCount = node.GetChildCount();
+ for(uint32_t i = 0; i < childrenCount; ++i)
+ {
+ Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+ if(!childNode)
+ {
+ continue;
+ }
+ UpdateCastShadowRecursively(childNode, castShadow);
+ }
+}
+
+void Model::UpdateReceiveShadowRecursively(Scene3D::ModelNode node, bool receiveShadow)
+{
+ if(!node)
+ {
+ return;
+ }
+
+ GetImplementation(node).ReceiveShadow(receiveShadow);
+ uint32_t childrenCount = node.GetChildCount();
+ for(uint32_t i = 0; i < childrenCount; ++i)
+ {
+ Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+ if(!childNode)
+ {
+ continue;
+ }
+ UpdateReceiveShadowRecursively(childNode, receiveShadow);
+ }
+}
+
void Model::UpdateImageBasedLightTextureRecursively(Scene3D::ModelNode node, Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
{
if(!node)
return;
}
- node.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), iblScaleFactor);
GetImplementation(node).SetImageBasedLightScaleFactor(iblScaleFactor);
uint32_t childrenCount = node.GetChildCount();
camera.SetProperty(Actor::Property::SCALE, resultScale);
}
+void Model::NotifyShadowMapTexture(Dali::Texture shadowMapTexture)
+{
+ if(mShadowMapTexture != shadowMapTexture)
+ {
+ mShadowMapTexture = shadowMapTexture;
+ UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture);
+ }
+}
+
void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels)
{
if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
void Model::OnModelLoadComplete()
{
+ IntrusivePtr<Model> self = this; // Keep reference until this API finished
+
if(!mModelLoadTask->HasSucceeded())
{
ResetResourceTasks();
ResetCameraParameters();
if(!resources.mEnvironmentMaps.empty())
{
- mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse;
- mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
+ if(resources.mEnvironmentMaps.front().second.mDiffuse)
+ {
+ mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse;
+ }
+ if(resources.mEnvironmentMaps.front().second.mSpecular)
+ {
+ mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
+ }
}
+ if(mShadowMapTexture)
+ {
+ UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture);
+ }
UpdateImageBasedLightTexture();
UpdateImageBasedLightScaleFactor();
Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
mModelResourceReady = true;
- NotifyResourceReady();
ResetResourceTask(mModelLoadTask);
+ NotifyResourceReady();
}
void Model::OnIblDiffuseLoadComplete()
NotifyResourceReady();
}
+void Model::OnSizeNotification(Dali::PropertyNotification& source)
+{
+ ScaleModel(true);
+}
+
void Model::ResetResourceTasks()
{
if(!Dali::Adaptor::IsAvailable())
ResetResourceTask(mIblSpecularLoadTask);
}
-void Model::ResetResourceTask(IntrusivePtr<AsyncTask> asyncTask)
-{
- if(!asyncTask)
- {
- return;
- }
- Dali::AsyncTaskManager::Get().RemoveTask(asyncTask);
- asyncTask.Reset();
-}
-
void Model::NotifyResourceReady()
{
if(!IsResourceReady())
{
return;
}
- Control::SetResourceReady(false);
+ Control::SetResourceReady();
}
void Model::CreateModel()
{
- BoundingVolume AABB;
- auto& resources = mModelLoadTask->GetResources();
- auto& scene = mModelLoadTask->GetScene();
- auto& resourceChoices = mModelLoadTask->GetResourceChoices();
- Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
- Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}};
+ BoundingVolume AABB;
+ auto& resources = mModelLoadTask->GetResources();
+ auto& scene = mModelLoadTask->GetScene();
+ auto& resourceChoices = mModelLoadTask->GetResourceChoices();
+ Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
+
+ Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, mShaderManager, {}, {}, {}};
// Generate Dali handles from resource bundle. Note that we generate all scene's resouce immediatly.
resources.GenerateResources();
for(auto iRoot : scene.GetRoots())
{
- if(auto actor = scene.CreateNodes(iRoot, resourceChoices, nodeParams))
+ if(auto modelNode = scene.CreateNodes(iRoot, resourceChoices, nodeParams))
{
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
- 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);
Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize);
}
FitModelPosition();
- ScaleModel();
+ ScaleModel(false);
}
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);
}
}
+void Model::UpdateBlendShapeNodeMap()
+{
+ // Remove privous node map
+ mBlendShapeModelNodeMap.clear();
+
+ UpdateBlendShapeNodeMapRecursively(mBlendShapeModelNodeMap, mModelRoot);
+}
+
} // namespace Internal
} // namespace Scene3D
} // namespace Dali