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