2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/common/type-info-impl.h>
22 #include <algorithm> // std::find_if
26 #include <dali/integration-api/debug.h>
27 #include <dali/internal/event/common/object-impl.h>
28 #include <dali/internal/event/common/type-registry-impl.h>
39 * Functor to find by given type for vector of pairs
41 template<typename S, typename T>
44 PairFinder(const S& find)
49 bool operator()(const T& p) const
51 return p.first == mFind;
59 * Functor to find a matching property name
62 struct PropertyNameFinder
64 PropertyNameFinder(ConstString find)
69 bool operator()(const T& p) const
71 return p.second.name == mFind;
79 * Functor to find a matching property component index
82 struct PropertyComponentFinder
84 PropertyComponentFinder(Property::Index basePropertyIndex, const int find)
85 : mBasePropertyIndex(basePropertyIndex),
90 bool operator()(const T& p) const
92 return (p.second.basePropertyIndex == mBasePropertyIndex && p.second.componentIndex == mFind);
96 Property::Index mBasePropertyIndex;
101 * Helper function to find the right default property with given index and return the desired detail of it
103 template<typename Parameter, typename Member>
104 inline bool GetDefaultPropertyField(const Dali::PropertyDetails* propertyTable, Property::Index count, Property::Index index, Member member, Parameter& parameter)
107 // is index inside this table (bigger than first index but smaller than first + count)
108 if((index >= propertyTable->enumIndex) && (index < (propertyTable->enumIndex + count)))
110 // return the match. we're assuming here that there is no gaps between the indices in a table
111 parameter = propertyTable[index - propertyTable->enumIndex].*member;
114 // should never really get here
118 // static pointer value to mark that a base class address has not been resolved
119 // 0x01 is not a valid pointer but used here to differentiate from nullptr
120 // unfortunately it cannot be constexpr as C++ does not allow them to be initialised with reinterpret_cast
121 Internal::TypeInfo* const UNRESOLVED = reinterpret_cast<Internal::TypeInfo*>(0x1);
124 * Helper function to resolve and return the pointer to the base type info
125 * Not a member function to avoid having to #include additional headers and to make sure this gets inlined inside this cpp
126 * @param[in/out] baseType pointer to resolve and set
127 * @param[in] typeRegistry reference to the type registry
128 * @param[in] baseTypeName string name of the base type
129 * @return true is base type exists
131 inline bool GetBaseType(Internal::TypeInfo*& baseType, TypeRegistry& typeRegistry, const std::string& baseTypeName)
133 // if greater than unresolved means we have a base type, null means no base
134 bool baseExists = (baseType > UNRESOLVED);
135 // base only needs to be resolved once
136 if(UNRESOLVED == baseType)
138 TypeRegistry::TypeInfoPointer base = typeRegistry.GetTypeInfo(baseTypeName);
141 baseType = base.Get(); // dont pass ownership, just return raw pointer
146 // no type info found so assuming no base as all type registration is done in startup for now
153 } // unnamed namespace
155 TypeInfo::TypeInfo(const std::string& name, const std::string& baseTypeName, Dali::TypeInfo::CreateFunction creator, const Dali::PropertyDetails* defaultProperties, Property::Index defaultPropertyCount)
156 : mTypeRegistry(*TypeRegistry::Get()),
157 mBaseType(UNRESOLVED),
159 mBaseTypeName(baseTypeName),
161 mDefaultProperties(defaultProperties),
162 mDefaultPropertyCount(defaultPropertyCount),
165 DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
166 DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
169 TypeInfo::TypeInfo(const std::string& name, const std::string& baseTypeName, Dali::CSharpTypeInfo::CreateFunction creator)
170 : mTypeRegistry(*TypeRegistry::Get()),
171 mBaseType(UNRESOLVED),
173 mBaseTypeName(baseTypeName),
174 mCSharpCreate(creator),
177 DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
178 DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
181 TypeInfo::~TypeInfo() = default;
183 BaseHandle TypeInfo::CreateInstance() const
191 // CSharp currently only registers one create function for all custom controls
192 // it uses the type name to decide which one to create
193 ret = *mCSharpCreate(mTypeName.c_str());
202 BaseObject& handle = ret.GetBaseObject();
203 Object* object = dynamic_cast<Internal::Object*>(&handle);
207 object->SetTypeInfo(this);
214 bool TypeInfo::DoActionTo(BaseObject* object, const std::string& actionName, const Property::Map& properties)
218 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
219 auto iter = mActions.Get(ConstString(actionName));
221 ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
223 if(iter != mActions.end())
225 done = (iter->second)(object, actionName, properties);
230 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
232 // call base type recursively
233 done = mBaseType->DoActionTo(object, actionName, properties);
240 bool TypeInfo::ConnectSignal(BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor)
242 bool connected(false);
244 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
245 auto iter = mSignalConnectors.Get(ConstString(signalName));
247 ConnectorContainer::iterator iter = find_if(mSignalConnectors.begin(), mSignalConnectors.end(), PairFinder<std::string, ConnectionPair>(signalName));
249 if(iter != mSignalConnectors.end())
251 connected = (iter->second)(object, connectionTracker, signalName, functor);
256 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
258 // call base type recursively
259 connected = mBaseType->ConnectSignal(object, connectionTracker, signalName, functor);
266 const std::string& TypeInfo::GetName() const
271 const std::string& TypeInfo::GetBaseName() const
273 return mBaseTypeName;
276 Dali::TypeInfo::CreateFunction TypeInfo::GetCreator() const
281 uint32_t TypeInfo::GetActionCount() const
283 uint32_t count = static_cast<uint32_t>(mActions.size());
285 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
287 // call base type recursively
288 count += mBaseType->GetActionCount();
294 std::string TypeInfo::GetActionName(uint32_t index) const
297 const uint32_t count = static_cast<uint32_t>(mActions.size());
301 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
302 name = std::string(mActions.GetKeyByIndex(index).GetStringView());
304 name = mActions[index].first;
309 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
311 // call base type recursively
312 return mBaseType->GetActionName(index - count);
319 uint32_t TypeInfo::GetSignalCount() const
321 uint32_t count = static_cast<uint32_t>(mSignalConnectors.size());
323 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
325 // call base type recursively
326 count += mBaseType->GetSignalCount();
332 std::string TypeInfo::GetSignalName(uint32_t index) const
335 const uint32_t count = static_cast<uint32_t>(mSignalConnectors.size());
339 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
340 name = std::string(mSignalConnectors.GetKeyByIndex(index).GetStringView());
342 name = mSignalConnectors[index].first;
347 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
349 // call base type recursively
350 return mBaseType->GetSignalName(index - count);
357 void TypeInfo::GetPropertyIndices(Property::IndexContainer& indices) const
359 // Default Properties
360 if(mDefaultProperties)
362 indices.Reserve(indices.Size() + mDefaultPropertyCount);
363 for(Property::Index index = 0; index < mDefaultPropertyCount; ++index)
365 indices.PushBack(mDefaultProperties[index].enumIndex);
369 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
371 // call base type recursively
372 mBaseType->GetPropertyIndices(indices);
375 AppendProperties(indices, mRegisteredProperties);
378 void TypeInfo::GetChildPropertyIndices(Property::IndexContainer& indices) const
380 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
382 // call base type recursively
383 mBaseType->GetChildPropertyIndices(indices);
386 AppendProperties(indices, mRegisteredChildProperties);
390 * Append the indices in RegisteredProperties to the given index container.
392 void TypeInfo::AppendProperties(Dali::Property::IndexContainer& indices,
393 const TypeInfo::RegisteredPropertyContainer& registeredProperties) const
395 if(!registeredProperties.empty())
397 indices.Reserve(indices.Size() + registeredProperties.size());
399 for(auto&& elem : registeredProperties)
401 indices.PushBack(elem.first);
406 std::string_view TypeInfo::GetRegisteredPropertyName(Property::Index index) const
408 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
409 const auto& iter = mRegisteredProperties.Get(static_cast<std::uint32_t>(index));
411 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
413 if(iter != mRegisteredProperties.end())
415 return iter->second.name.GetStringView();
417 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
419 // call base type recursively
420 return mBaseType->GetRegisteredPropertyName(index);
422 static std::string empty;
426 std::string_view TypeInfo::GetPropertyName(Property::Index index) const
428 std::string_view propertyName;
430 if(mDefaultProperties && (index < DEFAULT_PROPERTY_MAX_COUNT))
432 std::string_view name;
433 if(GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::name, name))
440 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
441 const auto& iter = mRegisteredProperties.Get(static_cast<std::uint32_t>(index));
443 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
445 if(iter != mRegisteredProperties.end())
447 return iter->second.name.GetStringView();
450 // if not our property, go to parent
451 if(propertyName.empty())
453 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
455 // call base type recursively
456 return mBaseType->GetPropertyName(index);
463 void TypeInfo::AddActionFunction(std::string actionName, Dali::TypeInfo::ActionFunction function)
465 if(nullptr == function)
467 DALI_LOG_WARNING("Action function is empty\n");
471 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
472 if(!mActions.Register(ConstString(actionName), function))
474 DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str());
477 ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
479 if(iter == mActions.end())
481 mActions.push_back(ActionPair(std::move(actionName), function));
485 DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str());
491 void TypeInfo::AddConnectorFunction(std::string signalName, Dali::TypeInfo::SignalConnectorFunction function)
493 if(nullptr == function)
495 DALI_LOG_WARNING("Connector function is empty\n");
499 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
500 if(!mSignalConnectors.Register(ConstString(signalName), function))
502 DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str());
505 ConnectorContainer::iterator iter = find_if(mSignalConnectors.begin(), mSignalConnectors.end(), PairFinder<std::string, ConnectionPair>(signalName));
507 if(iter == mSignalConnectors.end())
509 mSignalConnectors.push_back(ConnectionPair(std::move(signalName), function));
513 DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str());
519 void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc)
521 // The setter can be empty as a property can be read-only.
523 if(nullptr == getFunc)
525 DALI_ASSERT_ALWAYS(!"GetProperty Function is empty");
529 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
530 if(!mRegisteredProperties.Register(static_cast<std::uint32_t>(index), RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)))
532 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
535 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
536 if(iter == mRegisteredProperties.end())
538 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
542 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
548 void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc)
550 // The setter can be empty as a property can be read-only.
552 if(nullptr == getFunc)
554 DALI_ASSERT_ALWAYS(!"GetProperty Function is empty");
558 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
559 if(!mRegisteredProperties.Register(static_cast<std::uint32_t>(index), RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)))
561 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
564 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
565 if(iter == mRegisteredProperties.end())
567 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
571 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
577 void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Property::Type type)
579 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
580 if(!mRegisteredProperties.Register(static_cast<std::uint32_t>(index), RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)))
582 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
585 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
586 if(iter == mRegisteredProperties.end())
588 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
592 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
597 void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Property::Value defaultValue)
599 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
600 if(!mRegisteredProperties.Register(static_cast<std::uint32_t>(index), RegisteredProperty(defaultValue.GetType(), ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)))
602 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
606 mPropertyDefaultValues.Register(static_cast<std::uint32_t>(index), std::move(defaultValue));
609 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
610 if(iter == mRegisteredProperties.end())
612 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(defaultValue.GetType(), ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
613 mPropertyDefaultValues.push_back(PropertyDefaultValuePair(index, std::move(defaultValue)));
617 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
622 void TypeInfo::AddAnimatablePropertyComponent(std::string name, Property::Index index, Property::Index baseIndex, uint32_t componentIndex)
624 Property::Type type = GetPropertyType(baseIndex);
625 DALI_ASSERT_ALWAYS((type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4) && "Base property does not support component");
627 bool success = false;
629 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
630 if(mRegisteredProperties.Get(static_cast<std::uint32_t>(index)) == mRegisteredProperties.end())
632 const auto& iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyComponentFinder<RegisteredPropertyPair>(baseIndex, componentIndex));
634 if(iter == mRegisteredProperties.end())
636 mRegisteredProperties.Register(static_cast<std::uint32_t>(index), RegisteredProperty(type, ConstString(name), baseIndex, componentIndex));
641 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
642 if(iter == mRegisteredProperties.end())
644 iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyComponentFinder<RegisteredPropertyPair>(baseIndex, componentIndex));
646 if(iter == mRegisteredProperties.end())
648 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), baseIndex, componentIndex)));
654 DALI_ASSERT_ALWAYS(success && "Property component already registered");
657 void TypeInfo::AddChildProperty(std::string name, Property::Index index, Property::Type type)
659 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
660 if(!mRegisteredChildProperties.Register(static_cast<std::uint32_t>(index), RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)))
662 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
663 if(iter == mRegisteredChildProperties.end())
665 mRegisteredChildProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
670 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
674 uint32_t TypeInfo::GetPropertyCount() const
676 uint32_t count = mDefaultPropertyCount + static_cast<uint32_t>(mRegisteredProperties.size());
678 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
680 // call base type recursively
681 count += mBaseType->GetPropertyCount();
687 Property::Index TypeInfo::GetPropertyIndex(ConstString name) const
689 Property::Index index = Property::INVALID_INDEX;
692 // check default properties
693 if(mDefaultProperties)
695 auto stringView = name.GetStringView();
696 for(Property::Index tableIndex = 0; tableIndex < mDefaultPropertyCount; ++tableIndex)
698 if(mDefaultProperties[tableIndex].name == stringView)
700 index = mDefaultProperties[tableIndex].enumIndex;
708 // Slow but should not be done that often
709 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(name));
710 if(iter != mRegisteredProperties.end())
714 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
716 // call base type recursively
717 index = mBaseType->GetPropertyIndex(name);
724 Property::Index TypeInfo::GetBasePropertyIndex(Property::Index index) const
726 Property::Index basePropertyIndex = Property::INVALID_INDEX;
728 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
729 const auto& iter = mRegisteredProperties.Get(static_cast<std::uint32_t>(index));
731 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
733 if(iter != mRegisteredProperties.end())
735 basePropertyIndex = iter->second.basePropertyIndex;
737 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
739 // call base type recursively
740 basePropertyIndex = mBaseType->GetBasePropertyIndex(index);
743 return basePropertyIndex;
746 int32_t TypeInfo::GetComponentIndex(Property::Index index) const
748 int componentIndex = Property::INVALID_COMPONENT_INDEX;
750 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
751 const auto& iter = mRegisteredProperties.Get(static_cast<std::uint32_t>(index));
753 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
755 if(iter != mRegisteredProperties.end())
757 componentIndex = iter->second.componentIndex;
759 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
761 // call base type recursively
762 componentIndex = mBaseType->GetComponentIndex(index);
765 return componentIndex;
768 Property::Index TypeInfo::GetChildPropertyIndex(ConstString name) const
770 Property::Index index = Property::INVALID_INDEX;
772 // Slow but should not be done that often
773 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(name));
775 if(iter != mRegisteredChildProperties.end())
779 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
781 // call base type recursively
782 index = mBaseType->GetChildPropertyIndex(name);
788 std::string_view TypeInfo::GetChildPropertyName(Property::Index index) const
790 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
791 const auto& iter = mRegisteredChildProperties.Get(static_cast<std::uint32_t>(index));
793 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
795 if(iter != mRegisteredChildProperties.end())
797 return iter->second.name.GetStringView();
800 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
802 // call base type recursively
803 return mBaseType->GetChildPropertyName(index);
806 DALI_LOG_ERROR("Property index %d not found\n", index);
811 Property::Type TypeInfo::GetChildPropertyType(Property::Index index) const
813 Property::Type type(Property::NONE);
815 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
816 const auto& iter = mRegisteredChildProperties.Get(static_cast<std::uint32_t>(index));
818 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
820 if(iter != mRegisteredChildProperties.end())
822 type = iter->second.type;
824 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
826 // call base type recursively
827 type = mBaseType->GetChildPropertyType(index);
831 DALI_LOG_ERROR("Property index %d not found\n", index);
837 bool TypeInfo::IsPropertyWritable(Property::Index index) const
839 bool writable = false;
843 if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties)
845 found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::writable, writable);
847 else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX))
849 writable = true; // animatable property is writable
854 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
855 const auto& iter = mRegisteredProperties.Get(static_cast<std::uint32_t>(index));
857 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
859 if(iter != mRegisteredProperties.end())
861 writable = iter->second.setFunc ? true : false;
866 // if not found, continue to base
869 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
871 // call base type recursively
872 writable = mBaseType->IsPropertyWritable(index);
876 DALI_LOG_ERROR("Property index %d not found\n", index);
883 bool TypeInfo::IsPropertyAnimatable(Property::Index index) const
885 bool animatable = false;
889 if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties)
891 found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::animatable, animatable);
893 else if((index >= PROPERTY_REGISTRATION_START_INDEX) && (index <= PROPERTY_REGISTRATION_MAX_INDEX))
895 // Type Registry event-thread only properties are not animatable.
899 else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX))
905 // if not found, continue to base
908 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
910 // call base type recursively
911 animatable = mBaseType->IsPropertyAnimatable(index);
915 DALI_LOG_ERROR("Property index %d not found\n", index);
922 bool TypeInfo::IsPropertyAConstraintInput(Property::Index index) const
924 bool constraintInput = false;
928 if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties)
930 found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::constraintInput, constraintInput);
932 else if((index >= PROPERTY_REGISTRATION_START_INDEX) && (index <= PROPERTY_REGISTRATION_MAX_INDEX))
934 // Type Registry event-thread only properties cannot be used as constraint input
935 constraintInput = false;
938 else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX))
940 constraintInput = true;
944 // if not found, continue to base
947 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
949 // call base type recursively
950 constraintInput = mBaseType->IsPropertyAConstraintInput(index);
954 DALI_LOG_ERROR("Property index %d not found\n", index);
958 return constraintInput;
961 Property::Type TypeInfo::GetPropertyType(Property::Index index) const
963 Property::Type type(Property::NONE);
967 if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties)
969 found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::type, type);
973 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
974 const auto& iter = mRegisteredProperties.Get(static_cast<std::uint32_t>(index));
976 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
978 if(iter != mRegisteredProperties.end())
980 if(iter->second.componentIndex == Property::INVALID_COMPONENT_INDEX)
982 type = iter->second.type;
987 // If component index is set, then we should return FLOAT
988 type = Property::FLOAT;
996 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
998 // call base type recursively
999 type = mBaseType->GetPropertyType(index);
1003 DALI_LOG_ERROR("Property index %d not found\n", index);
1010 Property::Value TypeInfo::GetPropertyDefaultValue(Property::Index index) const
1012 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
1013 const auto& iter = mPropertyDefaultValues.Get(static_cast<std::uint32_t>(index));
1015 PropertyDefaultValueContainer::const_iterator iter = find_if(mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(), PairFinder<Property::Index, PropertyDefaultValuePair>(index));
1017 if(iter != mPropertyDefaultValues.end())
1019 return iter->second;
1021 // we didn't have a value so ask base
1022 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
1024 // call base type recursively
1025 return mBaseType->GetPropertyDefaultValue(index);
1027 return Property::Value(); // return none
1030 void TypeInfo::SetProperty(BaseObject* object, Property::Index index, Property::Value value) const
1032 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
1033 const auto& iter = mRegisteredProperties.Get(static_cast<std::uint32_t>(index));
1035 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
1037 if(iter != mRegisteredProperties.end())
1039 if(iter->second.setFunc)
1043 // CSharp wants a property name not an index
1044 auto name = (iter->second).name;
1046 iter->second.cSharpSetFunc(object, name.GetCString(), const_cast<Property::Value*>(&value));
1050 iter->second.setFunc(object, index, std::move(value));
1054 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
1056 // call base type recursively
1057 mBaseType->SetProperty(object, index, std::move(value));
1061 DALI_LOG_ERROR("Property index %d not found\n", index);
1065 void TypeInfo::SetProperty(BaseObject* object, const std::string& name, Property::Value value) const
1067 // Slow but should not be done that often
1068 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(ConstString(name)));
1069 if(iter != mRegisteredProperties.end())
1071 DALI_ASSERT_ALWAYS(iter->second.setFunc && "Trying to write to a read-only property");
1075 // CSharp wants a property name not an index
1076 iter->second.cSharpSetFunc(object, name.c_str(), const_cast<Property::Value*>(&value));
1080 iter->second.setFunc(object, iter->first, std::move(value));
1083 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
1085 // call base type recursively
1086 mBaseType->SetProperty(object, name, std::move(value));
1090 DALI_LOG_ERROR("Property %s not found", name.c_str());
1094 Property::Value TypeInfo::GetProperty(const BaseObject* object, Property::Index index) const
1096 #ifdef USE_INDEXED_MAP_CONTAINER_AT_TYPE_INFO
1097 const auto& iter = mRegisteredProperties.Get(static_cast<std::uint32_t>(index));
1099 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
1101 if(iter != mRegisteredProperties.end())
1103 if(mCSharpType) // using csharp property get which returns a pointer to a Property::Value
1105 // CSharp wants a property name not an index
1106 // CSharp callback can't return an object by value, it can only return a pointer
1107 // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
1108 auto name = (iter->second).name;
1110 return *(iter->second.cSharpGetFunc(const_cast<BaseObject*>(object), name.GetCString()));
1114 // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
1115 return iter->second.getFunc(const_cast<BaseObject*>(object), index);
1119 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
1121 // call base type recursively
1122 return mBaseType->GetProperty(object, index);
1125 DALI_LOG_ERROR("Property index %d not found\n", index);
1126 return Property::Value();
1129 Property::Value TypeInfo::GetProperty(const BaseObject* object, const std::string& name) const
1131 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(ConstString(name)));
1133 if(iter != mRegisteredProperties.end())
1135 if(mCSharpType) // using csharp property get which returns a pointer to a Property::Value
1137 // CSharp wants a property name not an index
1138 // CSharp callback can't return an object by value, it can only return a pointer
1139 // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
1140 return *(iter->second.cSharpGetFunc(const_cast<BaseObject*>(object), name.c_str()));
1144 // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
1145 return iter->second.getFunc(const_cast<BaseObject*>(object), iter->first);
1149 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
1151 // call base type recursively
1152 return mBaseType->GetProperty(object, name);
1155 DALI_LOG_ERROR("Property %s not found", name.c_str());
1156 return Property::Value();
1159 } // namespace Internal