Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-core.git] / dali / internal / event / common / object-impl.cpp
1 /*
2  * Copyright (c) 2020 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/object-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/integration-api/debug.h>
26 #include <dali/devel-api/object/handle-devel.h>
27 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
28 #include <dali/internal/update/common/animatable-property.h>
29 #include <dali/internal/update/common/property-owner.h>
30 #include <dali/internal/update/common/property-owner-messages.h>
31 #include <dali/internal/update/common/uniform-map.h>
32 #include <dali/internal/event/animation/constraint-impl.h>
33 #include <dali/internal/event/common/property-helper.h>
34 #include <dali/internal/event/common/property-notification-impl.h>
35 #include <dali/internal/event/common/stage-impl.h>
36 #include <dali/internal/event/common/type-registry-impl.h>
37
38 using Dali::Internal::SceneGraph::AnimatableProperty;
39 using Dali::Internal::SceneGraph::PropertyBase;
40
41 namespace Dali
42 {
43
44 namespace Internal
45 {
46
47 namespace // unnamed namespace
48 {
49 const int32_t SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES;  // Object provides this capability
50
51 #if defined(DEBUG_ENABLED)
52 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" );
53 #endif
54
55 constexpr Property::Index MAX_PER_CLASS_PROPERTY_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX;
56
57 } // unnamed namespace
58
59 IntrusivePtr<Object> Object::New()
60 {
61   return new Object( nullptr ); // no scene object by default
62 }
63
64 void Object::AddObserver(Observer& observer)
65 {
66   // make sure an observer doesn't observe the same object twice
67   // otherwise it will get multiple calls to OnSceneObjectAdd(), OnSceneObjectRemove() and ObjectDestroyed()
68   DALI_ASSERT_DEBUG( mObservers.End() == std::find( mObservers.Begin(), mObservers.End(), &observer));
69
70   mObservers.PushBack( &observer );
71 }
72
73 void Object::RemoveObserver(Observer& observer)
74 {
75   // Find the observer...
76   const auto endIter =  mObservers.End();
77   for( auto iter = mObservers.Begin(); iter != endIter; ++iter)
78   {
79     if( (*iter) == &observer)
80     {
81       mObservers.Erase( iter );
82       break;
83     }
84   }
85   DALI_ASSERT_DEBUG(endIter != mObservers.End());
86 }
87
88 bool Object::Supports( Capability capability ) const
89 {
90   return (capability & SUPPORTED_CAPABILITIES);
91 }
92
93 uint32_t Object::GetPropertyCount() const
94 {
95   uint32_t count = 0u;
96   const TypeInfo* typeInfo( GetTypeInfo() );
97   if ( typeInfo )
98   {
99     count = typeInfo->GetPropertyCount();
100
101     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Registered Properties:  %d\n", count );
102   }
103
104   uint32_t custom = static_cast<uint32_t>( mCustomProperties.Count() );
105   count += custom;
106   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties:  %d\n", custom );
107
108   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties:   %d\n", count );
109
110   return count;
111 }
112
113 std::string Object::GetPropertyName( Property::Index index ) const
114 {
115   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
116
117   // is this a per class or per instance property
118   if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
119   {
120     const TypeInfo* typeInfo( GetTypeInfo() );
121     if ( typeInfo )
122     {
123       return typeInfo->GetPropertyName( index );
124     }
125   }
126   else // child property or custom property
127   {
128     CustomPropertyMetadata* custom = FindCustomProperty( index );
129     if( custom )
130     {
131       return custom->name;
132     }
133   }
134
135   DALI_LOG_ERROR( "Property index %d not found\n", index );
136   return std::string();
137 }
138
139 Property::Index Object::GetPropertyIndex( Property::Key key ) const
140 {
141   Property::Index index = Property::INVALID_INDEX;
142
143   if( key.type == Property::Key::STRING )
144   {
145     const TypeInfo* typeInfo( GetTypeInfo() );
146     if ( typeInfo )
147     {
148       index = typeInfo->GetPropertyIndex( key.stringKey );
149     }
150   }
151
152   if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) )
153   {
154     Property::Index count = PROPERTY_CUSTOM_START_INDEX;
155     const auto end = mCustomProperties.End();
156     for( auto iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
157     {
158       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
159
160       if( ( key.type == Property::Key::STRING && custom->name == key.stringKey) ||
161           ( key.type == Property::Key::INDEX && custom->key == key.indexKey ) )
162       {
163         if ( custom->childPropertyIndex != Property::INVALID_INDEX )
164         {
165           // If it is a child property, return the child property index
166           index = custom->childPropertyIndex;
167         }
168         else
169         {
170           index = count;
171         }
172         break;
173       }
174     }
175   }
176
177   return index;
178 }
179
180 bool Object::IsPropertyWritable( Property::Index index ) const
181 {
182   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
183
184   bool writable = false;
185
186   // is this a per class or per instance property
187   if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
188   {
189     const TypeInfo* typeInfo( GetTypeInfo() );
190     if ( typeInfo )
191     {
192       writable = typeInfo->IsPropertyWritable( index );
193     }
194   }
195   else
196   {
197     CustomPropertyMetadata* custom = FindCustomProperty( index );
198     if( custom )
199     {
200       writable = custom->IsWritable();
201     }
202   }
203
204   return writable;
205 }
206
207 bool Object::IsPropertyAnimatable( Property::Index index ) const
208 {
209   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
210
211   bool animatable = false;
212
213   // is this a per class or per instance property
214   if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
215   {
216     const TypeInfo* typeInfo( GetTypeInfo() );
217     if ( typeInfo )
218     {
219       animatable = typeInfo->IsPropertyAnimatable( index );
220     }
221   }
222   else
223   {
224     CustomPropertyMetadata* custom = FindCustomProperty( index );
225     if( custom )
226     {
227       animatable = custom->IsAnimatable();
228     }
229   }
230
231   return animatable;
232 }
233
234 bool Object::IsPropertyAConstraintInput( Property::Index index ) const
235 {
236   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
237
238   bool isConstraintInput = false;
239
240   // is this a per class or per instance property
241   if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
242   {
243     const TypeInfo* typeInfo( GetTypeInfo() );
244     if ( typeInfo )
245     {
246       isConstraintInput = typeInfo->IsPropertyAConstraintInput( index );
247     }
248   }
249   else
250   {
251     CustomPropertyMetadata* custom = FindCustomProperty( index );
252     if( custom )
253     {
254       // ... custom properties can be used as input to a constraint.
255       isConstraintInput = true;
256     }
257   }
258
259   return isConstraintInput;
260 }
261
262 Property::Type Object::GetPropertyType( Property::Index index ) const
263 {
264   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
265
266   // is this a per class or per instance property
267   if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
268   {
269     const TypeInfo* typeInfo( GetTypeInfo() );
270     if ( typeInfo )
271     {
272       return typeInfo->GetPropertyType( index );
273     }
274   }
275
276   CustomPropertyMetadata* custom = FindCustomProperty( index );
277   if( custom )
278   {
279     return custom->GetType();
280   }
281
282   return Property::NONE;
283 }
284
285 void Object::SetProperty( Property::Index index, const Property::Value& propertyValue )
286 {
287   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
288
289   bool propertySet( true );
290
291   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
292   {
293     SetDefaultProperty( index, propertyValue );
294   }
295   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
296   {
297     const TypeInfo* typeInfo( GetTypeInfo() );
298     if ( typeInfo )
299     {
300       typeInfo->SetProperty( this, index, propertyValue );
301     }
302     else
303     {
304       // cannot register this property as there is no setter for it.
305       // event side properties must have a setter for now so need to be registered
306       DALI_LOG_ERROR( "Property index %d not found\n", index );
307       propertySet = false;
308     }
309   }
310   else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
311   {
312     // check whether the animatable property is registered already, if not then register one.
313     AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, &propertyValue );
314     if( !animatableProperty )
315     {
316       DALI_LOG_ERROR( "Property index %d not found\n", index );
317       propertySet = false;
318     }
319     else
320     {
321       // update the cached property value
322       animatableProperty->SetPropertyValue( propertyValue );
323
324       // set the scene graph property value
325       SetSceneGraphProperty( index, *animatableProperty, propertyValue );
326     }
327   }
328   else
329   {
330     CustomPropertyMetadata* custom = FindCustomProperty( index );
331
332     if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
333     {
334       if( !custom )
335       {
336         // If the child property is not registered yet, register it.
337         custom = new CustomPropertyMetadata( "", propertyValue, Property::READ_WRITE );
338         mCustomProperties.PushBack( custom );
339       }
340
341       custom->childPropertyIndex = index;
342
343       // Resolve name for the child property
344       Object* parent = GetParentObject();
345       if( parent )
346       {
347         const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
348         if( parentTypeInfo )
349         {
350           custom->name = parentTypeInfo->GetChildPropertyName( index );
351         }
352       }
353     }
354
355     if( custom )
356     {
357       if( custom->IsAnimatable() )
358       {
359         // update the cached property value
360         custom->SetPropertyValue( propertyValue );
361
362         // set the scene graph property value
363         SetSceneGraphProperty( index, *custom, propertyValue );
364       }
365       else if( custom->IsWritable() )
366       {
367         // update the cached property value
368         custom->SetPropertyValue( propertyValue );
369       }
370       else
371       {
372         // trying to set value on read only property is no-op
373         propertySet = false;
374       }
375     }
376     else
377     {
378       DALI_LOG_ERROR( "Property index %d not found\n", index );
379       propertySet = false;
380     }
381   }
382
383   // Let derived classes know that a property has been set
384   // TODO: We should not call this for read-only properties, SetDefaultProperty() && TypeInfo::SetProperty() should return a bool, which would be true if the property is set
385   if ( propertySet )
386   {
387     OnPropertySet( index, propertyValue );
388     Dali::Handle handle( this );
389     mPropertySetSignal.Emit( handle, index, propertyValue );
390   }
391 }
392
393 Property::Value Object::GetProperty( Property::Index index ) const
394 {
395   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
396
397   Property::Value value;
398
399   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
400   {
401     value = GetDefaultProperty( index );
402   }
403   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
404   {
405     const TypeInfo* typeInfo( GetTypeInfo() );
406     if ( typeInfo )
407     {
408       value = typeInfo->GetProperty( this, index );
409     }
410     else
411     {
412       DALI_LOG_ERROR( "Property index %d not found\n", index );
413     }
414   }
415   else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
416   {
417     // check whether the animatable property is registered already, if not then register one.
418     // this is needed because property value may have been set as full property and get as a property component
419     AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, nullptr );
420     if( animatableProperty )
421     {
422       // get the cached animatable property value
423       value = animatableProperty->GetPropertyValue();
424     }
425     else
426     {
427       DALI_LOG_ERROR( "Property index %d not found\n", index );
428     }
429   }
430   else if(mCustomProperties.Count() > 0)
431   {
432     CustomPropertyMetadata* custom = FindCustomProperty( index );
433     if(custom)
434     {
435       // get the cached custom property value
436       value = custom->GetPropertyValue();
437     }
438     else
439     {
440       DALI_LOG_ERROR( "Property index %d not found\n", index );
441     }
442   } // if custom
443
444   return value;
445 }
446
447 Property::Value Object::GetCurrentProperty( Property::Index index ) const
448 {
449   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
450
451   Property::Value value;
452
453   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
454   {
455     value = GetDefaultPropertyCurrentValue( index );
456   }
457   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
458   {
459     const TypeInfo* typeInfo( GetTypeInfo() );
460     if ( typeInfo )
461     {
462       value = typeInfo->GetProperty( this, index );
463     }
464     else
465     {
466       DALI_LOG_ERROR( "Property index %d not found\n", index );
467     }
468   }
469   else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
470   {
471     // check whether the animatable property is registered already, if not then register one.
472     // this is needed because property value may have been set as full property and get as a property component
473     AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, nullptr );
474     if( animatableProperty )
475     {
476       // get the animatable property value
477       value = GetCurrentPropertyValue( *animatableProperty );
478     }
479     else
480     {
481       DALI_LOG_ERROR( "Property index %d not found\n", index );
482     }
483   }
484   else if(mCustomProperties.Count() > 0)
485   {
486     CustomPropertyMetadata* custom = FindCustomProperty( index );
487     if(custom)
488     {
489       // get the custom property value
490       value = GetCurrentPropertyValue( *custom );
491     }
492     else
493     {
494       DALI_LOG_ERROR( "Property index %d not found\n", index );
495     }
496   } // if custom
497
498   return value;
499 }
500
501 void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
502 {
503   indices.Clear();
504
505   // Manual Properties
506   const TypeInfo* typeInfo( GetTypeInfo() );
507   if ( typeInfo )
508   {
509     typeInfo->GetPropertyIndices( indices );
510   }
511
512   // Custom Properties
513   if ( mCustomProperties.Count() > 0 )
514   {
515     indices.Reserve( indices.Size() + mCustomProperties.Count() );
516
517     auto iter = mCustomProperties.Begin();
518     const auto endIter = mCustomProperties.End();
519     int32_t i = 0;
520     for ( ; iter != endIter; ++iter, ++i )
521     {
522       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( *iter );
523       if ( custom->childPropertyIndex != Property::INVALID_INDEX )
524       {
525         // If it is a child property, add the child property index
526         indices.PushBack( custom->childPropertyIndex );
527       }
528       else
529       {
530         indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i );
531       }
532     }
533   }
534 }
535
536 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
537 {
538   return RegisterProperty( name, Property::INVALID_KEY, propertyValue, Property::ANIMATABLE );
539 }
540
541 Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue )
542 {
543   return RegisterProperty( name, key, propertyValue, Property::ANIMATABLE );
544 }
545
546 void Object::SetProperties( const Property::Map& properties )
547 {
548   const auto count = properties.Count();
549   for( auto position = 0u; position < count; ++position )
550   {
551     // GetKeyAt and GetValue both return references which means no potential copying of maps/arrays.
552     // Iterating twice to get the value we want should still be fairly quick in a Property::Map.
553
554     const auto& key = properties.GetKeyAt( position );
555     const auto propertyIndex = ( key.type == Property::Key::INDEX ) ? key.indexKey : GetPropertyIndex( key );
556
557     if( propertyIndex != Property::INVALID_INDEX )
558     {
559       const auto& value = properties.GetValue( position );
560       SetProperty( propertyIndex, value );
561     }
562   }
563 }
564
565 void Object::GetProperties( Property::Map& properties )
566 {
567   properties.Clear();
568
569   Property::IndexContainer indexContainer;
570   GetPropertyIndices( indexContainer );
571
572   for( auto index : indexContainer )
573   {
574     properties[ index ] = GetProperty( index );
575   }
576 }
577
578 Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
579 {
580   return RegisterProperty( name, Property::INVALID_KEY, propertyValue, accessMode );
581 }
582
583 Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue, Property::AccessMode accessMode )
584 {
585   // If property with the required key already exists, then just set it.
586   Property::Index index = Property::INVALID_INDEX;
587   if( key != Property::INVALID_KEY ) // Try integer key first if it's valid
588   {
589     index = GetPropertyIndex( key );
590   }
591   if( index == Property::INVALID_INDEX ) // If it wasn't valid, or doesn't exist, try name
592   {
593     index = GetPropertyIndex( name );
594   }
595
596   if( index != Property::INVALID_INDEX ) // If there was a valid index found by either key, set it.
597   {
598     SetProperty( index, propertyValue );
599   }
600   else
601   {
602     // Otherwise register the property
603     if( Property::ANIMATABLE == accessMode )
604     {
605       index = RegisterSceneGraphProperty( name, key, PROPERTY_CUSTOM_START_INDEX + static_cast<Property::Index>( mCustomProperties.Count() ), propertyValue );
606       AddUniformMapping( index, name );
607     }
608     else
609     {
610       // Add entry to the property lookup
611       index = PROPERTY_CUSTOM_START_INDEX + static_cast<Property::Index>( mCustomProperties.Count() );
612
613       CustomPropertyMetadata* customProperty = new CustomPropertyMetadata( name, propertyValue, accessMode );
614
615       // Resolve index for the child property
616       Object* parent = GetParentObject();
617       if( parent )
618       {
619         const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
620         if( parentTypeInfo )
621         {
622           Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( name );
623           if( childPropertyIndex != Property::INVALID_INDEX )
624           {
625             customProperty->childPropertyIndex = childPropertyIndex;
626             index = childPropertyIndex;
627           }
628         }
629       }
630
631       mCustomProperties.PushBack( customProperty );
632     }
633   }
634
635   return index;
636 }
637
638 bool Object::DoesCustomPropertyExist( Property::Index index )
639 {
640   auto metadata = FindCustomProperty( index );
641   return metadata != nullptr;
642 }
643
644 Dali::PropertyNotification Object::AddPropertyNotification( Property::Index index,
645                                                             int32_t componentIndex,
646                                                             const Dali::PropertyCondition& condition)
647 {
648   if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
649   {
650     if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
651     {
652       DALI_ABORT( "Property notification added to event side only property." );
653     }
654     else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
655     {
656       // check whether the animatable property is registered already, if not then register one.
657       AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty( index, nullptr );
658       DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
659     }
660     else if ( mCustomProperties.Count() > 0 )
661     {
662       CustomPropertyMetadata* custom = FindCustomProperty( index );
663       DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
664       DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
665     }
666   }
667
668   Dali::Handle self(this);
669   Property target( self, index );
670
671   PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
672   Dali::PropertyNotification propertyNotification(internal.Get());
673
674   if( !mPropertyNotifications )
675   {
676     mPropertyNotifications = new PropertyNotificationContainer;
677   }
678   mPropertyNotifications->push_back(propertyNotification);
679
680   return propertyNotification;
681 }
682
683 void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
684 {
685   if( mPropertyNotifications )
686   {
687     auto iter = mPropertyNotifications->begin();
688     while(iter != mPropertyNotifications->end() )
689     {
690       if(*iter == propertyNotification)
691       {
692         mPropertyNotifications->erase(iter);
693         // As we can't ensure all references are removed, we can just disable
694         // the notification.
695         GetImplementation(propertyNotification).Disable();
696         return;
697       }
698       ++iter;
699     }
700   }
701 }
702
703 void Object::RemovePropertyNotifications()
704 {
705   if( mPropertyNotifications )
706   {
707     auto iter = mPropertyNotifications->begin();
708     while(iter != mPropertyNotifications->end() )
709     {
710       // As we can't ensure all references are removed, we can just disable
711       // the notification.
712       GetImplementation(*iter).Disable();
713       ++iter;
714     }
715
716     mPropertyNotifications->clear();
717   }
718 }
719
720 void Object::NotifyPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
721 {
722   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
723   {
724     OnNotifyDefaultPropertyAnimation( animation, index, value, animationType );
725   }
726   else
727   {
728     PropertyMetadata* propertyMetadata = nullptr;
729     if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
730     {
731       propertyMetadata = FindAnimatableProperty( index );
732     }
733     else
734     {
735       CustomPropertyMetadata* custom = FindCustomProperty( index );
736       if( custom && custom->IsAnimatable() )
737       {
738         propertyMetadata = custom;
739       }
740     }
741
742     if( propertyMetadata )
743     {
744       switch( animationType )
745       {
746         case Animation::TO:
747         case Animation::BETWEEN:
748         {
749           // Update the cached property value
750           propertyMetadata->SetPropertyValue( value );
751           break;
752         }
753         case Animation::BY:
754         {
755           // Adjust the cached property value
756           propertyMetadata->AdjustPropertyValueBy( value );
757           break;
758         }
759       }
760     }
761   }
762 }
763
764 void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName ) const
765 {
766   // Get the address of the property if it's a scene property
767   const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
768
769   // Check instead for newly registered properties
770   if( propertyPtr == nullptr )
771   {
772     PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
773     if( animatable )
774     {
775       propertyPtr = animatable->GetSceneGraphProperty();
776     }
777   }
778
779   if( propertyPtr == nullptr )
780   {
781     PropertyMetadata* custom = FindCustomProperty( propertyIndex );
782     if( custom )
783     {
784       propertyPtr = custom->GetSceneGraphProperty();
785     }
786   }
787
788   if( propertyPtr )
789   {
790     const SceneGraph::PropertyOwner& sceneObject = GetSceneObject();
791
792     OwnerPointer< SceneGraph::UniformPropertyMapping > map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
793     // Message takes ownership of Uniform map (and will delete it after copy)
794     AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, map );
795   }
796 }
797
798 void Object::RemoveUniformMapping( const std::string& uniformName ) const
799 {
800   const SceneGraph::PropertyOwner& sceneObject = GetSceneObject();
801   RemoveUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, uniformName);
802 }
803
804 void Object::ApplyConstraint( ConstraintBase& constraint )
805 {
806   if( !mConstraints )
807   {
808     mConstraints = new ConstraintContainer;
809   }
810   mConstraints->push_back( Dali::Constraint( &constraint ) );
811 }
812
813 void Object::RemoveConstraint( ConstraintBase& constraint )
814 {
815   // nullptr if the Constraint sources are destroyed before Constraint::Apply()
816   if( mConstraints )
817   {
818     ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
819     if( it != mConstraints->end() )
820     {
821       mConstraints->erase( it );
822     }
823   }
824 }
825
826 void Object::RemoveConstraints()
827 {
828   // guard against constraint sending messages during core destruction
829   if( mConstraints && Stage::IsInstalled() )
830   {
831     for ( auto&& item : *mConstraints )
832     {
833       GetImplementation( item ).RemoveInternal();
834     }
835
836     delete mConstraints;
837     mConstraints = nullptr;
838   }
839 }
840
841 void Object::RemoveConstraints( uint32_t tag )
842 {
843   // guard against constraint sending messages during core destruction
844   if( mConstraints && Stage::IsInstalled() )
845   {
846     auto iter( mConstraints->begin() );
847     while(iter != mConstraints->end() )
848     {
849       ConstraintBase& constraint = GetImplementation( *iter );
850       if( constraint.GetTag() == tag )
851       {
852         GetImplementation( *iter ).RemoveInternal();
853         iter = mConstraints->erase( iter );
854       }
855       else
856       {
857         ++iter;
858       }
859     }
860
861     if ( mConstraints->empty() )
862     {
863       delete mConstraints;
864       mConstraints = nullptr;
865     }
866   }
867 }
868
869 void Object::SetTypeInfo( const TypeInfo* typeInfo )
870 {
871   mTypeInfo = typeInfo;
872 }
873
874 const SceneGraph::PropertyOwner& Object::GetSceneObject() const
875 {
876   if( !mUpdateObject )
877   {
878     auto sceneObject = SceneGraph::PropertyOwner::New();
879     OwnerPointer< SceneGraph::PropertyOwner > transferOwnership( sceneObject );
880     mUpdateObject = sceneObject;
881     AddObjectMessage( const_cast<EventThreadServices&>( GetEventThreadServices() ).GetUpdateManager(), transferOwnership );
882   }
883   DALI_ASSERT_DEBUG( mUpdateObject && "there must always be a scene object" );
884   return *mUpdateObject;
885 }
886
887 const PropertyBase* Object::GetSceneObjectAnimatableProperty( Property::Index index ) const
888 {
889   const SceneGraph::PropertyBase* property = nullptr;
890   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
891   {
892     AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty( index, nullptr );
893     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
894
895     property = animatable->GetSceneGraphProperty();
896   }
897   else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
898             ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
899   {
900     CustomPropertyMetadata* custom = FindCustomProperty( index );
901     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
902
903     property = custom->GetSceneGraphProperty();
904   }
905   return property;
906 }
907
908 const PropertyInputImpl* Object::GetSceneObjectInputProperty( Property::Index index ) const
909 {
910   // reuse animatable version as they are inputs as well
911   return GetSceneObjectAnimatableProperty( index );
912 }
913
914 int32_t Object::GetPropertyComponentIndex( Property::Index index ) const
915 {
916   int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
917
918   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
919   {
920     // check whether the animatable property is registered already, if not then register one.
921     AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, nullptr );
922     if( animatableProperty )
923     {
924       componentIndex = animatableProperty->componentIndex;
925     }
926   }
927   if( Property::INVALID_COMPONENT_INDEX == componentIndex )
928   {
929     const TypeInfo* typeInfo( GetTypeInfo() );
930     if ( typeInfo )
931     {
932       componentIndex = typeInfo->GetComponentIndex(index);
933     }
934   }
935
936   return componentIndex;
937 }
938
939 Handle::PropertySetSignalType& Object::PropertySetSignal()
940 {
941   return mPropertySetSignal;
942 }
943
944 Object::Object( const SceneGraph::PropertyOwner* sceneObject )
945 : mEventThreadServices( EventThreadServices::Get() ),
946   mUpdateObject( sceneObject ),
947   mTypeInfo( nullptr ),
948   mConstraints( nullptr ),
949   mPropertyNotifications( nullptr )
950 {
951 }
952
953 Object::~Object()
954 {
955   // Notification for observers
956   for( auto&& item : mObservers )
957   {
958     item->ObjectDestroyed( *this );
959   }
960   delete mConstraints;
961   delete mPropertyNotifications;
962
963   // Guard to allow handle destruction after Core has been destroyed
964   if( Stage::IsInstalled() )
965   {
966     if( nullptr != mUpdateObject )
967     {
968       RemoveObjectMessage( GetEventThreadServices().GetUpdateManager(), mUpdateObject );
969     }
970   }
971 }
972
973 void Object::OnSceneObjectAdd()
974 {
975   // Notification for observers
976   for( auto&& item : mObservers )
977   {
978     item->SceneObjectAdded(*this);
979   }
980
981   // enable property notifications in scene graph
982   EnablePropertyNotifications();
983 }
984
985 void Object::OnSceneObjectRemove()
986 {
987   // Notification for observers
988   for( auto&& item : mObservers )
989   {
990     item->SceneObjectRemoved(*this);
991   }
992
993   // disable property notifications in scene graph
994   DisablePropertyNotifications();
995 }
996
997 const TypeInfo* Object::GetTypeInfo() const
998 {
999   if ( !mTypeInfo )
1000   {
1001     // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
1002     // especially as the type-info does not change during the life-time of an application
1003
1004     TypeRegistry::TypeInfoPointer typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
1005     if ( typeInfoHandle )
1006     {
1007       mTypeInfo = typeInfoHandle.Get(); // just a raw pointer to use, ownership is kept
1008     }
1009   }
1010
1011   return mTypeInfo;
1012 }
1013
1014 CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
1015 {
1016   CustomPropertyMetadata* property = nullptr;
1017   if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
1018   {
1019     for ( std::size_t arrayIndex = 0; arrayIndex < mCustomProperties.Count(); arrayIndex++ )
1020     {
1021       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( mCustomProperties[ arrayIndex ] );
1022       if( custom->childPropertyIndex == index )
1023       {
1024         property = custom;
1025       }
1026     }
1027   }
1028   else
1029   {
1030     int32_t arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
1031     if( arrayIndex >= 0 )
1032     {
1033       if( arrayIndex < static_cast<int32_t>( mCustomProperties.Count() ) ) // we can only access the first 2 billion custom properties
1034       {
1035         property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
1036       }
1037     }
1038   }
1039   return property;
1040 }
1041
1042 AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
1043 {
1044   for( auto&& entry : mAnimatableProperties )
1045   {
1046     AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( entry );
1047     if( property->index == index )
1048     {
1049       return property;
1050     }
1051   }
1052   return nullptr;
1053 }
1054
1055 Property::Index Object::RegisterSceneGraphProperty( const std::string& name, Property::Index key, Property::Index index, const Property::Value& propertyValue ) const
1056 {
1057   // Create a new property
1058   Dali::Internal::OwnerPointer<PropertyBase> newProperty;
1059
1060   switch ( propertyValue.GetType() )
1061   {
1062     case Property::BOOLEAN:
1063     {
1064       newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
1065       break;
1066     }
1067
1068     case Property::INTEGER:
1069     {
1070       newProperty = new AnimatableProperty<int32_t>( propertyValue.Get<int32_t>() );
1071       break;
1072     }
1073
1074     case Property::FLOAT:
1075     {
1076       newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
1077       break;
1078     }
1079
1080     case Property::VECTOR2:
1081     {
1082       newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
1083       break;
1084     }
1085
1086     case Property::VECTOR3:
1087     {
1088       newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
1089       break;
1090     }
1091
1092     case Property::VECTOR4:
1093     {
1094       newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
1095       break;
1096     }
1097
1098     case Property::MATRIX:
1099     {
1100       newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
1101       break;
1102     }
1103
1104     case Property::MATRIX3:
1105     {
1106       newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
1107       break;
1108     }
1109
1110     case Property::ROTATION:
1111     {
1112       newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
1113       break;
1114     }
1115
1116     case Property::RECTANGLE:
1117     case Property::STRING:
1118     case Property::ARRAY:
1119     case Property::MAP:
1120     case Property::EXTENTS:
1121     case Property::NONE:
1122     {
1123       DALI_ASSERT_ALWAYS( !"Property type is not animatable" );
1124       break;
1125     }
1126   }
1127
1128   // get the scene property owner
1129   const SceneGraph::PropertyOwner& scenePropertyOwner = GetSceneObject();
1130   // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
1131   const PropertyBase* property = newProperty.Get();
1132   if(index >= PROPERTY_CUSTOM_START_INDEX)
1133   {
1134     DALI_ASSERT_ALWAYS( index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered" );
1135
1136     mCustomProperties.PushBack( new CustomPropertyMetadata( name, key, propertyValue, property ) );
1137   }
1138   else
1139   {
1140     mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, propertyValue, property ) );
1141   }
1142
1143   // queue a message to add the property
1144   InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), scenePropertyOwner, newProperty ); // Message takes ownership
1145
1146   return index;
1147 }
1148
1149 void Object::RegisterAnimatableProperty( const TypeInfo& typeInfo,
1150                                           Property::Index index,
1151                                           const Property::Value* value ) const
1152 {
1153   // If the property is not a component of a base property, register the whole property itself.
1154   const std::string& propertyName = typeInfo.GetPropertyName( index );
1155   Property::Value initialValue;
1156   if( value )
1157   {
1158     initialValue = *value;
1159   }
1160   else
1161   {
1162     initialValue = typeInfo.GetPropertyDefaultValue( index ); // recurses type hierarchy
1163     if( Property::NONE == initialValue.GetType() )
1164     {
1165       initialValue = Property::Value( typeInfo.GetPropertyType( index ) ); // recurses type hierarchy
1166     }
1167   }
1168   RegisterSceneGraphProperty( propertyName, Property::INVALID_KEY, index, initialValue );
1169   AddUniformMapping( index, propertyName );
1170 }
1171
1172 AnimatablePropertyMetadata* Object::GetSceneAnimatableProperty( Property::Index index, const Property::Value* value ) const
1173 {
1174   // property range already checked by calling methods
1175   // check whether the animatable property is registered already, if not then register one.
1176   AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
1177   if( !animatableProperty )
1178   {
1179     const TypeInfo* typeInfo( GetTypeInfo() );
1180     if( typeInfo )
1181     {
1182       Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex( index );
1183       if( basePropertyIndex == Property::INVALID_INDEX )
1184       {
1185         // If the property is not a component of a base property, register the whole property itself.
1186         RegisterAnimatableProperty( *typeInfo, index, value );
1187       }
1188       else
1189       {
1190         // Since the property is a component of a base property, check whether the base property is registered.
1191         animatableProperty = FindAnimatableProperty( basePropertyIndex );
1192         if( !animatableProperty )
1193         {
1194           // If the base property is not registered yet, register the base property first.
1195           RegisterAnimatableProperty( *typeInfo, basePropertyIndex, value );
1196           animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1197         }
1198
1199         // Create the metadata for the property component.
1200         mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->value, animatableProperty->GetSceneGraphProperty() ) );
1201       }
1202
1203       // The metadata has just been added and therefore should be in the end of the vector.
1204       animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1205     }
1206   }
1207
1208   return animatableProperty;
1209 }
1210
1211 void Object::ResolveChildProperties()
1212 {
1213   // Resolve index for the child property
1214   Object* parent = GetParentObject();
1215   if( parent )
1216   {
1217     const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
1218     if( parentTypeInfo )
1219     {
1220       // Go through each custom property
1221       for( auto&& entry : mCustomProperties )
1222       {
1223         CustomPropertyMetadata* customProperty = static_cast<CustomPropertyMetadata*>( entry );
1224
1225         if( customProperty->name.empty() )
1226         {
1227           if( customProperty->childPropertyIndex != Property::INVALID_INDEX )
1228           {
1229             // Resolve name for any child property with no name
1230             customProperty->name = parentTypeInfo->GetChildPropertyName( customProperty->childPropertyIndex );
1231           }
1232         }
1233         else
1234         {
1235           Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( customProperty->name );
1236           if( childPropertyIndex != Property::INVALID_INDEX )
1237           {
1238             // Resolve index for any property with a name that matches the parent's child property name
1239             customProperty->childPropertyIndex = childPropertyIndex;
1240           }
1241         }
1242       }
1243     }
1244   }
1245 }
1246
1247 void Object::SetDefaultProperty( Property::Index index, const Property::Value& property )
1248 {
1249   // do nothing
1250 }
1251
1252 Property::Value Object::GetDefaultProperty(Property::Index index) const
1253 {
1254   return Property::Value();
1255 }
1256
1257 Property::Value Object::GetDefaultPropertyCurrentValue( Property::Index index ) const
1258 {
1259   return GetDefaultProperty( index );
1260 }
1261
1262 void Object::EnablePropertyNotifications()
1263 {
1264   if( mPropertyNotifications )
1265   {
1266     for( auto&& element : *mPropertyNotifications )
1267     {
1268       GetImplementation( element ).Enable();
1269     }
1270   }
1271 }
1272
1273 void Object::DisablePropertyNotifications()
1274 {
1275   if( mPropertyNotifications )
1276   {
1277     for( auto&& element : *mPropertyNotifications )
1278     {
1279       GetImplementation( element ).Disable();
1280     }
1281   }
1282 }
1283
1284 Property::Value Object::GetCurrentPropertyValue( const PropertyMetadata& entry ) const
1285 {
1286   Property::Value value;
1287
1288   if( !entry.IsAnimatable() )
1289   {
1290     value = entry.GetPropertyValue();
1291   }
1292   else
1293   {
1294     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1295
1296     switch ( entry.GetType() )
1297     {
1298       case Property::BOOLEAN:
1299       {
1300         const AnimatableProperty<bool>* property = static_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
1301         DALI_ASSERT_DEBUG( property );
1302
1303         value = (*property)[ bufferIndex ];
1304         break;
1305       }
1306
1307       case Property::INTEGER:
1308       {
1309         const AnimatableProperty<int32_t>* property = static_cast< const AnimatableProperty<int32_t>* >( entry.GetSceneGraphProperty() );
1310         DALI_ASSERT_DEBUG( property );
1311
1312         value = (*property)[ bufferIndex ];
1313         break;
1314       }
1315
1316       case Property::FLOAT:
1317       {
1318         const AnimatableProperty<float>* property = static_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
1319         DALI_ASSERT_DEBUG( property );
1320
1321         value = (*property)[ bufferIndex ];
1322         break;
1323       }
1324
1325       case Property::VECTOR2:
1326       {
1327         const AnimatableProperty<Vector2>* property = static_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
1328         DALI_ASSERT_DEBUG( property );
1329
1330         if(entry.componentIndex == 0)
1331         {
1332           value = (*property)[ bufferIndex ].x;
1333         }
1334         else if(entry.componentIndex == 1)
1335         {
1336           value = (*property)[ bufferIndex ].y;
1337         }
1338         else
1339         {
1340           value = (*property)[ bufferIndex ];
1341         }
1342         break;
1343       }
1344
1345       case Property::VECTOR3:
1346       {
1347         const AnimatableProperty<Vector3>* property = static_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
1348         DALI_ASSERT_DEBUG( property );
1349
1350         if(entry.componentIndex == 0)
1351         {
1352           value = (*property)[ bufferIndex ].x;
1353         }
1354         else if(entry.componentIndex == 1)
1355         {
1356           value = (*property)[ bufferIndex ].y;
1357         }
1358         else if(entry.componentIndex == 2)
1359         {
1360           value = (*property)[ bufferIndex ].z;
1361         }
1362         else
1363         {
1364           value = (*property)[ bufferIndex ];
1365         }
1366         break;
1367       }
1368
1369       case Property::VECTOR4:
1370       {
1371         const AnimatableProperty<Vector4>* property = static_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1372         DALI_ASSERT_DEBUG( property );
1373
1374         if(entry.componentIndex == 0)
1375         {
1376           value = (*property)[ bufferIndex ].x;
1377         }
1378         else if(entry.componentIndex == 1)
1379         {
1380           value = (*property)[ bufferIndex ].y;
1381         }
1382         else if(entry.componentIndex == 2)
1383         {
1384           value = (*property)[ bufferIndex ].z;
1385         }
1386         else if(entry.componentIndex == 3)
1387         {
1388           value = (*property)[ bufferIndex ].w;
1389         }
1390         else
1391         {
1392           value = (*property)[ bufferIndex ];
1393         }
1394         break;
1395       }
1396
1397       case Property::MATRIX:
1398       {
1399         const AnimatableProperty<Matrix>* property = static_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1400         DALI_ASSERT_DEBUG( property );
1401
1402         value = (*property)[ bufferIndex ];
1403         break;
1404       }
1405
1406       case Property::MATRIX3:
1407       {
1408         const AnimatableProperty<Matrix3>* property = static_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1409         DALI_ASSERT_DEBUG( property );
1410
1411         value = (*property)[ bufferIndex ];
1412         break;
1413       }
1414
1415       case Property::ROTATION:
1416       {
1417         const AnimatableProperty<Quaternion>* property = static_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1418         DALI_ASSERT_DEBUG( property );
1419
1420         value = (*property)[ bufferIndex ];
1421         break;
1422       }
1423
1424       default:
1425       {
1426         // unreachable code due to higher level logic
1427       }
1428     } // switch(type)
1429   } // if animatable
1430
1431   return value;
1432 }
1433
1434 void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1435 {
1436   switch ( entry.GetType() )
1437   {
1438     case Property::BOOLEAN:
1439     {
1440       const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
1441       DALI_ASSERT_DEBUG( property );
1442
1443       // property is being used in a separate thread; queue a message to set the property
1444       BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
1445       break;
1446     }
1447
1448     case Property::INTEGER:
1449     {
1450       const AnimatableProperty<int32_t>* property = dynamic_cast< const AnimatableProperty<int32_t>* >( entry.GetSceneGraphProperty() );
1451       DALI_ASSERT_DEBUG( property );
1452
1453       // property is being used in a separate thread; queue a message to set the property
1454       BakeMessage<int32_t>( GetEventThreadServices(), *property, value.Get<int32_t>() );
1455       break;
1456     }
1457
1458     case Property::FLOAT:
1459     {
1460       const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
1461       DALI_ASSERT_DEBUG( property );
1462
1463       // property is being used in a separate thread; queue a message to set the property
1464       BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
1465       break;
1466     }
1467
1468     case Property::VECTOR2:
1469     {
1470       const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
1471       DALI_ASSERT_DEBUG( property );
1472
1473       // property is being used in a separate thread; queue a message to set the property
1474       if(entry.componentIndex == 0)
1475       {
1476         SetXComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1477       }
1478       else if(entry.componentIndex == 1)
1479       {
1480         SetYComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1481       }
1482       else
1483       {
1484         BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
1485       }
1486       break;
1487     }
1488
1489     case Property::VECTOR3:
1490     {
1491       const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
1492       DALI_ASSERT_DEBUG( property );
1493
1494       // property is being used in a separate thread; queue a message to set the property
1495       if(entry.componentIndex == 0)
1496       {
1497         SetXComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1498       }
1499       else if(entry.componentIndex == 1)
1500       {
1501         SetYComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1502       }
1503       else if(entry.componentIndex == 2)
1504       {
1505         SetZComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1506       }
1507       else
1508       {
1509         BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
1510       }
1511
1512       break;
1513     }
1514
1515     case Property::VECTOR4:
1516     {
1517       const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1518       DALI_ASSERT_DEBUG( property );
1519
1520       // property is being used in a separate thread; queue a message to set the property
1521       if(entry.componentIndex == 0)
1522       {
1523         SetXComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1524       }
1525       else if(entry.componentIndex == 1)
1526       {
1527         SetYComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1528       }
1529       else if(entry.componentIndex == 2)
1530       {
1531         SetZComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1532       }
1533       else if(entry.componentIndex == 3)
1534       {
1535         SetWComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1536       }
1537       else
1538       {
1539         BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
1540       }
1541       break;
1542     }
1543
1544     case Property::ROTATION:
1545     {
1546       const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1547       DALI_ASSERT_DEBUG( property );
1548
1549       // property is being used in a separate thread; queue a message to set the property
1550       BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
1551       break;
1552     }
1553
1554     case Property::MATRIX:
1555     {
1556       const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1557       DALI_ASSERT_DEBUG( property );
1558
1559       // property is being used in a separate thread; queue a message to set the property
1560       BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
1561       break;
1562     }
1563
1564     case Property::MATRIX3:
1565     {
1566       const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1567       DALI_ASSERT_DEBUG( property );
1568
1569       // property is being used in a separate thread; queue a message to set the property
1570       BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
1571       break;
1572     }
1573
1574     default:
1575     {
1576       // non-animatable scene graph property, do nothing
1577     }
1578   }
1579 }
1580
1581 } // namespace Internal
1582
1583 } // namespace Dali