+ 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:
+ {
+ newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
+ break;
+ }
+
+ case Property::MATRIX:
+ {
+ newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
+ break;
+ }
+
+ case Property::MATRIX3:
+ {
+ newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
+ break;
+ }
+
+ case Property::ROTATION:
+ {
+ newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
+ break;
+ }
+
+ case Property::RECTANGLE:
+ case Property::STRING:
+ case Property::ARRAY:
+ case Property::MAP:
+ case Property::EXTENTS:
+ case Property::NONE:
+ {
+ DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
+ break;
+ }
+ }
+
+ // get the scene property owner from derived class
+ const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
+ // we can only pass properties to scene graph side if there is a scene object
+ if( scenePropertyOwner )
+ {
+ // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
+ const PropertyBase* property = newProperty.Get();
+ if(index >= PROPERTY_CUSTOM_START_INDEX)
+ {
+ 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, propertyValue, property ) );
+ }
+
+ // queue a message to add the property
+ InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty ); // Message takes ownership
+
+ return index;
+ }
+ else
+ {
+ // property was orphaned and killed so return invalid index
+ return Property::INVALID_INDEX;