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 f667b18..7d00513 100644 (file)
 
 // INTERNAL INCLUDES
 #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>
@@ -48,17 +48,13 @@ 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 ),
   mPropertyNotifications( NULL )
 {
@@ -159,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" );
 
@@ -194,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
@@ -217,14 +207,16 @@ Property::Index ProxyObject::GetPropertyIndex(const std::string& name) const
     }
   }
 
-  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;
       }
     }
@@ -251,17 +243,14 @@ bool ProxyObject::IsPropertyWritable( Property::Index index ) const
     }
     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;
 }
@@ -281,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");
 
@@ -307,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;
   }
@@ -341,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;
 }
@@ -357,8 +338,6 @@ 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 ) )
@@ -373,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
   }
 }
 
@@ -411,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:
         {
-          const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -437,7 +418,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::FLOAT:
         {
-          const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -446,7 +427,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::INTEGER:
         {
-          const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -455,7 +436,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::VECTOR2:
         {
-          const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -464,7 +445,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::VECTOR3:
         {
-          const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -473,7 +454,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::VECTOR4:
         {
-          const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -482,7 +463,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::MATRIX:
         {
-          const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -491,7 +472,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::MATRIX3:
         {
-          const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -500,7 +481,7 @@ Property::Value ProxyObject::GetProperty(Property::Index index) const
 
         case Property::ROTATION:
         {
-          const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->second.GetSceneGraphProperty() );
+          const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( custom->GetSceneGraphProperty() );
           DALI_ASSERT_DEBUG( NULL != property );
 
           value = (*property)[ bufferIndex ];
@@ -535,23 +516,22 @@ void ProxyObject::GetPropertyIndices( Property::IndexContainer& indices ) const
   }
 
   // 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
   Dali::Internal::OwnerPointer<PropertyBase> newProperty;
 
@@ -618,40 +598,45 @@ Property::Index ProxyObject::RegisterProperty( std::string name, const Property:
     case Property::MAP:
     {
       DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
-      DALI_ASSERT_ALWAYS( false && "PropertyType is not animatable" );
+      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
-  // TODO: change this so that OwnerPointer is passed all the way as owership passing cannot be done with a reference
-  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;
 
@@ -661,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;
@@ -683,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." );
     }
   }
 
@@ -813,119 +791,105 @@ ActiveConstraintBase* ProxyObject::DoApplyConstraint( Constraint& constraint, Da
   return activeConstraintImpl;
 }
 
-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 )
 {
-  if( entry.IsAnimatable() )
+  switch ( entry.type )
   {
-    switch ( entry.type )
+    case Property::BOOLEAN:
     {
-      case Property::BOOLEAN:
-      {
-        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
-        BakeMessage<bool>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<bool>() );
-        break;
-      }
+      const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      case Property::FLOAT:
-      {
-        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
+      BakeMessage<bool>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<bool>() );
+      break;
+    }
 
-        // property is being used in a separate thread; queue a message to set the property
-        BakeMessage<float>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<float>() );
-        break;
-      }
+    case Property::FLOAT:
+    {
+      const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      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<float>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<float>() );
+      break;
+    }
 
-        // 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::INTEGER:
+    {
+      const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      case Property::VECTOR2:
-      {
-        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
+      BakeMessage<int>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<int>() );
+      break;
+    }
 
-        // property is being used in a separate thread; queue a message to set the property
-        BakeMessage<Vector2>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector2>() );
-        break;
-      }
+    case Property::VECTOR2:
+    {
+      const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      case Property::VECTOR3:
-      {
-        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
+      BakeMessage<Vector2>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector2>() );
+      break;
+    }
 
-        // property is being used in a separate thread; queue a message to set the property
-        BakeMessage<Vector3>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector3>() );
-        break;
-      }
+    case Property::VECTOR3:
+    {
+      const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      case Property::VECTOR4:
-      {
-        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
+      BakeMessage<Vector3>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector3>() );
+      break;
+    }
 
-        // property is being used in a separate thread; queue a message to set the property
-        BakeMessage<Vector4>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector4>() );
-        break;
-      }
+    case Property::VECTOR4:
+    {
+      const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      case Property::ROTATION:
-      {
-        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
+      BakeMessage<Vector4>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector4>() );
+      break;
+    }
 
-        // property is being used in a separate thread; queue a message to set the property
-        BakeMessage<Quaternion>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Quaternion>() );
-        break;
-      }
+    case Property::ROTATION:
+    {
+      const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      case Property::MATRIX:
-      {
-        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
+      BakeMessage<Quaternion>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Quaternion>() );
+      break;
+    }
 
-        // property is being used in a separate thread; queue a message to set the property
-        BakeMessage<Matrix>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Matrix>() );
-        break;
-      }
+    case Property::MATRIX:
+    {
+      const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      case Property::MATRIX3:
-      {
-        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
+      BakeMessage<Matrix>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Matrix>() );
+      break;
+    }
 
-        // property is being used in a separate thread; queue a message to set the property
-        BakeMessage<Matrix3>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Matrix3>() );
-        break;
-      }
+    case Property::MATRIX3:
+    {
+      const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
 
-      default:
-      {
-        DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds"); // should not come here
-        break;
-      }
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Matrix3>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Matrix3>() );
+      break;
     }
-  }
-}
 
-CustomPropertyLookup& ProxyObject::GetCustomPropertyLookup() const
-{
-  // lazy create
-  if( !mCustomProperties )
-  {
-    mCustomProperties = new CustomPropertyLookup;
+    default:
+    {
+      // non-animatable scene graph property, do nothing
+    }
   }
-  return *mCustomProperties;
 }
 
 const TypeInfo* ProxyObject::GetTypeInfo() const
@@ -1044,11 +1008,24 @@ ProxyObject::~ProxyObject()
     (*iter)->ProxyDestroyed(*this);
   }
 
-  delete mCustomProperties;
   delete mConstraints;
   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