Fix AddUniformMapping() interface to take uniform name by value.
[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, 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 =
793       new SceneGraph::UniformPropertyMapping(std::move(uniformName), propertyPtr);
794     // Message takes ownership of Uniform map (and will delete it after copy)
795     AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, map );
796   }
797 }
798
799 void Object::RemoveUniformMapping( const std::string& uniformName ) const
800 {
801   const SceneGraph::PropertyOwner& sceneObject = GetSceneObject();
802   RemoveUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), sceneObject, uniformName);
803 }
804
805 void Object::ApplyConstraint( ConstraintBase& constraint )
806 {
807   if( !mConstraints )
808   {
809     mConstraints = new ConstraintContainer;
810   }
811   mConstraints->push_back( Dali::Constraint( &constraint ) );
812 }
813
814 void Object::RemoveConstraint( ConstraintBase& constraint )
815 {
816   // nullptr if the Constraint sources are destroyed before Constraint::Apply()
817   if( mConstraints )
818   {
819     ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
820     if( it != mConstraints->end() )
821     {
822       mConstraints->erase( it );
823     }
824   }
825 }
826
827 void Object::RemoveConstraints()
828 {
829   // guard against constraint sending messages during core destruction
830   if( mConstraints && Stage::IsInstalled() )
831   {
832     for ( auto&& item : *mConstraints )
833     {
834       GetImplementation( item ).RemoveInternal();
835     }
836
837     delete mConstraints;
838     mConstraints = nullptr;
839   }
840 }
841
842 void Object::RemoveConstraints( uint32_t tag )
843 {
844   // guard against constraint sending messages during core destruction
845   if( mConstraints && Stage::IsInstalled() )
846   {
847     auto iter( mConstraints->begin() );
848     while(iter != mConstraints->end() )
849     {
850       ConstraintBase& constraint = GetImplementation( *iter );
851       if( constraint.GetTag() == tag )
852       {
853         GetImplementation( *iter ).RemoveInternal();
854         iter = mConstraints->erase( iter );
855       }
856       else
857       {
858         ++iter;
859       }
860     }
861
862     if ( mConstraints->empty() )
863     {
864       delete mConstraints;
865       mConstraints = nullptr;
866     }
867   }
868 }
869
870 void Object::SetTypeInfo( const TypeInfo* typeInfo )
871 {
872   mTypeInfo = typeInfo;
873 }
874
875 const SceneGraph::PropertyOwner& Object::GetSceneObject() const
876 {
877   if( !mUpdateObject )
878   {
879     auto sceneObject = SceneGraph::PropertyOwner::New();
880     OwnerPointer< SceneGraph::PropertyOwner > transferOwnership( sceneObject );
881     mUpdateObject = sceneObject;
882     AddObjectMessage( const_cast<EventThreadServices&>( GetEventThreadServices() ).GetUpdateManager(), transferOwnership );
883   }
884   DALI_ASSERT_DEBUG( mUpdateObject && "there must always be a scene object" );
885   return *mUpdateObject;
886 }
887
888 const PropertyBase* Object::GetSceneObjectAnimatableProperty( Property::Index index ) const
889 {
890   const SceneGraph::PropertyBase* property = nullptr;
891   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
892   {
893     AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty( index, nullptr );
894     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
895
896     property = animatable->GetSceneGraphProperty();
897   }
898   else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
899             ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
900   {
901     CustomPropertyMetadata* custom = FindCustomProperty( index );
902     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
903
904     property = custom->GetSceneGraphProperty();
905   }
906   return property;
907 }
908
909 const PropertyInputImpl* Object::GetSceneObjectInputProperty( Property::Index index ) const
910 {
911   // reuse animatable version as they are inputs as well
912   return GetSceneObjectAnimatableProperty( index );
913 }
914
915 int32_t Object::GetPropertyComponentIndex( Property::Index index ) const
916 {
917   int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
918
919   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
920   {
921     // check whether the animatable property is registered already, if not then register one.
922     AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, nullptr );
923     if( animatableProperty )
924     {
925       componentIndex = animatableProperty->componentIndex;
926     }
927   }
928   if( Property::INVALID_COMPONENT_INDEX == componentIndex )
929   {
930     const TypeInfo* typeInfo( GetTypeInfo() );
931     if ( typeInfo )
932     {
933       componentIndex = typeInfo->GetComponentIndex(index);
934     }
935   }
936
937   return componentIndex;
938 }
939
940 Handle::PropertySetSignalType& Object::PropertySetSignal()
941 {
942   return mPropertySetSignal;
943 }
944
945 Object::Object( const SceneGraph::PropertyOwner* sceneObject )
946 : mEventThreadServices( EventThreadServices::Get() ),
947   mUpdateObject( sceneObject ),
948   mTypeInfo( nullptr ),
949   mConstraints( nullptr ),
950   mPropertyNotifications( nullptr )
951 {
952 }
953
954 Object::~Object()
955 {
956   // Notification for observers
957   for( auto&& item : mObservers )
958   {
959     item->ObjectDestroyed( *this );
960   }
961   delete mConstraints;
962   delete mPropertyNotifications;
963
964   // Guard to allow handle destruction after Core has been destroyed
965   if( Stage::IsInstalled() )
966   {
967     if( nullptr != mUpdateObject )
968     {
969       RemoveObjectMessage( GetEventThreadServices().GetUpdateManager(), mUpdateObject );
970     }
971   }
972 }
973
974 void Object::OnSceneObjectAdd()
975 {
976   // Notification for observers
977   for( auto&& item : mObservers )
978   {
979     item->SceneObjectAdded(*this);
980   }
981
982   // enable property notifications in scene graph
983   EnablePropertyNotifications();
984 }
985
986 void Object::OnSceneObjectRemove()
987 {
988   // Notification for observers
989   for( auto&& item : mObservers )
990   {
991     item->SceneObjectRemoved(*this);
992   }
993
994   // disable property notifications in scene graph
995   DisablePropertyNotifications();
996 }
997
998 const TypeInfo* Object::GetTypeInfo() const
999 {
1000   if ( !mTypeInfo )
1001   {
1002     // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
1003     // especially as the type-info does not change during the life-time of an application
1004
1005     TypeRegistry::TypeInfoPointer typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
1006     if ( typeInfoHandle )
1007     {
1008       mTypeInfo = typeInfoHandle.Get(); // just a raw pointer to use, ownership is kept
1009     }
1010   }
1011
1012   return mTypeInfo;
1013 }
1014
1015 CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
1016 {
1017   CustomPropertyMetadata* property = nullptr;
1018   if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
1019   {
1020     for ( std::size_t arrayIndex = 0; arrayIndex < mCustomProperties.Count(); arrayIndex++ )
1021     {
1022       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( mCustomProperties[ arrayIndex ] );
1023       if( custom->childPropertyIndex == index )
1024       {
1025         property = custom;
1026       }
1027     }
1028   }
1029   else
1030   {
1031     int32_t arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
1032     if( arrayIndex >= 0 )
1033     {
1034       if( arrayIndex < static_cast<int32_t>( mCustomProperties.Count() ) ) // we can only access the first 2 billion custom properties
1035       {
1036         property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
1037       }
1038     }
1039   }
1040   return property;
1041 }
1042
1043 AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
1044 {
1045   for( auto&& entry : mAnimatableProperties )
1046   {
1047     AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( entry );
1048     if( property->index == index )
1049     {
1050       return property;
1051     }
1052   }
1053   return nullptr;
1054 }
1055
1056 Property::Index Object::RegisterSceneGraphProperty( const std::string& name, Property::Index key, Property::Index index, const Property::Value& propertyValue ) const
1057 {
1058   // Create a new property
1059   Dali::Internal::OwnerPointer<PropertyBase> newProperty;
1060
1061   switch ( propertyValue.GetType() )
1062   {
1063     case Property::BOOLEAN:
1064     {
1065       newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
1066       break;
1067     }
1068
1069     case Property::INTEGER:
1070     {
1071       newProperty = new AnimatableProperty<int32_t>( propertyValue.Get<int32_t>() );
1072       break;
1073     }
1074
1075     case Property::FLOAT:
1076     {
1077       newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
1078       break;
1079     }
1080
1081     case Property::VECTOR2:
1082     {
1083       newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
1084       break;
1085     }
1086
1087     case Property::VECTOR3:
1088     {
1089       newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
1090       break;
1091     }
1092
1093     case Property::VECTOR4:
1094     {
1095       newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
1096       break;
1097     }
1098
1099     case Property::MATRIX:
1100     {
1101       newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
1102       break;
1103     }
1104
1105     case Property::MATRIX3:
1106     {
1107       newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
1108       break;
1109     }
1110
1111     case Property::ROTATION:
1112     {
1113       newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
1114       break;
1115     }
1116
1117     case Property::RECTANGLE:
1118     case Property::STRING:
1119     case Property::ARRAY:
1120     case Property::MAP:
1121     case Property::EXTENTS:
1122     case Property::NONE:
1123     {
1124       DALI_ASSERT_ALWAYS( !"Property type is not animatable" );
1125       break;
1126     }
1127   }
1128
1129   // get the scene property owner
1130   const SceneGraph::PropertyOwner& scenePropertyOwner = GetSceneObject();
1131   // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
1132   const PropertyBase* property = newProperty.Get();
1133   if(index >= PROPERTY_CUSTOM_START_INDEX)
1134   {
1135     DALI_ASSERT_ALWAYS( index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered" );
1136
1137     mCustomProperties.PushBack( new CustomPropertyMetadata( name, key, propertyValue, property ) );
1138   }
1139   else
1140   {
1141     mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, propertyValue, property ) );
1142   }
1143
1144   // queue a message to add the property
1145   InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), scenePropertyOwner, newProperty ); // Message takes ownership
1146
1147   return index;
1148 }
1149
1150 void Object::RegisterAnimatableProperty( const TypeInfo& typeInfo,
1151                                           Property::Index index,
1152                                           const Property::Value* value ) const
1153 {
1154   // If the property is not a component of a base property, register the whole property itself.
1155   const std::string& propertyName = typeInfo.GetPropertyName( index );
1156   Property::Value initialValue;
1157   if( value )
1158   {
1159     initialValue = *value;
1160   }
1161   else
1162   {
1163     initialValue = typeInfo.GetPropertyDefaultValue( index ); // recurses type hierarchy
1164     if( Property::NONE == initialValue.GetType() )
1165     {
1166       initialValue = Property::Value( typeInfo.GetPropertyType( index ) ); // recurses type hierarchy
1167     }
1168   }
1169   RegisterSceneGraphProperty( propertyName, Property::INVALID_KEY, index, initialValue );
1170   AddUniformMapping( index, propertyName );
1171 }
1172
1173 AnimatablePropertyMetadata* Object::GetSceneAnimatableProperty( Property::Index index, const Property::Value* value ) const
1174 {
1175   // property range already checked by calling methods
1176   // check whether the animatable property is registered already, if not then register one.
1177   AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
1178   if( !animatableProperty )
1179   {
1180     const TypeInfo* typeInfo( GetTypeInfo() );
1181     if( typeInfo )
1182     {
1183       Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex( index );
1184       if( basePropertyIndex == Property::INVALID_INDEX )
1185       {
1186         // If the property is not a component of a base property, register the whole property itself.
1187         RegisterAnimatableProperty( *typeInfo, index, value );
1188       }
1189       else
1190       {
1191         // Since the property is a component of a base property, check whether the base property is registered.
1192         animatableProperty = FindAnimatableProperty( basePropertyIndex );
1193         if( !animatableProperty )
1194         {
1195           // If the base property is not registered yet, register the base property first.
1196           RegisterAnimatableProperty( *typeInfo, basePropertyIndex, value );
1197           animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1198         }
1199
1200         // Create the metadata for the property component.
1201         mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->value, animatableProperty->GetSceneGraphProperty() ) );
1202       }
1203
1204       // The metadata has just been added and therefore should be in the end of the vector.
1205       animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
1206     }
1207   }
1208
1209   return animatableProperty;
1210 }
1211
1212 void Object::ResolveChildProperties()
1213 {
1214   // Resolve index for the child property
1215   Object* parent = GetParentObject();
1216   if( parent )
1217   {
1218     const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
1219     if( parentTypeInfo )
1220     {
1221       // Go through each custom property
1222       for( auto&& entry : mCustomProperties )
1223       {
1224         CustomPropertyMetadata* customProperty = static_cast<CustomPropertyMetadata*>( entry );
1225
1226         if( customProperty->name.empty() )
1227         {
1228           if( customProperty->childPropertyIndex != Property::INVALID_INDEX )
1229           {
1230             // Resolve name for any child property with no name
1231             customProperty->name = parentTypeInfo->GetChildPropertyName( customProperty->childPropertyIndex );
1232           }
1233         }
1234         else
1235         {
1236           Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( customProperty->name );
1237           if( childPropertyIndex != Property::INVALID_INDEX )
1238           {
1239             // Resolve index for any property with a name that matches the parent's child property name
1240             customProperty->childPropertyIndex = childPropertyIndex;
1241           }
1242         }
1243       }
1244     }
1245   }
1246 }
1247
1248 void Object::SetDefaultProperty( Property::Index index, const Property::Value& property )
1249 {
1250   // do nothing
1251 }
1252
1253 Property::Value Object::GetDefaultProperty(Property::Index index) const
1254 {
1255   return Property::Value();
1256 }
1257
1258 Property::Value Object::GetDefaultPropertyCurrentValue( Property::Index index ) const
1259 {
1260   return GetDefaultProperty( index );
1261 }
1262
1263 void Object::EnablePropertyNotifications()
1264 {
1265   if( mPropertyNotifications )
1266   {
1267     for( auto&& element : *mPropertyNotifications )
1268     {
1269       GetImplementation( element ).Enable();
1270     }
1271   }
1272 }
1273
1274 void Object::DisablePropertyNotifications()
1275 {
1276   if( mPropertyNotifications )
1277   {
1278     for( auto&& element : *mPropertyNotifications )
1279     {
1280       GetImplementation( element ).Disable();
1281     }
1282   }
1283 }
1284
1285 Property::Value Object::GetCurrentPropertyValue( const PropertyMetadata& entry ) const
1286 {
1287   Property::Value value;
1288
1289   if( !entry.IsAnimatable() )
1290   {
1291     value = entry.GetPropertyValue();
1292   }
1293   else
1294   {
1295     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1296
1297     switch ( entry.GetType() )
1298     {
1299       case Property::BOOLEAN:
1300       {
1301         const AnimatableProperty<bool>* property = static_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
1302         DALI_ASSERT_DEBUG( property );
1303
1304         value = (*property)[ bufferIndex ];
1305         break;
1306       }
1307
1308       case Property::INTEGER:
1309       {
1310         const AnimatableProperty<int32_t>* property = static_cast< const AnimatableProperty<int32_t>* >( entry.GetSceneGraphProperty() );
1311         DALI_ASSERT_DEBUG( property );
1312
1313         value = (*property)[ bufferIndex ];
1314         break;
1315       }
1316
1317       case Property::FLOAT:
1318       {
1319         const AnimatableProperty<float>* property = static_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
1320         DALI_ASSERT_DEBUG( property );
1321
1322         value = (*property)[ bufferIndex ];
1323         break;
1324       }
1325
1326       case Property::VECTOR2:
1327       {
1328         const AnimatableProperty<Vector2>* property = static_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
1329         DALI_ASSERT_DEBUG( property );
1330
1331         if(entry.componentIndex == 0)
1332         {
1333           value = (*property)[ bufferIndex ].x;
1334         }
1335         else if(entry.componentIndex == 1)
1336         {
1337           value = (*property)[ bufferIndex ].y;
1338         }
1339         else
1340         {
1341           value = (*property)[ bufferIndex ];
1342         }
1343         break;
1344       }
1345
1346       case Property::VECTOR3:
1347       {
1348         const AnimatableProperty<Vector3>* property = static_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
1349         DALI_ASSERT_DEBUG( property );
1350
1351         if(entry.componentIndex == 0)
1352         {
1353           value = (*property)[ bufferIndex ].x;
1354         }
1355         else if(entry.componentIndex == 1)
1356         {
1357           value = (*property)[ bufferIndex ].y;
1358         }
1359         else if(entry.componentIndex == 2)
1360         {
1361           value = (*property)[ bufferIndex ].z;
1362         }
1363         else
1364         {
1365           value = (*property)[ bufferIndex ];
1366         }
1367         break;
1368       }
1369
1370       case Property::VECTOR4:
1371       {
1372         const AnimatableProperty<Vector4>* property = static_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1373         DALI_ASSERT_DEBUG( property );
1374
1375         if(entry.componentIndex == 0)
1376         {
1377           value = (*property)[ bufferIndex ].x;
1378         }
1379         else if(entry.componentIndex == 1)
1380         {
1381           value = (*property)[ bufferIndex ].y;
1382         }
1383         else if(entry.componentIndex == 2)
1384         {
1385           value = (*property)[ bufferIndex ].z;
1386         }
1387         else if(entry.componentIndex == 3)
1388         {
1389           value = (*property)[ bufferIndex ].w;
1390         }
1391         else
1392         {
1393           value = (*property)[ bufferIndex ];
1394         }
1395         break;
1396       }
1397
1398       case Property::MATRIX:
1399       {
1400         const AnimatableProperty<Matrix>* property = static_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1401         DALI_ASSERT_DEBUG( property );
1402
1403         value = (*property)[ bufferIndex ];
1404         break;
1405       }
1406
1407       case Property::MATRIX3:
1408       {
1409         const AnimatableProperty<Matrix3>* property = static_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1410         DALI_ASSERT_DEBUG( property );
1411
1412         value = (*property)[ bufferIndex ];
1413         break;
1414       }
1415
1416       case Property::ROTATION:
1417       {
1418         const AnimatableProperty<Quaternion>* property = static_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1419         DALI_ASSERT_DEBUG( property );
1420
1421         value = (*property)[ bufferIndex ];
1422         break;
1423       }
1424
1425       default:
1426       {
1427         // unreachable code due to higher level logic
1428       }
1429     } // switch(type)
1430   } // if animatable
1431
1432   return value;
1433 }
1434
1435 void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1436 {
1437   switch ( entry.GetType() )
1438   {
1439     case Property::BOOLEAN:
1440     {
1441       const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
1442       DALI_ASSERT_DEBUG( property );
1443
1444       // property is being used in a separate thread; queue a message to set the property
1445       BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
1446       break;
1447     }
1448
1449     case Property::INTEGER:
1450     {
1451       const AnimatableProperty<int32_t>* property = dynamic_cast< const AnimatableProperty<int32_t>* >( entry.GetSceneGraphProperty() );
1452       DALI_ASSERT_DEBUG( property );
1453
1454       // property is being used in a separate thread; queue a message to set the property
1455       BakeMessage<int32_t>( GetEventThreadServices(), *property, value.Get<int32_t>() );
1456       break;
1457     }
1458
1459     case Property::FLOAT:
1460     {
1461       const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
1462       DALI_ASSERT_DEBUG( property );
1463
1464       // property is being used in a separate thread; queue a message to set the property
1465       BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
1466       break;
1467     }
1468
1469     case Property::VECTOR2:
1470     {
1471       const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
1472       DALI_ASSERT_DEBUG( property );
1473
1474       // property is being used in a separate thread; queue a message to set the property
1475       if(entry.componentIndex == 0)
1476       {
1477         SetXComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1478       }
1479       else if(entry.componentIndex == 1)
1480       {
1481         SetYComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
1482       }
1483       else
1484       {
1485         BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
1486       }
1487       break;
1488     }
1489
1490     case Property::VECTOR3:
1491     {
1492       const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
1493       DALI_ASSERT_DEBUG( property );
1494
1495       // property is being used in a separate thread; queue a message to set the property
1496       if(entry.componentIndex == 0)
1497       {
1498         SetXComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1499       }
1500       else if(entry.componentIndex == 1)
1501       {
1502         SetYComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1503       }
1504       else if(entry.componentIndex == 2)
1505       {
1506         SetZComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
1507       }
1508       else
1509       {
1510         BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
1511       }
1512
1513       break;
1514     }
1515
1516     case Property::VECTOR4:
1517     {
1518       const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
1519       DALI_ASSERT_DEBUG( property );
1520
1521       // property is being used in a separate thread; queue a message to set the property
1522       if(entry.componentIndex == 0)
1523       {
1524         SetXComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1525       }
1526       else if(entry.componentIndex == 1)
1527       {
1528         SetYComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1529       }
1530       else if(entry.componentIndex == 2)
1531       {
1532         SetZComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1533       }
1534       else if(entry.componentIndex == 3)
1535       {
1536         SetWComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
1537       }
1538       else
1539       {
1540         BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
1541       }
1542       break;
1543     }
1544
1545     case Property::ROTATION:
1546     {
1547       const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
1548       DALI_ASSERT_DEBUG( property );
1549
1550       // property is being used in a separate thread; queue a message to set the property
1551       BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
1552       break;
1553     }
1554
1555     case Property::MATRIX:
1556     {
1557       const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
1558       DALI_ASSERT_DEBUG( property );
1559
1560       // property is being used in a separate thread; queue a message to set the property
1561       BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
1562       break;
1563     }
1564
1565     case Property::MATRIX3:
1566     {
1567       const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
1568       DALI_ASSERT_DEBUG( property );
1569
1570       // property is being used in a separate thread; queue a message to set the property
1571       BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
1572       break;
1573     }
1574
1575     default:
1576     {
1577       // non-animatable scene graph property, do nothing
1578     }
1579   }
1580 }
1581
1582 } // namespace Internal
1583
1584 } // namespace Dali