Cleaning up the property framework; removal of duplicate methods and incorrect assers
[platform/core/uifw/dali-core.git] / dali / internal / event / common / proxy-object.cpp
index fafe4be..7d00513 100644 (file)
 #include <algorithm>
 
 // INTERNAL INCLUDES
-#include <dali/public-api/object/property-index.h>
 #include <dali/integration-api/debug.h>
-#include <dali/internal/event/common/stage-impl.h>
-#include <dali/internal/update/common/animatable-property.h>
 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/update/common/animatable-property.h>
 #include <dali/internal/update/common/property-owner-messages.h>
 #include <dali/internal/event/animation/active-constraint-base.h>
 #include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
 #include <dali/internal/event/common/property-notification-impl.h>
 #include <dali/internal/event/common/property-index-ranges.h>
 #include <dali/internal/event/common/type-registry-impl.h>
@@ -49,19 +48,14 @@ const int SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES;  // ProxyOb
 typedef Dali::Vector<ProxyObject::Observer*>::Iterator ObserverIter;
 typedef Dali::Vector<ProxyObject::Observer*>::ConstIterator ConstObserverIter;
 
-static std::string EMPTY_PROPERTY_NAME;
-
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_PROXY_OBJECT" );
 #endif
 } // unnamed namespace
 
 ProxyObject::ProxyObject()
-: mNextCustomPropertyIndex( 0u ),
-  mCustomProperties( NULL ),
-  mTypeInfo( NULL ),
+: mTypeInfo( NULL ),
   mConstraints( NULL ),
-  mRemovedConstraints( NULL ),
   mPropertyNotifications( NULL )
 {
 }
@@ -92,6 +86,17 @@ void ProxyObject::RemoveObserver(Observer& observer)
 
 void ProxyObject::OnSceneObjectAdd()
 {
+  // Notification for this object's constraints
+  if( mConstraints )
+  {
+    const ActiveConstraintConstIter endIter = mConstraints->end();
+    for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
+    {
+      ActiveConstraintBase& baseConstraint = GetImplementation( *iter );
+      baseConstraint.OnParentSceneObjectAdded();
+    }
+  }
+
   // Notification for observers
   for( ConstObserverIter iter = mObservers.Begin(),  endIter =  mObservers.End(); iter != endIter; ++iter)
   {
@@ -104,6 +109,17 @@ void ProxyObject::OnSceneObjectAdd()
 
 void ProxyObject::OnSceneObjectRemove()
 {
+  // Notification for this object's constraints
+  if( mConstraints )
+  {
+    const ActiveConstraintConstIter endIter = mConstraints->end();
+    for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
+    {
+      ActiveConstraintBase& baseConstraint = GetImplementation( *iter );
+      baseConstraint.OnParentSceneObjectRemoved();
+    }
+  }
+
   // Notification for observers
   for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
   {
@@ -130,7 +146,7 @@ unsigned int ProxyObject::GetPropertyCount() const
 
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Default Properties: %d\n", count );
 
-  TypeInfo* typeInfo( GetTypeInfo() );
+  const TypeInfo* typeInfo( GetTypeInfo() );
   if ( typeInfo )
   {
     unsigned int manual( typeInfo->GetPropertyCount() );
@@ -139,20 +155,16 @@ unsigned int ProxyObject::GetPropertyCount() const
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties:  %d\n", manual );
   }
 
-  if( mCustomProperties )
-  {
-    unsigned int custom( mCustomProperties->size() );
-    count += custom;
-
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties:  %d\n", custom );
-  }
+  unsigned int custom( mCustomProperties.Count() );
+  count += custom;
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties:  %d\n", custom );
 
   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties:   %d\n", count );
 
   return count;
 }
 
-const std::string& ProxyObject::GetPropertyName( Property::Index index ) const
+std::string ProxyObject::GetPropertyName( Property::Index index ) const
 {
   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
 
@@ -163,7 +175,7 @@ const std::string& ProxyObject::GetPropertyName( Property::Index index ) const
 
   if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
   {
-    TypeInfo* typeInfo( GetTypeInfo() );
+    const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       return typeInfo->GetPropertyName( index );
@@ -174,14 +186,12 @@ const std::string& ProxyObject::GetPropertyName( Property::Index index ) const
     }
   }
 
-  if( mCustomProperties )
+  CustomProperty* custom = FindCustomProperty( index );
+  if( custom )
   {
-    CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
-    DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Property index is invalid" );
-
-    return entry->second.name;
+    return custom->name;
   }
-  return EMPTY_PROPERTY_NAME;
+  return "";
 }
 
 Property::Index ProxyObject::GetPropertyIndex(const std::string& name) const
@@ -190,21 +200,23 @@ Property::Index ProxyObject::GetPropertyIndex(const std::string& name) const
 
   if ( index == Property::INVALID_INDEX )
   {
-    TypeInfo* typeInfo( GetTypeInfo() );
+    const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       index = typeInfo->GetPropertyIndex( name );
     }
   }
 
-  if( index == Property::INVALID_INDEX && mCustomProperties )
+  if( ( index == Property::INVALID_INDEX )&&( mCustomProperties.Count() > 0 ) )
   {
-    // This is slow, but we're not (supposed to be) using property names frequently
-    for ( CustomPropertyLookup::const_iterator iter = mCustomProperties->begin(); mCustomProperties->end() != iter; ++iter )
+    Property::Index count = PROPERTY_CUSTOM_START_INDEX;
+    const CustomPropertyLookup::ConstIterator end = mCustomProperties.End();
+    for( CustomPropertyLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
     {
-      if (iter->second.name == name)
+      CustomProperty* custom = *iter;
+      if ( custom->name == name )
       {
-        index = iter->first;
+        index = count;
         break;
       }
     }
@@ -224,24 +236,21 @@ bool ProxyObject::IsPropertyWritable( Property::Index index ) const
 
   if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
   {
-    TypeInfo* typeInfo( GetTypeInfo() );
+    const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       return typeInfo->IsPropertyWritable( index );
     }
     else
     {
-      DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
+      DALI_ASSERT_ALWAYS( ! "Invalid property index" );
     }
   }
 
-  if( mCustomProperties)
+  CustomProperty* custom = FindCustomProperty( index );
+  if( custom )
   {
-    // Check that the index is valid
-    CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
-    DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-
-    return entry->second.IsWritable();
+    return custom->IsWritable();
   }
   return false;
 }
@@ -261,18 +270,15 @@ bool ProxyObject::IsPropertyAnimatable( Property::Index index ) const
     return false;
   }
 
-  if( mCustomProperties )
+  CustomProperty* custom = FindCustomProperty( index );
+  if( custom )
   {
-    // Check custom property
-    CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
-    DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-
-    return entry->second.IsAnimatable();
+    return custom->IsAnimatable();
   }
   return false;
 }
 
-bool ProxyObject::IsPropertyAConstraintInput(Property::Index index) const
+bool ProxyObject::IsPropertyAConstraintInput( Property::Index index ) const
 {
   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
 
@@ -287,12 +293,9 @@ bool ProxyObject::IsPropertyAConstraintInput(Property::Index index) const
     return false;
   }
 
-  if( mCustomProperties )
+  CustomProperty* custom = FindCustomProperty( index );
+  if( custom )
   {
-    // Check custom property
-    CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
-    DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-
     // ... custom properties can be used as input to a constraint.
     return true;
   }
@@ -310,7 +313,7 @@ Property::Type ProxyObject::GetPropertyType( Property::Index index ) const
 
   if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
   {
-    TypeInfo* typeInfo( GetTypeInfo() );
+    const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       return typeInfo->GetPropertyType( index );
@@ -321,12 +324,10 @@ Property::Type ProxyObject::GetPropertyType( Property::Index index ) const
     }
   }
 
-  if( mCustomProperties )
+  CustomProperty* custom = FindCustomProperty( index );
+  if( custom )
   {
-    CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
-    DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find Property index" );
-
-    return entry->second.type;
+    return custom->type;
   }
   return Property::NONE;
 }
@@ -337,13 +338,11 @@ void ProxyObject::SetProperty( Property::Index index, const Property::Value& pro
 
   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
   {
-    DALI_ASSERT_ALWAYS( IsDefaultPropertyWritable(index) && "Property is read-only" );
-
     SetDefaultProperty( index, propertyValue );
   }
   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
   {
-    TypeInfo* typeInfo( GetTypeInfo() );
+    const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       typeInfo->SetProperty( this, index, propertyValue );
@@ -353,19 +352,21 @@ void ProxyObject::SetProperty( Property::Index index, const Property::Value& pro
       DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
     }
   }
-  else if( mCustomProperties )
+  else
   {
-    CustomPropertyLookup::iterator entry = mCustomProperties->find( index );
-    DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-    DALI_ASSERT_ALWAYS( entry->second.IsWritable() && "Property is read-only" );
-
-    // this is only relevant for non animatable properties
-    if(entry->second.IsWritable())
+    CustomProperty* custom = FindCustomProperty( index );
+    DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
+    if( custom->IsAnimatable() )
     {
-      entry->second.value = propertyValue;
+      // set the scene graph property value
+      SetSceneGraphProperty( index, *custom, propertyValue );
     }
-
-    SetCustomProperty(index, entry->second, propertyValue);
+    else if( custom->IsWritable() )
+    {
+      custom->value = propertyValue;
+      OnPropertySet(index, propertyValue);
+    }
+    // trying to set value on read only property is no-op
   }
 }
 
@@ -381,7 +382,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
   }
   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
   {
-    TypeInfo* typeInfo( GetTypeInfo() );
+    const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       value = typeInfo->GetProperty( this, index );
@@ -391,24 +392,24 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
       DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
     }
   }
-  else if( mCustomProperties )
+  else if( mCustomProperties.Count() > 0 )
   {
-    CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
-    DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
+    CustomProperty* custom = FindCustomProperty( index );
+    DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
 
-    if( !entry->second.IsAnimatable() )
+    if( !custom->IsAnimatable() )
     {
-      value = entry->second.value;
+      value = custom->value;
     }
     else
     {
       BufferIndex bufferIndex( Stage::GetCurrent()->GetEventBufferIndex() );
 
-      switch ( entry->second.type )
+      switch ( custom->type )
       {
         case Property::BOOLEAN:
         {
-          AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -417,7 +418,16 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::FLOAT:
         {
-          AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( custom->GetSceneGraphProperty() );
+          DALI_ASSERT_DEBUG( NULL != property );
+
+          value = (*property)[ bufferIndex ];
+          break;
+        }
+
+        case Property::INTEGER:
+        {
+          const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -426,7 +436,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::VECTOR2:
         {
-          AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -435,7 +445,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::VECTOR3:
         {
-          AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -444,7 +454,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::VECTOR4:
         {
-          AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -453,7 +463,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::MATRIX:
         {
-          AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -462,7 +472,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::MATRIX3:
         {
-          AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -471,7 +481,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::ROTATION:
         {
-          AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -499,112 +509,134 @@ void ProxyObject::GetPropertyIndices( Property::IndexContainer& indices ) const
   GetDefaultPropertyIndices( indices );
 
   // Manual Properties
-  TypeInfo* typeInfo( GetTypeInfo() );
+  const TypeInfo* typeInfo( GetTypeInfo() );
   if ( typeInfo )
   {
     typeInfo->GetPropertyIndices( indices );
   }
 
   // Custom Properties
-  if ( mCustomProperties )
+  if ( mCustomProperties.Count() > 0 )
   {
-    indices.reserve( indices.size() + mCustomProperties->size() );
+    indices.reserve( indices.size() + mCustomProperties.Count() );
 
-    const CustomPropertyLookup::const_iterator endIter = mCustomProperties->end();
-    for ( CustomPropertyLookup::const_iterator iter = mCustomProperties->begin(); iter != endIter; ++iter )
+    CustomPropertyLookup::ConstIterator iter = mCustomProperties.Begin();
+    const CustomPropertyLookup::ConstIterator endIter = mCustomProperties.End();
+    int i=0;
+    for ( ; iter != endIter; ++iter, ++i )
     {
-      indices.push_back( iter->first );
+      indices.push_back( PROPERTY_CUSTOM_START_INDEX + i );
     }
   }
 }
 
-Property::Index ProxyObject::RegisterProperty( std::string name, const Property::Value& propertyValue)
+Property::Index ProxyObject::RegisterProperty( const std::string& name, const Property::Value& propertyValue)
 {
-  // Assert that property name is unused
-  DALI_ASSERT_ALWAYS( Property::INVALID_INDEX == GetPropertyIndex(name) && "Property index is out of bounds" );
-
   // Create a new property
-  std::auto_ptr<PropertyBase> newProperty;
+  Dali::Internal::OwnerPointer<PropertyBase> newProperty;
 
   switch ( propertyValue.GetType() )
   {
     case Property::BOOLEAN:
     {
-      newProperty.reset(new AnimatableProperty<bool>( propertyValue.Get<bool>()));
+      newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
       break;
     }
 
     case Property::FLOAT:
     {
-      newProperty.reset(new AnimatableProperty<float>( propertyValue.Get<float>()));
+      newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
+      break;
+    }
+
+    case Property::INTEGER:
+    {
+      newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
       break;
     }
 
     case Property::VECTOR2:
     {
-      newProperty.reset(new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>()));
+      newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
       break;
     }
 
     case Property::VECTOR3:
     {
-      newProperty.reset(new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>()));
+      newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
       break;
     }
 
     case Property::VECTOR4:
     {
-      newProperty.reset(new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>()));
+      newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
       break;
     }
 
     case Property::MATRIX:
     {
-      newProperty.reset(new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>()));
+      newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
       break;
     }
 
     case Property::MATRIX3:
     {
-      newProperty.reset(new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>()));
+      newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
       break;
     }
 
     case Property::ROTATION:
     {
-      newProperty.reset(new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>()));
+      newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
+      break;
+    }
+
+    case Property::UNSIGNED_INTEGER:
+    case Property::RECTANGLE:
+    case Property::STRING:
+    case Property::ARRAY:
+    case Property::MAP:
+    {
+      DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
+      DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
       break;
     }
 
     default:
     {
       DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
-      DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
+      DALI_ASSERT_ALWAYS( !"PropertyType enumeration is out of bounds" );
       break;
     }
   }
 
-  // Default properties start from index zero
-  if ( 0u == mNextCustomPropertyIndex )
+  // get the scene property owner from derived class
+  const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
+  Property::Index index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
+  // we can only pass properties to scene graph side if there is a scene object
+  if( scenePropertyOwner )
   {
-    mNextCustomPropertyIndex = PROPERTY_CUSTOM_START_INDEX;
-  }
-
-  // Add entry to the property lookup
-  const Property::Index index = mNextCustomPropertyIndex++;
+    // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
+    const PropertyBase* property = newProperty.Get();
+    mCustomProperties.PushBack( new CustomProperty( name, propertyValue.GetType(), property ) );
 
-  CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
-  DALI_ASSERT_ALWAYS( mCustomProperties->end() == entry && "Custom property already registered" );
+    // queue a message to add the property
+    InstallCustomPropertyMessage( Stage::GetCurrent()->GetUpdateInterface(), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
 
-  (*mCustomProperties)[ index ] = CustomProperty( name, propertyValue.GetType(), newProperty.get() );
-
-  // The derived class now passes ownership of this new property to a scene-object
-  InstallSceneObjectProperty( *(newProperty.release()), name, index );
+    // notify the derived class (optional) method in case it needs to do some more work on the new property
+    // note! have to use the local pointer as OwnerPointer now points to NULL as it handed over its ownership
+    NotifyScenePropertyInstalled( *property, name, index );
+  }
+  else
+  {
+    // property was orphaned and killed so return invalid index
+    index = Property::INVALID_INDEX;
+  }
 
   return index;
 }
 
-Property::Index ProxyObject::RegisterProperty( std::string name, const Property::Value& propertyValue, Property::AccessMode accessMode)
+Property::Index ProxyObject::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode)
 {
   Property::Index index = Property::INVALID_INDEX;
 
@@ -614,15 +646,9 @@ Property::Index ProxyObject::RegisterProperty( std::string name, const Property:
   }
   else
   {
-    // Default properties start from index zero
-    if ( 0u == mNextCustomPropertyIndex )
-    {
-      mNextCustomPropertyIndex = PROPERTY_CUSTOM_START_INDEX;
-    }
-
     // Add entry to the property lookup
-    index = mNextCustomPropertyIndex++;
-    GetCustomPropertyLookup()[ index ] = CustomProperty( name, propertyValue, accessMode );
+    index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
+    mCustomProperties.PushBack( new CustomProperty( name, propertyValue, accessMode ) );
   }
 
   return index;
@@ -636,14 +662,13 @@ Dali::PropertyNotification ProxyObject::AddPropertyNotification(Property::Index
   {
     if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
     {
-      DALI_ASSERT_ALWAYS( false && "Property notification added to non animatable property." );
+      DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
     }
-    else if ( mCustomProperties )
+    else if ( mCustomProperties.Count() > 0 )
     {
-      CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
-      DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
-
-      DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "Property notification added to non animatable property (currently not suppported )");
+      CustomProperty* custom = FindCustomProperty( index );
+      DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
+      DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
     }
   }
 
@@ -766,34 +791,13 @@ ActiveConstraintBase* ProxyObject::DoApplyConstraint( Constraint& constraint, Da
   return activeConstraintImpl;
 }
 
-void ProxyObject::DeleteRemovedConstraints()
-{
-  if( ! mRemovedConstraints )
-  {
-    return;
-  }
-
-  // Discard constraints which are fully removed
-  for ( ActiveConstraintIter iter = mRemovedConstraints->begin(); mRemovedConstraints->end() != iter ;)
-  {
-    if ( !( GetImplementation( *iter ).IsRemoving() ) )
-    {
-      iter = mRemovedConstraints->erase( iter );
-    }
-    else
-    {
-      ++iter;
-    }
-  }
-}
-
-void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
+void ProxyObject::SetSceneGraphProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
 {
   switch ( entry.type )
   {
     case Property::BOOLEAN:
     {
-      AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
+      const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
       DALI_ASSERT_DEBUG( NULL != property );
 
       // property is being used in a separate thread; queue a message to set the property
@@ -803,7 +807,7 @@ void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty
 
     case Property::FLOAT:
     {
-      AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
+      const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
       DALI_ASSERT_DEBUG( NULL != property );
 
       // property is being used in a separate thread; queue a message to set the property
@@ -811,9 +815,19 @@ void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty
       break;
     }
 
+    case Property::INTEGER:
+    {
+      const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<int>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<int>() );
+      break;
+    }
+
     case Property::VECTOR2:
     {
-      AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
+      const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
       DALI_ASSERT_DEBUG( NULL != property );
 
       // property is being used in a separate thread; queue a message to set the property
@@ -823,7 +837,7 @@ void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty
 
     case Property::VECTOR3:
     {
-      AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
+      const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
       DALI_ASSERT_DEBUG( NULL != property );
 
       // property is being used in a separate thread; queue a message to set the property
@@ -833,7 +847,7 @@ void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty
 
     case Property::VECTOR4:
     {
-      AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
+      const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
       DALI_ASSERT_DEBUG( NULL != property );
 
       // property is being used in a separate thread; queue a message to set the property
@@ -843,7 +857,7 @@ void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty
 
     case Property::ROTATION:
     {
-      AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
+      const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
       DALI_ASSERT_DEBUG( NULL != property );
 
       // property is being used in a separate thread; queue a message to set the property
@@ -853,7 +867,7 @@ void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty
 
     case Property::MATRIX:
     {
-      AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
+      const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
       DALI_ASSERT_DEBUG( NULL != property );
 
       // property is being used in a separate thread; queue a message to set the property
@@ -863,7 +877,7 @@ void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty
 
     case Property::MATRIX3:
     {
-      AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
+      const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
       DALI_ASSERT_DEBUG( NULL != property );
 
       // property is being used in a separate thread; queue a message to set the property
@@ -873,23 +887,12 @@ void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty
 
     default:
     {
-      DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds"); // should not come here
-      break;
+      // non-animatable scene graph property, do nothing
     }
   }
 }
 
-CustomPropertyLookup& ProxyObject::GetCustomPropertyLookup() const
-{
-  // lazy create
-  if( !mCustomProperties )
-  {
-    mCustomProperties = new CustomPropertyLookup;
-  }
-  return *mCustomProperties;
-}
-
-TypeInfo* ProxyObject::GetTypeInfo() const
+const TypeInfo* ProxyObject::GetTypeInfo() const
 {
   if ( !mTypeInfo )
   {
@@ -915,20 +918,6 @@ void ProxyObject::RemoveConstraint( ActiveConstraint& constraint, bool isInScene
     {
       ActiveConstraintBase& baseConstraint = GetImplementation( constraint );
       baseConstraint.BeginRemove();
-      if ( baseConstraint.IsRemoving() )
-      {
-        if( !mRemovedConstraints )
-        {
-          mRemovedConstraints = new ActiveConstraintContainer;
-        }
-        // Wait for remove animation before destroying active-constraints
-        mRemovedConstraints->push_back( constraint );
-      }
-    }
-    else if( mRemovedConstraints )
-    {
-      delete mRemovedConstraints;
-      mRemovedConstraints = NULL;
     }
   }
 }
@@ -939,10 +928,6 @@ void ProxyObject::RemoveConstraint( Dali::ActiveConstraint activeConstraint )
   if( mConstraints && Stage::IsInstalled() )
   {
     bool isInSceneGraph( NULL != GetSceneObject() );
-    if( isInSceneGraph )
-    {
-      DeleteRemovedConstraints();
-    }
 
     ActiveConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), activeConstraint ) );
     if( it !=  mConstraints->end() )
@@ -959,10 +944,6 @@ void ProxyObject::RemoveConstraints( unsigned int tag )
   if( mConstraints && Stage::IsInstalled() )
   {
     bool isInSceneGraph( NULL != GetSceneObject() );
-    if( isInSceneGraph )
-    {
-      DeleteRemovedConstraints();
-    }
 
     ActiveConstraintIter iter( mConstraints->begin() );
     while(iter != mConstraints->end() )
@@ -988,16 +969,8 @@ void ProxyObject::RemoveConstraints()
   {
     // If we have nothing in the scene-graph, just clear constraint containers
     const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
-    if ( NULL == propertyOwner )
-    {
-      delete mRemovedConstraints;
-      mRemovedConstraints = NULL;
-    }
-    else
+    if ( NULL != propertyOwner )
     {
-      // Discard constraints which are fully removed
-      DeleteRemovedConstraints();
-
       const ActiveConstraintConstIter endIter = mConstraints->end();
       for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
       {
@@ -1010,25 +983,49 @@ void ProxyObject::RemoveConstraints()
   }
 }
 
-void ProxyObject::SetTypeInfo( TypeInfo* typeInfo )
+void ProxyObject::SetTypeInfo( const TypeInfo* typeInfo )
 {
   mTypeInfo = typeInfo;
 }
 
 ProxyObject::~ProxyObject()
 {
+  // Notification for this object's constraints
+  // (note that the ActiveConstraint handles may outlive the ProxyObject)
+  if( mConstraints )
+  {
+    const ActiveConstraintConstIter endIter = mConstraints->end();
+    for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
+    {
+      ActiveConstraintBase& baseConstraint = GetImplementation( *iter );
+      baseConstraint.OnParentDestroyed();
+    }
+  }
+
   // Notification for observers
   for( ConstObserverIter iter = mObservers.Begin(), endIter =  mObservers.End(); iter != endIter; ++iter)
   {
     (*iter)->ProxyDestroyed(*this);
   }
 
-  delete mCustomProperties;
   delete mConstraints;
-  delete mRemovedConstraints;
   delete mPropertyNotifications;
 }
 
+CustomProperty* ProxyObject::FindCustomProperty( Property::Index index ) const
+{
+  CustomProperty* property( NULL );
+  int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
+  if( arrayIndex >= 0 )
+  {
+    if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
+    {
+      property = mCustomProperties[ arrayIndex ];
+    }
+  }
+  return property;
+}
+
 } // namespace Internal
 
 } // namespace Dali