+ mConstraints->erase( it );
+ }
+ }
+}
+
+void Object::RemoveConstraints()
+{
+ // guard against constraint sending messages during core destruction
+ if( mConstraints && Stage::IsInstalled() )
+ {
+ for ( auto&& item : *mConstraints )
+ {
+ GetImplementation( item ).RemoveInternal();
+ }
+
+ delete mConstraints;
+ mConstraints = nullptr;
+ }
+}
+
+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 = nullptr;
+ }
+ }
+}
+
+void Object::SetTypeInfo( const TypeInfo* typeInfo )
+{
+ mTypeInfo = typeInfo;
+}
+
+const SceneGraph::PropertyOwner& Object::GetSceneObject() const
+{
+ if( !mUpdateObject )
+ {
+ auto sceneObject = SceneGraph::PropertyOwner::New();
+ OwnerPointer< SceneGraph::PropertyOwner > transferOwnership( sceneObject );
+ mUpdateObject = sceneObject;
+ AddObjectMessage( const_cast<EventThreadServices&>( GetEventThreadServices() ).GetUpdateManager(), transferOwnership );
+ }
+ DALI_ASSERT_DEBUG( mUpdateObject && "there must always be a scene object" );
+ return *mUpdateObject;
+}
+
+const PropertyBase* Object::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+ const SceneGraph::PropertyBase* property = nullptr;
+ if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
+ {
+ AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty( index, nullptr );
+ DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
+
+ property = animatable->GetSceneGraphProperty();
+ }
+ else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
+ ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
+ {
+ CustomPropertyMetadata* custom = FindCustomProperty( index );
+ DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+
+ property = custom->GetSceneGraphProperty();
+ }
+ return property;
+}
+
+const PropertyInputImpl* Object::GetSceneObjectInputProperty( Property::Index index ) const
+{
+ // reuse animatable version as they are inputs as well
+ return GetSceneObjectAnimatableProperty( index );
+}
+
+int32_t Object::GetPropertyComponentIndex( Property::Index index ) const
+{
+ int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
+
+ 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 = GetSceneAnimatableProperty( index, nullptr );
+ if( animatableProperty )
+ {
+ componentIndex = animatableProperty->componentIndex;
+ }
+ }
+ if( Property::INVALID_COMPONENT_INDEX == componentIndex )
+ {
+ const TypeInfo* typeInfo( GetTypeInfo() );
+ if ( typeInfo )
+ {
+ componentIndex = typeInfo->GetComponentIndex(index);
+ }
+ }
+
+ return componentIndex;
+}
+
+Handle::PropertySetSignalType& Object::PropertySetSignal()
+{
+ return mPropertySetSignal;
+}
+
+Object::Object( const SceneGraph::PropertyOwner* sceneObject )
+: mEventThreadServices( EventThreadServices::Get() ),
+ mUpdateObject( sceneObject ),
+ mTypeInfo( nullptr ),
+ mConstraints( nullptr ),
+ mPropertyNotifications( nullptr )
+{
+}
+
+Object::~Object()
+{
+ // Notification for observers
+ for( auto&& item : mObservers )
+ {
+ item->ObjectDestroyed( *this );
+ }
+ delete mConstraints;
+ delete mPropertyNotifications;
+
+ // Guard to allow handle destruction after Core has been destroyed
+ if( Stage::IsInstalled() )
+ {
+ if( nullptr != mUpdateObject )
+ {
+ RemoveObjectMessage( GetEventThreadServices().GetUpdateManager(), mUpdateObject );
+ }
+ }
+}
+
+void Object::OnSceneObjectAdd()
+{
+ // Notification for observers
+ for( auto&& item : mObservers )
+ {
+ item->SceneObjectAdded(*this);
+ }
+
+ // enable property notifications in scene graph
+ EnablePropertyNotifications();
+}
+
+void Object::OnSceneObjectRemove()
+{
+ // Notification for observers
+ for( auto&& item : mObservers )
+ {
+ item->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 = nullptr;
+ 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
+ {
+ int32_t arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
+ if( arrayIndex >= 0 )
+ {
+ if( arrayIndex < static_cast<int32_t>( 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 nullptr;
+}
+
+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<int32_t>( propertyValue.Get<int32_t>() );
+ 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( !"Property type is not animatable" );
+ break;
+ }
+ }
+
+ // get the scene property owner
+ const SceneGraph::PropertyOwner& scenePropertyOwner = GetSceneObject();
+ // 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;
+}
+
+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 ); // recurses type hierarchy
+ if( Property::NONE == initialValue.GetType() )
+ {
+ initialValue = Property::Value( typeInfo.GetPropertyType( index ) ); // recurses type hierarchy
+ }
+ }
+ 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]);