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