Harmonize Animation API parameter checking and add test cases for them
[platform/core/uifw/dali-core.git] / dali / internal / event / common / object-impl.cpp
index b384b8b..5e68a6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
 
 // INTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <dali/devel-api/object/handle-devel.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/update/common/uniform-map.h>
 #include <dali/internal/event/animation/constraint-impl.h>
-#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/property-helper.h>
 #include <dali/internal/event/common/property-notification-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
 #include <dali/internal/event/common/type-registry-impl.h>
 
 using Dali::Internal::SceneGraph::AnimatableProperty;
@@ -44,13 +46,12 @@ namespace Internal
 namespace // unnamed namespace
 {
 const int SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES;  // Object provides this capability
-typedef Dali::Vector<Object::Observer*>::Iterator ObserverIter;
-typedef Dali::Vector<Object::Observer*>::ConstIterator ConstObserverIter;
 
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" );
 #endif
 
+constexpr Property::Index MAX_PER_CLASS_PROPERTY_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX;
 
 } // unnamed namespace
 
@@ -74,8 +75,8 @@ void Object::AddObserver(Observer& observer)
 void Object::RemoveObserver(Observer& observer)
 {
   // Find the observer...
-  const ConstObserverIter endIter =  mObservers.End();
-  for( ObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  const auto endIter =  mObservers.End();
+  for( auto iter = mObservers.Begin(); iter != endIter; ++iter)
   {
     if( (*iter) == &observer)
     {
@@ -86,70 +87,23 @@ void Object::RemoveObserver(Observer& observer)
   DALI_ASSERT_DEBUG(endIter != mObservers.End());
 }
 
-void Object::OnSceneObjectAdd()
-{
-  // Notification for observers
-  for( ConstObserverIter iter = mObservers.Begin(),  endIter =  mObservers.End(); iter != endIter; ++iter)
-  {
-    (*iter)->SceneObjectAdded(*this);
-  }
-
-  // enable property notifications in scene graph
-  EnablePropertyNotifications();
-}
-
-void Object::OnSceneObjectRemove()
-{
-  // Notification for observers
-  for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
-  {
-    (*iter)->SceneObjectRemoved(*this);
-  }
-
-  // disable property notifications in scene graph
-  DisablePropertyNotifications();
-}
-
-int Object::GetPropertyComponentIndex( Property::Index index ) const
-{
-  int componentIndex = Property::INVALID_COMPONENT_INDEX;
-
-  const TypeInfo* typeInfo( GetTypeInfo() );
-  if ( typeInfo )
-  {
-    componentIndex = typeInfo->GetComponentIndex(index);
-  }
-
-  // For animatable property, check whether it is registered already and register it if not yet.
-  if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) && ( NULL == RegisterAnimatableProperty(index) ) )
-  {
-    componentIndex = Property::INVALID_COMPONENT_INDEX;
-  }
-
-  return componentIndex;
-}
-
 bool Object::Supports( Capability capability ) const
 {
   return (capability & SUPPORTED_CAPABILITIES);
 }
 
-unsigned int Object::GetPropertyCount() const
+uint32_t Object::GetPropertyCount() const
 {
-  unsigned int count = GetDefaultPropertyCount();
-
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Default Properties: %d\n", count );
-
+  uint32_t count = 0u;
   const TypeInfo* typeInfo( GetTypeInfo() );
   if ( typeInfo )
   {
-    unsigned int manual( typeInfo->GetPropertyCount() );
-    count += manual;
+    count = typeInfo->GetPropertyCount();
 
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties:  %d\n", manual );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Registered Properties:  %d\n", count );
   }
 
-  unsigned int custom( mCustomProperties.Count() );
+  uint32_t custom = static_cast<uint32_t>( mCustomProperties.Count() );
   count += custom;
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties:  %d\n", custom );
 
@@ -162,64 +116,77 @@ std::string Object::GetPropertyName( Property::Index index ) const
 {
   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
 
-  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
-  {
-    return GetDefaultPropertyName( index );
-  }
-
-  if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
-    || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
+  // is this a per class or per instance property
+  if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
   {
     const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       return typeInfo->GetPropertyName( index );
     }
-    else
+  }
+  else // child property or custom property
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if( custom )
     {
-      DALI_ASSERT_ALWAYS( ! "Property index is invalid" );
+      return custom->name;
     }
   }
 
-  CustomPropertyMetadata* custom = FindCustomProperty( index );
-  if( custom )
-  {
-    return custom->name;
-  }
-  return "";
+  DALI_LOG_ERROR( "Property index %d not found\n", index );
+  return std::string();
 }
 
-Property::Index Object::GetPropertyIndex(const std::string& name) const
+Property::Index Object::GetPropertyIndex( const std::string& name ) const
 {
-  Property::Index index = GetDefaultPropertyIndex( name );
+  Property::Index index = Property::INVALID_INDEX;
 
-  if(index == Property::INVALID_INDEX)
+  const TypeInfo* typeInfo( GetTypeInfo() );
+  if ( typeInfo )
   {
-    const TypeInfo* typeInfo( GetTypeInfo() );
-    if ( typeInfo )
+    index = typeInfo->GetPropertyIndex( name );
+  }
+  if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) )
+  {
+    Property::Index count = PROPERTY_CUSTOM_START_INDEX;
+    const auto end = mCustomProperties.End();
+    for( auto iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
     {
-      index = typeInfo->GetPropertyIndex( name );
-      if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+      CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
+      if ( custom->name == name )
       {
-        // check whether the animatable property is registered already, if not then register one.
-        if ( NULL == RegisterAnimatableProperty(index) )
+        if ( custom->childPropertyIndex != Property::INVALID_INDEX )
         {
-          index = Property::INVALID_INDEX;
+          // If it is a child property, return the child property index
+          index = custom->childPropertyIndex;
+        }
+        else
+        {
+          index = count;
         }
+        break;
       }
     }
   }
 
-  if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) )
+  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 )
+    const auto end = mCustomProperties.End();
+    for( auto iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
     {
       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
-      if ( custom->name == name )
+      if( custom->key == key )
       {
-        if ( custom->childPropertyIndex != Property::INVALID_INDEX )
+        if( custom->childPropertyIndex != Property::INVALID_INDEX )
         {
           // If it is a child property, return the child property index
           index = custom->childPropertyIndex;
@@ -236,32 +203,34 @@ 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");
 
   bool writable = false;
 
-  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
-  {
-    writable = IsDefaultPropertyWritable( index );
-  }
-  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+  // is this a per class or per instance property
+  if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
   {
     const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       writable = typeInfo->IsPropertyWritable( index );
     }
-    else
-    {
-      DALI_ASSERT_ALWAYS( ! "Invalid property index" );
-    }
-  }
-  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
-  {
-    // Type Registry scene-graph properties are writable.
-    writable = true;
   }
   else
   {
@@ -281,19 +250,14 @@ bool Object::IsPropertyAnimatable( Property::Index index ) const
 
   bool animatable = false;
 
-  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
-  {
-    animatable = IsDefaultPropertyAnimatable( index );
-  }
-  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
-  {
-    // Type Registry event-thread only properties are not animatable.
-    animatable = false;
-  }
-  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  // is this a per class or per instance property
+  if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
   {
-    // Type Registry scene-graph properties are animatable.
-    animatable = true;
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      animatable = typeInfo->IsPropertyAnimatable( index );
+    }
   }
   else
   {
@@ -313,19 +277,14 @@ bool Object::IsPropertyAConstraintInput( Property::Index index ) const
 
   bool isConstraintInput = false;
 
-  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
-  {
-    isConstraintInput = IsDefaultPropertyAConstraintInput( index );
-  }
-  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
-  {
-    // Type Registry event-thread only properties cannot be used as an input to a constraint.
-    isConstraintInput = false;
-  }
-  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  // is this a per class or per instance property
+  if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
   {
-    // scene graph properties can be used as input to a constraint.
-    isConstraintInput = true;
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      isConstraintInput = typeInfo->IsPropertyAConstraintInput( index );
+    }
   }
   else
   {
@@ -344,23 +303,14 @@ Property::Type Object::GetPropertyType( Property::Index index ) const
 {
   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
 
-  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
-  {
-    return GetDefaultPropertyType( index );
-  }
-
-  if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
-    || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
+  // is this a per class or per instance property
+  if ( index < MAX_PER_CLASS_PROPERTY_INDEX )
   {
     const TypeInfo* typeInfo( GetTypeInfo() );
     if ( typeInfo )
     {
       return typeInfo->GetPropertyType( index );
     }
-    else
-    {
-      DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
-    }
   }
 
   CustomPropertyMetadata* custom = FindCustomProperty( index );
@@ -391,21 +341,26 @@ void Object::SetProperty( Property::Index index, const Property::Value& property
     }
     else
     {
-      DALI_LOG_ERROR("Cannot find property index\n");
+      // cannot register this property as there is no setter for it.
+      // event side properties must have a setter for now so need to be registered
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
       propertySet = false;
     }
   }
   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)
+    AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, &propertyValue );
+    if( !animatableProperty )
     {
-      DALI_LOG_ERROR("Cannot find property index\n");
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
       propertySet = false;
     }
     else
     {
+      // update the cached property value
+      animatableProperty->SetPropertyValue( propertyValue );
+
       // set the scene graph property value
       SetSceneGraphProperty( index, *animatableProperty, propertyValue );
     }
@@ -441,12 +396,16 @@ void Object::SetProperty( Property::Index index, const Property::Value& property
     {
       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
       {
@@ -456,7 +415,7 @@ void Object::SetProperty( Property::Index index, const Property::Value& property
     }
     else
     {
-      DALI_LOG_ERROR("Invalid property index\n");
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
       propertySet = false;
     }
   }
@@ -465,7 +424,9 @@ void Object::SetProperty( Property::Index index, const Property::Value& property
   // 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
   if ( propertySet )
   {
-    OnPropertySet(index, propertyValue);
+    OnPropertySet( index, propertyValue );
+    Dali::Handle handle( this );
+    mPropertySetSignal.Emit( handle, index, propertyValue );
   }
 }
 
@@ -488,21 +449,76 @@ Property::Value Object::GetProperty(Property::Index index) const
     }
     else
     {
-      DALI_LOG_ERROR("Cannot find property index\n");
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
     }
   }
   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)
+         // this is needed because property value may have been set as full property and get as a property component
+    AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, nullptr );
+    if( animatableProperty )
+    {
+      // get the cached animatable property value
+      value = animatableProperty->GetPropertyValue();
+    }
+    else
+    {
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
+    }
+  }
+  else if(mCustomProperties.Count() > 0)
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if(custom)
+    {
+      // get the cached custom property value
+      value = custom->GetPropertyValue();
+    }
+    else
+    {
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
+    }
+  } // 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 )
     {
-      DALI_LOG_ERROR("Cannot find property index\n");
+      value = typeInfo->GetProperty( this, index );
     }
     else
     {
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
+    }
+  }
+  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.
+         // this is needed because property value may have been set as full property and get as a property component
+    AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, nullptr );
+    if( animatableProperty )
+    {
       // get the animatable property value
-      value = GetPropertyValue( animatableProperty );
+      value = GetCurrentPropertyValue( *animatableProperty );
+    }
+    else
+    {
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
     }
   }
   else if(mCustomProperties.Count() > 0)
@@ -511,11 +527,11 @@ Property::Value Object::GetProperty(Property::Index index) const
     if(custom)
     {
       // get the custom property value
-      value = GetPropertyValue( custom );
+      value = GetCurrentPropertyValue( *custom );
     }
     else
     {
-      DALI_LOG_ERROR("Invalid property index\n");
+      DALI_LOG_ERROR( "Property index %d not found\n", index );
     }
   } // if custom
 
@@ -526,9 +542,6 @@ void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
 {
   indices.Clear();
 
-  // Default Properties
-  GetDefaultPropertyIndices( indices );
-
   // Manual Properties
   const TypeInfo* typeInfo( GetTypeInfo() );
   if ( typeInfo )
@@ -541,9 +554,9 @@ void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
   {
     indices.Reserve( indices.Size() + mCustomProperties.Count() );
 
-    PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin();
-    const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End();
-    int i=0;
+    auto iter = mCustomProperties.Begin();
+    const auto endIter = mCustomProperties.End();
+    int32_t i = 0;
     for ( ; iter != endIter; ++iter, ++i )
     {
       CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( *iter );
@@ -560,41 +573,473 @@ void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
   }
 }
 
-Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
+Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
 {
-  // Create a new property
-  Dali::Internal::OwnerPointer<PropertyBase> newProperty;
+  return RegisterProperty( name, Property::INVALID_KEY, propertyValue, Property::ANIMATABLE );
+}
 
-  switch ( propertyValue.GetType() )
+Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue )
+{
+  return RegisterProperty( name, key, propertyValue, Property::ANIMATABLE );
+}
+
+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, 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
   {
-    case Property::BOOLEAN:
+    index = GetPropertyIndex( key );
+  }
+  if( index == Property::INVALID_INDEX ) // If it wasn't valid, or doesn't exist, try name
+  {
+    index = GetPropertyIndex( name );
+  }
+
+  if( index != Property::INVALID_INDEX ) // If there was a valid index found by either key, set it.
+  {
+    SetProperty( index, propertyValue );
+  }
+  else
+  {
+    // Otherwise register the property
+
+    if( Property::ANIMATABLE == accessMode )
     {
-      newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
-      break;
+      index = RegisterSceneGraphProperty( name, key, PROPERTY_CUSTOM_START_INDEX + static_cast<Property::Index>( mCustomProperties.Count() ), propertyValue );
+      AddUniformMapping( index, name );
     }
-
-    case Property::INTEGER:
+    else
     {
-      newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
-      break;
+      // Add entry to the property lookup
+      index = PROPERTY_CUSTOM_START_INDEX + static_cast<Property::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 );
     }
+  }
 
-    case Property::FLOAT:
+  return index;
+}
+
+bool Object::DoesCustomPropertyExist( Property::Index index )
+{
+  auto metadata = FindCustomProperty( index );
+  return metadata != nullptr;
+}
+
+Dali::PropertyNotification Object::AddPropertyNotification( Property::Index index,
+                                                            int32_t componentIndex,
+                                                            const Dali::PropertyCondition& condition)
+{
+  if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
     {
-      newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
-      break;
+      DALI_ABORT( "Property notification added to event side only property." );
     }
-
-    case Property::VECTOR2:
+    else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
     {
-      newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
-      break;
+      // check whether the animatable property is registered already, if not then register one.
+      AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty( index, nullptr );
+      DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
     }
-
-    case Property::VECTOR3:
+    else if ( mCustomProperties.Count() > 0 )
     {
-      newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
-      break;
+      CustomPropertyMetadata* custom = FindCustomProperty( index );
+      DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
+      DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
+    }
+  }
+
+  Dali::Handle self(this);
+  Property target( self, index );
+
+  PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
+  Dali::PropertyNotification propertyNotification(internal.Get());
+
+  if( !mPropertyNotifications )
+  {
+    mPropertyNotifications = new PropertyNotificationContainer;
+  }
+  mPropertyNotifications->push_back(propertyNotification);
+
+  return propertyNotification;
+}
+
+void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
+{
+  if( mPropertyNotifications )
+  {
+    auto iter = mPropertyNotifications->begin();
+    while(iter != mPropertyNotifications->end() )
+    {
+      if(*iter == propertyNotification)
+      {
+        mPropertyNotifications->erase(iter);
+        // As we can't ensure all references are removed, we can just disable
+        // the notification.
+        GetImplementation(propertyNotification).Disable();
+        return;
+      }
+      ++iter;
+    }
+  }
+}
+
+void Object::RemovePropertyNotifications()
+{
+  if( mPropertyNotifications )
+  {
+    auto iter = mPropertyNotifications->begin();
+    while(iter != mPropertyNotifications->end() )
+    {
+      // As we can't ensure all references are removed, we can just disable
+      // the notification.
+      GetImplementation(*iter).Disable();
+      ++iter;
+    }
+
+    mPropertyNotifications->clear();
+  }
+}
+
+void Object::NotifyPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
+{
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    OnNotifyDefaultPropertyAnimation( animation, index, value, animationType );
+  }
+  else
+  {
+    PropertyMetadata* propertyMetadata = NULL;
+    if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+    {
+      propertyMetadata = FindAnimatableProperty( index );
+    }
+    else
+    {
+      CustomPropertyMetadata* custom = FindCustomProperty( index );
+      if( custom && custom->IsAnimatable() )
+      {
+        propertyMetadata = custom;
+      }
+    }
+
+    if( propertyMetadata )
+    {
+      switch( animationType )
+      {
+        case Animation::TO:
+        case Animation::BETWEEN:
+        {
+          // Update the cached property value
+          propertyMetadata->SetPropertyValue( value );
+          break;
+        }
+        case Animation::BY:
+        {
+          // Adjust the cached property value
+          propertyMetadata->AdjustPropertyValueBy( value );
+          break;
+        }
+      }
+    }
+  }
+}
+
+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 );
+
+  // Check instead for newly registered properties
+  if( propertyPtr == NULL )
+  {
+    PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
+    if( animatable != NULL )
+    {
+      propertyPtr = animatable->GetSceneGraphProperty();
+    }
+  }
+
+  if( propertyPtr == NULL )
+  {
+    PropertyMetadata* custom = FindCustomProperty( propertyIndex );
+    if( custom != NULL )
+    {
+      propertyPtr = custom->GetSceneGraphProperty();
+    }
+  }
+
+  if( propertyPtr != NULL )
+  {
+    const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
+
+    if( sceneObject != NULL )
+    {
+      OwnerPointer< SceneGraph::UniformPropertyMapping > map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
+      // Message takes ownership of Uniform map (and will delete it after copy)
+      AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *sceneObject, map );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
+    }
+  }
+}
+
+void Object::RemoveUniformMapping( const std::string& uniformName )
+{
+  const SceneGraph::PropertyOwner* sceneObject = GetSceneObject();
+  RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
+}
+
+void Object::ApplyConstraint( ConstraintBase& constraint )
+{
+  if( !mConstraints )
+  {
+    mConstraints = new ConstraintContainer;
+  }
+  mConstraints->push_back( Dali::Constraint( &constraint ) );
+}
+
+void Object::RemoveConstraint( ConstraintBase& constraint )
+{
+  // NULL if the Constraint sources are destroyed before Constraint::Apply()
+  if( mConstraints )
+  {
+    ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
+    if( it != mConstraints->end() )
+    {
+      mConstraints->erase( it );
+    }
+  }
+}
+
+void Object::RemoveConstraints()
+{
+  // guard against constraint sending messages during core destruction
+  if( mConstraints && Stage::IsInstalled() )
+  {
+    // If we have nothing in the scene-graph, just clear constraint containers
+    const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
+    if ( NULL != propertyOwner )
+    {
+      const auto endIter = mConstraints->end();
+      for ( auto iter = mConstraints->begin(); endIter != iter; ++iter )
+      {
+        GetImplementation( *iter ).RemoveInternal();
+      }
+    }
+
+    delete mConstraints;
+    mConstraints = NULL;
+  }
+}
+
+void Object::RemoveConstraints( uint32_t tag )
+{
+  // guard against constraint sending messages during core destruction
+  if( mConstraints && Stage::IsInstalled() )
+  {
+    auto iter( mConstraints->begin() );
+    while(iter != mConstraints->end() )
+    {
+      ConstraintBase& constraint = GetImplementation( *iter );
+      if( constraint.GetTag() == tag )
+      {
+        GetImplementation( *iter ).RemoveInternal();
+        iter = mConstraints->erase( iter );
+      }
+      else
+      {
+        ++iter;
+      }
+    }
+
+    if ( mConstraints->empty() )
+    {
+      delete mConstraints;
+      mConstraints = NULL;
+    }
+  }
+}
+
+void Object::SetTypeInfo( const TypeInfo* typeInfo )
+{
+  mTypeInfo = typeInfo;
+}
+
+int32_t Object::GetPropertyComponentIndex( Property::Index index ) const
+{
+  int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
+
+  const TypeInfo* typeInfo( GetTypeInfo() );
+  if ( typeInfo )
+  {
+    componentIndex = typeInfo->GetComponentIndex(index);
+  }
+
+  return componentIndex;
+}
+
+DevelHandle::PropertySetSignalType& Object::PropertySetSignal()
+{
+  return mPropertySetSignal;
+}
+
+Object::~Object()
+{
+  // Notification for observers
+  for( auto iter = mObservers.Begin(), endIter =  mObservers.End(); iter != endIter; ++iter)
+  {
+    (*iter)->ObjectDestroyed(*this);
+  }
+
+  delete mConstraints;
+  delete mPropertyNotifications;
+}
+
+void Object::OnSceneObjectAdd()
+{
+  // Notification for observers
+  for( auto iter = mObservers.Begin(), endIter =  mObservers.End(); iter != endIter; ++iter)
+  {
+    (*iter)->SceneObjectAdded(*this);
+  }
+
+  // enable property notifications in scene graph
+  EnablePropertyNotifications();
+}
+
+void Object::OnSceneObjectRemove()
+{
+  // Notification for observers
+  for( auto iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
+  {
+    (*iter)->SceneObjectRemoved(*this);
+  }
+
+  // disable property notifications in scene graph
+  DisablePropertyNotifications();
+}
+
+const TypeInfo* Object::GetTypeInfo() const
+{
+  if ( !mTypeInfo )
+  {
+    // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
+    // especially as the type-info does not change during the life-time of an application
+
+    TypeRegistry::TypeInfoPointer typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
+    if ( typeInfoHandle )
+    {
+      mTypeInfo = typeInfoHandle.Get(); // just a raw pointer to use, ownership is kept
+    }
+  }
+
+  return mTypeInfo;
+}
+
+CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
+{
+  CustomPropertyMetadata* property( NULL );
+  if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    for ( std::size_t arrayIndex = 0; arrayIndex < mCustomProperties.Count(); 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 < static_cast<int>( mCustomProperties.Count() ) ) // we can only access the first 2 billion custom properties
+      {
+        property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
+      }
+    }
+  }
+  return property;
+}
+
+AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
+{
+  for( auto&& entry : mAnimatableProperties )
+  {
+    AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( entry );
+    if( property->index == index )
+    {
+      return property;
+    }
+  }
+  return NULL;
+}
+
+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;
+
+  switch ( propertyValue.GetType() )
+  {
+    case Property::BOOLEAN:
+    {
+      newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
+      break;
+    }
+
+    case Property::INTEGER:
+    {
+      newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
+      break;
+    }
+
+    case Property::FLOAT:
+    {
+      newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
+      break;
+    }
+
+    case Property::VECTOR2:
+    {
+      newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
+      break;
+    }
+
+    case Property::VECTOR3:
+    {
+      newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
+      break;
     }
 
     case Property::VECTOR4:
@@ -625,9 +1070,10 @@ Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Prop
     case Property::STRING:
     case Property::ARRAY:
     case Property::MAP:
+    case Property::EXTENTS:
     case Property::NONE:
     {
-      DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
+      DALI_ASSERT_ALWAYS( !"Property type is not animatable" );
       break;
     }
   }
@@ -641,19 +1087,17 @@ 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
-    InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
-
-    // 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 );
+    InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty ); // Message takes ownership
 
     return index;
   }
@@ -664,131 +1108,101 @@ Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Prop
   }
 }
 
-Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
+void Object::RegisterAnimatableProperty( const TypeInfo& typeInfo,
+                                          Property::Index index,
+                                          const Property::Value* value ) const
 {
-  return RegisterProperty( name, propertyValue, Property::ANIMATABLE );
-}
-
-Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
-{
-  // If property with the required name already exists, then just set it.
-  Property::Index index = GetPropertyIndex( name );
-  if( index != Property::INVALID_INDEX )
+  // If the property is not a component of a base property, register the whole property itself.
+  const std::string& propertyName = typeInfo.GetPropertyName( index );
+  Property::Value initialValue;
+  if( value )
   {
-    SetProperty( index, propertyValue );
+    initialValue = *value;
   }
   else
   {
-    // Otherwise register the property
-
-    if(Property::ANIMATABLE == accessMode)
+    initialValue = typeInfo.GetPropertyDefaultValue( index ); // recurses type hierarchy
+    if( Property::NONE == initialValue.GetType() )
     {
-      index = RegisterSceneGraphProperty( name, 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 );
+      initialValue = Property::Value( typeInfo.GetPropertyType( index ) ); // recurses type hierarchy
     }
   }
-
-  return index;
+  RegisterSceneGraphProperty( propertyName, Property::INVALID_KEY, index, initialValue );
+  AddUniformMapping( index, propertyName );
 }
 
-Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index,
-                                                                int componentIndex,
-                                                                const Dali::PropertyCondition& condition)
+AnimatablePropertyMetadata* Object::GetSceneAnimatableProperty( Property::Index index, const Property::Value* value ) const
 {
-  if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
+  // property range already checked by calling methods
+  // check whether the animatable property is registered already, if not then register one.
+  AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
+  if( !animatableProperty )
   {
-    if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
-    {
-      DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
-    }
-    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* animatable = RegisterAnimatableProperty( index );
-      DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
-    }
-    else if ( mCustomProperties.Count() > 0 )
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if( typeInfo )
     {
-      CustomPropertyMetadata* custom = FindCustomProperty( index );
-      DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
-      DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
-    }
-  }
-
-  Dali::Handle self(this);
-  Property target( self, index );
+      Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex( index );
+      if( basePropertyIndex == Property::INVALID_INDEX )
+      {
+        // If the property is not a component of a base property, register the whole property itself.
+        RegisterAnimatableProperty( *typeInfo, index, value );
+      }
+      else
+      {
+        // Since the property is a component of a base property, check whether the base property is registered.
+        animatableProperty = FindAnimatableProperty( basePropertyIndex );
+        if( !animatableProperty )
+        {
+          // If the base property is not registered yet, register the base property first.
+          RegisterAnimatableProperty( *typeInfo, basePropertyIndex, value );
+          animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
+        }
 
-  PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
-  Dali::PropertyNotification propertyNotification(internal.Get());
+        // Create the metadata for the property component.
+        mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->value, animatableProperty->GetSceneGraphProperty() ) );
+      }
 
-  if( !mPropertyNotifications )
-  {
-    mPropertyNotifications = new PropertyNotificationContainer;
+      // The metadata has just been added and therefore should be in the end of the vector.
+      animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
+    }
   }
-  mPropertyNotifications->push_back(propertyNotification);
 
-  return propertyNotification;
+  return animatableProperty;
 }
 
-void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
+void Object::ResolveChildProperties()
 {
-  if( mPropertyNotifications )
+  // Resolve index for the child property
+  Object* parent = GetParentObject();
+  if( parent )
   {
-    PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
-    while(iter != mPropertyNotifications->end() )
+    const TypeInfo* parentTypeInfo( parent->GetTypeInfo() );
+    if( parentTypeInfo )
     {
-      if(*iter == propertyNotification)
+      // Go through each custom property
+      for( auto&& entry : mCustomProperties )
       {
-        mPropertyNotifications->erase(iter);
-        // As we can't ensure all references are removed, we can just disable
-        // the notification.
-        GetImplementation(propertyNotification).Disable();
-        return;
-      }
-      ++iter;
-    }
-  }
-}
+        CustomPropertyMetadata* customProperty = static_cast<CustomPropertyMetadata*>( entry );
 
-void Object::RemovePropertyNotifications()
-{
-  if( mPropertyNotifications )
-  {
-    PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
-    while(iter != mPropertyNotifications->end() )
-    {
-      // As we can't ensure all references are removed, we can just disable
-      // the notification.
-      GetImplementation(*iter).Disable();
-      ++iter;
+        if( customProperty->name.empty() )
+        {
+          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;
+          }
+        }
+      }
     }
-
-    mPropertyNotifications->clear();
   }
 }
 
@@ -796,12 +1210,9 @@ void Object::EnablePropertyNotifications()
 {
   if( mPropertyNotifications )
   {
-    PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
-    PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
-
-    for( ; iter != endIter; ++iter )
+    for( auto&& element : *mPropertyNotifications )
     {
-      GetImplementation(*iter).Enable();
+      GetImplementation( element ).Enable();
     }
   }
 }
@@ -810,82 +1221,30 @@ void Object::DisablePropertyNotifications()
 {
   if( mPropertyNotifications )
   {
-    PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
-    PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
-
-    for( ; iter != endIter; ++iter )
-    {
-      GetImplementation(*iter).Disable();
-    }
-  }
-}
-
-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 );
-
-  // Check instead for newly registered properties
-  if( propertyPtr == NULL )
-  {
-    PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
-    if( animatable != NULL )
-    {
-      propertyPtr = animatable->GetSceneGraphProperty();
-    }
-  }
-
-  if( propertyPtr == NULL )
-  {
-    PropertyMetadata* custom = FindCustomProperty( propertyIndex );
-    if( custom != NULL )
-    {
-      propertyPtr = custom->GetSceneGraphProperty();
-    }
-  }
-
-  if( propertyPtr != NULL )
-  {
-    const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
-
-    if( sceneObject != NULL )
-    {
-      SceneGraph::UniformPropertyMapping* map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
-      // Message takes ownership of Uniform map (and will delete it after copy)
-      AddUniformMapMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *sceneObject, map);
-    }
-    else
+    for( auto&& element : *mPropertyNotifications )
     {
-      DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
+      GetImplementation( element ).Disable();
     }
   }
 }
 
-void Object::RemoveUniformMapping( const std::string& uniformName )
-{
-  const SceneGraph::PropertyOwner* sceneObject = GetSceneObject();
-  RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
-}
-
-Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
+Property::Value Object::GetCurrentPropertyValue( const PropertyMetadata& entry ) const
 {
   Property::Value value;
 
-  DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" );
-
-  if( !entry->IsAnimatable() )
+  if( !entry.IsAnimatable() )
   {
-    value = entry->value;
+    value = entry.GetPropertyValue();
   }
   else
   {
     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
 
-    switch ( entry->GetType() )
+    switch ( entry.GetType() )
     {
       case Property::BOOLEAN:
       {
-        const AnimatableProperty<bool>* property = static_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 ];
@@ -894,7 +1253,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::INTEGER:
       {
-        const AnimatableProperty<int>* property = static_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 ];
@@ -903,7 +1262,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::FLOAT:
       {
-        const AnimatableProperty<float>* property = static_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 ];
@@ -912,14 +1271,14 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::VECTOR2:
       {
-        const AnimatableProperty<Vector2>* property = static_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)
+        if(entry.componentIndex == 0)
         {
           value = (*property)[ bufferIndex ].x;
         }
-        else if(entry->componentIndex == 1)
+        else if(entry.componentIndex == 1)
         {
           value = (*property)[ bufferIndex ].y;
         }
@@ -932,18 +1291,18 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::VECTOR3:
       {
-        const AnimatableProperty<Vector3>* property = static_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)
+        if(entry.componentIndex == 0)
         {
           value = (*property)[ bufferIndex ].x;
         }
-        else if(entry->componentIndex == 1)
+        else if(entry.componentIndex == 1)
         {
           value = (*property)[ bufferIndex ].y;
         }
-        else if(entry->componentIndex == 2)
+        else if(entry.componentIndex == 2)
         {
           value = (*property)[ bufferIndex ].z;
         }
@@ -956,22 +1315,22 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::VECTOR4:
       {
-        const AnimatableProperty<Vector4>* property = static_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)
+        if(entry.componentIndex == 0)
         {
           value = (*property)[ bufferIndex ].x;
         }
-        else if(entry->componentIndex == 1)
+        else if(entry.componentIndex == 1)
         {
           value = (*property)[ bufferIndex ].y;
         }
-        else if(entry->componentIndex == 2)
+        else if(entry.componentIndex == 2)
         {
           value = (*property)[ bufferIndex ].z;
         }
-        else if(entry->componentIndex == 3)
+        else if(entry.componentIndex == 3)
         {
           value = (*property)[ bufferIndex ].w;
         }
@@ -984,7 +1343,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::MATRIX:
       {
-        const AnimatableProperty<Matrix>* property = static_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 ];
@@ -993,7 +1352,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::MATRIX3:
       {
-        const AnimatableProperty<Matrix3>* property = static_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 ];
@@ -1002,7 +1361,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
 
       case Property::ROTATION:
       {
-        const AnimatableProperty<Quaternion>* property = static_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 ];
@@ -1011,8 +1370,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
@@ -1167,239 +1525,6 @@ void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadat
   }
 }
 
-const TypeInfo* Object::GetTypeInfo() const
-{
-  if ( !mTypeInfo )
-  {
-    // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
-    // especially as the type-info does not change during the life-time of an application
-
-    Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
-    if ( typeInfoHandle )
-    {
-      mTypeInfo = &GetImplementation( typeInfoHandle );
-    }
-  }
-
-  return mTypeInfo;
-}
-
-void Object::ApplyConstraint( ConstraintBase& constraint )
-{
-  if( !mConstraints )
-  {
-    mConstraints = new ConstraintContainer;
-  }
-  mConstraints->push_back( Dali::Constraint( &constraint ) );
-}
-
-void Object::RemoveConstraint( ConstraintBase& constraint )
-{
-  // NULL if the Constraint sources are destroyed before Constraint::Apply()
-  if( mConstraints )
-  {
-    ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
-    if( it != mConstraints->end() )
-    {
-      mConstraints->erase( it );
-    }
-  }
-}
-
-void Object::RemoveConstraints()
-{
-  // guard against constraint sending messages during core destruction
-  if( mConstraints && Stage::IsInstalled() )
-  {
-    // If we have nothing in the scene-graph, just clear constraint containers
-    const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
-    if ( NULL != propertyOwner )
-    {
-      const ConstraintConstIter endIter = mConstraints->end();
-      for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
-      {
-        GetImplementation( *iter ).RemoveInternal();
-      }
-    }
-
-    delete mConstraints;
-    mConstraints = NULL;
-  }
-}
-
-void Object::RemoveConstraints( unsigned int tag )
-{
-  // guard against constraint sending messages during core destruction
-  if( mConstraints && Stage::IsInstalled() )
-  {
-    ConstraintIter iter( mConstraints->begin() );
-    while(iter != mConstraints->end() )
-    {
-      ConstraintBase& constraint = GetImplementation( *iter );
-      if( constraint.GetTag() == tag )
-      {
-        GetImplementation( *iter ).RemoveInternal();
-        iter = mConstraints->erase( iter );
-      }
-      else
-      {
-        ++iter;
-      }
-    }
-
-    if ( mConstraints->empty() )
-    {
-      delete mConstraints;
-      mConstraints = NULL;
-    }
-  }
-}
-
-void Object::SetTypeInfo( const TypeInfo* typeInfo )
-{
-  mTypeInfo = typeInfo;
-}
-
-Object::~Object()
-{
-  // Notification for observers
-  for( ConstObserverIter iter = mObservers.Begin(), endIter =  mObservers.End(); iter != endIter; ++iter)
-  {
-    (*iter)->ObjectDestroyed(*this);
-  }
-
-  delete mConstraints;
-  delete mPropertyNotifications;
-}
-
-CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
-{
-  CustomPropertyMetadata* property( NULL );
-  int arrayIndex;
-  if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
-  {
-    for ( arrayIndex = 0; arrayIndex < (int)mCustomProperties.Count(); arrayIndex++ )
-    {
-      CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>( mCustomProperties[ arrayIndex ] );
-      if( custom->childPropertyIndex == index )
-      {
-        property = custom;
-      }
-    }
-  }
-  else
-  {
-    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;
-}
-
-AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
-{
-  for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ )
-  {
-    AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( mAnimatableProperties[ arrayIndex ] );
-    if( property->index == index )
-    {
-      return property;
-    }
-  }
-  return NULL;
-}
-
-AnimatablePropertyMetadata* Object::RegisterAnimatableProperty(Property::Index index) const
-{
-  DALI_ASSERT_ALWAYS( (( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ))
-                      && "Property index is out of bounds" );
-
-  // check whether the animatable property is registered already, if not then register one.
-  AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
-  if(!animatableProperty)
-  {
-    const TypeInfo* typeInfo( GetTypeInfo() );
-    if (typeInfo)
-    {
-      Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index);
-      if(basePropertyIndex == Property::INVALID_INDEX)
-      {
-        // If the property is not a component of a base property, register the whole property itself.
-        const  std::string& propertyName = typeInfo->GetPropertyName(index);
-        RegisterSceneGraphProperty(propertyName, 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.
-        animatableProperty = FindAnimatableProperty( basePropertyIndex );
-        if(!animatableProperty)
-        {
-          // If the base property is not registered yet, register the base property first.
-          const  std::string& basePropertyName = typeInfo->GetPropertyName(basePropertyIndex);
-          if(Property::INVALID_INDEX != RegisterSceneGraphProperty(basePropertyName, basePropertyIndex, Property::Value(typeInfo->GetPropertyType(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->GetType(), animatableProperty->GetSceneGraphProperty() ) );
-        }
-      }
-
-      // The metadata has just been added and therefore should be in the end of the vector.
-      animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
-    }
-  }
-
-  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