+ 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;
+ }
+}
+
+void Object::RegisterAnimatableProperty( const TypeInfo& typeInfo,
+ Property::Index index,
+ const Property::Value* value ) const
+{
+ // 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 )
+ {
+ initialValue = *value;
+ }
+ else
+ {
+ initialValue = typeInfo.GetPropertyDefaultValue( index );
+ }
+ RegisterSceneGraphProperty( propertyName, Property::INVALID_KEY, index, initialValue );
+ AddUniformMapping( index, propertyName );
+}
+
+AnimatablePropertyMetadata* Object::GetSceneAnimatableProperty( Property::Index index, const Property::Value* value ) const
+{
+ // 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 )
+ {
+ 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.
+ 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]);
+ }
+
+ // Create the metadata for the property component.
+ mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->value, 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( auto&& entry : mCustomProperties )
+ {
+ CustomPropertyMetadata* customProperty = static_cast<CustomPropertyMetadata*>( entry );
+
+ 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;
+ }
+ }
+ }