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( const SceneGraph::Node& parentNode )
39 StagePtr stage = Stage::GetCurrent();
41 MeshAttachmentPtr attachment( new MeshAttachment( *stage ) );
43 // Transfer object ownership of scene-object to message
44 SceneGraph::MeshAttachment* sceneObject = SceneGraph::MeshAttachment::New();
45 AttachToNodeMessage( stage->GetUpdateManager(), parentNode, sceneObject );
47 // Keep raw pointer for message passing
48 attachment->mSceneObject = sceneObject;
53 MeshAttachment::MeshAttachment( Stage& stage )
54 : RenderableAttachment( stage ),
56 mAffectedByLighting( true )
60 MeshAttachment::~MeshAttachment()
62 // Belt and braces - should already have been disconnected from stage
63 if ( Stage::IsInstalled() &&
70 void MeshAttachment::SetMesh( const MeshIPtr meshPtr,
72 const BoneContainer& bones,
73 const MaterialIPtr material )
75 mMesh.mMesh = meshPtr;
76 mMesh.mCustomMaterial = 0;
78 std::size_t boneCount = bones.size();
82 // Copy bone names locally in order to perform actor binding later
84 // Must keep names in same order (vertices reference into bone matrix array by index)
85 for ( BoneContainer::const_iterator iter = bones.begin(); iter != bones.end(); ++iter )
87 const Bone& bone = (*iter);
88 mMesh.mBoneNames.push_back( bone.GetName() );
92 mMesh.mMaterial = material;
93 const SceneGraph::Material* materialSceneObject = material->GetSceneObject();
95 // sceneObject is being used in a separate thread; queue a message to set
96 SetMeshMessage( mStage->GetUpdateInterface(), *mSceneObject, meshId, materialSceneObject, boneCount );
99 void MeshAttachment::SetMesh( const ResourceTicketPtr ticket,
100 const BoneContainer& bones,
101 const MaterialIPtr material )
103 SetMesh( 0, ticket->GetId(), bones, material );
106 void MeshAttachment::SetMaterial( MaterialIPtr material )
108 const SceneGraph::Material* materialSceneObject = NULL;
112 // We have a new material.
115 DisconnectMaterial();
117 // connect the new material
121 mMesh.mCustomMaterial = material;
123 materialSceneObject = material->GetSceneObject();
124 DALI_ASSERT_DEBUG( materialSceneObject != NULL );
128 // We are unsetting the current material, and reverting to the original material
129 if ( mMesh.mCustomMaterial )
133 mMesh.mCustomMaterial->Disconnect();
135 mMesh.mCustomMaterial = NULL;
138 // connect original material
139 DALI_ASSERT_DEBUG( mMesh.mMaterial );
143 mMesh.mMaterial->Connect();
145 materialSceneObject = mMesh.mMaterial->GetSceneObject();
150 // sceneObject is being used in a separate thread; queue a message to set
151 SetMaterialMessage( mStage->GetUpdateInterface(), *mSceneObject, materialSceneObject );
155 Internal::MaterialIPtr MeshAttachment::GetMaterial( ) const
157 Internal::MaterialIPtr material;
159 if ( mMesh.mCustomMaterial )
161 material = mMesh.mCustomMaterial;
163 else if ( mMesh.mMaterial )
165 material = mMesh.mMaterial;
171 void MeshAttachment::DisconnectMaterial()
173 if ( mMesh.mCustomMaterial )
175 mMesh.mCustomMaterial->Disconnect();
177 else if ( mMesh.mMaterial )
179 mMesh.mMaterial->Disconnect();
183 void MeshAttachment::SetAffectedByLighting( bool affectedByLighting )
185 // sceneObject is being used in a separate thread; queue a message to set
186 SetAffectedByLightingMessage( mStage->GetUpdateInterface(), *mSceneObject, affectedByLighting );
188 mAffectedByLighting = affectedByLighting;
191 bool MeshAttachment::IsAffectedByLighting()
193 return mAffectedByLighting;
196 void MeshAttachment::BindBonesToMesh( Internal::ActorPtr rootActor )
199 size_t boneCount = mMesh.mBoneNames.size();
203 for ( BoneNamesIter boneIter=mMesh.mBoneNames.begin(); boneIter != mMesh.mBoneNames.end(); ++boneIter )
205 ActorPtr boneActor = rootActor->FindChildByName( *boneIter );
208 ConnectBoneActor( boneActor, boneIdx, boneCount );
215 void MeshAttachment::ConnectBoneActor( Internal::ActorPtr boneActor,
219 Connector* connector = new Connector( boneActor, boneIdx, *this );
220 mConnectors.PushBack( connector );
221 connector->ConnectNode();
224 void MeshAttachment::OnStageConnection2()
226 // Ensure current materials are staged
227 const SceneGraph::MeshAttachment& sceneObject = *mSceneObject;
229 const SceneGraph::Material* materialSceneObject = NULL;
230 if ( mMesh.mCustomMaterial )
232 mMesh.mCustomMaterial->Connect();
233 materialSceneObject = mMesh.mCustomMaterial->GetSceneObject();
235 else if ( mMesh.mMaterial )
237 mMesh.mMaterial->Connect();
238 materialSceneObject = mMesh.mMaterial->GetSceneObject();
240 DALI_ASSERT_DEBUG( materialSceneObject );
242 // And that the scene object has a connection to each material
243 SetMaterialMessage( mStage->GetUpdateInterface(), sceneObject, materialSceneObject );
245 // Ensure all staged bones are reconnected
246 for(ConnectorList::Iterator iter=mConnectors.Begin(); iter != mConnectors.End(); ++iter)
248 Connector* connector = (*iter);
249 connector->ConnectNode();
253 void MeshAttachment::OnStageDisconnection2()
255 DisconnectMaterial();
258 const SceneGraph::RenderableAttachment& MeshAttachment::GetSceneObject() const
260 DALI_ASSERT_DEBUG( mSceneObject != NULL );
261 return *mSceneObject;
264 void MeshAttachment::SetBoneNode( SceneGraph::Node* node, size_t boneIdx )
266 size_t boneCount = mMesh.mBoneNames.size();
268 SetBoneNodeMessage( mStage->GetUpdateInterface(), *mSceneObject, node, boneIdx, boneCount );
271 // Helper class for connecting Nodes to the scene-graph MeshAttachment
272 MeshAttachment::Connector::Connector(
273 Internal::ActorPtr boneActor,
275 MeshAttachment& meshAttachment)
276 : mMeshAttachment(meshAttachment),
277 mActor(boneActor.Get()),
282 mActor->AddObserver( *this );
287 MeshAttachment::Connector::~Connector()
291 mActor->RemoveObserver( *this );
295 void MeshAttachment::Connector::SceneObjectAdded( ProxyObject& proxy )
300 void MeshAttachment::Connector::SceneObjectRemoved( ProxyObject& proxy )
305 void MeshAttachment::Connector::ProxyDestroyed( ProxyObject& proxy )
312 void MeshAttachment::Connector::ConnectNode()
314 SceneGraph::Node* theNode( NULL );
318 const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
319 if ( NULL != object )
321 const SceneGraph::Node* aNode = dynamic_cast< const SceneGraph::Node* >( object );
324 theNode = const_cast< SceneGraph::Node* >( aNode );
329 mMeshAttachment.SetBoneNode( theNode, mBoneIdx );
333 } // namespace Internal