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