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