2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-scene3d/internal/model-components/model-node-impl.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/public-api/object/type-registry.h>
27 #include <dali-scene3d/internal/model-components/model-primitive-impl.h>
38 * Creates control through type registry
42 return Scene3D::ModelNode::New();
45 // Setup properties, signals and actions using the type-registry.
46 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelNode, Dali::CustomActor, Create);
47 DALI_TYPE_REGISTRATION_END()
48 } // unnamed namespace
50 Dali::Scene3D::ModelNode ModelNode::New()
52 // Create the implementation, temporarily owned on stack
53 IntrusivePtr<ModelNode> nodeImpl = new ModelNode();
55 // Pass ownership to handle
56 Scene3D::ModelNode handle(*nodeImpl);
58 // Second-phase init of the implementation
59 // This can only be done after the CustomActor connection has been made...
60 nodeImpl->Initialize();
65 ModelNode::ModelNode()
66 : CustomActorImpl(ActorFlags::DISABLE_SIZE_NEGOTIATION)
70 ModelNode::~ModelNode()
74 void ModelNode::Initialize()
79 void ModelNode::OnInitialize()
83 void ModelNode::OnSceneConnection(int depth)
87 void ModelNode::OnSceneDisconnection()
91 void ModelNode::OnChildAdd(Actor& child)
95 void ModelNode::OnChildRemove(Actor& child)
99 void ModelNode::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
103 void ModelNode::OnSizeSet(const Vector3& targetSize)
107 void ModelNode::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
109 // @todo size negotiate background to new size, animate as well?
112 void ModelNode::OnRelayout(const Vector2& size, RelayoutContainer& container)
116 void ModelNode::OnSetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
120 Vector3 ModelNode::GetNaturalSize()
122 return Vector3::ZERO;
125 float ModelNode::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
130 float ModelNode::GetHeightForWidth(float width)
135 float ModelNode::GetWidthForHeight(float height)
140 bool ModelNode::RelayoutDependentOnChildren(Dimension::Type dimension)
145 void ModelNode::OnCalculateRelayoutSize(Dimension::Type dimension)
149 void ModelNode::OnLayoutNegotiated(float size, Dimension::Type dimension)
153 ModelNode& GetImplementation(Dali::Scene3D::ModelNode& handle)
155 CustomActorImpl& customInterface = handle.GetImplementation();
156 ModelNode& impl = dynamic_cast<Internal::ModelNode&>(customInterface);
160 const ModelNode& GetImplementation(const Dali::Scene3D::ModelNode& handle)
162 const CustomActorImpl& customInterface = handle.GetImplementation();
163 // downcast to control
164 const ModelNode& impl = dynamic_cast<const Internal::ModelNode&>(customInterface);
170 uint32_t ModelNode::GetModelPrimitiveCount() const
172 return static_cast<uint32_t>(mModelPrimitiveContainer.size());
175 void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
177 for(auto&& primitive : mModelPrimitiveContainer)
179 if(primitive == modelPrimitive)
185 mModelPrimitiveContainer.push_back(modelPrimitive);
188 GetImplementation(modelPrimitive).AddPrimitiveObserver(this);
189 if(mDiffuseTexture && mSpecularTexture)
191 GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
194 Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
197 uint32_t rendererCount = self.GetRendererCount();
199 for(uint32_t i = 0; i < rendererCount; ++i)
201 if(renderer == self.GetRendererAt(i))
209 self.AddRenderer(renderer);
214 void ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
216 uint32_t primitiveCount = GetModelPrimitiveCount();
217 for(uint32_t i = 0; i < primitiveCount; ++i)
219 if(mModelPrimitiveContainer[i] != modelPrimitive)
223 RemoveModelPrimitive(i);
228 void ModelNode::RemoveModelPrimitive(uint32_t index)
230 if(index >= mModelPrimitiveContainer.size())
236 GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
238 Dali::Renderer renderer = GetImplementation(mModelPrimitiveContainer[index]).GetRenderer();
241 self.RemoveRenderer(renderer);
244 mModelPrimitiveContainer.erase(mModelPrimitiveContainer.begin() + index);
247 Dali::Scene3D::ModelPrimitive ModelNode::GetModelPrimitive(uint32_t index) const
249 if(index < mModelPrimitiveContainer.size())
251 return mModelPrimitiveContainer[index];
253 return Scene3D::ModelPrimitive();
256 Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName)
258 Actor childActor = Self().FindChildByName(nodeName);
259 return Scene3D::ModelNode::DownCast(childActor);
262 void ModelNode::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
264 mDiffuseTexture = diffuseTexture;
265 mSpecularTexture = specularTexture;
266 mIblScaleFactor = iblScaleFactor;
267 mSpecularMipmapLevels = specularMipmapLevels;
268 for(auto&& primitive : mModelPrimitiveContainer)
270 GetImplementation(primitive).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
274 void ModelNode::SetImageBasedLightScaleFactor(float iblScaleFactor)
276 mIblScaleFactor = iblScaleFactor;
277 for(auto&& primitive : mModelPrimitiveContainer)
279 GetImplementation(primitive).SetImageBasedLightScaleFactor(iblScaleFactor);
283 void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
285 GetImplementation(primitive).SetBlendShapeData(data);
288 void ModelNode::SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex)
290 Dali::Scene3D::Loader::Skinning::BoneData boneData;
291 boneData.primitive = primitive;
292 boneData.boneIndex = boneIndex;
293 char propertyNameBuffer[32];
294 snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Dali::Scene3D::Loader::Skinning::BONE_UNIFORM_NAME, boneIndex);
295 boneData.propertyName = propertyNameBuffer;
296 boneData.inverseMatrix = inverseMatrix;
297 mBoneDataContainer.push_back(std::move(boneData));
299 UpdateBoneMatrix(primitive);
302 void ModelNode::OnRendererCreated(Renderer renderer)
304 Self().AddRenderer(renderer);
307 void ModelNode::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
309 for(auto&& boneData : mBoneDataContainer)
311 if(boneData.primitive != primitive)
316 Dali::Renderer renderer = GetImplementation(primitive).GetRenderer();
322 Dali::Shader shader = renderer.GetShader();
328 if(boneData.constraint)
330 boneData.constraint.Remove();
331 boneData.constraint.Reset();
334 if(shader.GetPropertyIndex(boneData.propertyName) == Property::INVALID_INDEX)
336 auto propBoneXform = shader.RegisterProperty(boneData.propertyName, Matrix{false});
338 Matrix inverseMatrix = boneData.inverseMatrix;
339 // Constrain bone matrix to joint transform.
340 boneData.constraint = Constraint::New<Matrix>(shader, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs)
341 { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
343 Actor joint = Self();
344 boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
345 boneData.constraint.ApplyPost();
351 } // namespace Internal
353 } // namespace Scene3D