2 * Copyright (c) 2014 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/internal/event/actor-attachments/mesh-attachment-impl.h>
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/internal/update/node-attachments/scene-graph-mesh-attachment.h>
24 #include <dali/internal/update/modeling/scene-graph-material.h>
25 #include <dali/internal/event/common/stage-impl.h>
26 #include <dali/internal/update/nodes/node.h>
28 using Dali::Internal::MeshIPtr;
29 using Dali::Internal::MaterialIPtr;
37 MeshAttachmentPtr MeshAttachment::New( Stage& stage, const SceneGraph::Node& parentNode )
39 MeshAttachmentPtr attachment( new MeshAttachment( stage ) );
41 // Transfer object ownership of scene-object to message
42 SceneGraph::MeshAttachment* sceneObject = SceneGraph::MeshAttachment::New();
43 AttachToNodeMessage( stage.GetUpdateManager(), parentNode, sceneObject );
45 // Keep raw pointer for message passing
46 attachment->mSceneObject = sceneObject;
51 MeshAttachment::MeshAttachment( Stage& stage )
52 : RenderableAttachment( stage ),
54 mAffectedByLighting( true )
58 MeshAttachment::~MeshAttachment()
60 // Belt and braces - should already have been disconnected from stage
61 if ( Stage::IsInstalled() &&
68 void MeshAttachment::SetMesh( const MeshIPtr meshPtr,
70 const BoneContainer& bones,
71 const MaterialIPtr material )
73 mMesh.mMesh = meshPtr;
74 mMesh.mCustomMaterial = 0;
76 std::size_t boneCount = bones.size();
80 // Copy bone names locally in order to perform actor binding later
82 // Must keep names in same order (vertices reference into bone matrix array by index)
83 for ( BoneContainer::const_iterator iter = bones.begin(); iter != bones.end(); ++iter )
85 const Bone& bone = (*iter);
86 mMesh.mBoneNames.push_back( bone.GetName() );
90 mMesh.mMaterial = material;
91 const SceneGraph::Material* materialSceneObject = material->GetSceneObject();
93 // sceneObject is being used in a separate thread; queue a message to set
94 SetMeshMessage( mStage->GetUpdateInterface(), *mSceneObject, meshId, materialSceneObject, boneCount );
97 void MeshAttachment::SetMesh( const ResourceTicketPtr ticket,
98 const BoneContainer& bones,
99 const MaterialIPtr material )
101 SetMesh( 0, ticket->GetId(), bones, material );
104 void MeshAttachment::SetMaterial( MaterialIPtr material )
106 const SceneGraph::Material* materialSceneObject = NULL;
110 // We have a new material.
113 DisconnectMaterial();
115 // connect the new material
119 mMesh.mCustomMaterial = material;
121 materialSceneObject = material->GetSceneObject();
122 DALI_ASSERT_DEBUG( materialSceneObject != NULL );
126 // We are unsetting the current material, and reverting to the original material
127 if ( mMesh.mCustomMaterial )
131 mMesh.mCustomMaterial->Disconnect();
133 mMesh.mCustomMaterial = NULL;
136 // connect original material
137 DALI_ASSERT_DEBUG( mMesh.mMaterial );
141 mMesh.mMaterial->Connect();
143 materialSceneObject = mMesh.mMaterial->GetSceneObject();
148 // sceneObject is being used in a separate thread; queue a message to set
149 SetMaterialMessage( mStage->GetUpdateInterface(), *mSceneObject, materialSceneObject );
153 Internal::MaterialIPtr MeshAttachment::GetMaterial( ) const
155 Internal::MaterialIPtr material;
157 if ( mMesh.mCustomMaterial )
159 material = mMesh.mCustomMaterial;
161 else if ( mMesh.mMaterial )
163 material = mMesh.mMaterial;
169 void MeshAttachment::DisconnectMaterial()
171 if ( mMesh.mCustomMaterial )
173 mMesh.mCustomMaterial->Disconnect();
175 else if ( mMesh.mMaterial )
177 mMesh.mMaterial->Disconnect();
181 void MeshAttachment::SetAffectedByLighting( bool affectedByLighting )
183 // sceneObject is being used in a separate thread; queue a message to set
184 SetAffectedByLightingMessage( mStage->GetUpdateInterface(), *mSceneObject, affectedByLighting );
186 mAffectedByLighting = affectedByLighting;
189 bool MeshAttachment::IsAffectedByLighting()
191 return mAffectedByLighting;
194 void MeshAttachment::BindBonesToMesh( Internal::ActorPtr rootActor )
197 size_t boneCount = mMesh.mBoneNames.size();
201 for ( BoneNamesIter boneIter=mMesh.mBoneNames.begin(); boneIter != mMesh.mBoneNames.end(); ++boneIter )
203 ActorPtr boneActor = rootActor->FindChildByName( *boneIter );
206 ConnectBoneActor( boneActor, boneIdx, boneCount );
213 void MeshAttachment::ConnectBoneActor( Internal::ActorPtr boneActor,
217 Connector* connector = new Connector( boneActor, boneIdx, *this );
218 mConnectors.PushBack( connector );
219 connector->ConnectNode();
222 void MeshAttachment::OnStageConnection2()
224 // Ensure current materials are staged
225 const SceneGraph::MeshAttachment& sceneObject = *mSceneObject;
227 const SceneGraph::Material* materialSceneObject = NULL;
228 if ( mMesh.mCustomMaterial )
230 mMesh.mCustomMaterial->Connect();
231 materialSceneObject = mMesh.mCustomMaterial->GetSceneObject();
233 else if ( mMesh.mMaterial )
235 mMesh.mMaterial->Connect();
236 materialSceneObject = mMesh.mMaterial->GetSceneObject();
238 DALI_ASSERT_DEBUG( materialSceneObject );
240 // And that the scene object has a connection to each material
241 SetMaterialMessage( mStage->GetUpdateInterface(), sceneObject, materialSceneObject );
243 // Ensure all staged bones are reconnected
244 for(ConnectorList::Iterator iter=mConnectors.Begin(); iter != mConnectors.End(); ++iter)
246 Connector* connector = (*iter);
247 connector->ConnectNode();
251 void MeshAttachment::OnStageDisconnection2()
253 DisconnectMaterial();
256 const SceneGraph::RenderableAttachment& MeshAttachment::GetSceneObject() const
258 DALI_ASSERT_DEBUG( mSceneObject != NULL );
259 return *mSceneObject;
262 void MeshAttachment::SetBoneNode( SceneGraph::Node* node, size_t boneIdx )
264 size_t boneCount = mMesh.mBoneNames.size();
266 SetBoneNodeMessage( mStage->GetUpdateInterface(), *mSceneObject, node, boneIdx, boneCount );
269 // Helper class for connecting Nodes to the scene-graph MeshAttachment
270 MeshAttachment::Connector::Connector(
271 Internal::ActorPtr boneActor,
273 MeshAttachment& meshAttachment)
274 : mMeshAttachment(meshAttachment),
275 mActor(boneActor.Get()),
280 mActor->AddObserver( *this );
285 MeshAttachment::Connector::~Connector()
289 mActor->RemoveObserver( *this );
293 void MeshAttachment::Connector::SceneObjectAdded( ProxyObject& proxy )
298 void MeshAttachment::Connector::SceneObjectRemoved( ProxyObject& proxy )
303 void MeshAttachment::Connector::ProxyDestroyed( ProxyObject& proxy )
310 void MeshAttachment::Connector::ConnectNode()
312 SceneGraph::Node* theNode( NULL );
316 const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
317 if ( NULL != object )
319 const SceneGraph::Node* aNode = dynamic_cast< const SceneGraph::Node* >( object );
322 theNode = const_cast< SceneGraph::Node* >( aNode );
327 mMeshAttachment.SetBoneNode( theNode, mBoneIdx );
331 } // namespace Internal