X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fcommon%2Fobject-impl.cpp;h=5e68a6ed1945971a0ad8125605dd628a71d9f685;hb=41e9a0ad46f71f270f69e75a08098f5105275cd3;hp=a9af75062da72b80a2f0e45e8f7d369f53c27b88;hpb=3a5b25aa7510b0c2fb60aaa616cde0bf0a17b70a;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 a9af750..5e68a6e 100644 --- a/dali/internal/event/common/object-impl.cpp +++ b/dali/internal/event/common/object-impl.cpp @@ -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. @@ -23,13 +23,15 @@ // INTERNAL INCLUDES #include +#include #include #include #include #include #include -#include +#include #include +#include #include 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::Iterator ObserverIter; -typedef Dali::Vector::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( mCustomProperties.Count() ); count += custom; DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties: %d\n", custom ); @@ -162,71 +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 ) - { - 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 ) ) - || ( ( 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(*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 ) + { + // If it is a child property, return the child property index + index = custom->childPropertyIndex; + } + else { - index = Property::INVALID_INDEX; + 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(*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; @@ -243,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 { @@ -288,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 { @@ -320,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 ) ) + // is this a per class or per instance property + if ( index < MAX_PER_CLASS_PROPERTY_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 ) ) - { - // scene graph properties can be used as input to a constraint. - isConstraintInput = true; + const TypeInfo* typeInfo( GetTypeInfo() ); + if ( typeInfo ) + { + isConstraintInput = typeInfo->IsPropertyAConstraintInput( index ); + } } else { @@ -351,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 ); @@ -398,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 ); } @@ -448,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 { @@ -463,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; } } @@ -472,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 ); } } @@ -495,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) @@ -518,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 @@ -533,9 +542,6 @@ void Object::GetPropertyIndices( Property::IndexContainer& indices ) const { indices.Clear(); - // Default Properties - GetDefaultPropertyIndices( indices ); - // Manual Properties const TypeInfo* typeInfo( GetTypeInfo() ); if ( typeInfo ) @@ -548,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( *iter ); @@ -567,237 +573,636 @@ 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 newProperty; + return RegisterProperty( name, Property::INVALID_KEY, propertyValue, Property::ANIMATABLE ); +} - switch ( propertyValue.GetType() ) - { - case Property::BOOLEAN: - { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; - } +Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue ) +{ + return RegisterProperty( name, key, propertyValue, Property::ANIMATABLE ); +} - case Property::INTEGER: - { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; - } +Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode ) +{ + return RegisterProperty( name, Property::INVALID_KEY, propertyValue, accessMode ); +} - case Property::FLOAT: - { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; - } +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 ); + } - case Property::VECTOR2: - { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; - } + 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 - case Property::VECTOR3: + if( Property::ANIMATABLE == accessMode ) { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; + index = RegisterSceneGraphProperty( name, key, PROPERTY_CUSTOM_START_INDEX + static_cast( mCustomProperties.Count() ), propertyValue ); + AddUniformMapping( index, name ); } - - case Property::VECTOR4: + else { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; - } + // Add entry to the property lookup + index = PROPERTY_CUSTOM_START_INDEX + static_cast( mCustomProperties.Count() ); - case Property::MATRIX: - { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; - } + CustomPropertyMetadata* customProperty = new CustomPropertyMetadata( name, propertyValue, accessMode ); - case Property::MATRIX3: - { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; + // 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::ROTATION: + 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( propertyValue.Get() ); - break; + 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 = GetSceneAnimatableProperty( index, nullptr ); + DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" ); + } + else if ( mCustomProperties.Count() > 0 ) + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + DALI_ASSERT_ALWAYS( custom && "Invalid property index" ); + DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." ); + } + } - case Property::RECTANGLE: - case Property::STRING: - case Property::ARRAY: - case Property::MAP: - case Property::NONE: + 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() ) { - DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" ); - break; + 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; } } +} - // 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 ) +void Object::RemovePropertyNotifications() +{ + if( mPropertyNotifications ) { - // 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) + auto iter = mPropertyNotifications->begin(); + while(iter != mPropertyNotifications->end() ) { - DALI_ASSERT_ALWAYS( index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered" ); + // As we can't ensure all references are removed, we can just disable + // the notification. + GetImplementation(*iter).Disable(); + ++iter; + } + + mPropertyNotifications->clear(); + } +} - mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) ); +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 { - mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, Property::INVALID_COMPONENT_INDEX, propertyValue.GetType(), property ) ); // base property + CustomPropertyMetadata* custom = FindCustomProperty( index ); + if( custom && custom->IsAnimatable() ) + { + propertyMetadata = custom; + } } - // queue a message to add the property - InstallCustomPropertyMessage( const_cast(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership + 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; + } + } + } + } +} - // 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 ); +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 ); - return index; + // Check instead for newly registered properties + if( propertyPtr == NULL ) + { + PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex ); + if( animatable != NULL ) + { + propertyPtr = animatable->GetSceneGraphProperty(); + } } - else + + if( propertyPtr == NULL ) { - // property was orphaned and killed so return invalid index - return Property::INVALID_INDEX; + 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(GetEventThreadServices()), *sceneObject, map ); + } + else + { + DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" ); + } } } -Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue ) +void Object::RemoveUniformMapping( const std::string& uniformName ) { - return RegisterProperty( name, propertyValue, Property::ANIMATABLE ); + const SceneGraph::PropertyOwner* sceneObject = GetSceneObject(); + RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName); } -Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode ) +void Object::ApplyConstraint( ConstraintBase& constraint ) { - // If property with the required name already exists, then just set it. - Property::Index index = GetPropertyIndex( name ); - if( index != Property::INVALID_INDEX ) + if( !mConstraints ) { - SetProperty( index, propertyValue ); + mConstraints = new ConstraintContainer; } - else - { - // Otherwise register the property + mConstraints->push_back( Dali::Constraint( &constraint ) ); +} - if(Property::ANIMATABLE == accessMode) +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() ) { - index = RegisterSceneGraphProperty( name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue ); - AddUniformMapping( index, name ); + mConstraints->erase( it ); } - else + } +} + +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 ) { - // Add entry to the property lookup - index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(); + const auto endIter = mConstraints->end(); + for ( auto iter = mConstraints->begin(); endIter != iter; ++iter ) + { + GetImplementation( *iter ).RemoveInternal(); + } + } - CustomPropertyMetadata* customProperty = new CustomPropertyMetadata( name, propertyValue, accessMode ); + delete mConstraints; + mConstraints = NULL; + } +} - // Resolve index for the child property - Object* parent = GetParentObject(); - if( parent ) +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 ) { - const TypeInfo* parentTypeInfo( parent->GetTypeInfo() ); - if( parentTypeInfo ) - { - Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( name ); - if( childPropertyIndex != Property::INVALID_INDEX ) - { - customProperty->childPropertyIndex = childPropertyIndex; - index = childPropertyIndex; - } - } + GetImplementation( *iter ).RemoveInternal(); + iter = mConstraints->erase( iter ); } + else + { + ++iter; + } + } - mCustomProperties.PushBack( customProperty ); + if ( mConstraints->empty() ) + { + delete mConstraints; + mConstraints = NULL; } } +} - return index; +void Object::SetTypeInfo( const TypeInfo* typeInfo ) +{ + mTypeInfo = typeInfo; } -Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index, - int componentIndex, - const Dali::PropertyCondition& condition) +int32_t Object::GetPropertyComponentIndex( Property::Index index ) const { - if ( index >= DEFAULT_PROPERTY_MAX_COUNT ) + int32_t componentIndex = Property::INVALID_COMPONENT_INDEX; + + const TypeInfo* typeInfo( GetTypeInfo() ); + if ( typeInfo ) { - if ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) + 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 ) { - DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." ); + mTypeInfo = typeInfoHandle.Get(); // just a raw pointer to use, ownership is kept } - else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + } + + 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++ ) { - // 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" ); + CustomPropertyMetadata* custom = static_cast( mCustomProperties[ arrayIndex ] ); + if( custom->childPropertyIndex == index ) + { + property = custom; + } } - else if ( mCustomProperties.Count() > 0 ) + } + else + { + int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX; + if( arrayIndex >= 0 ) { - CustomPropertyMetadata* custom = FindCustomProperty( index ); - DALI_ASSERT_ALWAYS( custom && "Invalid property index" ); - DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." ); + if( arrayIndex < static_cast( mCustomProperties.Count() ) ) // we can only access the first 2 billion custom properties + { + property = static_cast(mCustomProperties[ arrayIndex ]); + } } } + return property; +} - Dali::Handle self(this); - Property target( self, index ); +AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const +{ + for( auto&& entry : mAnimatableProperties ) + { + AnimatablePropertyMetadata* property = static_cast( entry ); + if( property->index == index ) + { + return property; + } + } + return NULL; +} - PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition ); - Dali::PropertyNotification propertyNotification(internal.Get()); +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; - if( !mPropertyNotifications ) + switch ( propertyValue.GetType() ) { - mPropertyNotifications = new PropertyNotificationContainer; + case Property::BOOLEAN: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + break; + } + + case Property::INTEGER: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + break; + } + + case Property::FLOAT: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + break; + } + + case Property::VECTOR2: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + break; + } + + case Property::VECTOR3: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + break; + } + + case Property::VECTOR4: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + break; + } + + case Property::MATRIX: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + break; + } + + case Property::MATRIX3: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + break; + } + + case Property::ROTATION: + { + newProperty = new AnimatableProperty( propertyValue.Get() ); + 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; + } } - mPropertyNotifications->push_back(propertyNotification); - return propertyNotification; + // 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(GetEventThreadServices()), *scenePropertyOwner, newProperty ); // Message takes ownership + + return index; + } + else + { + // property was orphaned and killed so return invalid index + return Property::INVALID_INDEX; + } } -void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification) +void Object::RegisterAnimatableProperty( const TypeInfo& typeInfo, + Property::Index index, + const Property::Value* value ) const { - if( mPropertyNotifications ) + // 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 ) { - PropertyNotificationContainerIter iter = mPropertyNotifications->begin(); - while(iter != mPropertyNotifications->end() ) + initialValue = *value; + } + else + { + initialValue = typeInfo.GetPropertyDefaultValue( index ); // recurses type hierarchy + if( Property::NONE == initialValue.GetType() ) { - if(*iter == propertyNotification) + 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 ) { - mPropertyNotifications->erase(iter); - // As we can't ensure all references are removed, we can just disable - // the notification. - GetImplementation(propertyNotification).Disable(); - return; + // If the property is not a component of a base property, register the whole property itself. + RegisterAnimatableProperty( *typeInfo, index, value ); } - ++iter; + 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(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(mAnimatableProperties[mAnimatableProperties.Size()-1]); } } + + return animatableProperty; } -void Object::RemovePropertyNotifications() +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 ) { - // As we can't ensure all references are removed, we can just disable - // the notification. - GetImplementation(*iter).Disable(); - ++iter; + // Go through each custom property + for( auto&& entry : mCustomProperties ) + { + CustomPropertyMetadata* customProperty = static_cast( 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; + } + } + } } - - mPropertyNotifications->clear(); } } @@ -805,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(); } } } @@ -819,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(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* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); DALI_ASSERT_DEBUG( NULL != property ); value = (*property)[ bufferIndex ]; @@ -903,7 +1253,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const case Property::INTEGER: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); DALI_ASSERT_DEBUG( NULL != property ); value = (*property)[ bufferIndex ]; @@ -912,7 +1262,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const case Property::FLOAT: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); DALI_ASSERT_DEBUG( NULL != property ); value = (*property)[ bufferIndex ]; @@ -921,14 +1271,14 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const case Property::VECTOR2: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( 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; } @@ -941,18 +1291,18 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const case Property::VECTOR3: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( 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; } @@ -965,22 +1315,22 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const case Property::VECTOR4: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( 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; } @@ -993,7 +1343,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const case Property::MATRIX: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); DALI_ASSERT_DEBUG( NULL != property ); value = (*property)[ bufferIndex ]; @@ -1002,7 +1352,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const case Property::MATRIX3: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); DALI_ASSERT_DEBUG( NULL != property ); value = (*property)[ bufferIndex ]; @@ -1011,7 +1361,7 @@ Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const case Property::ROTATION: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); + const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); DALI_ASSERT_DEBUG( NULL != property ); value = (*property)[ bufferIndex ]; @@ -1020,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 @@ -1176,238 +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 ); - 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( 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, 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(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(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