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