9ba760681afb5bc1aaf14bf1bca8eab4092f5b54
[platform/core/uifw/dali-core.git] / dali / internal / event / modeling / animatable-mesh-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 #include <dali/internal/event/common/property-index-ranges.h>
19 #include <dali/internal/event/common/stage-impl.h>
20 #include <dali/internal/event/common/thread-local-storage.h>
21 #include <dali/internal/event/modeling/animatable-mesh-impl.h>
22 #include <dali/internal/event/modeling/mesh-impl.h>
23 #include <dali/internal/event/modeling/material-impl.h>
24 #include <dali/internal/update/manager/update-manager.h>
25 #include <dali/internal/update/modeling/scene-graph-animatable-mesh.h>
26
27 namespace Dali
28 {
29
30 const Property::Index AnimatableVertex::POSITION          = 0;
31 const Property::Index AnimatableVertex::COLOR             = 1;
32 const Property::Index AnimatableVertex::TEXTURE_COORDS    = 2;
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 const PropertyDetails DEFAULT_PROPERTY_DETAILS[] =
41 {
42  // Name               Type            writable animatable constraint-input
43  { "position",       Property::VECTOR3, true,    true,   true  }, // POSITION
44  { "vertex-color",   Property::VECTOR4, true,    true,   true  }, // COLOR
45  { "texture-coords", Property::VECTOR2, true,    true,   true  }, // TEXTURE_COORDS
46 };
47
48 const int VERTEX_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( DEFAULT_PROPERTY_DETAILS[0] );
49
50 } // namespace
51
52 AnimatableMesh::AnimatableMesh(
53   SceneGraph::UpdateManager& updateManager,
54   SceneGraph::AnimatableMesh* sceneObject,
55   MeshIPtr mesh,
56   int numberOfVertices )
57 : mUpdateManager( updateManager ),
58   mSceneObject( sceneObject ),
59   mMesh( mesh ),
60   mNumberOfVertices( numberOfVertices ),
61   mPropertyCount( numberOfVertices * VERTEX_PROPERTY_COUNT )
62 {
63   // Transfer animatable ownership to a scene message
64   AddAnimatableMeshMessage( mUpdateManager, *mSceneObject );
65 }
66
67
68 AnimatableMeshPtr AnimatableMesh::New(
69   unsigned int numVertices,
70   const Dali::AnimatableMesh::Faces& faceIndices )
71 {
72   return New( numVertices, faceIndices, Dali::Material::New("dummy material"), true );
73 }
74
75 AnimatableMeshPtr AnimatableMesh::New(
76   unsigned int numVertices,
77   const Dali::AnimatableMesh::Faces& faceIndices,
78   Dali::Material material)
79 {
80   return New( numVertices, faceIndices, material, false );
81 }
82
83
84 AnimatableMeshPtr AnimatableMesh::New(
85   unsigned int numVertices,
86   const Dali::AnimatableMesh::Faces& faceIndices,
87   Dali::Material material,
88   bool useVertexColor )
89 {
90   DALI_ASSERT_ALWAYS( numVertices > 0 && "Mesh has no vertices" );
91   DALI_ASSERT_ALWAYS( ( numVertices * 3 ) < DEFAULT_PROPERTY_MAX_COUNT && "Mesh exceeds maximum supported vertices" );
92   DALI_ASSERT_ALWAYS( faceIndices.size() > 0 && "Mesh has no faces" );
93   for( Dali::AnimatableMesh::FacesConstIter faceIter=faceIndices.begin();
94        faceIter != faceIndices.end();
95        ++faceIter )
96   {
97     unsigned int faceIndex = *faceIter;
98     DALI_ASSERT_ALWAYS( faceIndex < numVertices && "Face index out of range" );
99   }
100
101   ThreadLocalStorage& tls = ThreadLocalStorage::Get();
102   SceneGraph::UpdateManager& updateManager = tls.GetUpdateManager();
103   ResourceManager& resourceManager = tls.GetResourceManager();
104
105   Dali::MeshData meshData;
106
107   // We need a valid mesh data object to create the scene graph mesh
108   Dali::MeshData::VertexContainer vertices( numVertices );
109   BoneContainer bones;
110   meshData.SetData(vertices, faceIndices, bones, material);
111   bool useColor = false;
112   if(useVertexColor)
113   {
114     useColor=true;
115   }
116   meshData.SetHasColor(useColor);
117   meshData.SetHasNormals(false);
118   meshData.SetHasTextureCoords(true);
119
120   MeshIPtr mesh( Mesh::New( meshData, false /* not discardable, data is updated in the update thread */, true /* Scaling is required */ ) );
121
122   // Create the scene object
123   SceneGraph::AnimatableMesh* sceneObject = new SceneGraph::AnimatableMesh( resourceManager, mesh->GetResourceId(), meshData.GetVertices() );
124
125   // Create the event object
126   AnimatableMeshPtr animatableMeshPtr( new AnimatableMesh( updateManager, sceneObject, mesh, meshData.GetVertexCount() ) );
127
128   return animatableMeshPtr;
129 }
130
131
132 AnimatableMesh::~AnimatableMesh()
133 {
134   // Guard to allow handle destruction after Core has been destroyed
135   if ( Stage::IsInstalled() )
136   {
137     if( mSceneObject )
138     {
139       RemoveAnimatableMeshMessage( mUpdateManager, *mSceneObject );
140     }
141   }
142 }
143
144 unsigned int AnimatableMesh::GetNumberOfVertices() const
145 {
146   return mNumberOfVertices;
147 }
148
149 Property::Index AnimatableMesh::GetVertexPropertyIndex(
150   unsigned int vertex,
151   Property::Index property ) const
152 {
153   DALI_ASSERT_DEBUG(property < VERTEX_PROPERTY_COUNT );
154   return ( vertex * VERTEX_PROPERTY_COUNT ) + property;
155 }
156
157 void AnimatableMesh::SetPosition( unsigned int vertexIndex, const Vector3& position)
158 {
159   StagePtr stage = Stage::GetCurrent();
160   BakeVertexPositionMessage( stage->GetUpdateInterface(), *mSceneObject, vertexIndex, position );
161 }
162
163 void AnimatableMesh::SetColor( unsigned int vertexIndex, const Vector4& color)
164 {
165   StagePtr stage = Stage::GetCurrent();
166   BakeVertexColorMessage( stage->GetUpdateInterface(), *mSceneObject, vertexIndex, color );
167 }
168
169 void AnimatableMesh::SetTextureCoords( unsigned int vertexIndex, const Vector2& coords)
170 {
171   StagePtr stage = Stage::GetCurrent();
172   BakeVertexTextureCoordsMessage( stage->GetUpdateInterface(), *mSceneObject, vertexIndex, coords );
173 }
174
175 const Vector3& AnimatableMesh::GetCurrentPosition( unsigned int vertexIndex) const
176 {
177   StagePtr stage = Stage::GetCurrent();
178   return mSceneObject->GetPosition(stage->GetEventBufferIndex(), vertexIndex);
179 }
180
181 const Vector4& AnimatableMesh::GetCurrentColor( unsigned int vertexIndex) const
182 {
183   StagePtr stage = Stage::GetCurrent();
184   return mSceneObject->GetColor(stage->GetEventBufferIndex(), vertexIndex);
185 }
186
187 const Vector2& AnimatableMesh::GetCurrentTextureCoords( unsigned int vertexIndex) const
188 {
189   StagePtr stage = Stage::GetCurrent();
190   return mSceneObject->GetTextureCoords(stage->GetEventBufferIndex(), vertexIndex);
191 }
192
193 MeshIPtr AnimatableMesh::GetMesh()
194 {
195   return mMesh;
196 }
197
198 /********************************************************************************
199  ********************************************************************************
200  ********************************   PROPERTY METHODS   **************************
201  ********************************************************************************
202  ********************************************************************************/
203
204 bool AnimatableMesh::Supports( Capability capability ) const
205 {
206   return false;
207 }
208
209 bool AnimatableMesh::IsSceneObjectRemovable() const
210 {
211   return false; // The scene object is permanently "on stage" whilst this object is alive
212 }
213
214 unsigned int AnimatableMesh::GetDefaultPropertyCount() const
215 {
216   return mPropertyCount;
217 }
218
219 void AnimatableMesh::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
220 {
221   indices.reserve( mPropertyCount );
222
223   for ( int i = 0; i < mPropertyCount; ++i )
224   {
225     indices.push_back( i );
226   }
227 }
228
229 const char* AnimatableMesh::GetDefaultPropertyName( Property::Index index ) const
230 {
231   if ( ( index >= 0 ) && ( index < mPropertyCount ) )
232   {
233     return DEFAULT_PROPERTY_DETAILS[index % VERTEX_PROPERTY_COUNT].name;
234   }
235   else
236   {
237     return NULL;
238   }
239 }
240
241 Property::Index AnimatableMesh::GetDefaultPropertyIndex(const std::string& name) const
242 {
243   Property::Index index = Property::INVALID_INDEX;
244
245   // Look for name in default properties
246   for( int i = 0; i < VERTEX_PROPERTY_COUNT; ++i )
247   {
248     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
249     if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
250     {
251       index = i;
252       break;
253     }
254   }
255   return index;
256 }
257
258 bool AnimatableMesh::IsDefaultPropertyWritable(Property::Index index) const
259 {
260   return DEFAULT_PROPERTY_DETAILS[ index % VERTEX_PROPERTY_COUNT ].writable;
261 }
262
263 bool AnimatableMesh::IsDefaultPropertyAnimatable(Property::Index index) const
264 {
265   return DEFAULT_PROPERTY_DETAILS[ index % VERTEX_PROPERTY_COUNT ].animatable;
266 }
267
268 bool AnimatableMesh::IsDefaultPropertyAConstraintInput( Property::Index index ) const
269 {
270   return DEFAULT_PROPERTY_DETAILS[ index % VERTEX_PROPERTY_COUNT ].constraintInput;
271 }
272
273 Property::Type AnimatableMesh::GetDefaultPropertyType(Property::Index index) const
274 {
275   if ( ( index >= 0 ) && ( index < mPropertyCount ) )
276   {
277     return DEFAULT_PROPERTY_DETAILS[ index % VERTEX_PROPERTY_COUNT ].type;
278   }
279   else
280   {
281     // Index out-of-bounds
282     return Property::NONE;
283   }
284 }
285
286 void AnimatableMesh::SetDefaultProperty( Property::Index index, const Property::Value& property )
287 {
288   DALI_ASSERT_ALWAYS( ( index >= 0 ) && ( index < mPropertyCount ) );
289
290   int vertexProperty = index % VERTEX_PROPERTY_COUNT;
291   int vertexIndex    = index / VERTEX_PROPERTY_COUNT;
292   switch ( vertexProperty )
293   {
294     case Dali::AnimatableVertex::POSITION:
295     {
296       SetPosition( vertexIndex, property.Get<Vector3>() );
297       break;
298     }
299     case Dali::AnimatableVertex::COLOR:
300     {
301       SetColor( vertexIndex, property.Get<Vector4>() );
302       break;
303     }
304     case Dali::AnimatableVertex::TEXTURE_COORDS:
305     {
306       SetTextureCoords( vertexIndex, property.Get<Vector2>() );
307       break;
308     }
309   }
310 }
311
312 void AnimatableMesh::SetCustomProperty( Property::Index /*index*/, const CustomProperty& /*entry*/, const Property::Value& /*value*/ )
313 {
314   DALI_ASSERT_ALWAYS( 0 && "AnimatableMesh does not support custom properties");
315 }
316
317 Property::Value AnimatableMesh::GetDefaultProperty(Property::Index index) const
318 {
319   Property::Value value;
320   int vertexProperty = index % VERTEX_PROPERTY_COUNT;
321   int vertexIndex    = index / VERTEX_PROPERTY_COUNT;
322
323   switch ( vertexProperty )
324   {
325     case Dali::AnimatableVertex::POSITION:
326     {
327       value = GetCurrentPosition(vertexIndex);
328       break;
329     }
330     case Dali::AnimatableVertex::COLOR:
331     {
332       value = GetCurrentColor(vertexIndex);
333       break;
334     }
335     case Dali::AnimatableVertex::TEXTURE_COORDS:
336     {
337       value = GetCurrentTextureCoords(vertexIndex);
338       break;
339     }
340   }
341
342   return value;
343 }
344
345 void AnimatableMesh::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
346 {
347   DALI_ASSERT_ALWAYS( 0 && "AnimatableMesh does not support custom properties" );
348 }
349
350 const SceneGraph::PropertyOwner* AnimatableMesh::GetSceneObject() const
351 {
352   return mSceneObject;
353 }
354
355 const SceneGraph::PropertyBase* AnimatableMesh::GetSceneObjectAnimatableProperty( Property::Index index ) const
356 {
357   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
358
359   const SceneGraph::PropertyBase* property( NULL );
360
361   // This method should only return a property which is part of the scene-graph
362   if( mSceneObject != NULL )
363   {
364     int vertexProperty = index % VERTEX_PROPERTY_COUNT;
365     int vertexIndex    = index / VERTEX_PROPERTY_COUNT;
366
367     switch ( vertexProperty )
368     {
369       case Dali::AnimatableVertex::POSITION:
370         property = &mSceneObject->mVertices[vertexIndex].position;
371         break;
372       case Dali::AnimatableVertex::COLOR:
373         property = &mSceneObject->mVertices[vertexIndex].color;
374         break;
375       case Dali::AnimatableVertex::TEXTURE_COORDS:
376         property = &mSceneObject->mVertices[vertexIndex].textureCoords;
377         break;
378     }
379   }
380
381   return property;
382 }
383
384 const PropertyInputImpl* AnimatableMesh::GetSceneObjectInputProperty( Property::Index index ) const
385 {
386   const PropertyInputImpl* property( NULL );
387   if( mSceneObject != NULL )
388   {
389     int vertexProperty = index % VERTEX_PROPERTY_COUNT;
390     int vertexIndex    = index / VERTEX_PROPERTY_COUNT;
391
392     switch ( vertexProperty )
393     {
394       case Dali::AnimatableVertex::POSITION:
395         property = &mSceneObject->mVertices[vertexIndex].position;
396         break;
397       case Dali::AnimatableVertex::COLOR:
398         property = &mSceneObject->mVertices[vertexIndex].color;
399         break;
400       case Dali::AnimatableVertex::TEXTURE_COORDS:
401         property = &mSceneObject->mVertices[vertexIndex].textureCoords;
402         break;
403     }
404   }
405
406   return property;
407 }
408
409 } // internal
410 } // dali