X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fcommon%2Fobject-impl.cpp;h=344e72c2e9cb2abc40f81cbc5720c72adc3ebf94;hb=462cbee2270984cdca45488f3733d664dcf49187;hp=e435c7b467122fa30399b6dd2da3c51454beaad0;hpb=3bcb54791a6777e77f02612a1f7916e83ef1c86f;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/common/object-impl.cpp b/dali/internal/event/common/object-impl.cpp index e435c7b..344e72c 100644 --- a/dali/internal/event/common/object-impl.cpp +++ b/dali/internal/event/common/object-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -50,6 +50,8 @@ typedef Dali::Vector::ConstIterator ConstObserverIter; #if defined(DEBUG_ENABLED) Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" ); #endif + + } // unnamed namespace Object::Object() @@ -86,17 +88,6 @@ void Object::RemoveObserver(Observer& observer) void Object::OnSceneObjectAdd() { - // Notification for this object's constraints - if( mConstraints ) - { - const ActiveConstraintConstIter endIter = mConstraints->end(); - for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) - { - ActiveConstraintBase& baseConstraint = GetImplementation( *iter ); - baseConstraint.OnParentSceneObjectAdded(); - } - } - // Notification for observers for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter) { @@ -109,17 +100,6 @@ void Object::OnSceneObjectAdd() void Object::OnSceneObjectRemove() { - // Notification for this object's constraints - if( mConstraints ) - { - const ActiveConstraintConstIter endIter = mConstraints->end(); - for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) - { - ActiveConstraintBase& baseConstraint = GetImplementation( *iter ); - baseConstraint.OnParentSceneObjectRemoved(); - } - } - // Notification for observers for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter ) { @@ -132,7 +112,21 @@ void Object::OnSceneObjectRemove() int Object::GetPropertyComponentIndex( Property::Index index ) const { - return Property::INVALID_COMPONENT_INDEX; + 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 @@ -170,10 +164,18 @@ std::string Object::GetPropertyName( Property::Index index ) const if ( index < DEFAULT_PROPERTY_MAX_COUNT ) { - return GetDefaultPropertyName( index ); + std::string string; + + const char * propertyName = GetDefaultPropertyName( index ); + if( propertyName ) + { + string = propertyName; + } + return string; } - if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) + if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) + || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) ) { const TypeInfo* typeInfo( GetTypeInfo() ); if ( typeInfo ) @@ -186,7 +188,7 @@ std::string Object::GetPropertyName( Property::Index index ) const } } - CustomProperty* custom = FindCustomProperty( index ); + CustomPropertyMetadata* custom = FindCustomProperty( index ); if( custom ) { return custom->name; @@ -198,25 +200,71 @@ Property::Index Object::GetPropertyIndex(const std::string& name) const { Property::Index index = GetDefaultPropertyIndex( name ); - if ( index == Property::INVALID_INDEX ) + if(index == Property::INVALID_INDEX) { const TypeInfo* typeInfo( GetTypeInfo() ); if ( typeInfo ) { index = typeInfo->GetPropertyIndex( name ); + 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. + if ( NULL == RegisterAnimatableProperty(index) ) + { + index = Property::INVALID_INDEX; + } + } } } - if( ( index == Property::INVALID_INDEX )&&( mCustomProperties.Count() > 0 ) ) + if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) ) { Property::Index count = PROPERTY_CUSTOM_START_INDEX; - const CustomPropertyLookup::ConstIterator end = mCustomProperties.End(); - for( CustomPropertyLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count ) + const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End(); + for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count ) { - CustomProperty* custom = *iter; + CustomPropertyMetadata* custom = static_cast(*iter); if ( custom->name == name ) { - index = count; + if ( custom->childPropertyIndex != Property::INVALID_INDEX ) + { + // If it is a child property, return the child property index + index = custom->childPropertyIndex; + } + else + { + index = count; + } + break; + } + } + } + + return index; +} + +Property::Index Object::GetPropertyIndex( Property::Index key ) const +{ + Property::Index index = Property::INVALID_INDEX; + + if( mCustomProperties.Count() > 0 ) + { + Property::Index count = PROPERTY_CUSTOM_START_INDEX; + const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End(); + for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count ) + { + CustomPropertyMetadata* custom = static_cast(*iter); + if( custom->key == key ) + { + if( custom->childPropertyIndex != Property::INVALID_INDEX ) + { + // If it is a child property, return the child property index + index = custom->childPropertyIndex; + } + else + { + index = count; + } break; } } @@ -225,81 +273,122 @@ 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 ) { - return IsDefaultPropertyWritable( index ); + writable = IsDefaultPropertyWritable( index ); } - - if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) + else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) { const TypeInfo* typeInfo( GetTypeInfo() ); if ( typeInfo ) { - return typeInfo->IsPropertyWritable( index ); + writable = typeInfo->IsPropertyWritable( index ); } else { DALI_ASSERT_ALWAYS( ! "Invalid property index" ); } } - - CustomProperty* custom = FindCustomProperty( index ); - if( custom ) + else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) { - return custom->IsWritable(); + // Type Registry scene-graph properties are writable. + writable = true; + } + else + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + if( custom ) + { + writable = custom->IsWritable(); + } } - return false; + + return writable; } bool Object::IsPropertyAnimatable( Property::Index index ) const { DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds"); + bool animatable = false; + if ( index < DEFAULT_PROPERTY_MAX_COUNT ) { - return IsDefaultPropertyAnimatable( index ); + animatable = IsDefaultPropertyAnimatable( index ); } - - if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) + else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) { // Type Registry event-thread only properties are not animatable. - return false; + animatable = false; } - - CustomProperty* custom = FindCustomProperty( index ); - if( custom ) + else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + // Type Registry scene-graph properties are animatable. + animatable = true; + } + else { - return custom->IsAnimatable(); + CustomPropertyMetadata* custom = FindCustomProperty( index ); + if( custom ) + { + animatable = custom->IsAnimatable(); + } } - return false; + + return animatable; } bool Object::IsPropertyAConstraintInput( Property::Index index ) const { DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds"); + bool isConstraintInput = false; + if ( index < DEFAULT_PROPERTY_MAX_COUNT ) { - return IsDefaultPropertyAConstraintInput( index ); + isConstraintInput = IsDefaultPropertyAConstraintInput( index ); } - - if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_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. - return false; + isConstraintInput = false; } - - CustomProperty* custom = FindCustomProperty( index ); - if( custom ) + else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + // scene graph properties can be used as input to a constraint. + isConstraintInput = true; + } + else { - // ... custom properties can be used as input to a constraint. - return true; + CustomPropertyMetadata* custom = FindCustomProperty( index ); + if( custom ) + { + // ... custom properties can be used as input to a constraint. + isConstraintInput = true; + } } - return false; + + return isConstraintInput; } Property::Type Object::GetPropertyType( Property::Index index ) const @@ -311,7 +400,8 @@ Property::Type Object::GetPropertyType( Property::Index index ) const return GetDefaultPropertyType( index ); } - if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) + if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) + || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) ) { const TypeInfo* typeInfo( GetTypeInfo() ); if ( typeInfo ) @@ -324,11 +414,12 @@ Property::Type Object::GetPropertyType( Property::Index index ) const } } - CustomProperty* custom = FindCustomProperty( index ); + CustomPropertyMetadata* custom = FindCustomProperty( index ); if( custom ) { - return custom->type; + return custom->GetType(); } + return Property::NONE; } @@ -336,6 +427,8 @@ void Object::SetProperty( Property::Index index, const Property::Value& property { DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" ); + bool propertySet( true ); + if ( index < DEFAULT_PROPERTY_MAX_COUNT ) { SetDefaultProperty( index, propertyValue ); @@ -349,24 +442,88 @@ void Object::SetProperty( Property::Index index, const Property::Value& property } else { - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); + DALI_LOG_ERROR("Cannot find property index\n"); + propertySet = false; } } - else + else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) { - CustomProperty* custom = FindCustomProperty( index ); - DALI_ASSERT_ALWAYS( custom && "Invalid property index" ); - if( custom->IsAnimatable() ) + // check whether the animatable property is registered already, if not then register one. + AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index ); + if(!animatableProperty) { + DALI_LOG_ERROR("Cannot find property index\n"); + propertySet = false; + } + else + { + // update the cached property value + animatableProperty->SetPropertyValue( propertyValue ); + // set the scene graph property value - SetSceneGraphProperty( index, *custom, propertyValue ); + SetSceneGraphProperty( index, *animatableProperty, propertyValue ); + } + } + else + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + + if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + if( !custom ) + { + // If the child property is not registered yet, register it. + custom = new CustomPropertyMetadata( "", propertyValue, Property::READ_WRITE ); + mCustomProperties.PushBack( custom ); + } + + custom->childPropertyIndex = index; + + // Resolve name for the child property + Object* parent = GetParentObject(); + if( parent ) + { + const TypeInfo* parentTypeInfo( parent->GetTypeInfo() ); + if( parentTypeInfo ) + { + custom->name = parentTypeInfo->GetChildPropertyName( index ); + } + } + } + + if( custom ) + { + if( custom->IsAnimatable() ) + { + // update the cached property value + custom->SetPropertyValue( propertyValue ); + + // set the scene graph property value + SetSceneGraphProperty( index, *custom, propertyValue ); + } + else if( custom->IsWritable() ) + { + // update the cached property value + custom->SetPropertyValue( propertyValue ); + } + else + { + // trying to set value on read only property is no-op + propertySet = false; + } } - else if( custom->IsWritable() ) + else { - custom->value = propertyValue; - OnPropertySet(index, propertyValue); + DALI_LOG_ERROR("Invalid property index\n"); + propertySet = false; } - // trying to set value on read only property is no-op + } + + // Let derived classes know that a property has been set + // 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); } } @@ -389,113 +546,88 @@ Property::Value Object::GetProperty(Property::Index index) const } else { - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); + DALI_LOG_ERROR("Cannot find property index\n"); } } - else if( mCustomProperties.Count() > 0 ) + else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) { - CustomProperty* custom = FindCustomProperty( index ); - DALI_ASSERT_ALWAYS( custom && "Invalid property index" ); - - if( !custom->IsAnimatable() ) + // check whether the animatable property is registered already, if not then register one. + AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index ); + if(!animatableProperty) { - value = custom->value; + DALI_LOG_ERROR("Cannot find property index\n"); } else { - BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() ); - - switch ( custom->type ) - { - case Property::BOOLEAN: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; - } - - case Property::FLOAT: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; - } - - case Property::INTEGER: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; - } - - case Property::VECTOR2: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; - } - - case Property::VECTOR3: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; - } - - case Property::VECTOR4: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; - } - - case Property::MATRIX: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; - } - - case Property::MATRIX3: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; - } + // get the cached animatable property value + value = animatableProperty->GetPropertyValue(); + } + } + else if(mCustomProperties.Count() > 0) + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + if(custom) + { + // get the cached custom property value + value = custom->GetPropertyValue(); + } + else + { + DALI_LOG_ERROR("Invalid property index\n"); + } + } // if custom - case Property::ROTATION: - { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( custom->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + return value; +} - value = (*property)[ bufferIndex ]; - break; - } +Property::Value Object::GetCurrentProperty( Property::Index index ) const +{ + DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" ); - default: - { - DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" ); - break; - } - } // switch(type) - } // if animatable + Property::Value value; + if ( index < DEFAULT_PROPERTY_MAX_COUNT ) + { + value = GetDefaultPropertyCurrentValue( index ); + } + else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + const TypeInfo* typeInfo( GetTypeInfo() ); + if ( typeInfo ) + { + value = typeInfo->GetProperty( this, index ); + } + else + { + DALI_LOG_ERROR("Cannot find property index\n"); + } + } + else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + // check whether the animatable property is registered already, if not then register one. + AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index ); + if(!animatableProperty) + { + DALI_LOG_ERROR("Cannot find property index\n"); + } + else + { + // get the animatable property value + value = GetCurrentPropertyValue( animatableProperty ); + } + } + else if(mCustomProperties.Count() > 0) + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + if(custom) + { + // get the custom property value + value = GetCurrentPropertyValue( custom ); + } + else + { + DALI_LOG_ERROR("Invalid property index\n"); + } } // if custom return value; @@ -503,7 +635,7 @@ Property::Value Object::GetProperty(Property::Index index) const void Object::GetPropertyIndices( Property::IndexContainer& indices ) const { - indices.clear(); + indices.Clear(); // Default Properties GetDefaultPropertyIndices( indices ); @@ -518,19 +650,28 @@ void Object::GetPropertyIndices( Property::IndexContainer& indices ) const // Custom Properties if ( mCustomProperties.Count() > 0 ) { - indices.reserve( indices.size() + mCustomProperties.Count() ); + indices.Reserve( indices.Size() + mCustomProperties.Count() ); - CustomPropertyLookup::ConstIterator iter = mCustomProperties.Begin(); - const CustomPropertyLookup::ConstIterator endIter = mCustomProperties.End(); + PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); + const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End(); int i=0; for ( ; iter != endIter; ++iter, ++i ) { - indices.push_back( PROPERTY_CUSTOM_START_INDEX + i ); + CustomPropertyMetadata* custom = static_cast( *iter ); + if ( custom->childPropertyIndex != Property::INVALID_INDEX ) + { + // If it is a child property, add the child property index + indices.PushBack( custom->childPropertyIndex ); + } + else + { + indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i ); + } } } } -Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue) +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 newProperty; @@ -543,15 +684,15 @@ Property::Index Object::RegisterProperty( const std::string& name, const Propert break; } - case Property::FLOAT: + case Property::INTEGER: { - newProperty = new AnimatableProperty( propertyValue.Get() ); + newProperty = new AnimatableProperty( propertyValue.Get() ); break; } - case Property::INTEGER: + case Property::FLOAT: { - newProperty = new AnimatableProperty( propertyValue.Get() ); + newProperty = new AnimatableProperty( propertyValue.Get() ); break; } @@ -591,64 +732,117 @@ Property::Index Object::RegisterProperty( const std::string& name, const Propert break; } - case Property::UNSIGNED_INTEGER: case Property::RECTANGLE: case Property::STRING: case Property::ARRAY: case Property::MAP: + case Property::NONE: { - DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() ); DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" ); break; } - - default: - { - DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() ); - DALI_ASSERT_ALWAYS( !"PropertyType enumeration is out of bounds" ); - break; - } } // get the scene property owner from derived class const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner(); - Property::Index index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(); // 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(); - mCustomProperties.PushBack( new CustomProperty( name, propertyValue.GetType(), property ) ); + 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( GetEventThreadServices(), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership + InstallCustomPropertyMessage( const_cast(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 ); + + return index; } else { // property was orphaned and killed so return invalid index - index = Property::INVALID_INDEX; + return Property::INVALID_INDEX; } +} - return index; +Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue ) +{ + return RegisterProperty( name, Property::INVALID_KEY, propertyValue, Property::ANIMATABLE ); } -Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode) +Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue ) { - Property::Index index = Property::INVALID_INDEX; + return RegisterProperty( name, key, propertyValue, Property::ANIMATABLE ); +} - if(Property::ANIMATABLE == accessMode) - { - index = RegisterProperty(name, propertyValue); - } - else - { - // Add entry to the property lookup - index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(); - mCustomProperties.PushBack( new CustomProperty( name, propertyValue, accessMode ) ); +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 + { + 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 ) + { + index = RegisterSceneGraphProperty( name, key, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue ); + AddUniformMapping( index, name ); + } + else + { + // Add entry to the property lookup + index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(); + + CustomPropertyMetadata* customProperty = new CustomPropertyMetadata( name, propertyValue, accessMode ); + + // Resolve index for the child property + Object* parent = GetParentObject(); + if( parent ) + { + const TypeInfo* parentTypeInfo( parent->GetTypeInfo() ); + if( parentTypeInfo ) + { + Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( name ); + if( childPropertyIndex != Property::INVALID_INDEX ) + { + customProperty->childPropertyIndex = childPropertyIndex; + index = childPropertyIndex; + } + } + } + + mCustomProperties.PushBack( customProperty ); + } } return index; @@ -662,11 +856,17 @@ Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index { if ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) { - DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." ); + DALI_ABORT( "Property notification added to event side only property." ); + } + else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + // 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 ) { - CustomProperty* custom = FindCustomProperty( index ); + CustomPropertyMetadata* custom = FindCustomProperty( index ); DALI_ASSERT_ALWAYS( custom && "Invalid property index" ); DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." ); } @@ -724,6 +924,32 @@ void Object::RemovePropertyNotifications() } } +void Object::NotifyPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value ) +{ + if ( index < DEFAULT_PROPERTY_MAX_COUNT ) + { + OnNotifyDefaultPropertyAnimation( animation, index, value ); + } + else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index ); + if( animatableProperty ) + { + // update the cached property value + animatableProperty->SetPropertyValue( value ); + } + } + else + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + if( custom && custom->IsAnimatable() ) + { + // update the cached property value + custom->SetPropertyValue( value ); + } + } +} + void Object::EnablePropertyNotifications() { if( mPropertyNotifications ) @@ -752,48 +978,208 @@ void Object::DisablePropertyNotifications() } } -Dali::ActiveConstraint Object::ApplyConstraint( Constraint& constraint ) +void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName ) const { - return Dali::ActiveConstraint( DoApplyConstraint( constraint, Dali::Handle() ) ); + // 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(GetEventThreadServices()), *sceneObject, map); + } + else + { + DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" ); + } + } } -Dali::ActiveConstraint Object::ApplyConstraint( Constraint& constraint, Dali::Handle weightObject ) +void Object::RemoveUniformMapping( const std::string& uniformName ) { - return Dali::ActiveConstraint( DoApplyConstraint( constraint, weightObject ) ); + const SceneGraph::PropertyOwner* sceneObject = GetSceneObject(); + RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName); } -ActiveConstraintBase* Object::DoApplyConstraint( Constraint& constraint, Dali::Handle weightObject ) +Property::Value Object::GetCurrentPropertyValue( const PropertyMetadata* entry ) const { - ActiveConstraintBase* activeConstraintImpl = constraint.CreateActiveConstraint(); - DALI_ASSERT_DEBUG( NULL != activeConstraintImpl ); + Property::Value value; - Dali::ActiveConstraint activeConstraint( activeConstraintImpl ); + DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" ); - if( weightObject ) + if( !entry->IsAnimatable() ) + { + value = entry->GetPropertyValue(); + } + else { - Object& weightObjectImpl = GetImplementation( weightObject ); - Property::Index weightIndex = weightObjectImpl.GetPropertyIndex( "weight" ); + BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() ); - if( Property::INVALID_INDEX != weightIndex ) + switch ( entry->GetType() ) { - activeConstraintImpl->SetCustomWeightObject( weightObjectImpl, weightIndex ); - } - } + case Property::BOOLEAN: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); - if( !mConstraints ) - { - mConstraints = new ActiveConstraintContainer; - } - mConstraints->push_back( activeConstraint ); + value = (*property)[ bufferIndex ]; + break; + } + + case Property::INTEGER: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + value = (*property)[ bufferIndex ]; + break; + } + + case Property::FLOAT: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + value = (*property)[ bufferIndex ]; + break; + } + + case Property::VECTOR2: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + if(entry->componentIndex == 0) + { + value = (*property)[ bufferIndex ].x; + } + else if(entry->componentIndex == 1) + { + value = (*property)[ bufferIndex ].y; + } + else + { + value = (*property)[ bufferIndex ]; + } + break; + } + + case Property::VECTOR3: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + if(entry->componentIndex == 0) + { + value = (*property)[ bufferIndex ].x; + } + else if(entry->componentIndex == 1) + { + value = (*property)[ bufferIndex ].y; + } + else if(entry->componentIndex == 2) + { + value = (*property)[ bufferIndex ].z; + } + else + { + value = (*property)[ bufferIndex ]; + } + break; + } + + case Property::VECTOR4: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + if(entry->componentIndex == 0) + { + value = (*property)[ bufferIndex ].x; + } + else if(entry->componentIndex == 1) + { + value = (*property)[ bufferIndex ].y; + } + else if(entry->componentIndex == 2) + { + value = (*property)[ bufferIndex ].z; + } + else if(entry->componentIndex == 3) + { + value = (*property)[ bufferIndex ].w; + } + else + { + value = (*property)[ bufferIndex ]; + } + break; + } + + case Property::MATRIX: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + value = (*property)[ bufferIndex ]; + break; + } + + case Property::MATRIX3: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + value = (*property)[ bufferIndex ]; + break; + } + + case Property::ROTATION: + { + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); - activeConstraintImpl->FirstApply( *this, constraint.GetApplyTime() ); + value = (*property)[ bufferIndex ]; + break; + } + + default: + { + // unreachable code due to higher level logic + } + } // switch(type) + } // if animatable - return activeConstraintImpl; + return value; } -void Object::SetSceneGraphProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value ) +void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value ) { - switch ( entry.type ) + switch ( entry.GetType() ) { case Property::BOOLEAN: { @@ -805,23 +1191,23 @@ void Object::SetSceneGraphProperty( Property::Index index, const CustomProperty& break; } - case Property::FLOAT: + case Property::INTEGER: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); + const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - BakeMessage( GetEventThreadServices(), *property, value.Get() ); + BakeMessage( GetEventThreadServices(), *property, value.Get() ); break; } - case Property::INTEGER: + case Property::FLOAT: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); + const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - BakeMessage( GetEventThreadServices(), *property, value.Get() ); + BakeMessage( GetEventThreadServices(), *property, value.Get() ); break; } @@ -831,7 +1217,18 @@ void Object::SetSceneGraphProperty( Property::Index index, const CustomProperty& DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - BakeMessage( GetEventThreadServices(), *property, value.Get() ); + if(entry.componentIndex == 0) + { + SetXComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else if(entry.componentIndex == 1) + { + SetYComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else + { + BakeMessage( GetEventThreadServices(), *property, value.Get() ); + } break; } @@ -841,7 +1238,23 @@ void Object::SetSceneGraphProperty( Property::Index index, const CustomProperty& DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - BakeMessage( GetEventThreadServices(), *property, value.Get() ); + if(entry.componentIndex == 0) + { + SetXComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else if(entry.componentIndex == 1) + { + SetYComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else if(entry.componentIndex == 2) + { + SetZComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else + { + BakeMessage( GetEventThreadServices(), *property, value.Get() ); + } + break; } @@ -851,7 +1264,26 @@ void Object::SetSceneGraphProperty( Property::Index index, const CustomProperty& DALI_ASSERT_DEBUG( NULL != property ); // property is being used in a separate thread; queue a message to set the property - BakeMessage( GetEventThreadServices(), *property, value.Get() ); + if(entry.componentIndex == 0) + { + SetXComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else if(entry.componentIndex == 1) + { + SetYComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else if(entry.componentIndex == 2) + { + SetZComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else if(entry.componentIndex == 3) + { + SetWComponentMessage( GetEventThreadServices(), *property, value.Get() ); + } + else + { + BakeMessage( GetEventThreadServices(), *property, value.Get() ); + } break; } @@ -909,32 +1341,46 @@ const TypeInfo* Object::GetTypeInfo() const return mTypeInfo; } -void Object::RemoveConstraint( ActiveConstraint& constraint, bool isInScenegraph ) +void Object::ApplyConstraint( ConstraintBase& constraint ) { - // guard against constraint sending messages during core destruction - if ( Stage::IsInstalled() ) + if( !mConstraints ) { - if( isInScenegraph ) + 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() ) { - ActiveConstraintBase& baseConstraint = GetImplementation( constraint ); - baseConstraint.BeginRemove(); + mConstraints->erase( it ); } } } -void Object::RemoveConstraint( Dali::ActiveConstraint activeConstraint ) +void Object::RemoveConstraints() { // guard against constraint sending messages during core destruction if( mConstraints && Stage::IsInstalled() ) { - bool isInSceneGraph( NULL != GetSceneObject() ); - - ActiveConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), activeConstraint ) ); - if( it != mConstraints->end() ) + // If we have nothing in the scene-graph, just clear constraint containers + const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject(); + if ( NULL != propertyOwner ) { - RemoveConstraint( *it, isInSceneGraph ); - mConstraints->erase( it ); + const ConstraintConstIter endIter = mConstraints->end(); + for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) + { + GetImplementation( *iter ).RemoveInternal(); + } } + + delete mConstraints; + mConstraints = NULL; } } @@ -943,15 +1389,13 @@ void Object::RemoveConstraints( unsigned int tag ) // guard against constraint sending messages during core destruction if( mConstraints && Stage::IsInstalled() ) { - bool isInSceneGraph( NULL != GetSceneObject() ); - - ActiveConstraintIter iter( mConstraints->begin() ); + ConstraintIter iter( mConstraints->begin() ); while(iter != mConstraints->end() ) { - ActiveConstraintBase& constraint = GetImplementation( *iter ); + ConstraintBase& constraint = GetImplementation( *iter ); if( constraint.GetTag() == tag ) { - RemoveConstraint( *iter, isInSceneGraph ); + GetImplementation( *iter ).RemoveInternal(); iter = mConstraints->erase( iter ); } else @@ -959,27 +1403,12 @@ void Object::RemoveConstraints( unsigned int tag ) ++iter; } } - } -} -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 ) + if ( mConstraints->empty() ) { - const ActiveConstraintConstIter endIter = mConstraints->end(); - for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) - { - RemoveConstraint( *iter, true ); - } + delete mConstraints; + mConstraints = NULL; } - - delete mConstraints; - mConstraints = NULL; } } @@ -990,18 +1419,6 @@ void Object::SetTypeInfo( const TypeInfo* typeInfo ) Object::~Object() { - // Notification for this object's constraints - // (note that the ActiveConstraint handles may outlive the Object) - if( mConstraints ) - { - const ActiveConstraintConstIter endIter = mConstraints->end(); - for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) - { - ActiveConstraintBase& baseConstraint = GetImplementation( *iter ); - baseConstraint.OnParentDestroyed(); - } - } - // Notification for observers for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter) { @@ -1012,20 +1429,134 @@ Object::~Object() delete mPropertyNotifications; } -CustomProperty* Object::FindCustomProperty( Property::Index index ) const +CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const { - CustomProperty* property( NULL ); - int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX; - if( arrayIndex >= 0 ) + CustomPropertyMetadata* property( NULL ); + if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) ) { - if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties + for ( std::size_t arrayIndex = 0; arrayIndex < mCustomProperties.Count(); arrayIndex++ ) { - property = mCustomProperties[ arrayIndex ]; + CustomPropertyMetadata* custom = static_cast( mCustomProperties[ arrayIndex ] ); + if( custom->childPropertyIndex == index ) + { + property = custom; + } + } + } + else + { + int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX; + if( arrayIndex >= 0 ) + { + if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties + { + property = static_cast(mCustomProperties[ arrayIndex ]); + } } } return property; } +AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const +{ + for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ ) + { + AnimatablePropertyMetadata* property = static_cast( 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, Property::INVALID_KEY, index, typeInfo->GetPropertyDefaultValue(index)); + AddUniformMapping( index, propertyName ); + } + else + { + // Since the property is a component of a base property, check whether the base property is registered. + 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, Property::INVALID_KEY, basePropertyIndex, typeInfo->GetPropertyDefaultValue( basePropertyIndex ) ) ) + { + animatableProperty = static_cast(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->value, animatableProperty->GetSceneGraphProperty() ) ); + } + } + + // The metadata has just been added and therefore should be in the end of the vector. + animatableProperty = static_cast(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( 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