2 * Copyright (c) 2021 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 ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
220 if(iter != mActions.end())
222 done = (iter->second)(object, actionName, properties);
227 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
229 // call base type recursively
230 done = mBaseType->DoActionTo(object, actionName, properties);
237 bool TypeInfo::ConnectSignal(BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor)
239 bool connected(false);
241 ConnectorContainer::iterator iter = find_if(mSignalConnectors.begin(), mSignalConnectors.end(), PairFinder<std::string, ConnectionPair>(signalName));
243 if(iter != mSignalConnectors.end())
245 connected = (iter->second)(object, connectionTracker, signalName, functor);
250 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
252 // call base type recursively
253 connected = mBaseType->ConnectSignal(object, connectionTracker, signalName, functor);
260 const std::string& TypeInfo::GetName() const
265 const std::string& TypeInfo::GetBaseName() const
267 return mBaseTypeName;
270 Dali::TypeInfo::CreateFunction TypeInfo::GetCreator() const
275 uint32_t TypeInfo::GetActionCount() const
277 uint32_t count = static_cast<uint32_t>(mActions.size());
279 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
281 // call base type recursively
282 count += mBaseType->GetActionCount();
288 std::string TypeInfo::GetActionName(uint32_t index) const
291 const uint32_t count = static_cast<uint32_t>(mActions.size());
295 name = mActions[index].first;
299 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
301 // call base type recursively
302 return mBaseType->GetActionName(index - count);
309 uint32_t TypeInfo::GetSignalCount() const
311 uint32_t count = static_cast<uint32_t>(mSignalConnectors.size());
313 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
315 // call base type recursively
316 count += mBaseType->GetSignalCount();
322 std::string TypeInfo::GetSignalName(uint32_t index) const
325 const uint32_t count = static_cast<uint32_t>(mSignalConnectors.size());
329 name = mSignalConnectors[index].first;
333 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
335 // call base type recursively
336 return mBaseType->GetSignalName(index - count);
343 void TypeInfo::GetPropertyIndices(Property::IndexContainer& indices) const
345 // Default Properties
346 if(mDefaultProperties)
348 indices.Reserve(indices.Size() + mDefaultPropertyCount);
349 for(Property::Index index = 0; index < mDefaultPropertyCount; ++index)
351 indices.PushBack(mDefaultProperties[index].enumIndex);
355 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
357 // call base type recursively
358 mBaseType->GetPropertyIndices(indices);
361 AppendProperties(indices, mRegisteredProperties);
364 void TypeInfo::GetChildPropertyIndices(Property::IndexContainer& indices) const
366 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
368 // call base type recursively
369 mBaseType->GetChildPropertyIndices(indices);
372 AppendProperties(indices, mRegisteredChildProperties);
376 * Append the indices in RegisteredProperties to the given index container.
378 void TypeInfo::AppendProperties(Dali::Property::IndexContainer& indices,
379 const TypeInfo::RegisteredPropertyContainer& registeredProperties) const
381 if(!registeredProperties.empty())
383 indices.Reserve(indices.Size() + registeredProperties.size());
385 for(auto&& elem : registeredProperties)
387 indices.PushBack(elem.first);
392 std::string_view TypeInfo::GetRegisteredPropertyName(Property::Index index) const
394 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
395 if(iter != mRegisteredProperties.end())
397 return iter->second.name.GetStringView();
399 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
401 // call base type recursively
402 return mBaseType->GetRegisteredPropertyName(index);
404 static std::string empty;
408 std::string_view TypeInfo::GetPropertyName(Property::Index index) const
410 std::string_view propertyName;
412 if(mDefaultProperties && (index < DEFAULT_PROPERTY_MAX_COUNT))
414 std::string_view name;
415 if(GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::name, name))
422 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
423 if(iter != mRegisteredProperties.end())
425 return iter->second.name.GetStringView();
428 // if not our property, go to parent
429 if(propertyName.empty())
431 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
433 // call base type recursively
434 return mBaseType->GetPropertyName(index);
441 void TypeInfo::AddActionFunction(std::string actionName, Dali::TypeInfo::ActionFunction function)
443 if(nullptr == function)
445 DALI_LOG_WARNING("Action function is empty\n");
449 ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
451 if(iter == mActions.end())
453 mActions.push_back(ActionPair(std::move(actionName), function));
457 DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str());
462 void TypeInfo::AddConnectorFunction(std::string signalName, Dali::TypeInfo::SignalConnectorFunction function)
464 if(nullptr == function)
466 DALI_LOG_WARNING("Connector function is empty\n");
470 ConnectorContainer::iterator iter = find_if(mSignalConnectors.begin(), mSignalConnectors.end(), PairFinder<std::string, ConnectionPair>(signalName));
472 if(iter == mSignalConnectors.end())
474 mSignalConnectors.push_back(ConnectionPair(std::move(signalName), function));
478 DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str());
483 void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc)
485 // The setter can be empty as a property can be read-only.
487 if(nullptr == getFunc)
489 DALI_ASSERT_ALWAYS(!"GetProperty Function is empty");
493 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
495 if(iter == mRegisteredProperties.end())
497 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
501 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
506 void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc)
508 // The setter can be empty as a property can be read-only.
510 if(nullptr == getFunc)
512 DALI_ASSERT_ALWAYS(!"GetProperty Function is empty");
516 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
518 if(iter == mRegisteredProperties.end())
520 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
524 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
529 void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Property::Type type)
531 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
533 if(iter == mRegisteredProperties.end())
535 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
539 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
543 void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Property::Value defaultValue)
545 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
547 if(iter == mRegisteredProperties.end())
549 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(defaultValue.GetType(), ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
550 mPropertyDefaultValues.push_back(PropertyDefaultValuePair(index, std::move(defaultValue)));
554 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
558 void TypeInfo::AddAnimatablePropertyComponent(std::string name, Property::Index index, Property::Index baseIndex, uint32_t componentIndex)
560 Property::Type type = GetPropertyType(baseIndex);
561 DALI_ASSERT_ALWAYS((type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4) && "Base property does not support component");
563 bool success = false;
565 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
567 if(iter == mRegisteredProperties.end())
569 iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyComponentFinder<RegisteredPropertyPair>(baseIndex, componentIndex));
571 if(iter == mRegisteredProperties.end())
573 mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), baseIndex, componentIndex)));
578 DALI_ASSERT_ALWAYS(success && "Property component already registered");
581 void TypeInfo::AddChildProperty(std::string name, Property::Index index, Property::Type type)
583 RegisteredPropertyContainer::iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
585 if(iter == mRegisteredChildProperties.end())
587 mRegisteredChildProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
591 DALI_ASSERT_ALWAYS(!"Property index already added to Type");
595 uint32_t TypeInfo::GetPropertyCount() const
597 uint32_t count = mDefaultPropertyCount + static_cast<uint32_t>(mRegisteredProperties.size());
599 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
601 // call base type recursively
602 count += mBaseType->GetPropertyCount();
608 Property::Index TypeInfo::GetPropertyIndex(ConstString name) const
610 Property::Index index = Property::INVALID_INDEX;
613 // check default properties
614 if(mDefaultProperties)
616 auto stringView = name.GetStringView();
617 for(Property::Index tableIndex = 0; tableIndex < mDefaultPropertyCount; ++tableIndex)
619 if(mDefaultProperties[tableIndex].name == stringView)
621 index = mDefaultProperties[tableIndex].enumIndex;
629 // Slow but should not be done that often
630 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(name));
631 if(iter != mRegisteredProperties.end())
635 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
637 // call base type recursively
638 index = mBaseType->GetPropertyIndex(name);
645 Property::Index TypeInfo::GetBasePropertyIndex(Property::Index index) const
647 Property::Index basePropertyIndex = Property::INVALID_INDEX;
649 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
651 if(iter != mRegisteredProperties.end())
653 basePropertyIndex = iter->second.basePropertyIndex;
655 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
657 // call base type recursively
658 basePropertyIndex = mBaseType->GetBasePropertyIndex(index);
661 return basePropertyIndex;
664 int32_t TypeInfo::GetComponentIndex(Property::Index index) const
666 int componentIndex = Property::INVALID_COMPONENT_INDEX;
668 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
670 if(iter != mRegisteredProperties.end())
672 componentIndex = iter->second.componentIndex;
674 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
676 // call base type recursively
677 componentIndex = mBaseType->GetComponentIndex(index);
680 return componentIndex;
683 Property::Index TypeInfo::GetChildPropertyIndex(ConstString name) const
685 Property::Index index = Property::INVALID_INDEX;
687 // Slow but should not be done that often
688 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(name));
690 if(iter != mRegisteredChildProperties.end())
694 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
696 // call base type recursively
697 index = mBaseType->GetChildPropertyIndex(name);
703 std::string_view TypeInfo::GetChildPropertyName(Property::Index index) const
705 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
707 if(iter != mRegisteredChildProperties.end())
709 return iter->second.name.GetStringView();
712 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
714 // call base type recursively
715 return mBaseType->GetChildPropertyName(index);
718 DALI_LOG_ERROR("Property index %d not found\n", index);
723 Property::Type TypeInfo::GetChildPropertyType(Property::Index index) const
725 Property::Type type(Property::NONE);
727 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
729 if(iter != mRegisteredChildProperties.end())
731 type = iter->second.type;
733 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
735 // call base type recursively
736 type = mBaseType->GetChildPropertyType(index);
740 DALI_LOG_ERROR("Property index %d not found\n", index);
746 bool TypeInfo::IsPropertyWritable(Property::Index index) const
748 bool writable = false;
752 if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties)
754 found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::writable, writable);
756 else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX))
758 writable = true; // animatable property is writable
763 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
764 if(iter != mRegisteredProperties.end())
766 writable = iter->second.setFunc ? true : false;
771 // if not found, continue to base
774 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
776 // call base type recursively
777 writable = mBaseType->IsPropertyWritable(index);
781 DALI_LOG_ERROR("Property index %d not found\n", index);
788 bool TypeInfo::IsPropertyAnimatable(Property::Index index) const
790 bool animatable = false;
794 if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties)
796 found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::animatable, animatable);
798 else if((index >= PROPERTY_REGISTRATION_START_INDEX) && (index <= PROPERTY_REGISTRATION_MAX_INDEX))
800 // Type Registry event-thread only properties are not animatable.
804 else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX))
810 // if not found, continue to base
813 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
815 // call base type recursively
816 animatable = mBaseType->IsPropertyAnimatable(index);
820 DALI_LOG_ERROR("Property index %d not found\n", index);
827 bool TypeInfo::IsPropertyAConstraintInput(Property::Index index) const
829 bool constraintInput = false;
833 if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties)
835 found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::constraintInput, constraintInput);
837 else if((index >= PROPERTY_REGISTRATION_START_INDEX) && (index <= PROPERTY_REGISTRATION_MAX_INDEX))
839 // Type Registry event-thread only properties cannot be used as constraint input
840 constraintInput = false;
843 else if((index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX) && (index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX))
845 constraintInput = true;
849 // if not found, continue to base
852 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
854 // call base type recursively
855 constraintInput = mBaseType->IsPropertyAConstraintInput(index);
859 DALI_LOG_ERROR("Property index %d not found\n", index);
863 return constraintInput;
866 Property::Type TypeInfo::GetPropertyType(Property::Index index) const
868 Property::Type type(Property::NONE);
872 if((index < DEFAULT_PROPERTY_MAX_COUNT) && mDefaultProperties)
874 found = GetDefaultPropertyField(mDefaultProperties, mDefaultPropertyCount, index, &Dali::PropertyDetails::type, type);
878 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
880 if(iter != mRegisteredProperties.end())
882 if(iter->second.componentIndex == Property::INVALID_COMPONENT_INDEX)
884 type = iter->second.type;
889 // If component index is set, then we should return FLOAT
890 type = Property::FLOAT;
898 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
900 // call base type recursively
901 type = mBaseType->GetPropertyType(index);
905 DALI_LOG_ERROR("Property index %d not found\n", index);
912 Property::Value TypeInfo::GetPropertyDefaultValue(Property::Index index) const
914 PropertyDefaultValueContainer::const_iterator iter = find_if(mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(), PairFinder<Property::Index, PropertyDefaultValuePair>(index));
915 if(iter != mPropertyDefaultValues.end())
919 // we didn't have a value so ask base
920 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
922 // call base type recursively
923 return mBaseType->GetPropertyDefaultValue(index);
925 return Property::Value(); // return none
928 void TypeInfo::SetProperty(BaseObject* object, Property::Index index, Property::Value value) const
930 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
931 if(iter != mRegisteredProperties.end())
933 if(iter->second.setFunc)
937 // CSharp wants a property name not an index
938 auto name = (iter->second).name;
940 iter->second.cSharpSetFunc(object, name.GetCString(), const_cast<Property::Value*>(&value));
944 iter->second.setFunc(object, index, std::move(value));
948 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
950 // call base type recursively
951 mBaseType->SetProperty(object, index, std::move(value));
955 DALI_LOG_ERROR("Property index %d not found\n", index);
959 void TypeInfo::SetProperty(BaseObject* object, const std::string& name, Property::Value value) const
961 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(ConstString(name)));
962 if(iter != mRegisteredProperties.end())
964 DALI_ASSERT_ALWAYS(iter->second.setFunc && "Trying to write to a read-only property");
968 // CSharp wants a property name not an index
969 iter->second.cSharpSetFunc(object, name.c_str(), const_cast<Property::Value*>(&value));
973 iter->second.setFunc(object, iter->first, std::move(value));
976 else if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
978 // call base type recursively
979 mBaseType->SetProperty(object, name, std::move(value));
983 DALI_LOG_ERROR("Property %s not found", name.c_str());
987 Property::Value TypeInfo::GetProperty(const BaseObject* object, Property::Index index) const
989 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PairFinder<Property::Index, RegisteredPropertyPair>(index));
990 if(iter != mRegisteredProperties.end())
992 if(mCSharpType) // using csharp property get which returns a pointer to a Property::Value
994 // CSharp wants a property name not an index
995 // CSharp callback can't return an object by value, it can only return a pointer
996 // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
997 auto name = (iter->second).name;
999 return *(iter->second.cSharpGetFunc(const_cast<BaseObject*>(object), name.GetCString()));
1003 // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
1004 return iter->second.getFunc(const_cast<BaseObject*>(object), index);
1008 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
1010 // call base type recursively
1011 return mBaseType->GetProperty(object, index);
1014 DALI_LOG_ERROR("Property index %d not found\n", index);
1015 return Property::Value();
1018 Property::Value TypeInfo::GetProperty(const BaseObject* object, const std::string& name) const
1020 RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(ConstString(name)));
1022 if(iter != mRegisteredProperties.end())
1024 if(mCSharpType) // using csharp property get which returns a pointer to a Property::Value
1026 // CSharp wants a property name not an index
1027 // CSharp callback can't return an object by value, it can only return a pointer
1028 // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
1029 return *(iter->second.cSharpGetFunc(const_cast<BaseObject*>(object), name.c_str()));
1033 // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
1034 return iter->second.getFunc(const_cast<BaseObject*>(object), iter->first);
1038 if(GetBaseType(mBaseType, mTypeRegistry, mBaseTypeName))
1040 // call base type recursively
1041 return mBaseType->GetProperty(object, name);
1044 DALI_LOG_ERROR("Property %s not found", name.c_str());
1045 return Property::Value();
1048 } // namespace Internal