Fix issues reported by cppcheck
[platform/core/uifw/dali-core.git] / dali / internal / event / actor-attachments / mesh-attachment-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/actor-attachments/mesh-attachment-impl.h>
20
21 // INTERNAL INCLUDES
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>
27
28 using Dali::Internal::MeshIPtr;
29 using Dali::Internal::MaterialIPtr;
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 MeshAttachmentPtr MeshAttachment::New( const SceneGraph::Node& parentNode )
38 {
39   StagePtr stage = Stage::GetCurrent();
40
41   MeshAttachmentPtr attachment( new MeshAttachment( *stage ) );
42
43   // Transfer object ownership of scene-object to message
44   SceneGraph::MeshAttachment* sceneObject = SceneGraph::MeshAttachment::New();
45   AttachToNodeMessage( stage->GetUpdateManager(), parentNode, sceneObject );
46
47   // Keep raw pointer for message passing
48   attachment->mSceneObject = sceneObject;
49
50   return attachment;
51 }
52
53 MeshAttachment::MeshAttachment( Stage& stage )
54 : RenderableAttachment( stage ),
55   mSceneObject( NULL ),
56   mAffectedByLighting( true )
57 {
58 }
59
60 MeshAttachment::~MeshAttachment()
61 {
62   // Belt and braces - should already have been disconnected from stage
63   if ( Stage::IsInstalled() &&
64        OnStage() )
65   {
66     DisconnectMaterial();
67   }
68 }
69
70 void MeshAttachment::SetMesh( const MeshIPtr        meshPtr,
71                               ResourceId            meshId,
72                               const BoneContainer&  bones,
73                               const MaterialIPtr    material )
74 {
75   mMesh.mMesh = meshPtr;
76   mMesh.mCustomMaterial = 0;
77
78   std::size_t boneCount = bones.size();
79
80   if ( boneCount > 0 )
81   {
82     // Copy bone names locally in order to perform actor binding later
83
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 )
86     {
87       const Bone& bone = (*iter);
88       mMesh.mBoneNames.push_back( bone.GetName() );
89     }
90   }
91
92   mMesh.mMaterial = material;
93   const SceneGraph::Material* materialSceneObject = material->GetSceneObject();
94
95   // sceneObject is being used in a separate thread; queue a message to set
96   SetMeshMessage( mStage->GetUpdateInterface(), *mSceneObject, meshId, materialSceneObject, boneCount );
97 }
98
99 void MeshAttachment::SetMesh( const ResourceTicketPtr ticket,
100                               const BoneContainer& bones,
101                               const MaterialIPtr material )
102 {
103   SetMesh( 0, ticket->GetId(), bones, material );
104 }
105
106 void MeshAttachment::SetMaterial( MaterialIPtr material )
107 {
108   const SceneGraph::Material* materialSceneObject = NULL;
109
110   if ( material )
111   {
112     // We have a new material.
113     if ( OnStage() )
114     {
115       DisconnectMaterial();
116
117       // connect the new material
118       material->Connect();
119     }
120
121     mMesh.mCustomMaterial = material;
122
123     materialSceneObject = material->GetSceneObject();
124     DALI_ASSERT_DEBUG( materialSceneObject != NULL );
125   }
126   else
127   {
128     // We are unsetting the current material, and reverting to the original material
129     if ( mMesh.mCustomMaterial )
130     {
131       if ( OnStage() )
132       {
133         mMesh.mCustomMaterial->Disconnect();
134       }
135       mMesh.mCustomMaterial = NULL;
136     }
137
138     // connect original material
139     DALI_ASSERT_DEBUG( mMesh.mMaterial );
140
141     if ( OnStage() )
142     {
143       mMesh.mMaterial->Connect();
144     }
145     materialSceneObject = mMesh.mMaterial->GetSceneObject();
146   }
147
148   if ( OnStage() )
149   {
150     // sceneObject is being used in a separate thread; queue a message to set
151     SetMaterialMessage( mStage->GetUpdateInterface(), *mSceneObject, materialSceneObject );
152   }
153 }
154
155 Internal::MaterialIPtr MeshAttachment::GetMaterial( ) const
156 {
157   Internal::MaterialIPtr material;
158
159   if ( mMesh.mCustomMaterial )
160   {
161     material = mMesh.mCustomMaterial;
162   }
163   else if ( mMesh.mMaterial )
164   {
165     material = mMesh.mMaterial;
166   }
167   return material;
168 }
169
170
171 void MeshAttachment::DisconnectMaterial()
172 {
173   if ( mMesh.mCustomMaterial )
174   {
175     mMesh.mCustomMaterial->Disconnect();
176   }
177   else if ( mMesh.mMaterial )
178   {
179     mMesh.mMaterial->Disconnect();
180   }
181 }
182
183 void MeshAttachment::SetAffectedByLighting( bool affectedByLighting )
184 {
185   // sceneObject is being used in a separate thread; queue a message to set
186   SetAffectedByLightingMessage( mStage->GetUpdateInterface(), *mSceneObject, affectedByLighting );
187
188   mAffectedByLighting = affectedByLighting;
189 }
190
191 bool MeshAttachment::IsAffectedByLighting()
192 {
193   return mAffectedByLighting;
194 }
195
196 void MeshAttachment::BindBonesToMesh( Internal::ActorPtr rootActor )
197 {
198   size_t boneIdx = 0;
199   size_t boneCount = mMesh.mBoneNames.size();
200
201   if ( boneCount > 0 )
202   {
203     for ( BoneNamesIter boneIter=mMesh.mBoneNames.begin(); boneIter != mMesh.mBoneNames.end(); ++boneIter )
204     {
205       ActorPtr boneActor = rootActor->FindChildByName( *boneIter );
206       if ( boneActor )
207       {
208         ConnectBoneActor( boneActor, boneIdx, boneCount );
209         boneIdx++;
210       }
211     }
212   }
213 }
214
215 void MeshAttachment::ConnectBoneActor( Internal::ActorPtr boneActor,
216                                        size_t             boneIdx,
217                                        size_t             boneCount )
218 {
219   Connector* connector = new Connector( boneActor, boneIdx, *this );
220   mConnectors.PushBack( connector );
221   connector->ConnectNode();
222 }
223
224 void MeshAttachment::OnStageConnection2()
225 {
226   // Ensure current materials are staged
227   const SceneGraph::MeshAttachment& sceneObject = *mSceneObject;
228
229   const SceneGraph::Material* materialSceneObject = NULL;
230   if ( mMesh.mCustomMaterial )
231   {
232     mMesh.mCustomMaterial->Connect();
233     materialSceneObject = mMesh.mCustomMaterial->GetSceneObject();
234   }
235   else if ( mMesh.mMaterial )
236   {
237     mMesh.mMaterial->Connect();
238     materialSceneObject = mMesh.mMaterial->GetSceneObject();
239   }
240   DALI_ASSERT_DEBUG( materialSceneObject );
241
242   // And that the scene object has a connection to each material
243   SetMaterialMessage( mStage->GetUpdateInterface(), sceneObject, materialSceneObject );
244
245   // Ensure all staged bones are reconnected
246   for(ConnectorList::Iterator iter=mConnectors.Begin(); iter != mConnectors.End(); ++iter)
247   {
248     Connector* connector = (*iter);
249     connector->ConnectNode();
250   }
251 }
252
253 void MeshAttachment::OnStageDisconnection2()
254 {
255   DisconnectMaterial();
256 }
257
258 const SceneGraph::RenderableAttachment& MeshAttachment::GetSceneObject() const
259 {
260   DALI_ASSERT_DEBUG( mSceneObject != NULL );
261   return *mSceneObject;
262 }
263
264 void MeshAttachment::SetBoneNode( SceneGraph::Node* node, size_t boneIdx )
265 {
266   size_t boneCount = mMesh.mBoneNames.size();
267
268   SetBoneNodeMessage( mStage->GetUpdateInterface(), *mSceneObject, node, boneIdx, boneCount );
269 }
270
271 // Helper class for connecting Nodes to the scene-graph MeshAttachment
272 MeshAttachment::Connector::Connector(
273   Internal::ActorPtr boneActor,
274   size_t             boneIdx,
275   MeshAttachment&    meshAttachment)
276 : mMeshAttachment(meshAttachment),
277   mActor(boneActor.Get()),
278   mBoneIdx(boneIdx)
279 {
280   if( mActor )
281   {
282     mActor->AddObserver( *this );
283     ConnectNode();
284   }
285 }
286
287 MeshAttachment::Connector::~Connector()
288 {
289   if( mActor)
290   {
291     mActor->RemoveObserver( *this );
292   }
293 }
294
295 void MeshAttachment::Connector::SceneObjectAdded( ProxyObject& proxy )
296 {
297   ConnectNode();
298 }
299
300 void MeshAttachment::Connector::SceneObjectRemoved( ProxyObject& proxy )
301 {
302   ConnectNode();
303 }
304
305 void MeshAttachment::Connector::ProxyDestroyed( ProxyObject& proxy )
306 {
307   mActor = NULL;
308
309   ConnectNode();
310 }
311
312 void MeshAttachment::Connector::ConnectNode()
313 {
314   SceneGraph::Node* theNode( NULL );
315
316   if( mActor != NULL )
317   {
318     const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
319     if ( NULL != object )
320     {
321       const SceneGraph::Node* aNode = dynamic_cast< const SceneGraph::Node* >( object );
322       if( aNode != NULL )
323       {
324         theNode = const_cast< SceneGraph::Node* >( aNode );
325       }
326     }
327   }
328
329   mMeshAttachment.SetBoneNode( theNode, mBoneIdx );
330 }
331
332
333 } // namespace Internal
334
335 } // namespace Dali