X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fcommon%2Fobject-impl.cpp;h=e9f5dbb5375c5a9a93003a943a4997de84d1b8de;hb=75a9e686d7bd23619b22640b01979968772d6303;hp=1663e618a31b599c12562ff3a4e0aea1e9335dbc;hpb=b9455f1f8798591d4a67c7ac116c67c65c2efe62;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 1663e61..e9f5dbb 100644 --- a/dali/internal/event/common/object-impl.cpp +++ b/dali/internal/event/common/object-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -22,242 +22,144 @@ #include // INTERNAL INCLUDES -#include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include #include -#include -#include -#include -#include using Dali::Internal::SceneGraph::AnimatableProperty; using Dali::Internal::SceneGraph::PropertyBase; namespace Dali { - 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; +const int32_t SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES; // Object provides this capability #if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" ); +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 -Object::Object() -: mEventThreadServices( *Stage::GetCurrent() ), - mTypeInfo( NULL ), - mConstraints( NULL ), - mPropertyNotifications( NULL ) +IntrusivePtr Object::New() { + return new Object(nullptr); // no scene object by default } void Object::AddObserver(Observer& observer) { // make sure an observer doesn't observe the same object twice // otherwise it will get multiple calls to OnSceneObjectAdd(), OnSceneObjectRemove() and ObjectDestroyed() - DALI_ASSERT_DEBUG( mObservers.End() == std::find( mObservers.Begin(), mObservers.End(), &observer)); + DALI_ASSERT_DEBUG(mObservers.End() == std::find(mObservers.Begin(), mObservers.End(), &observer)); - mObservers.PushBack( &observer ); + mObservers.PushBack(&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) + if((*iter) == &observer) { - mObservers.Erase( iter ); + mObservers.Erase(iter); break; } } 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 +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 ); - - const TypeInfo* typeInfo( GetTypeInfo() ); - if ( typeInfo ) + 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 ); + DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Custom Properties: %d\n", custom); - DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties: %d\n", count ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "Total Properties: %d\n", count); return count; } -std::string Object::GetPropertyName( Property::Index index ) const +std::string_view Object::GetPropertyName(Property::Index index) const { - DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" ); + DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index out of bounds"); - if ( index < DEFAULT_PROPERTY_MAX_COUNT ) + // is this a per class or per instance property + if(index < MAX_PER_CLASS_PROPERTY_INDEX) { - std::string string; - - const char * propertyName = GetDefaultPropertyName( index ); - if( propertyName ) + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) { - string = propertyName; + return typeInfo->GetPropertyName(index); } - 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 ) ) ) + else // child property or custom property { - const TypeInfo* typeInfo( GetTypeInfo() ); - if ( typeInfo ) - { - return typeInfo->GetPropertyName( index ); - } - else + CustomPropertyMetadata* custom = FindCustomProperty(index); + if(custom) { - DALI_ASSERT_ALWAYS( ! "Property index is invalid" ); + return custom->name.GetStringView(); } } - CustomPropertyMetadata* custom = FindCustomProperty( index ); - if( custom ) - { - return custom->name; - } - return ""; + DALI_LOG_ERROR("Property index %d not found\n", index); + return {}; } -Property::Index Object::GetPropertyIndex(const std::string& name) const +Property::Index Object::GetPropertyIndex(KeyRef key) const { - Property::Index index = GetDefaultPropertyIndex( name ); + Property::Index index = Property::INVALID_INDEX; - if(index == Property::INVALID_INDEX) + if(key.mType == Property::Key::STRING) { - const TypeInfo* typeInfo( GetTypeInfo() ); - if ( typeInfo ) + 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; - } - } + index = typeInfo->GetPropertyIndex(key.mString); } } - if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) ) + if((index == Property::INVALID_INDEX) && (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->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((key.mType == Property::Key::STRING && custom->name == key.mString) || + (key.mType == Property::Key::INDEX && custom->key == key.mIndex)) { - 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; @@ -274,51 +176,25 @@ Property::Index Object::GetPropertyIndex( Property::Index key ) 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 +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 + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) { - DALI_ASSERT_ALWAYS( ! "Invalid property index" ); + writable = typeInfo->IsPropertyWritable(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 { - CustomPropertyMetadata* custom = FindCustomProperty( index ); - if( custom ) + CustomPropertyMetadata* custom = FindCustomProperty(index); + if(custom) { writable = custom->IsWritable(); } @@ -327,30 +203,25 @@ bool Object::IsPropertyWritable( Property::Index index ) const return writable; } -bool Object::IsPropertyAnimatable( Property::Index index ) const +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 ) - { - 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 { - CustomPropertyMetadata* custom = FindCustomProperty( index ); - if( custom ) + CustomPropertyMetadata* custom = FindCustomProperty(index); + if(custom) { animatable = custom->IsAnimatable(); } @@ -359,30 +230,25 @@ bool Object::IsPropertyAnimatable( Property::Index index ) const return animatable; } -bool Object::IsPropertyAConstraintInput( Property::Index index ) const +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 ) - { - 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 { - CustomPropertyMetadata* custom = FindCustomProperty( index ); - if( custom ) + CustomPropertyMetadata* custom = FindCustomProperty(index); + if(custom) { // ... custom properties can be used as input to a constraint. isConstraintInput = true; @@ -392,31 +258,22 @@ bool Object::IsPropertyAConstraintInput( Property::Index index ) const return isConstraintInput; } -Property::Type Object::GetPropertyType( Property::Index index ) const +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 ); - } + DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds"); - 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 + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) { - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); + return typeInfo->GetPropertyType(index); } } - CustomPropertyMetadata* custom = FindCustomProperty( index ); - if( custom ) + CustomPropertyMetadata* custom = FindCustomProperty(index); + if(custom) { return custom->GetType(); } @@ -424,93 +281,90 @@ Property::Type Object::GetPropertyType( Property::Index index ) const return Property::NONE; } -DevelHandle::PropertySetSignalType& Object::PropertySetSignal() +void Object::SetProperty(Property::Index index, Property::Value propertyValue) { - return mPropertySetSignal; -} - -void Object::SetProperty( Property::Index index, const Property::Value& propertyValue ) -{ - DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" ); + DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds"); - bool propertySet( true ); + bool propertySet(true); - if ( index < DEFAULT_PROPERTY_MAX_COUNT ) + if(index < DEFAULT_PROPERTY_MAX_COUNT) { - SetDefaultProperty( index, propertyValue ); + SetDefaultProperty(index, propertyValue); } - else 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 ) + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) { - typeInfo->SetProperty( this, index, propertyValue ); + typeInfo->SetProperty(this, index, propertyValue); } 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 ) ) + 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 ); + 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 ); + animatableProperty->SetPropertyValue(propertyValue); // set the scene graph property value - SetSceneGraphProperty( index, *animatableProperty, propertyValue ); + SetSceneGraphProperty(index, *animatableProperty, propertyValue); } } else { - CustomPropertyMetadata* custom = FindCustomProperty( index ); + CustomPropertyMetadata* custom = FindCustomProperty(index); - if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) ) + if((index >= CHILD_PROPERTY_REGISTRATION_START_INDEX) && (index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX)) { - if( !custom ) + if(!custom) { // If the child property is not registered yet, register it. - custom = new CustomPropertyMetadata( "", propertyValue, Property::READ_WRITE ); - mCustomProperties.PushBack( custom ); + custom = new CustomPropertyMetadata({}, propertyValue, Property::READ_WRITE); + mCustomProperties.PushBack(custom); } custom->childPropertyIndex = index; // Resolve name for the child property Object* parent = GetParentObject(); - if( parent ) + if(parent) { - const TypeInfo* parentTypeInfo( parent->GetTypeInfo() ); - if( parentTypeInfo ) + const TypeInfo* parentTypeInfo(parent->GetTypeInfo()); + if(parentTypeInfo) { - custom->name = parentTypeInfo->GetChildPropertyName( index ); + custom->name = ConstString(parentTypeInfo->GetChildPropertyName(index)); } } } - if( custom ) + if(custom) { - if( custom->IsAnimatable() ) + if(custom->IsAnimatable()) { // update the cached property value - custom->SetPropertyValue( propertyValue ); + custom->SetPropertyValue(propertyValue); // set the scene graph property value - SetSceneGraphProperty( index, *custom, propertyValue ); + SetSceneGraphProperty(index, *custom, propertyValue); } - else if( custom->IsWritable() ) + else if(custom->IsWritable()) { // update the cached property value - custom->SetPropertyValue( propertyValue ); + custom->SetPropertyValue(propertyValue); } else { @@ -520,60 +374,64 @@ 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; } } // 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 ) + if(propertySet) { - OnPropertySet( index, propertyValue ); - Dali::Handle handle( this ); - mPropertySetSignal.Emit( handle, index, propertyValue ); + OnPropertySet(index, propertyValue); + if(!mPropertySetSignal.Empty()) + { + Dali::Handle handle(this); + mPropertySetSignal.Emit(handle, index, propertyValue); + } } } Property::Value Object::GetProperty(Property::Index index) const { - DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" ); + DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds"); Property::Value value; - if ( index < DEFAULT_PROPERTY_MAX_COUNT ) + if(index < DEFAULT_PROPERTY_MAX_COUNT) { - value = GetDefaultProperty( index ); + value = GetDefaultProperty(index); } - else 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 ) + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) { - value = typeInfo->GetProperty( this, index ); + value = typeInfo->GetProperty(this, index); } 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 ) ) + 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) { - DALI_LOG_ERROR("Cannot find property index\n"); + // get the cached animatable property value + value = animatableProperty->GetPropertyValue(); } else { - // get the cached animatable property value - value = animatableProperty->GetPropertyValue(); + DALI_LOG_ERROR("Property index %d not found\n", index); } } else if(mCustomProperties.Count() > 0) { - CustomPropertyMetadata* custom = FindCustomProperty( index ); + CustomPropertyMetadata* custom = FindCustomProperty(index); if(custom) { // get the cached custom property value @@ -581,319 +439,252 @@ Property::Value Object::GetProperty(Property::Index index) const } else { - DALI_LOG_ERROR("Invalid property index\n"); + DALI_LOG_ERROR("Property index %d not found\n", index); } } // if custom return value; } -Property::Value Object::GetCurrentProperty( Property::Index index ) const +Property::Value Object::GetCurrentProperty(Property::Index index) const { - DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" ); + DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds"); Property::Value value; - if ( index < DEFAULT_PROPERTY_MAX_COUNT ) + if(index < DEFAULT_PROPERTY_MAX_COUNT) { - value = GetDefaultPropertyCurrentValue( index ); + value = GetDefaultPropertyCurrentValue(index); } - else 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 ) + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) { - value = typeInfo->GetProperty( this, index ); + value = typeInfo->GetProperty(this, index); } 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 ) ) + 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) { - DALI_LOG_ERROR("Cannot find property index\n"); + // get the animatable property value + value = GetCurrentPropertyValue(*animatableProperty); } else { - // get the animatable property value - value = GetCurrentPropertyValue( animatableProperty ); + DALI_LOG_ERROR("Property index %d not found\n", index); } } else if(mCustomProperties.Count() > 0) { - CustomPropertyMetadata* custom = FindCustomProperty( index ); + CustomPropertyMetadata* custom = FindCustomProperty(index); if(custom) { // get the custom property value - value = GetCurrentPropertyValue( custom ); + value = GetCurrentPropertyValue(*custom); } else { - DALI_LOG_ERROR("Invalid property index\n"); + DALI_LOG_ERROR("Property index %d not found\n", index); } } // if custom return value; } -void Object::GetPropertyIndices( Property::IndexContainer& indices ) const +void Object::GetPropertyIndices(Property::IndexContainer& indices) const { indices.Clear(); - // Default Properties - GetDefaultPropertyIndices( indices ); - // Manual Properties - const TypeInfo* typeInfo( GetTypeInfo() ); - if ( typeInfo ) + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) { - typeInfo->GetPropertyIndices( indices ); + typeInfo->GetPropertyIndices(indices); } // Custom Properties - if ( mCustomProperties.Count() > 0 ) + if(mCustomProperties.Count() > 0) { - indices.Reserve( indices.Size() + mCustomProperties.Count() ); + indices.Reserve(indices.Size() + mCustomProperties.Count()); - PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); - const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End(); - int i=0; - for ( ; iter != endIter; ++iter, ++i ) + auto iter = mCustomProperties.Begin(); + const auto endIter = mCustomProperties.End(); + int32_t i = 0; + for(; iter != endIter; ++iter, ++i) { - CustomPropertyMetadata* custom = static_cast( *iter ); - if ( custom->childPropertyIndex != Property::INVALID_INDEX ) + 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 ); + indices.PushBack(custom->childPropertyIndex); } else { - indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i ); + indices.PushBack(PROPERTY_CUSTOM_START_INDEX + i); } } } } -bool Object::DoesCustomPropertyExist( Property::Index index ) +Property::Index Object::RegisterProperty(std::string_view name, Property::Value propertyValue) { - auto metadata = FindCustomProperty( index ); - return metadata != nullptr; + return RegisterProperty(name, Property::INVALID_KEY, std::move(propertyValue), Property::ANIMATABLE); } -Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index key, Property::Index index, const Property::Value& propertyValue) const +Property::Index Object::RegisterProperty(std::string_view name, Property::Index key, Property::Value propertyValue) { - // Create a new property - Dali::Internal::OwnerPointer newProperty; + return RegisterProperty(name, key, std::move(propertyValue), Property::ANIMATABLE); +} - switch ( propertyValue.GetType() ) +void Object::SetProperties(const Property::Map& properties) +{ + const auto count = properties.Count(); + for(auto position = 0u; position < count; ++position) { - 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; - } + // GetKeyAt and GetValue both return references which means no potential copying of maps/arrays. + // Iterating twice to get the value we want should still be fairly quick in a Property::Map. - case Property::ROTATION: - { - newProperty = new AnimatableProperty( propertyValue.Get() ); - break; - } + const auto& key = properties.GetKeyAt(position); + const auto propertyIndex = (key.type == Property::Key::INDEX) ? key.indexKey : GetPropertyIndex(key); - case Property::RECTANGLE: - case Property::STRING: - case Property::ARRAY: - case Property::MAP: - case Property::EXTENTS: - case Property::NONE: + if(propertyIndex != Property::INVALID_INDEX) { - DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" ); - break; + const auto& value = properties.GetValue(position); + SetProperty(propertyIndex, value); } } +} - // 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 +void Object::GetProperties(Property::Map& properties) +{ + properties.Clear(); - // 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 ); + Property::IndexContainer indexContainer; + GetPropertyIndices(indexContainer); - return index; - } - else + for(auto index : indexContainer) { - // property was orphaned and killed so return invalid index - return Property::INVALID_INDEX; + properties[index] = GetProperty(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, Property::Index key, const Property::Value& propertyValue ) -{ - return RegisterProperty( name, key, propertyValue, Property::ANIMATABLE ); -} - -Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode ) +Property::Index Object::RegisterProperty(std::string_view name, + Property::Value propertyValue, + Property::AccessMode accessMode) { - return RegisterProperty( name, Property::INVALID_KEY, propertyValue, accessMode ); + return RegisterProperty(name, Property::INVALID_KEY, std::move(propertyValue), accessMode); } -Property::Index Object::RegisterProperty( const std::string& name, Property::Index key, const Property::Value& propertyValue, Property::AccessMode accessMode ) +Property::Index Object::RegisterProperty(std::string_view name, + Property::Index key, + Property::Value propertyValue, + Property::AccessMode accessMode) { + auto constString = ConstString(name); // 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 + if(key != Property::INVALID_KEY) // Try integer key first if it's valid { - index = GetPropertyIndex( key ); + index = GetPropertyIndex(key); } - if( index == Property::INVALID_INDEX ) // If it wasn't valid, or doesn't exist, try name + if(index == Property::INVALID_INDEX) // If it wasn't valid, or doesn't exist, try name { - index = GetPropertyIndex( name ); + index = GetPropertyIndex(constString); } - if( index != Property::INVALID_INDEX ) // If there was a valid index found by either key, set it. + if(index != Property::INVALID_INDEX) // If there was a valid index found by either key, set it. { - SetProperty( index, propertyValue ); + SetProperty(index, std::move(propertyValue)); } else { // Otherwise register the property - - if( Property::ANIMATABLE == accessMode ) + if(Property::ANIMATABLE == accessMode) { - index = RegisterSceneGraphProperty( name, key, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue ); - AddUniformMapping( index, name ); + index = RegisterSceneGraphProperty( + constString, + key, + PROPERTY_CUSTOM_START_INDEX + static_cast(mCustomProperties.Count()), + std::move(propertyValue)); + AddUniformMapping(index, constString); } else { // Add entry to the property lookup - index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(); + index = PROPERTY_CUSTOM_START_INDEX + static_cast(mCustomProperties.Count()); - CustomPropertyMetadata* customProperty = new CustomPropertyMetadata( name, propertyValue, accessMode ); + CustomPropertyMetadata* customProperty = + new CustomPropertyMetadata(constString, std::move(propertyValue), accessMode); // Resolve index for the child property Object* parent = GetParentObject(); - if( parent ) + if(parent) { - const TypeInfo* parentTypeInfo( parent->GetTypeInfo() ); - if( parentTypeInfo ) + const TypeInfo* parentTypeInfo(parent->GetTypeInfo()); + if(parentTypeInfo) { - Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex( name ); - if( childPropertyIndex != Property::INVALID_INDEX ) + Property::Index childPropertyIndex = parentTypeInfo->GetChildPropertyIndex(customProperty->name); + if(childPropertyIndex != Property::INVALID_INDEX) { customProperty->childPropertyIndex = childPropertyIndex; - index = childPropertyIndex; + index = childPropertyIndex; } } } - mCustomProperties.PushBack( customProperty ); + mCustomProperties.PushBack(customProperty); } } return index; } -Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index, - int componentIndex, - const Dali::PropertyCondition& condition) +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 >= DEFAULT_PROPERTY_MAX_COUNT) { - if ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) + if(index <= PROPERTY_REGISTRATION_MAX_INDEX) { - DALI_ABORT( "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 ) ) + 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" ); + AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty(index, nullptr); + DALI_ASSERT_ALWAYS(animatable && "Property index is invalid"); } - else if ( mCustomProperties.Count() > 0 ) + 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." ); + CustomPropertyMetadata* custom = FindCustomProperty(index); + DALI_ASSERT_ALWAYS(custom && "Invalid property index"); + DALI_ASSERT_ALWAYS(custom->IsAnimatable() && "Property notification added to event side only property."); } } Dali::Handle self(this); - Property target( self, index ); + Property target(self, index); - PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition ); + PropertyNotificationPtr internal = PropertyNotification::New(target, componentIndex, condition); Dali::PropertyNotification propertyNotification(internal.Get()); - if( !mPropertyNotifications ) + if(!mPropertyNotifications) { mPropertyNotifications = new PropertyNotificationContainer; } @@ -904,10 +695,10 @@ Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification) { - if( mPropertyNotifications ) + if(mPropertyNotifications) { - PropertyNotificationContainerIter iter = mPropertyNotifications->begin(); - while(iter != mPropertyNotifications->end() ) + auto iter = mPropertyNotifications->begin(); + while(iter != mPropertyNotifications->end()) { if(*iter == propertyNotification) { @@ -924,10 +715,10 @@ void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotif void Object::RemovePropertyNotifications() { - if( mPropertyNotifications ) + if(mPropertyNotifications) { - PropertyNotificationContainerIter iter = mPropertyNotifications->begin(); - while(iter != mPropertyNotifications->end() ) + auto iter = mPropertyNotifications->begin(); + while(iter != mPropertyNotifications->end()) { // As we can't ensure all references are removed, we can just disable // the notification. @@ -939,43 +730,43 @@ void Object::RemovePropertyNotifications() } } -void Object::NotifyPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType ) +void Object::NotifyPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType) { - if ( index < DEFAULT_PROPERTY_MAX_COUNT ) + if(index < DEFAULT_PROPERTY_MAX_COUNT) { - OnNotifyDefaultPropertyAnimation( animation, index, value, animationType ); + OnNotifyDefaultPropertyAnimation(animation, index, value, animationType); } else { - PropertyMetadata* propertyMetadata = NULL; - if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + PropertyMetadata* propertyMetadata = nullptr; + if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX)) { - propertyMetadata = FindAnimatableProperty( index ); + propertyMetadata = FindAnimatableProperty(index); } else { - CustomPropertyMetadata* custom = FindCustomProperty( index ); - if( custom && custom->IsAnimatable() ) + CustomPropertyMetadata* custom = FindCustomProperty(index); + if(custom && custom->IsAnimatable()) { propertyMetadata = custom; } } - if( propertyMetadata ) + if(propertyMetadata) { - switch( animationType ) + switch(animationType) { case Animation::TO: case Animation::BETWEEN: { // Update the cached property value - propertyMetadata->SetPropertyValue( value ); + propertyMetadata->SetPropertyValue(value); break; } case Animation::BY: { // Adjust the cached property value - propertyMetadata->AdjustPropertyValueBy( value ); + propertyMetadata->AdjustPropertyValueBy(value); break; } } @@ -983,220 +774,667 @@ void Object::NotifyPropertyAnimation( Animation& animation, Property::Index inde } } -void Object::EnablePropertyNotifications() -{ - if( mPropertyNotifications ) - { - PropertyNotificationContainerIter iter = mPropertyNotifications->begin(); - PropertyNotificationContainerIter endIter = mPropertyNotifications->end(); - - for( ; iter != endIter; ++iter ) - { - GetImplementation(*iter).Enable(); - } - } -} - -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 +void Object::AddUniformMapping(Property::Index propertyIndex, ConstString uniformName) const { // Get the address of the property if it's a scene property - const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex ); + const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty(propertyIndex); // Check instead for newly registered properties - if( propertyPtr == NULL ) + if(propertyPtr == nullptr) { - PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex ); - if( animatable != NULL ) + PropertyMetadata* animatable = FindAnimatableProperty(propertyIndex); + if(animatable) { propertyPtr = animatable->GetSceneGraphProperty(); } } - if( propertyPtr == NULL ) + if(propertyPtr == nullptr) { - PropertyMetadata* custom = FindCustomProperty( propertyIndex ); - if( custom != NULL ) + PropertyMetadata* custom = FindCustomProperty(propertyIndex); + if(custom) { propertyPtr = custom->GetSceneGraphProperty(); } } - if( propertyPtr != NULL ) + if(propertyPtr) { - const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner(); + const SceneGraph::PropertyOwner& sceneObject = GetSceneObject(); - 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" ); - } + SceneGraph::UniformPropertyMapping map(uniformName, propertyPtr); + // Message takes ownership of Uniform map (and will delete it after copy) + AddUniformMapMessage(const_cast(GetEventThreadServices()), sceneObject, map); } } -void Object::RemoveUniformMapping( const std::string& uniformName ) +void Object::RemoveUniformMapping(const std::string& uniformName) const { - const SceneGraph::PropertyOwner* sceneObject = GetSceneObject(); - RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName); + const SceneGraph::PropertyOwner& sceneObject = GetSceneObject(); + RemoveUniformMapMessage(const_cast(GetEventThreadServices()), sceneObject, ConstString(uniformName)); } -Property::Value Object::GetCurrentPropertyValue( const PropertyMetadata* entry ) const +void Object::ApplyConstraint(ConstraintBase& constraint) { - Property::Value value; - - DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" ); - - if( !entry->IsAnimatable() ) + if(!mConstraints) { - value = entry->GetPropertyValue(); + mConstraints = new ConstraintContainer; } - else - { - BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() ); + mConstraints->push_back(Dali::Constraint(&constraint)); +} - switch ( entry->GetType() ) +void Object::RemoveConstraint(ConstraintBase& constraint) +{ + // nullptr 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()) { - case Property::BOOLEAN: - { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); - - value = (*property)[ bufferIndex ]; - break; + mConstraints->erase(it); + } + } +} + +void Object::RemoveConstraints() +{ + // guard against constraint sending messages during core destruction + if(mConstraints && Stage::IsInstalled()) + { + for(auto&& item : *mConstraints) + { + GetImplementation(item).RemoveInternal(); + } + + delete mConstraints; + mConstraints = nullptr; + } +} + +void Object::RemoveConstraints(uint32_t tag) +{ + // guard against constraint sending messages during core destruction + if(mConstraints && Stage::IsInstalled()) + { + auto iter(mConstraints->begin()); + while(iter != mConstraints->end()) + { + ConstraintBase& constraint = GetImplementation(*iter); + if(constraint.GetTag() == tag) + { + GetImplementation(*iter).RemoveInternal(); + iter = mConstraints->erase(iter); + } + else + { + ++iter; + } + } + + if(mConstraints->empty()) + { + delete mConstraints; + mConstraints = nullptr; + } + } +} + +void Object::SetTypeInfo(const TypeInfo* typeInfo) +{ + mTypeInfo = typeInfo; +} + +const SceneGraph::PropertyOwner& Object::GetSceneObject() const +{ + if(!mUpdateObject) + { + auto sceneObject = SceneGraph::PropertyOwner::New(); + OwnerPointer transferOwnership(sceneObject); + mUpdateObject = sceneObject; + AddObjectMessage(const_cast(GetEventThreadServices()).GetUpdateManager(), transferOwnership); + } + DALI_ASSERT_DEBUG(mUpdateObject && "there must always be a scene object"); + return *mUpdateObject; +} + +const PropertyBase* Object::GetSceneObjectAnimatableProperty(Property::Index index) const +{ + const SceneGraph::PropertyBase* property = nullptr; + if(index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX) + { + AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty(index, nullptr); + DALI_ASSERT_ALWAYS(animatable && "Property index is invalid"); + + property = animatable->GetSceneGraphProperty(); + } + else if((index >= CHILD_PROPERTY_REGISTRATION_START_INDEX) && // Child properties are also stored as custom properties + (index <= PROPERTY_CUSTOM_MAX_INDEX)) + { + CustomPropertyMetadata* custom = FindCustomProperty(index); + DALI_ASSERT_ALWAYS(custom && "Property index is invalid"); + + property = custom->GetSceneGraphProperty(); + } + return property; +} + +const PropertyInputImpl* Object::GetSceneObjectInputProperty(Property::Index index) const +{ + // reuse animatable version as they are inputs as well + return GetSceneObjectAnimatableProperty(index); +} + +int32_t Object::GetPropertyComponentIndex(Property::Index index) const +{ + int32_t componentIndex = Property::INVALID_COMPONENT_INDEX; + + if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX)) + { + // check whether the animatable property is registered already, if not then register one. + AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty(index, nullptr); + if(animatableProperty) + { + componentIndex = animatableProperty->componentIndex; + } + } + if(Property::INVALID_COMPONENT_INDEX == componentIndex) + { + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) + { + componentIndex = typeInfo->GetComponentIndex(index); + } + } + + return componentIndex; +} + +Handle::PropertySetSignalType& Object::PropertySetSignal() +{ + return mPropertySetSignal; +} + +Object::Object(const SceneGraph::PropertyOwner* sceneObject) +: mEventThreadServices(EventThreadServices::Get()), + mUpdateObject(sceneObject), + mTypeInfo(nullptr), + mConstraints(nullptr), + mPropertyNotifications(nullptr) +{ +} + +Object::~Object() +{ + // Notification for observers + for(auto&& item : mObservers) + { + item->ObjectDestroyed(*this); + } + + // Disable property notifications in scene graph + DisablePropertyNotifications(); + + delete mConstraints; + delete mPropertyNotifications; + + // Guard to allow handle destruction after Core has been destroyed + if(Stage::IsInstalled()) + { + if(nullptr != mUpdateObject) + { + RemoveObjectMessage(GetEventThreadServices().GetUpdateManager(), mUpdateObject); + } + } +} + +void Object::OnSceneObjectAdd() +{ + // Notification for observers + for(auto&& item : mObservers) + { + item->SceneObjectAdded(*this); + } + + // enable property notifications in scene graph + EnablePropertyNotifications(); +} + +void Object::OnSceneObjectRemove() +{ + // Notification for observers + for(auto&& item : mObservers) + { + item->SceneObjectRemoved(*this); + } + + // disable property notifications in scene graph + DisablePropertyNotifications(); +} + +const TypeInfo* Object::GetTypeInfo() const +{ + if(!mTypeInfo) + { + // This uses a dynamic_cast so can be quite expensive so we only really want to do it once + // especially as the type-info does not change during the life-time of an application + + TypeRegistry::TypeInfoPointer typeInfoHandle = TypeRegistry::Get()->GetTypeInfo(this); + if(typeInfoHandle) + { + mTypeInfo = typeInfoHandle.Get(); // just a raw pointer to use, ownership is kept + } + } + + return mTypeInfo; +} + +CustomPropertyMetadata* Object::FindCustomProperty(Property::Index index) const +{ + CustomPropertyMetadata* property = nullptr; + if((index >= CHILD_PROPERTY_REGISTRATION_START_INDEX) && (index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX)) + { + for(std::size_t arrayIndex = 0; arrayIndex < mCustomProperties.Count(); arrayIndex++) + { + CustomPropertyMetadata* custom = static_cast(mCustomProperties[arrayIndex]); + if(custom->childPropertyIndex == index) + { + property = custom; + } + } + } + else + { + int32_t arrayIndex = index - PROPERTY_CUSTOM_START_INDEX; + if(arrayIndex >= 0) + { + if(arrayIndex < static_cast(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(auto&& entry : mAnimatableProperties) + { + AnimatablePropertyMetadata* property = static_cast(entry); + if(property->index == index) + { + return property; + } + } + return nullptr; +} + +Property::Index Object::RegisterSceneGraphProperty(ConstString name, Property::Index key, Property::Index index, Property::Value propertyValue) const +{ + // Create a new property + Dali::Internal::OwnerPointer newProperty; + + switch(propertyValue.GetType()) + { + 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; + } + } + + // get the scene property owner + const SceneGraph::PropertyOwner& scenePropertyOwner = GetSceneObject(); + // keep a local pointer to the property as the OwnerPointer will pass its copy to the message + const PropertyBase* property = newProperty.Get(); + if(index >= PROPERTY_CUSTOM_START_INDEX) + { + DALI_ASSERT_ALWAYS(index <= PROPERTY_CUSTOM_MAX_INDEX && "Too many custom properties have been registered"); + + mCustomProperties.PushBack(new CustomPropertyMetadata(name, key, std::move(propertyValue), property)); + } + else + { + mAnimatableProperties.PushBack(new AnimatablePropertyMetadata(index, std::move(propertyValue), property)); + } + + // queue a message to add the property + InstallCustomPropertyMessage(const_cast(GetEventThreadServices()), scenePropertyOwner, newProperty); // Message takes ownership + + return index; +} + +void Object::RegisterAnimatableProperty(const TypeInfo& typeInfo, + Property::Index index, + const Property::Value* value) const +{ + // If the property is not a component of a base property, register the whole property itself. + auto propertyName = ConstString(typeInfo.GetPropertyName(index)); + Property::Value initialValue; + if(value) + { + initialValue = *value; + } + else + { + initialValue = typeInfo.GetPropertyDefaultValue(index); // recurses type hierarchy + if(Property::NONE == initialValue.GetType()) + { + initialValue = Property::Value(typeInfo.GetPropertyType(index)); // recurses type hierarchy + } + } + RegisterSceneGraphProperty(propertyName, Property::INVALID_KEY, index, initialValue); + AddUniformMapping(index, propertyName); +} + +AnimatablePropertyMetadata* Object::GetSceneAnimatableProperty(Property::Index index, const Property::Value* value) const +{ + // property range already checked by calling methods + // check whether the animatable property is registered already, if not then register one. + AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty(index); + if(!animatableProperty) + { + const TypeInfo* typeInfo(GetTypeInfo()); + if(typeInfo) + { + Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index); + if(basePropertyIndex == Property::INVALID_INDEX) + { + // If the property is not a component of a base property, register the whole property itself. + RegisterAnimatableProperty(*typeInfo, index, value); + } + else + { + // Since the property is a component of a base property, check whether the base property is registered. + animatableProperty = FindAnimatableProperty(basePropertyIndex); + if(!animatableProperty) + { + // If the base property is not registered yet, register the base property first. + RegisterAnimatableProperty(*typeInfo, basePropertyIndex, value); + animatableProperty = static_cast(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::ResolveChildProperties() +{ + // Resolve index for the child property + Object* parent = GetParentObject(); + if(parent) + { + const TypeInfo* parentTypeInfo(parent->GetTypeInfo()); + if(parentTypeInfo) + { + // Go through each custom property + for(auto&& entry : mCustomProperties) + { + CustomPropertyMetadata* customProperty = static_cast(entry); + + if(customProperty->name.IsEmpty()) + { + if(customProperty->childPropertyIndex != Property::INVALID_INDEX) + { + // Resolve name for any child property with no name + customProperty->name = ConstString(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; + } + } + } + } + } +} + +void Object::SetDefaultProperty(Property::Index index, const Property::Value& property) +{ + // do nothing +} + +Property::Value Object::GetDefaultProperty(Property::Index index) const +{ + return Property::Value(); +} + +Property::Value Object::GetDefaultPropertyCurrentValue(Property::Index index) const +{ + return GetDefaultProperty(index); +} + +void Object::EnablePropertyNotifications() +{ + if(mPropertyNotifications) + { + for(auto&& element : *mPropertyNotifications) + { + GetImplementation(element).Enable(); + } + } +} + +void Object::DisablePropertyNotifications() +{ + if(mPropertyNotifications) + { + for(auto&& element : *mPropertyNotifications) + { + GetImplementation(element).Disable(); + } + } +} + +Property::Value Object::GetCurrentPropertyValue(const PropertyMetadata& entry) const +{ + Property::Value value; + + if(!entry.IsAnimatable()) + { + value = entry.GetPropertyValue(); + } + else + { + BufferIndex bufferIndex(GetEventThreadServices().GetEventBufferIndex()); + + switch(entry.GetType()) + { + case Property::BOOLEAN: + { + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); + + value = (*property)[bufferIndex]; + break; } case Property::INTEGER: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); - value = (*property)[ bufferIndex ]; + value = (*property)[bufferIndex]; break; } case Property::FLOAT: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); - value = (*property)[ bufferIndex ]; + value = (*property)[bufferIndex]; break; } case Property::VECTOR2: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); - if(entry->componentIndex == 0) + if(entry.componentIndex == 0) { - value = (*property)[ bufferIndex ].x; + value = (*property)[bufferIndex].x; } - else if(entry->componentIndex == 1) + else if(entry.componentIndex == 1) { - value = (*property)[ bufferIndex ].y; + value = (*property)[bufferIndex].y; } else { - value = (*property)[ bufferIndex ]; + value = (*property)[bufferIndex]; } break; } case Property::VECTOR3: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); - if(entry->componentIndex == 0) + if(entry.componentIndex == 0) { - value = (*property)[ bufferIndex ].x; + value = (*property)[bufferIndex].x; } - else if(entry->componentIndex == 1) + else if(entry.componentIndex == 1) { - value = (*property)[ bufferIndex ].y; + value = (*property)[bufferIndex].y; } - else if(entry->componentIndex == 2) + else if(entry.componentIndex == 2) { - value = (*property)[ bufferIndex ].z; + value = (*property)[bufferIndex].z; } else { - value = (*property)[ bufferIndex ]; + value = (*property)[bufferIndex]; } break; } case Property::VECTOR4: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); - if(entry->componentIndex == 0) + if(entry.componentIndex == 0) { - value = (*property)[ bufferIndex ].x; + value = (*property)[bufferIndex].x; } - else if(entry->componentIndex == 1) + else if(entry.componentIndex == 1) { - value = (*property)[ bufferIndex ].y; + value = (*property)[bufferIndex].y; } - else if(entry->componentIndex == 2) + else if(entry.componentIndex == 2) { - value = (*property)[ bufferIndex ].z; + value = (*property)[bufferIndex].z; } - else if(entry->componentIndex == 3) + else if(entry.componentIndex == 3) { - value = (*property)[ bufferIndex ].w; + value = (*property)[bufferIndex].w; } else { - value = (*property)[ bufferIndex ]; + value = (*property)[bufferIndex]; } break; } case Property::MATRIX: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); - value = (*property)[ bufferIndex ]; + value = (*property)[bufferIndex]; break; } case Property::MATRIX3: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); - value = (*property)[ bufferIndex ]; + value = (*property)[bufferIndex]; break; } case Property::ROTATION: { - const AnimatableProperty* property = static_cast< const AnimatableProperty* >( entry->GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = static_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); - value = (*property)[ bufferIndex ]; + value = (*property)[bufferIndex]; break; } @@ -1205,87 +1443,87 @@ Property::Value Object::GetCurrentPropertyValue( const PropertyMetadata* entry ) // unreachable code due to higher level logic } } // switch(type) - } // if animatable + } // if animatable return value; } -void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value ) +void Object::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value) { - switch ( entry.GetType() ) + switch(entry.GetType()) { case Property::BOOLEAN: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(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: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(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::FLOAT: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(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::VECTOR2: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); // property is being used in a separate thread; queue a message to set the property if(entry.componentIndex == 0) { - SetXComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetXComponentMessage(GetEventThreadServices(), *property, value.Get()); } else if(entry.componentIndex == 1) { - SetYComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetYComponentMessage(GetEventThreadServices(), *property, value.Get()); } else { - BakeMessage( GetEventThreadServices(), *property, value.Get() ); + BakeMessage(GetEventThreadServices(), *property, value.Get()); } break; } case Property::VECTOR3: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); // property is being used in a separate thread; queue a message to set the property if(entry.componentIndex == 0) { - SetXComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetXComponentMessage(GetEventThreadServices(), *property, value.Get()); } else if(entry.componentIndex == 1) { - SetYComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetYComponentMessage(GetEventThreadServices(), *property, value.Get()); } else if(entry.componentIndex == 2) { - SetZComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetZComponentMessage(GetEventThreadServices(), *property, value.Get()); } else { - BakeMessage( GetEventThreadServices(), *property, value.Get() ); + BakeMessage(GetEventThreadServices(), *property, value.Get()); } break; @@ -1293,60 +1531,60 @@ void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadat case Property::VECTOR4: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(property); // property is being used in a separate thread; queue a message to set the property if(entry.componentIndex == 0) { - SetXComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetXComponentMessage(GetEventThreadServices(), *property, value.Get()); } else if(entry.componentIndex == 1) { - SetYComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetYComponentMessage(GetEventThreadServices(), *property, value.Get()); } else if(entry.componentIndex == 2) { - SetZComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetZComponentMessage(GetEventThreadServices(), *property, value.Get()); } else if(entry.componentIndex == 3) { - SetWComponentMessage( GetEventThreadServices(), *property, value.Get() ); + SetWComponentMessage(GetEventThreadServices(), *property, value.Get()); } else { - BakeMessage( GetEventThreadServices(), *property, value.Get() ); + BakeMessage(GetEventThreadServices(), *property, value.Get()); } break; } case Property::ROTATION: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(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::MATRIX: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(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::MATRIX3: { - const AnimatableProperty* property = dynamic_cast< const AnimatableProperty* >( entry.GetSceneGraphProperty() ); - DALI_ASSERT_DEBUG( NULL != property ); + const AnimatableProperty* property = dynamic_cast*>(entry.GetSceneGraphProperty()); + DALI_ASSERT_DEBUG(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; } @@ -1357,241 +1595,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 < static_cast( 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 -{ - const PropertyMetadataLookup::SizeType count = mAnimatableProperties.Count(); - for ( PropertyMetadataLookup::SizeType arrayIndex = 0; arrayIndex < 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 - const PropertyMetadataLookup::SizeType count = mCustomProperties.Count(); - for ( PropertyMetadataLookup::SizeType arrayIndex = 0; arrayIndex < 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