X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fcommon%2Ftype-info-impl.cpp;h=7133dce6b839dcdaa073cd651f06b6a266c16979;hb=33a8477946185463936981476e9772d40c37fd72;hp=b73d9255cdb49c879560b9a756aed8030d595615;hpb=4d2271bd7ba9d977bfa62147fc33837f727e8df8;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/common/type-info-impl.cpp b/dali/internal/event/common/type-info-impl.cpp index b73d925..7133dce 100644 --- a/dali/internal/event/common/type-info-impl.cpp +++ b/dali/internal/event/common/type-info-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -24,18 +24,21 @@ // INTERNAL INCLUDES #include -#include #include +#include using std::find_if; +namespace Dali +{ +namespace Internal +{ namespace { - /* * Functor to find by given type for vector of pairs */ -template +template struct PairFinder { PairFinder(const S& find) @@ -49,137 +52,212 @@ struct PairFinder } private: - const S& mFind; }; /** * Functor to find a matching property name */ -template +template struct PropertyNameFinder { - PropertyNameFinder( const std::string& find ) - : mFind( find ) + PropertyNameFinder(ConstString find) + : mFind(find) { } - bool operator()(const T &p) const + bool operator()(const T& p) const { return p.second.name == mFind; } private: - - const std::string& mFind; + ConstString mFind; }; /** * Functor to find a matching property component index */ -template +template struct PropertyComponentFinder { - PropertyComponentFinder( Dali::Property::Index basePropertyIndex, const int find ) - : mBasePropertyIndex( basePropertyIndex ), - mFind( find ) + PropertyComponentFinder(Property::Index basePropertyIndex, const int find) + : mBasePropertyIndex(basePropertyIndex), + mFind(find) { } - bool operator()(const T &p) const + bool operator()(const T& p) const { - return ( p.second.basePropertyIndex == mBasePropertyIndex && p.second.componentIndex == mFind ); + return (p.second.basePropertyIndex == mBasePropertyIndex && p.second.componentIndex == mFind); } private: - - Dali::Property::Index mBasePropertyIndex; - const int mFind; + Property::Index mBasePropertyIndex; + const int mFind; }; -} // namespace anon - -namespace Dali +/** + * Helper function to find the right default property with given index and return the desired detail of it + */ +template +inline bool GetDefaultPropertyField(const Dali::PropertyDetails* propertyTable, Property::Index count, Property::Index index, Member member, Parameter& parameter) { + bool found = false; + // is index inside this table (bigger than first index but smaller than first + count) + if((index >= propertyTable->enumIndex) && (index < (propertyTable->enumIndex + count))) + { + // return the match. we're assuming here that there is no gaps between the indices in a table + parameter = propertyTable[index - propertyTable->enumIndex].*member; + found = true; + } + // should never really get here + return found; +} -namespace Internal +// static pointer value to mark that a base class address has not been resolved +// 0x01 is not a valid pointer but used here to differentiate from nullptr +// unfortunately it cannot be constexpr as C++ does not allow them to be initialised with reinterpret_cast +Internal::TypeInfo* const UNRESOLVED = reinterpret_cast(0x1); + +/** + * Helper function to resolve and return the pointer to the base type info + * Not a member function to avoid having to #include additional headers and to make sure this gets inlined inside this cpp + * @param[in/out] baseType pointer to resolve and set + * @param[in] typeRegistry reference to the type registry + * @param[in] baseTypeName string name of the base type + * @return true is base type exists + */ +inline bool GetBaseType(Internal::TypeInfo*& baseType, TypeRegistry& typeRegistry, const std::string& baseTypeName) { + // if greater than unresolved means we have a base type, null means no base + bool baseExists = (baseType > UNRESOLVED); + // base only needs to be resolved once + if(UNRESOLVED == baseType) + { + TypeRegistry::TypeInfoPointer base = typeRegistry.GetTypeInfo(baseTypeName); + if(base) + { + baseType = base.Get(); // dont pass ownership, just return raw pointer + baseExists = true; + } + else + { + // no type info found so assuming no base as all type registration is done in startup for now + baseType = nullptr; + } + } + return baseExists; +} -TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator) - : mTypeName(name), mBaseTypeName(baseTypeName), mCreate(creator) +} // unnamed namespace + +TypeInfo::TypeInfo(const std::string& name, const std::string& baseTypeName, Dali::TypeInfo::CreateFunction creator, const Dali::PropertyDetails* defaultProperties, Property::Index defaultPropertyCount) +: mTypeRegistry(*TypeRegistry::Get()), + mBaseType(UNRESOLVED), + mTypeName(name), + mBaseTypeName(baseTypeName), + mCreate(creator), + mDefaultProperties(defaultProperties), + mDefaultPropertyCount(defaultPropertyCount), + mCSharpType(false) { DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name"); DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name"); } -TypeInfo::~TypeInfo() +TypeInfo::TypeInfo(const std::string& name, const std::string& baseTypeName, Dali::CSharpTypeInfo::CreateFunction creator) +: mTypeRegistry(*TypeRegistry::Get()), + mBaseType(UNRESOLVED), + mTypeName(name), + mBaseTypeName(baseTypeName), + mCSharpCreate(creator), + mCSharpType(true) { + DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name"); + DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name"); } +TypeInfo::~TypeInfo() = default; + BaseHandle TypeInfo::CreateInstance() const { BaseHandle ret; if(mCreate) { - ret = mCreate(); + if(mCSharpType) + { + // CSharp currently only registers one create function for all custom controls + // it uses the type name to decide which one to create + ret = *mCSharpCreate(mTypeName.c_str()); + } + else + { + ret = mCreate(); + } - if ( ret ) + if(ret) { BaseObject& handle = ret.GetBaseObject(); - Object *object = dynamic_cast(&handle); + Object* object = dynamic_cast(&handle); - if ( object ) + if(object) { - object->SetTypeInfo( this ); + object->SetTypeInfo(this); } } } return ret; } - bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const Property::Map &properties) +bool TypeInfo::DoActionTo(BaseObject* object, const std::string& actionName, const Property::Map& properties) { bool done = false; - ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder(actionName)); - - if( iter != mActions.end() ) +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + auto iter = mActions.Get(ConstString(actionName)); +#else + ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder(actionName)); +#endif + if(iter != mActions.end()) { done = (iter->second)(object, actionName, properties); } - else - { - DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", mTypeName.c_str(), actionName.c_str()); - } if(!done) { - Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName ); - while( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - done = GetImplementation(base).DoActionTo(object, actionName, properties); - if( done ) - { - break; - } - base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() ); + // call base type recursively + done = mBaseType->DoActionTo(object, actionName, properties); } } return done; } -bool TypeInfo::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor ) +bool TypeInfo::ConnectSignal(BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor) { - bool connected( false ); - - ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(), - PairFinder(signalName) ); + bool connected(false); + +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + auto iter = mSignalConnectors.Get(ConstString(signalName)); +#else + ConnectorContainer::iterator iter = find_if(mSignalConnectors.begin(), mSignalConnectors.end(), PairFinder(signalName)); +#endif + if(iter != mSignalConnectors.end()) + { + connected = (iter->second)(object, connectionTracker, signalName, functor); + } - if( iter != mSignalConnectors.end() ) + if(!connected) { - connected = (iter->second)( object, connectionTracker, signalName, functor ); + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + connected = mBaseType->ConnectSignal(object, connectionTracker, signalName, functor); + } } return connected; @@ -200,476 +278,882 @@ Dali::TypeInfo::CreateFunction TypeInfo::GetCreator() const return mCreate; } -size_t TypeInfo::GetActionCount() const +uint32_t TypeInfo::GetActionCount() const { - size_t count = mActions.size(); + uint32_t count = static_cast(mActions.size()); - Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName ); - while( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - count += GetImplementation(base).mActions.size(); - base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() ); + // call base type recursively + count += mBaseType->GetActionCount(); } return count; } -std::string TypeInfo::GetActionName(size_t index) const +std::string TypeInfo::GetActionName(uint32_t index) const { - std::string name; + std::string name; + const uint32_t count = static_cast(mActions.size()); - if( index < mActions.size() ) + if(index < count) { +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + name = std::string(mActions.GetKeyByIndex(index).GetStringView()); +#else name = mActions[index].first; +#endif } else { - size_t count = mActions.size(); - - Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName ); - while( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - size_t baseCount = GetImplementation(base).mActions.size(); - - if( index < count + baseCount ) - { - name = GetImplementation(base).mActions[ index - count ].first; - break; - } - - count += baseCount; - - base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() ); + // call base type recursively + return mBaseType->GetActionName(index - count); } } return name; } -size_t TypeInfo::GetSignalCount() const +uint32_t TypeInfo::GetSignalCount() const { - size_t count = mSignalConnectors.size(); + uint32_t count = static_cast(mSignalConnectors.size()); - Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName ); - while( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - count += GetImplementation(base).mSignalConnectors.size(); - base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() ); + // call base type recursively + count += mBaseType->GetSignalCount(); } return count; } -std::string TypeInfo::GetSignalName(size_t index) const +std::string TypeInfo::GetSignalName(uint32_t index) const { - std::string name; + std::string name; + const uint32_t count = static_cast(mSignalConnectors.size()); - if( index < mSignalConnectors.size() ) + if(index < count) { +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + name = std::string(mSignalConnectors.GetKeyByIndex(index).GetStringView()); +#else name = mSignalConnectors[index].first; +#endif } else { - size_t count = mSignalConnectors.size(); - - Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName ); - while( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - size_t baseCount = GetImplementation(base).mSignalConnectors.size(); - - if( index < count + baseCount ) - { - name = GetImplementation(base).mSignalConnectors[ index - count ].first; - break; - } + // call base type recursively + return mBaseType->GetSignalName(index - count); + } + } - count += baseCount; + return name; +} - base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() ); +void TypeInfo::GetPropertyIndices(Property::IndexContainer& indices) const +{ + // Default Properties + if(mDefaultProperties) + { + indices.Reserve(indices.Size() + mDefaultPropertyCount); + for(Property::Index index = 0; index < mDefaultPropertyCount; ++index) + { + indices.PushBack(mDefaultProperties[index].enumIndex); } } - return name; + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + mBaseType->GetPropertyIndices(indices); + } + + AppendProperties(indices, mRegisteredProperties); } -void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const +void TypeInfo::GetChildPropertyIndices(Property::IndexContainer& indices) const { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - const TypeInfo& baseImpl( GetImplementation( base ) ); - baseImpl.GetPropertyIndices( indices ); + // call base type recursively + mBaseType->GetChildPropertyIndices(indices); } - if ( ! mRegisteredProperties.empty() ) + AppendProperties(indices, mRegisteredChildProperties); +} + +/** + * Append the indices in RegisteredProperties to the given index container. + */ +void TypeInfo::AppendProperties(Dali::Property::IndexContainer& indices, + const TypeInfo::RegisteredPropertyContainer& registeredProperties) const +{ + if(!registeredProperties.empty()) { - indices.Reserve( indices.Size() + mRegisteredProperties.size() ); + indices.Reserve(indices.Size() + registeredProperties.size()); - const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end(); - for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter ) + for(auto&& elem : registeredProperties) { - indices.PushBack( iter->first ); + indices.PushBack(elem.first); } } } -const std::string& TypeInfo::GetPropertyName( Property::Index index ) const +std::string_view TypeInfo::GetRegisteredPropertyName(Property::Index index) const { - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair >( index ) ); - - if ( iter != mRegisteredProperties.end() ) +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredProperties.end()) { - return iter->second.name; + return iter->second.name.GetStringView(); } + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + return mBaseType->GetRegisteredPropertyName(index); + } + static std::string empty; + return empty; +} - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) +std::string_view TypeInfo::GetPropertyName(Property::Index index) const +{ + std::string_view propertyName; + // default or custom + if(mDefaultProperties && (index < DEFAULT_PROPERTY_MAX_COUNT)) + { + std::string_view name; + if(GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::name, name)) + { + propertyName = name; + } + } + else { - return GetImplementation(base).GetPropertyName( index ); +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredProperties.end()) + { + return iter->second.name.GetStringView(); + } + } + // if not our property, go to parent + if(propertyName.empty()) + { + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + return mBaseType->GetPropertyName(index); + } } - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object + return propertyName; } -void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function ) +void TypeInfo::AddActionFunction(std::string actionName, Dali::TypeInfo::ActionFunction function) { - if( NULL == function) + if(nullptr == function) { DALI_LOG_WARNING("Action function is empty\n"); } else { - ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(), - PairFinder(actionName)); +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + if(!mActions.Register(ConstString(actionName), function)) + { + DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str()); + } +#else + ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(), PairFinder(actionName)); - if( iter == mActions.end() ) + if(iter == mActions.end()) { - mActions.push_back( ActionPair( actionName, function ) ); + mActions.push_back(ActionPair(std::move(actionName), function)); } else { - DALI_LOG_WARNING("Action already exists in TypeRegistry Type", actionName.c_str()); + DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str()); } +#endif } } -void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function ) +void TypeInfo::AddConnectorFunction(std::string signalName, Dali::TypeInfo::SignalConnectorFunction function) { - if( NULL == function) + if(nullptr == function) { DALI_LOG_WARNING("Connector function is empty\n"); } else { - ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(), - PairFinder(signalName) ); +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + if(!mSignalConnectors.Register(ConstString(signalName), function)) + { + DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str()); + } +#else + ConnectorContainer::iterator iter = find_if(mSignalConnectors.begin(), mSignalConnectors.end(), PairFinder(signalName)); - if( iter == mSignalConnectors.end() ) + if(iter == mSignalConnectors.end()) { - mSignalConnectors.push_back( ConnectionPair( signalName, function ) ); + mSignalConnectors.push_back(ConnectionPair(std::move(signalName), function)); } else { - DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function", signalName.c_str()); + DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str()); } +#endif } } -void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc ) +void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc) { // The setter can be empty as a property can be read-only. - if ( NULL == getFunc ) + if(nullptr == getFunc) { - DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" ); + DALI_ASSERT_ALWAYS(!"GetProperty Function is empty"); } else { - RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair>(index) ); +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + if(!mRegisteredProperties.Register(static_cast(index), RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))) + { + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); + } +#else + RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); + if(iter == mRegisteredProperties.end()) + { + mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))); + } + else + { + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); + } +#endif + } +} - if ( iter == mRegisteredProperties.end() ) +void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc) +{ + // The setter can be empty as a property can be read-only. + + if(nullptr == getFunc) + { + DALI_ASSERT_ALWAYS(!"GetProperty Function is empty"); + } + else + { +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + if(!mRegisteredProperties.Register(static_cast(index), RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))) + { + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); + } +#else + RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); + if(iter == mRegisteredProperties.end()) { - mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) ); + mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))); } else { - DALI_ASSERT_ALWAYS( ! "Property index already added to Type" ); + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); } +#endif } } -void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type ) +void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Property::Type type) { - RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair>(index) ); +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + if(!mRegisteredProperties.Register(static_cast(index), RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))) + { + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); + } +#else + RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); + if(iter == mRegisteredProperties.end()) + { + mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))); + } + else + { + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); + } +#endif +} - if ( iter == mRegisteredProperties.end() ) +void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Property::Value defaultValue) +{ +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + if(!mRegisteredProperties.Register(static_cast(index), RegisteredProperty(defaultValue.GetType(), ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))) { - mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) ); + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); } else { - DALI_ASSERT_ALWAYS( ! "Property index already added to Type" ); + mPropertyDefaultValues.Register(static_cast(index), std::move(defaultValue)); + } +#else + RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); + if(iter == mRegisteredProperties.end()) + { + mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(defaultValue.GetType(), ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))); + mPropertyDefaultValues.push_back(PropertyDefaultValuePair(index, std::move(defaultValue))); } + else + { + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); + } +#endif } -void TypeInfo::AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex ) +void TypeInfo::AddAnimatablePropertyComponent(std::string name, Property::Index index, Property::Index baseIndex, uint32_t componentIndex) { - Property::Type type = GetPropertyType( baseIndex ); - DALI_ASSERT_ALWAYS( ( type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4 ) && "Base property does not support component" ); + Property::Type type = GetPropertyType(baseIndex); + DALI_ASSERT_ALWAYS((type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4) && "Base property does not support component"); bool success = false; - RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair>(index) ); +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + if(mRegisteredProperties.Get(static_cast(index)) == mRegisteredProperties.end()) + { + const auto& iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyComponentFinder(baseIndex, componentIndex)); - if ( iter == mRegisteredProperties.end() ) + if(iter == mRegisteredProperties.end()) + { + mRegisteredProperties.Register(static_cast(index), RegisteredProperty(type, ConstString(name), baseIndex, componentIndex)); + success = true; + } + } +#else + RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); + if(iter == mRegisteredProperties.end()) { - iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PropertyComponentFinder< RegisteredPropertyPair >( baseIndex, componentIndex ) ); + iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyComponentFinder(baseIndex, componentIndex)); - if ( iter == mRegisteredProperties.end() ) + if(iter == mRegisteredProperties.end()) { - mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, baseIndex, componentIndex ) ) ); + mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), baseIndex, componentIndex))); success = true; } } +#endif - DALI_ASSERT_ALWAYS( success && "Property component already registered" ); + DALI_ASSERT_ALWAYS(success && "Property component already registered"); +} + +void TypeInfo::AddChildProperty(std::string name, Property::Index index, Property::Type type) +{ +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + if(!mRegisteredChildProperties.Register(static_cast(index), RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))) +#else + RegisteredPropertyContainer::iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder(index)); + if(iter == mRegisteredChildProperties.end()) + { + mRegisteredChildProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX))); + } + else +#endif + { + DALI_ASSERT_ALWAYS(!"Property index already added to Type"); + } } -size_t TypeInfo::GetPropertyCount() const +uint32_t TypeInfo::GetPropertyCount() const { - size_t count( mRegisteredProperties.size() ); + uint32_t count = mDefaultPropertyCount + static_cast(mRegisteredProperties.size()); - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - while ( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - const TypeInfo& baseImpl( GetImplementation(base) ); - count += baseImpl.mRegisteredProperties.size(); - base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName ); + // call base type recursively + count += mBaseType->GetPropertyCount(); } return count; } -Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const +Property::Index TypeInfo::GetPropertyIndex(ConstString name) const { Property::Index index = Property::INVALID_INDEX; + bool found = false; - // Slow but should not be done that often - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PropertyNameFinder< RegisteredPropertyPair >( name ) ); - - if ( iter != mRegisteredProperties.end() ) + // check default properties + if(mDefaultProperties) { - index = iter->first; + auto stringView = name.GetStringView(); + for(Property::Index tableIndex = 0; tableIndex < mDefaultPropertyCount; ++tableIndex) + { + if(mDefaultProperties[tableIndex].name == stringView) + { + index = mDefaultProperties[tableIndex].enumIndex; + found = true; + break; + } + } } - else + if(!found) { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + // Slow but should not be done that often + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder(name)); + if(iter != mRegisteredProperties.end()) + { + index = iter->first; + } + else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - index = GetImplementation(base).GetPropertyIndex( name ); + // call base type recursively + index = mBaseType->GetPropertyIndex(name); } } return index; } -Property::Index TypeInfo::GetBasePropertyIndex( Property::Index index ) const +Property::Index TypeInfo::GetBasePropertyIndex(Property::Index index) const { Property::Index basePropertyIndex = Property::INVALID_INDEX; - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair >( index ) ); - - if ( iter != mRegisteredProperties.end() ) +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredProperties.end()) { basePropertyIndex = iter->second.basePropertyIndex; } - else + else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) - { - basePropertyIndex = GetImplementation(base).GetBasePropertyIndex( index ); - } + // call base type recursively + basePropertyIndex = mBaseType->GetBasePropertyIndex(index); } return basePropertyIndex; } -int TypeInfo::GetComponentIndex( Property::Index index ) const +int32_t TypeInfo::GetComponentIndex(Property::Index index) const { int componentIndex = Property::INVALID_COMPONENT_INDEX; - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair >( index ) ); - - if ( iter != mRegisteredProperties.end() ) +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredProperties.end()) { componentIndex = iter->second.componentIndex; } - else + else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) - { - componentIndex = GetImplementation(base).GetComponentIndex( index ); - } + // call base type recursively + componentIndex = mBaseType->GetComponentIndex(index); } return componentIndex; } -bool TypeInfo::IsPropertyWritable( Property::Index index ) const +Property::Index TypeInfo::GetChildPropertyIndex(ConstString name) const { - bool writable( false ); + Property::Index index = Property::INVALID_INDEX; - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair >( index ) ); + // Slow but should not be done that often + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PropertyNameFinder(name)); - if ( iter != mRegisteredProperties.end() ) + if(iter != mRegisteredChildProperties.end()) { - if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) - { - writable = true; // animatable property is writable - } - else + index = iter->first; + } + else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + index = mBaseType->GetChildPropertyIndex(name); + } + + return index; +} + +std::string_view TypeInfo::GetChildPropertyName(Property::Index index) const +{ +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredChildProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredChildProperties.end()) + { + return iter->second.name.GetStringView(); + } + + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + return mBaseType->GetChildPropertyName(index); + } + + DALI_LOG_ERROR("Property index %d not found\n", index); + + return {}; +} + +Property::Type TypeInfo::GetChildPropertyType(Property::Index index) const +{ + Property::Type type(Property::NONE); + +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredChildProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredChildProperties.end()) + { + type = iter->second.type; + } + else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + type = mBaseType->GetChildPropertyType(index); + } + else + { + DALI_LOG_ERROR("Property index %d not found\n", index); + } + + return type; +} + +bool TypeInfo::IsPropertyWritable(Property::Index index) const +{ + bool writable = false; + bool found = false; + + // default property? + if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties) + { + found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::writable, writable); + } + else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX)) + { + writable = true; // animatable property is writable + found = true; + } + else + { +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredProperties.end()) { writable = iter->second.setFunc ? true : false; + found = true; } } - else + + // if not found, continue to base + if(!found) { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - writable = GetImplementation(base).IsPropertyWritable( index ); + // call base type recursively + writable = mBaseType->IsPropertyWritable(index); } else { - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object + DALI_LOG_ERROR("Property index %d not found\n", index); } } return writable; } -Property::Type TypeInfo::GetPropertyType( Property::Index index ) const +bool TypeInfo::IsPropertyAnimatable(Property::Index index) const { - Property::Type type( Property::NONE ); + bool animatable = false; + bool found = false; - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair >( index ) ); - - if ( iter != mRegisteredProperties.end() ) + // default property? + if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties) { - type = iter->second.type; + found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::animatable, animatable); } - else + else if((index >= PROPERTY_REGISTRATION_START_INDEX) && (index <= PROPERTY_REGISTRATION_MAX_INDEX)) + { + // Type Registry event-thread only properties are not animatable. + animatable = false; + found = true; + } + else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX)) + { + animatable = true; + found = true; + } + + // if not found, continue to base + if(!found) { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - type = GetImplementation(base).GetPropertyType( index ); + // call base type recursively + animatable = mBaseType->IsPropertyAnimatable(index); } else { - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object + DALI_LOG_ERROR("Property index %d not found\n", index); } } - return type; + return animatable; } -void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const +bool TypeInfo::IsPropertyAConstraintInput(Property::Index index) const { - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair >( index ) ); - if ( iter != mRegisteredProperties.end() ) + bool constraintInput = false; + bool found = false; + + // default property? + if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties) + { + found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::constraintInput, constraintInput); + } + else if((index >= PROPERTY_REGISTRATION_START_INDEX) && (index <= PROPERTY_REGISTRATION_MAX_INDEX)) + { + // Type Registry event-thread only properties cannot be used as constraint input + constraintInput = false; + found = true; + } + else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX)) + { + constraintInput = true; + found = true; + } + + // if not found, continue to base + if(!found) { - if( iter->second.setFunc ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + constraintInput = mBaseType->IsPropertyAConstraintInput(index); + } + else { - iter->second.setFunc( object, index, value ); + DALI_LOG_ERROR("Property index %d not found\n", index); } } + + return constraintInput; +} + +Property::Type TypeInfo::GetPropertyType(Property::Index index) const +{ + Property::Type type(Property::NONE); + bool found = false; + + // default property? + if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties) + { + found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::type, type); + } else { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredProperties.end()) + { + if(iter->second.componentIndex == Property::INVALID_COMPONENT_INDEX) + { + type = iter->second.type; + found = true; + } + else + { + // If component index is set, then we should return FLOAT + type = Property::FLOAT; + found = true; + } + } + } + + if(!found) + { + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - GetImplementation(base).SetProperty( object, index, value ); + // call base type recursively + type = mBaseType->GetPropertyType(index); } else { - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object + DALI_LOG_ERROR("Property index %d not found\n", index); } } + + return type; +} + +Property::Value TypeInfo::GetPropertyDefaultValue(Property::Index index) const +{ +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mPropertyDefaultValues.Get(static_cast(index)); +#else + PropertyDefaultValueContainer::const_iterator iter = find_if(mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(), PairFinder(index)); +#endif + if(iter != mPropertyDefaultValues.end()) + { + return iter->second; + } + // we didn't have a value so ask base + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + return mBaseType->GetPropertyDefaultValue(index); + } + return Property::Value(); // return none } -void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const +void TypeInfo::SetProperty(BaseObject* object, Property::Index index, Property::Value value) const { - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PropertyNameFinder< RegisteredPropertyPair >( name ) ); - if ( iter != mRegisteredProperties.end() ) +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredProperties.end()) + { + if(iter->second.setFunc) + { + if(mCSharpType) + { + // CSharp wants a property name not an index + auto name = (iter->second).name; + + iter->second.cSharpSetFunc(object, name.GetCString(), const_cast(&value)); + } + else + { + iter->second.setFunc(object, index, std::move(value)); + } + } + } + else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" ); - iter->second.setFunc( object, iter->first, value ); + // call base type recursively + mBaseType->SetProperty(object, index, std::move(value)); } else { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + DALI_LOG_ERROR("Property index %d not found\n", index); + } +} + +void TypeInfo::SetProperty(BaseObject* object, const std::string& name, Property::Value value) const +{ + // Slow but should not be done that often + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder(ConstString(name))); + if(iter != mRegisteredProperties.end()) + { + DALI_ASSERT_ALWAYS(iter->second.setFunc && "Trying to write to a read-only property"); + + if(mCSharpType) { - GetImplementation(base).SetProperty( object, name, value ); + // CSharp wants a property name not an index + iter->second.cSharpSetFunc(object, name.c_str(), const_cast(&value)); } else { - DALI_ASSERT_ALWAYS( ! "Cannot find property name" ); + iter->second.setFunc(object, iter->first, std::move(value)); } } + else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) + { + // call base type recursively + mBaseType->SetProperty(object, name, std::move(value)); + } + else + { + DALI_LOG_ERROR("Property %s not found", name.c_str()); + } } -Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const +Property::Value TypeInfo::GetProperty(const BaseObject* object, Property::Index index) const { - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PairFinder< Property::Index, RegisteredPropertyPair >( index ) ); - if( iter != mRegisteredProperties.end() ) +#ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO + const auto& iter = mRegisteredProperties.Get(static_cast(index)); +#else + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder(index)); +#endif + if(iter != mRegisteredProperties.end()) { - // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object - return iter->second.getFunc( const_cast< BaseObject* >( object ), index ); + if(mCSharpType) // using csharp property get which returns a pointer to a Property::Value + { + // CSharp wants a property name not an index + // CSharp callback can't return an object by value, it can only return a pointer + // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value + auto name = (iter->second).name; + + return *(iter->second.cSharpGetFunc(const_cast(object), name.GetCString())); + } + else + { + // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object + return iter->second.getFunc(const_cast(object), index); + } } - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - return GetImplementation( base ).GetProperty( object, index ); + // call base type recursively + return mBaseType->GetProperty(object, index); } - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object + DALI_LOG_ERROR("Property index %d not found\n", index); + return Property::Value(); } -Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const +Property::Value TypeInfo::GetProperty(const BaseObject* object, const std::string& name) const { - RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(), - PropertyNameFinder< RegisteredPropertyPair >( name ) ); - if( iter != mRegisteredProperties.end() ) + RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder(ConstString(name))); + + if(iter != mRegisteredProperties.end()) { - // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object - return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first ); + if(mCSharpType) // using csharp property get which returns a pointer to a Property::Value + { + // CSharp wants a property name not an index + // CSharp callback can't return an object by value, it can only return a pointer + // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value + return *(iter->second.cSharpGetFunc(const_cast(object), name.c_str())); + } + else + { + // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object + return iter->second.getFunc(const_cast(object), iter->first); + } } - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName)) { - return GetImplementation( base ).GetProperty( object, name ); + // call base type recursively + return mBaseType->GetProperty(object, name); } - DALI_ASSERT_ALWAYS( ! "Cannot find property name" ); + DALI_LOG_ERROR("Property %s not found", name.c_str()); + return Property::Value(); } } // namespace Internal