Remove animatable property-buffer API.
[platform/core/uifw/dali-core.git] / dali / internal / event / common / property-buffer-impl.cpp
1 /*
2  * Copyright (c) 2015 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/common/property-buffer-impl.h>  // Dali::Internal::PropertyBuffer
20
21 // EXTERNAL INCLUDE
22 #include <algorithm> // std::sort
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/object/property-buffer.h> // Dali::Internal::PropertyBuffer
26 #include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
27 #include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
28 #include <dali/internal/update/common/scene-graph-property-buffer.h>
29 #include <dali/internal/update/manager/update-manager.h>
30
31 namespace Dali
32 {
33 namespace Internal
34 {
35
36 using SceneGraph::PropertyBufferMetadata::Format;
37 using SceneGraph::PropertyBufferMetadata::Component;
38
39 namespace
40 {
41
42 /**
43  *            |name    |type             |writable|animatable|constraint-input|enum for index-checking|
44  */
45 DALI_PROPERTY_TABLE_BEGIN
46 DALI_PROPERTY( "size",          UNSIGNED_INTEGER, true, false,  true,   Dali::PropertyBuffer::Property::SIZE )
47 DALI_PROPERTY( "buffer-format", MAP,              false, false, false,  Dali::PropertyBuffer::Property::BUFFER_FORMAT )
48 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
49
50 const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> PROPERTY_BUFFER_IMPL = { DEFAULT_PROPERTY_DETAILS };
51
52 /**
53  * Calculate the alignment requirements of a type
54  *
55  * This is used to calculate the memory alignment requirements of a type
56  * It creates a structure with a dummy char and a member of the type we want to check
57  * this will cause the second member to be aligned by it's alignment requirement.
58  */
59 template<Property::Type type>
60 struct PropertyImplementationTypeAlignment
61 {
62   // Create a structure that forces alignment of the data type
63   struct TestStructure
64   {
65     char oneChar;  ///< Member with sizeof() == 1
66     typename PropertyImplementationType<type>::Type data;
67   };
68   enum { VALUE = offsetof( TestStructure, data ) };
69 };
70
71 unsigned int GetPropertyImplementationAlignment( Property::Type& propertyType )
72 {
73   unsigned int alignment = 0u;
74
75   switch( propertyType )
76   {
77     case Property::NONE:
78     case Property::TYPE_COUNT:
79     case Property::STRING:
80     case Property::ARRAY:
81     case Property::MAP:
82     {
83       DALI_ASSERT_ALWAYS( "No size for properties with no type, or dynamic sizes" );
84       break;
85     }
86     case Property::BOOLEAN:
87     {
88       alignment = PropertyImplementationTypeAlignment< Property::BOOLEAN >::VALUE;
89       break;
90     }
91     case Property::INTEGER:
92     {
93       alignment = PropertyImplementationTypeAlignment< Property::INTEGER >::VALUE;
94       break;
95     }
96     case Property::UNSIGNED_INTEGER:
97     {
98       alignment = PropertyImplementationTypeAlignment< Property::UNSIGNED_INTEGER >::VALUE;
99       break;
100     }
101     case Property::FLOAT:
102     {
103       alignment = PropertyImplementationTypeAlignment< Property::FLOAT >::VALUE;
104       break;
105     }
106     case Property::VECTOR2:
107     {
108       alignment = PropertyImplementationTypeAlignment< Property::VECTOR2 >::VALUE;
109       break;
110     }
111     case Property::VECTOR3:
112     {
113       alignment = PropertyImplementationTypeAlignment< Property::VECTOR3 >::VALUE;
114       break;
115     }
116     case Property::VECTOR4:
117     {
118       alignment = PropertyImplementationTypeAlignment< Property::VECTOR4 >::VALUE;
119       break;
120     }
121     case Property::MATRIX3:
122     {
123       alignment = PropertyImplementationTypeAlignment< Property::MATRIX3 >::VALUE;
124       break;
125     }
126     case Property::MATRIX:
127     {
128       alignment = PropertyImplementationTypeAlignment< Property::MATRIX >::VALUE;
129       break;
130     }
131     case Property::RECTANGLE:
132     {
133       alignment = PropertyImplementationTypeAlignment< Property::RECTANGLE >::VALUE;
134       break;
135     }
136     case Property::ROTATION:
137     {
138       alignment = PropertyImplementationTypeAlignment< Property::ROTATION >::VALUE;
139       break;
140     }
141   }
142
143   return alignment;
144 }
145
146 } // unnamed namespace
147
148 PropertyBufferPtr PropertyBuffer::New()
149 {
150   PropertyBufferPtr propertyBuffer( new PropertyBuffer() );
151   propertyBuffer->Initialize();
152
153   return propertyBuffer;
154 }
155
156 void PropertyBuffer::SetSize( std::size_t size )
157 {
158   mSize = size;
159
160   SizeChanged();
161
162   SceneGraph::SetSizeMessage( GetEventThreadServices(),
163                               *mSceneObject,
164                               mSize );
165 }
166
167 std::size_t PropertyBuffer::GetSize() const
168 {
169   return mSize;
170 }
171
172 void PropertyBuffer::SetData( const void* data )
173 {
174   DALI_ASSERT_DEBUG( mFormat.Count() && "Format must be set before setting the data." );
175
176   DALI_ASSERT_ALWAYS( mSize && "Size of the buffer must be set before setting the data." );
177
178   const char* source = static_cast<const char*>( data );
179   std::copy( source, source + mBuffer.Size(), &mBuffer[0] );
180
181   SceneGraph::SetDataMessage( GetEventThreadServices(),
182                               *mSceneObject,
183                               new SceneGraph::PropertyBuffer::BufferType( mBuffer ) );
184 }
185
186 const SceneGraph::PropertyBuffer* PropertyBuffer::GetPropertyBufferSceneObject() const
187 {
188   return mSceneObject;
189 }
190
191 void PropertyBuffer::SetFormat( Dali::Property::Map& format )
192 {
193   DALI_ASSERT_ALWAYS( format.Count() && "Format cannot be empty." );
194
195   DALI_ASSERT_DEBUG( 0 == mFormat.Count() && "Format of property buffer can only be set once." );
196
197   mFormat = format;
198
199   FormatChanged();
200 }
201
202 unsigned int PropertyBuffer::GetDefaultPropertyCount() const
203 {
204   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyCount();
205 }
206
207 void PropertyBuffer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
208 {
209   PROPERTY_BUFFER_IMPL.GetDefaultPropertyIndices( indices );
210 }
211
212 const char* PropertyBuffer::GetDefaultPropertyName(Property::Index index) const
213 {
214   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyName( index );
215 }
216
217 Property::Index PropertyBuffer::GetDefaultPropertyIndex( const std::string& name ) const
218 {
219   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyIndex( name );
220 }
221
222 bool PropertyBuffer::IsDefaultPropertyWritable( Property::Index index ) const
223 {
224   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyWritable( index );
225 }
226
227 bool PropertyBuffer::IsDefaultPropertyAnimatable( Property::Index index ) const
228 {
229   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyAnimatable( index );
230 }
231
232 bool PropertyBuffer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
233 {
234   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyAConstraintInput( index );
235 }
236
237 Property::Type PropertyBuffer::GetDefaultPropertyType( Property::Index index ) const
238 {
239   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyType( index );
240 }
241
242 void PropertyBuffer::SetDefaultProperty( Property::Index index,
243                                          const Property::Value& propertyValue )
244 {
245   switch( index )
246   {
247     case Dali::PropertyBuffer::Property::SIZE:
248     {
249       SetSize( propertyValue.Get<int>() );
250       break;
251     }
252     case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
253     {
254       DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
255       break;
256     }
257   }
258 }
259
260 void PropertyBuffer::SetSceneGraphProperty( Property::Index index,
261                                             const PropertyMetadata& entry,
262                                             const Property::Value& value )
263 {
264   PROPERTY_BUFFER_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
265 }
266
267 Property::Value PropertyBuffer::GetDefaultProperty( Property::Index index ) const
268 {
269   Property::Value value;
270
271   switch( index )
272   {
273     case Dali::PropertyBuffer::Property::SIZE:
274     {
275       value = static_cast<int>( GetSize() ); // @todo MESH_REWORK Add a size_t type to PropertyValue
276       break;
277     }
278     case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
279     {
280       DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
281       break;
282     }
283   }
284   return value;
285 }
286
287 const SceneGraph::PropertyOwner* PropertyBuffer::GetPropertyOwner() const
288 {
289   return mSceneObject;
290 }
291
292 const SceneGraph::PropertyOwner* PropertyBuffer::GetSceneObject() const
293 {
294   return mSceneObject;
295 }
296
297 const SceneGraph::PropertyBase* PropertyBuffer::GetSceneObjectAnimatableProperty( Property::Index index ) const
298 {
299   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
300   const SceneGraph::PropertyBase* property = NULL;
301
302   if( OnStage() )
303   {
304     property = PROPERTY_BUFFER_IMPL.GetRegisteredSceneGraphProperty(
305       this,
306       &PropertyBuffer::FindAnimatableProperty,
307       &PropertyBuffer::FindCustomProperty,
308       index );
309
310     if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
311     {
312       DALI_ASSERT_ALWAYS( 0 && "Property is not animatable" );
313     }
314   }
315
316   return property;
317 }
318
319 const PropertyInputImpl* PropertyBuffer::GetSceneObjectInputProperty( Property::Index index ) const
320 {
321   const PropertyInputImpl* property = NULL;
322
323   if( OnStage() )
324   {
325     const SceneGraph::PropertyBase* baseProperty =
326       PROPERTY_BUFFER_IMPL.GetRegisteredSceneGraphProperty( this,
327                                                             &PropertyBuffer::FindAnimatableProperty,
328                                                             &PropertyBuffer::FindCustomProperty,
329                                                             index );
330     property = static_cast<const PropertyInputImpl*>( baseProperty );
331
332     if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
333     {
334       if( index == Dali::PropertyBuffer::Property::SIZE )
335       {
336         // @todo MESH_REWORK
337         DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
338       }
339     }
340   }
341
342   return property;
343 }
344
345 int PropertyBuffer::GetPropertyComponentIndex( Property::Index index ) const
346 {
347   return Property::INVALID_COMPONENT_INDEX;
348 }
349
350 bool PropertyBuffer::OnStage() const
351 {
352   return mOnStage;
353 }
354
355 void PropertyBuffer::Connect()
356 {
357   mOnStage = true;
358 }
359
360 void PropertyBuffer::Disconnect()
361 {
362   mOnStage = false;
363 }
364
365 PropertyBuffer::~PropertyBuffer()
366 {
367 }
368
369 PropertyBuffer::PropertyBuffer()
370 : mSceneObject( NULL ),
371   mBufferFormat( NULL ),
372   mSize( 0 ),
373   mOnStage( false )
374 {
375 }
376
377 void PropertyBuffer::Initialize()
378 {
379   EventThreadServices& eventThreadServices = GetEventThreadServices();
380   SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
381
382   DALI_ASSERT_ALWAYS( EventThreadServices::IsCoreRunning() && "Core is not running" );
383
384   mSceneObject = new SceneGraph::PropertyBuffer();
385   AddMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
386 }
387
388 void PropertyBuffer::FormatChanged()
389 {
390   size_t numComponents = mFormat.Count();
391
392   // Create the format
393   DALI_ASSERT_DEBUG( mBufferFormat == NULL && "PropertyFormat should not be set yet" );
394   Format* bufferFormat = new Format();
395   bufferFormat->components.resize( numComponents );
396
397   unsigned int currentAlignment = 0u;
398   unsigned int maxAlignmentRequired = 0u;
399
400   for( size_t i = 0u; i < numComponents; ++i )
401   {
402     StringValuePair component = mFormat.GetPair( i );
403
404     // Get the name
405     bufferFormat->components[i].name = component.first;
406
407     // enums are stored in the map as int
408     Property::Type type = Property::Type( component.second.Get<int>() );
409
410     // Get the size and alignment
411     unsigned int elementSize = GetPropertyImplementationSize( type );
412     unsigned int elementAlignment = GetPropertyImplementationAlignment( type );
413
414     // check if current alignment is compatible with new member
415     if( unsigned int offset = currentAlignment % elementAlignment )
416     {
417       // Not compatible, realign
418       currentAlignment = currentAlignment + elementSize - offset;
419     }
420
421     // write to the format
422     bufferFormat->components[i].size = elementSize;
423     bufferFormat->components[i].offset = currentAlignment;
424     bufferFormat->components[i].type = type;
425
426     // update offset
427     currentAlignment += elementSize;
428
429     // update max alignment requirement
430     if( elementAlignment > maxAlignmentRequired )
431     {
432       maxAlignmentRequired = elementAlignment;
433     }
434
435   }
436
437   // Check the alignment for the maxAlignment required to calculate the size of the format
438   if( unsigned int offset = currentAlignment % maxAlignmentRequired )
439   {
440     // Not compatible, realign
441     currentAlignment = currentAlignment + maxAlignmentRequired - offset;
442   }
443
444   // Set the format size
445   bufferFormat->size = currentAlignment;
446
447   mBufferFormat = bufferFormat;
448
449   SceneGraph::SetFormatMessage( GetEventThreadServices(),
450                                 *mSceneObject,
451                                 bufferFormat );
452
453   if( mSize )
454   {
455     SizeChanged();
456   }
457 }
458
459 void PropertyBuffer::SizeChanged()
460 {
461   // Check if format and size have been set yet
462   if( mBufferFormat != NULL )
463   {
464     unsigned int bufferSize = mBufferFormat->size * mSize;
465     mBuffer.Resize( bufferSize );
466   }
467 }
468
469 unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
470 {
471   unsigned int size = 0u;
472
473   switch( propertyType )
474   {
475     case Property::NONE:
476     case Property::TYPE_COUNT:
477     case Property::STRING:
478     case Property::ARRAY:
479     case Property::MAP:
480     {
481       DALI_ASSERT_ALWAYS( "No size for properties with no type, or dynamic sizes" );
482       break;
483     }
484     case Property::BOOLEAN:
485     {
486       size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
487       break;
488     }
489     case Property::INTEGER:
490     {
491       size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
492       break;
493     }
494     case Property::UNSIGNED_INTEGER:
495     {
496       size = sizeof( PropertyImplementationType< Property::UNSIGNED_INTEGER >::Type );
497       break;
498     }
499     case Property::FLOAT:
500     {
501       size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
502       break;
503     }
504     case Property::VECTOR2:
505     {
506       size = sizeof( PropertyImplementationType< Property::VECTOR2 >::Type );
507       break;
508     }
509     case Property::VECTOR3:
510     {
511       size = sizeof( PropertyImplementationType< Property::VECTOR3 >::Type );
512       break;
513     }
514     case Property::VECTOR4:
515     {
516       size = sizeof( PropertyImplementationType< Property::VECTOR4 >::Type );
517       break;
518     }
519     case Property::MATRIX3:
520     {
521       size = sizeof( PropertyImplementationType< Property::MATRIX3 >::Type );
522       break;
523     }
524     case Property::MATRIX:
525     {
526       size = sizeof( PropertyImplementationType< Property::MATRIX >::Type );
527       break;
528     }
529     case Property::RECTANGLE:
530     {
531       size = sizeof( PropertyImplementationType< Property::RECTANGLE >::Type );
532       break;
533     }
534     case Property::ROTATION:
535     {
536       size = sizeof( PropertyImplementationType< Property::ROTATION >::Type );
537       break;
538     }
539   }
540
541   return size;
542 }
543
544
545 } // namespace Internal
546 } // namespace Dali