Ensure cached values of properties animated using AnimateTo are updated
[platform/core/uifw/dali-core.git] / dali / internal / event / common / object-impl.cpp
index f50fb07..344e72c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -164,7 +164,14 @@ std::string Object::GetPropertyName( Property::Index index ) const
 
   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
   {
-    return GetDefaultPropertyName( index );
+    std::string string;
+
+    const char * propertyName = GetDefaultPropertyName( index );
+    if( propertyName )
+    {
+      string = propertyName;
+    }
+    return string;
   }
 
   if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
@@ -219,7 +226,45 @@ Property::Index Object::GetPropertyIndex(const std::string& name) const
       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
       if ( custom->name == name )
       {
-        index = count;
+        if ( custom->childPropertyIndex != Property::INVALID_INDEX )
+        {
+          // If it is a child property, return the child property index
+          index = custom->childPropertyIndex;
+        }
+        else
+        {
+          index = count;
+        }
+        break;
+      }
+    }
+  }
+
+  return index;
+}
+
+Property::Index Object::GetPropertyIndex( Property::Index key ) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  if( mCustomProperties.Count() > 0 )
+  {
+    Property::Index count = PROPERTY_CUSTOM_START_INDEX;
+    const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End();
+    for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
+    {
+      CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
+      if( custom->key == key )
+      {
+        if( custom->childPropertyIndex != Property::INVALID_INDEX )
+        {
+          // If it is a child property, return the child property index
+          index = custom->childPropertyIndex;
+        }
+        else
+        {
+          index = count;
+        }
         break;
       }
     }
@@ -228,6 +273,20 @@ Property::Index Object::GetPropertyIndex(const std::string& name) const
   return index;
 }
 
+Property::Index Object::GetPropertyIndex( Property::Key key ) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+  if( key.type == Property::Key::INDEX )
+  {
+    index = GetPropertyIndex( key.indexKey );
+  }
+  else
+  {
+    index = GetPropertyIndex( key.stringKey );
+  }
+  return index;
+}
+
 bool Object::IsPropertyWritable( Property::Index index ) const
 {
   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
@@ -358,8 +417,9 @@ Property::Type Object::GetPropertyType( Property::Index index ) const
   CustomPropertyMetadata* custom = FindCustomProperty( index );
   if( custom )
   {
-    return custom->type;
+    return custom->GetType();
   }
+
   return Property::NONE;
 }
 
@@ -397,6 +457,9 @@ void Object::SetProperty( Property::Index index, const Property::Value& property
     }
     else
     {
+      // update the cached property value
+      animatableProperty->SetPropertyValue( propertyValue );
+
       // set the scene graph property value
       SetSceneGraphProperty( index, *animatableProperty, propertyValue );
     }
@@ -404,16 +467,44 @@ void Object::SetProperty( Property::Index index, const Property::Value& property
   else
   {
     CustomPropertyMetadata* custom = FindCustomProperty( index );
+
+    if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
+    {
+      if( !custom )
+      {
+        // If the child property is not registered yet, register it.
+        custom = new CustomPropertyMetadata( "", propertyValue, Property::READ_WRITE );
+        mCustomProperties.PushBack( custom );
+      }
+
+      custom->childPropertyIndex = index;
+
+      // Resolve name for the child property
+      Object* parent = GetParentObject();
+      if( parent )
+      {
+        const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
+        if( parentTypeInfo )
+        {
+          custom->name = parentTypeInfo->GetChildPropertyName( index );
+        }
+      }
+    }
+
     if( custom )
     {
       if( custom->IsAnimatable() )
       {
+        // update the cached property value
+        custom->SetPropertyValue( propertyValue );
+
         // set the scene graph property value
         SetSceneGraphProperty( index, *custom, propertyValue );
       }
       else if( custom->IsWritable() )
       {
-        custom->value = propertyValue;
+        // update the cached property value
+        custom->SetPropertyValue( propertyValue );
       }
       else
       {
@@ -468,8 +559,61 @@ Property::Value Object::GetProperty(Property::Index index) const
     }
     else
     {
+      // get the cached animatable property value
+      value = animatableProperty->GetPropertyValue();
+    }
+  }
+  else if(mCustomProperties.Count() > 0)
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if(custom)
+    {
+      // get the cached custom property value
+      value = custom->GetPropertyValue();
+    }
+    else
+    {
+      DALI_LOG_ERROR("Invalid property index\n");
+    }
+  } // if custom
+
+  return value;
+}
+
+Property::Value Object::GetCurrentProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
+
+  Property::Value value;
+
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    value = GetDefaultPropertyCurrentValue( index );
+  }
+  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      value = typeInfo->GetProperty( this, index );
+    }
+    else
+    {
+      DALI_LOG_ERROR("Cannot find property index\n");
+    }
+  }
+  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // check whether the animatable property is registered already, if not then register one.
+    AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
+    if(!animatableProperty)
+    {
+      DALI_LOG_ERROR("Cannot find property index\n");
+    }
+    else
+    {
       // get the animatable property value
-      value = GetPropertyValue( animatableProperty );
+      value = GetCurrentPropertyValue( animatableProperty );
     }
   }
   else if(mCustomProperties.Count() > 0)
@@ -478,7 +622,7 @@ Property::Value Object::GetProperty(Property::Index index) const
     if(custom)
     {
       // get the custom property value
-      value = GetPropertyValue( custom );
+      value = GetCurrentPropertyValue( custom );
     }
     else
     {
@@ -513,12 +657,21 @@ void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
     int i=0;
     for ( ; iter != endIter; ++iter, ++i )
     {
-      indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i );
+      CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( *iter );
+      if ( custom->childPropertyIndex != Property::INVALID_INDEX )
+      {
+        // If it is a child property, add the child property index
+        indices.PushBack( custom->childPropertyIndex );
+      }
+      else
+      {
+        indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i );
+      }
     }
   }
 }
 
-Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
+Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index key, Property::Index index, const Property::Value& propertyValue) const
 {
   // Create a new property
   Dali::Internal::OwnerPointer<PropertyBase> newProperty;
@@ -599,11 +752,13 @@ Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Prop
     const PropertyBase* property = newProperty.Get();
     if(index >= PROPERTY_CUSTOM_START_INDEX)
     {
-      mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
+      DALI_ASSERT_ALWAYS( index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered" );
+
+      mCustomProperties.PushBack( new CustomPropertyMetadata( name, key, propertyValue, property ) );
     }
     else
     {
-      mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, Property::INVALID_COMPONENT_INDEX, propertyValue.GetType(), property ) ); // base property
+      mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, propertyValue, property ) );
     }
 
     // queue a message to add the property
@@ -622,29 +777,72 @@ Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Prop
   }
 }
 
-Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue)
+Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
 {
-  Property::Index index = RegisterSceneGraphProperty(name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue);
+  return RegisterProperty( name, Property::INVALID_KEY, propertyValue, Property::ANIMATABLE );
+}
 
-  /// @todo: don't keep a table of mappings per handle.
-  AddUniformMapping(index, name);
+Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue )
+{
+  return RegisterProperty( name, key, propertyValue, Property::ANIMATABLE );
+}
 
-  return index;
+Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
+{
+  return RegisterProperty( name, Property::INVALID_KEY, propertyValue, accessMode );
 }
 
-Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode)
+Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue, Property::AccessMode accessMode )
 {
+  // If property with the required key already exists, then just set it.
   Property::Index index = Property::INVALID_INDEX;
+  if( key != Property::INVALID_KEY ) // Try integer key first if it's valid
+  {
+    index = GetPropertyIndex( key );
+  }
+  if( index == Property::INVALID_INDEX ) // If it wasn't valid, or doesn't exist, try name
+  {
+    index = GetPropertyIndex( name );
+  }
 
-  if(Property::ANIMATABLE == accessMode)
+  if( index != Property::INVALID_INDEX ) // If there was a valid index found by either key, set it.
   {
-    index = RegisterProperty(name, propertyValue);
+    SetProperty( index, propertyValue );
   }
   else
   {
-    // Add entry to the property lookup
-    index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
-    mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue, accessMode ) );
+    // Otherwise register the property
+
+    if( Property::ANIMATABLE == accessMode )
+    {
+      index = RegisterSceneGraphProperty( name, key, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue );
+      AddUniformMapping( index, name );
+    }
+    else
+    {
+      // Add entry to the property lookup
+      index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
+
+      CustomPropertyMetadata* customProperty = new CustomPropertyMetadata( name, propertyValue, accessMode );
+
+      // Resolve index for the child property
+      Object* parent = GetParentObject();
+      if( parent )
+      {
+        const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
+        if( parentTypeInfo )
+        {
+          Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( name );
+          if( childPropertyIndex != Property::INVALID_INDEX )
+          {
+            customProperty->childPropertyIndex = childPropertyIndex;
+            index = childPropertyIndex;
+          }
+        }
+      }
+
+      mCustomProperties.PushBack( customProperty );
+    }
   }
 
   return index;
@@ -658,7 +856,7 @@ Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index
   {
     if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
     {
-      DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
+      DALI_ABORT( "Property notification added to event side only property." );
     }
     else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
     {
@@ -726,6 +924,32 @@ void Object::RemovePropertyNotifications()
   }
 }
 
+void Object::NotifyPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value )
+{
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    OnNotifyDefaultPropertyAnimation( animation, index, value );
+  }
+  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
+    if( animatableProperty )
+    {
+      // update the cached property value
+      animatableProperty->SetPropertyValue( value );
+    }
+  }
+  else
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if( custom && custom->IsAnimatable() )
+    {
+      // update the cached property value
+      custom->SetPropertyValue( value );
+    }
+  }
+}
+
 void Object::EnablePropertyNotifications()
 {
   if( mPropertyNotifications )
@@ -754,7 +978,7 @@ void Object::DisablePropertyNotifications()
   }
 }
 
-void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName )
+void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName ) const
 {
   // Get the address of the property if it's a scene property
   const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
@@ -778,8 +1002,6 @@ void Object::AddUniformMapping( Property::Index propertyIndex, const std::string
     }
   }
 
-  // @todo MESH_REWORK Store mappings for unstaged objects?
-
   if( propertyPtr != NULL )
   {
     const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
@@ -788,12 +1010,10 @@ void Object::AddUniformMapping( Property::Index propertyIndex, const std::string
     {
       SceneGraph::UniformPropertyMapping* map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
       // Message takes ownership of Uniform map (and will delete it after copy)
-      AddUniformMapMessage( GetEventThreadServices(), *sceneObject, map);
+      AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *sceneObject, map);
     }
     else
     {
-      // @todo MESH_REWORK FIXME Need to store something that can be sent to the scene
-      // object when staged.
       DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
     }
   }
@@ -805,7 +1025,7 @@ void Object::RemoveUniformMapping( const std::string& uniformName )
   RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
 }
 
-Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
+Property::Value Object::GetCurrentPropertyValue( const PropertyMetadata* entry ) const
 {
   Property::Value value;
 
@@ -813,17 +1033,17 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
   if( !entry->IsAnimatable() )
   {
-    value = entry->value;
+    value = entry->GetPropertyValue();
   }
   else
   {
     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
 
-    switch ( entry->type )
+    switch ( entry->GetType() )
     {
       case Property::BOOLEAN:
       {
-        const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<bool>* property = static_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         value = (*property)[ bufferIndex ];
@@ -832,7 +1052,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::INTEGER:
       {
-        const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<int>* property = static_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         value = (*property)[ bufferIndex ];
@@ -841,7 +1061,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::FLOAT:
       {
-        const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<float>* property = static_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         value = (*property)[ bufferIndex ];
@@ -850,7 +1070,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::VECTOR2:
       {
-        const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<Vector2>* property = static_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         if(entry->componentIndex == 0)
@@ -870,7 +1090,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::VECTOR3:
       {
-        const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<Vector3>* property = static_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         if(entry->componentIndex == 0)
@@ -894,7 +1114,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::VECTOR4:
       {
-        const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<Vector4>* property = static_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         if(entry->componentIndex == 0)
@@ -922,7 +1142,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::MATRIX:
       {
-        const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<Matrix>* property = static_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         value = (*property)[ bufferIndex ];
@@ -931,7 +1151,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::MATRIX3:
       {
-        const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<Matrix3>* property = static_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         value = (*property)[ bufferIndex ];
@@ -940,7 +1160,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::ROTATION:
       {
-        const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
+        const AnimatableProperty<Quaternion>* property = static_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
         DALI_ASSERT_DEBUG( NULL != property );
 
         value = (*property)[ bufferIndex ];
@@ -949,8 +1169,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       default:
       {
-        DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
-        break;
+        // unreachable code due to higher level logic
       }
     } // switch(type)
   } // if animatable
@@ -960,7 +1179,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
 void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
 {
-  switch ( entry.type )
+  switch ( entry.GetType() )
   {
     case Property::BOOLEAN:
     {
@@ -1213,12 +1432,26 @@ Object::~Object()
 CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
 {
   CustomPropertyMetadata* property( NULL );
-  int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
-  if( arrayIndex >= 0 )
+  if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
   {
-    if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
+    for ( std::size_t arrayIndex = 0; arrayIndex < mCustomProperties.Count(); arrayIndex++ )
     {
-      property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
+      CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( mCustomProperties[ arrayIndex ] );
+      if( custom->childPropertyIndex == index )
+      {
+        property = custom;
+      }
+    }
+  }
+  else
+  {
+    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 = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
+      }
     }
   }
   return property;
@@ -1244,34 +1477,39 @@ AnimatablePropertyMetadata* Object::RegisterAnimatableProperty(Property::Index i
 
   // check whether the animatable property is registered already, if not then register one.
   AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
-  if(!animatableProperty)
+  if( !animatableProperty )
   {
     const TypeInfo* typeInfo( GetTypeInfo() );
-    if (typeInfo)
+    if( typeInfo )
     {
       Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index);
-      if(basePropertyIndex == Property::INVALID_INDEX)
+      if( basePropertyIndex == Property::INVALID_INDEX )
       {
         // If the property is not a component of a base property, register the whole property itself.
-        index = RegisterSceneGraphProperty(typeInfo->GetPropertyName(index), index, Property::Value(typeInfo->GetPropertyType(index)));
+        const  std::string& propertyName = typeInfo->GetPropertyName(index);
+        RegisterSceneGraphProperty(propertyName, Property::INVALID_KEY, index, typeInfo->GetPropertyDefaultValue(index));
+        AddUniformMapping( index, propertyName );
       }
       else
       {
-        // Since the property is a component of a base property, check whether the base property is regsitered.
+        // Since the property is a component of a base property, check whether the base property is registered.
         animatableProperty = FindAnimatableProperty( basePropertyIndex );
-        if(!animatableProperty)
+        if( !animatableProperty )
         {
           // If the base property is not registered yet, register the base property first.
-          if(Property::INVALID_INDEX != RegisterSceneGraphProperty(typeInfo->GetPropertyName(basePropertyIndex), basePropertyIndex, Property::Value(typeInfo->GetPropertyType(basePropertyIndex))))
+          const  std::string& basePropertyName = typeInfo->GetPropertyName(basePropertyIndex);
+
+          if( Property::INVALID_INDEX != RegisterSceneGraphProperty( basePropertyName, Property::INVALID_KEY, basePropertyIndex, typeInfo->GetPropertyDefaultValue( basePropertyIndex ) ) )
           {
             animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
+            AddUniformMapping( basePropertyIndex, basePropertyName );
           }
         }
 
         if(animatableProperty)
         {
           // Create the metadata for the property component.
-          mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->type, animatableProperty->GetSceneGraphProperty() ) );
+          mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->value, animatableProperty->GetSceneGraphProperty() ) );
         }
       }
 
@@ -1283,6 +1521,42 @@ AnimatablePropertyMetadata* Object::RegisterAnimatableProperty(Property::Index i
   return animatableProperty;
 }
 
+void Object::ResolveChildProperties()
+{
+  // Resolve index for the child property
+  Object* parent = GetParentObject();
+  if( parent )
+  {
+    const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
+    if( parentTypeInfo )
+    {
+      // Go through each custom property
+      for ( int arrayIndex = 0; arrayIndex < (int)mCustomProperties.Count(); arrayIndex++ )
+      {
+        CustomPropertyMetadata* customProperty = static_cast<CustomPropertyMetadata*>( mCustomProperties[ arrayIndex ] );
+
+        if( customProperty->name == "" )
+        {
+          if( customProperty->childPropertyIndex != Property::INVALID_INDEX )
+          {
+            // Resolve name for any child property with no name
+            customProperty->name = parentTypeInfo->GetChildPropertyName( customProperty->childPropertyIndex );
+          }
+        }
+        else
+        {
+          Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( customProperty->name );
+          if( childPropertyIndex != Property::INVALID_INDEX )
+          {
+            // Resolve index for any property with a name that matches the parent's child property name
+            customProperty->childPropertyIndex = childPropertyIndex;
+          }
+        }
+      }
+    }
+  }
+}
+
 } // namespace Internal
 
 } // namespace Dali