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