|
|
@@ -43,7 +43,7 @@ namespace Rml {
|
|
|
#define RMLUI_LOG_TYPE_ERROR_ASSERT(T, val, msg) RMLUI_ASSERTMSG(val, (String(msg) + String(" T: ") + String(rmlui_type_name<T>())).c_str())
|
|
|
|
|
|
template<typename T>
|
|
|
-struct is_valid_data_scalar {
|
|
|
+struct is_builtin_data_scalar {
|
|
|
static constexpr bool value = std::is_arithmetic<T>::value
|
|
|
|| std::is_same<typename std::remove_cv<T>::type, String>::value;
|
|
|
};
|
|
|
@@ -54,29 +54,82 @@ class StructHandle {
|
|
|
public:
|
|
|
StructHandle(DataTypeRegister* type_register, StructDefinition* struct_definition) : type_register(type_register), struct_definition(struct_definition) {}
|
|
|
|
|
|
- // Register a member object. Any data type can be used.
|
|
|
+ /// Register a member object or member getter function.
|
|
|
+ /// @note Underlying type must be registered before it is used as a member.
|
|
|
+ /// @note Getter functions can return by reference, raw pointer, or by value. If returned by value,
|
|
|
+ /// the returned type must be a scalar data type, otherwise any data type can be used.
|
|
|
+ /// @example
|
|
|
+ /// struct Invader {
|
|
|
+ /// int health;
|
|
|
+ /// std::vector<Weapon>& GetWeapons();
|
|
|
+ /// /* ... */
|
|
|
+ /// };
|
|
|
+ /// struct_handle.RegisterMember("health", &Invader::health);
|
|
|
+ /// struct_handle.RegisterMember("weapons", &Invader::GetWeapons);
|
|
|
template <typename MemberType>
|
|
|
- StructHandle<Object>& RegisterMember(const String& name, MemberType Object::* member_ptr);
|
|
|
-
|
|
|
- // Register a member using a getter function. Must return value by reference or by raw pointer. Any data type can be used.
|
|
|
- template<typename ReturnType>
|
|
|
- StructHandle<Object>& RegisterMember(const String& name, ReturnType(Object::* member_get_func_ptr)());
|
|
|
+ StructHandle<Object>& RegisterMember(const String& name, MemberType Object::* member_ptr) {
|
|
|
+ RegisterMemberDetail(name, member_ptr);
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
|
|
|
- // Register a member using a getter function and optionally a setter function. Only scalar data types can be used.
|
|
|
- // Can get and set by value or by reference.
|
|
|
+ /// Register member getter and setter functions. The getter and setter functions must return and assign scalar value types.
|
|
|
+ /// @note Underlying type must be registered before it is used as a member.
|
|
|
+ /// @note Getter and setter functions can return by reference, raw pointer, or by value. Only scalar data types allowed.
|
|
|
/// @example
|
|
|
- /// RegisterMemberScalar("color", &Invader::GetColor, &Invader::SetColor);
|
|
|
- /// where functions can be declared as
|
|
|
- /// MyColorType Invader::GetColor();
|
|
|
- /// void Invader::SetColor(MyColorType color);
|
|
|
- template<typename ReturnType = std::nullptr_t, typename AssignType = std::nullptr_t>
|
|
|
- StructHandle<Object>& RegisterMemberScalar(const String& name, ReturnType(Object::* member_get_func_ptr)(), void(Object::* member_set_func_ptr)(AssignType) = nullptr);
|
|
|
+ /// struct Invader {
|
|
|
+ /// MyColorType GetColor() const;
|
|
|
+ /// void SetColor(MyColorType color);
|
|
|
+ /// /* ... */
|
|
|
+ /// };
|
|
|
+ /// struct_handle.RegisterMember("color", &Invader::GetColor, &Invader::SetColor);
|
|
|
+ template <typename MemberGetType, typename MemberSetType>
|
|
|
+ StructHandle<Object>& RegisterMember(const String& name, MemberGetType Object::* member_get_func_ptr, MemberSetType Object::* member_set_func_ptr) {
|
|
|
+ RegisterMemberDetail(name, member_get_func_ptr, member_set_func_ptr);
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
|
|
|
explicit operator bool() const {
|
|
|
return type_register && struct_definition;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
+
|
|
|
+ template <typename MemberType>
|
|
|
+ bool RegisterMemberDetail(const String& name, MemberType Object::* member_object_ptr);
|
|
|
+
|
|
|
+ template <typename ReturnType>
|
|
|
+ bool RegisterMemberDetail(const String& name, ReturnType& (Object::* member_get_func_ptr)());
|
|
|
+
|
|
|
+ template <typename ReturnType>
|
|
|
+ bool RegisterMemberDetail(const String& name, ReturnType& (Object::* member_get_func_ptr)() const);
|
|
|
+
|
|
|
+ template <typename ReturnType>
|
|
|
+ bool RegisterMemberDetail(const String& name, ReturnType* (Object::* member_get_func_ptr)());
|
|
|
+
|
|
|
+ template <typename ReturnType>
|
|
|
+ bool RegisterMemberDetail(const String& name, ReturnType* (Object::* member_get_func_ptr)() const);
|
|
|
+
|
|
|
+ template <typename ReturnType>
|
|
|
+ bool RegisterMemberDetail(const String& name, ReturnType(Object::* member_get_func_ptr)());
|
|
|
+
|
|
|
+ template <typename ReturnType>
|
|
|
+ bool RegisterMemberDetail(const String& name, ReturnType(Object::* member_get_func_ptr)() const);
|
|
|
+
|
|
|
+ template <typename ReturnType, typename AssignType>
|
|
|
+ bool RegisterMemberDetail(const String& name, ReturnType(Object::* member_get_func_ptr)(), void(Object::* member_set_func_ptr)(AssignType));
|
|
|
+
|
|
|
+ template <typename ReturnType, typename AssignType>
|
|
|
+ bool RegisterMemberDetail(const String& name, ReturnType(Object::* member_get_func_ptr)() const, void(Object::* member_set_func_ptr)(AssignType));
|
|
|
+
|
|
|
+ template<typename MemberType>
|
|
|
+ bool CreateMemberObjectDefinition(const String& name, MemberType Object::* member_ptr);
|
|
|
+
|
|
|
+ template<typename BasicReturnType, typename MemberType>
|
|
|
+ bool CreateMemberGetFuncDefinition(const String& name, MemberType Object::* member_get_func_ptr);
|
|
|
+
|
|
|
+ template<typename UnderlyingType, typename MemberGetType, typename MemberSetType>
|
|
|
+ bool CreateMemberScalarGetSetFuncDefinition(const String& name, MemberGetType Object::* member_get_func_ptr, MemberSetType Object::* member_set_func_ptr);
|
|
|
+
|
|
|
DataTypeRegister* type_register;
|
|
|
StructDefinition* struct_definition;
|
|
|
};
|
|
|
@@ -145,7 +198,7 @@ public:
|
|
|
template<typename T>
|
|
|
bool RegisterScalar(DataTypeGetFunc<T> get_func, DataTypeSetFunc<T> set_func)
|
|
|
{
|
|
|
- static_assert(!is_valid_data_scalar<T>::value, "Cannot register scalar data type function. Arithmetic types and String are handled internally and does not need to be registered.");
|
|
|
+ static_assert(!is_builtin_data_scalar<T>::value, "Cannot register scalar data type function. Arithmetic types and String are handled internally and does not need to be registered.");
|
|
|
FamilyId id = Family<T>::Id();
|
|
|
|
|
|
auto scalar_func_definition = MakeUnique<ScalarFuncDefinition<T>>(get_func, set_func);
|
|
|
@@ -174,7 +227,7 @@ private:
|
|
|
|
|
|
// Get definition for scalar types that can be assigned to and from Rml::Variant.
|
|
|
// We automatically register these when needed, so users don't have to register trivial types manually.
|
|
|
- template<typename T, typename std::enable_if<!PointerTraits<T>::is_pointer::value&& is_valid_data_scalar<T>::value, int>::type = 0>
|
|
|
+ template<typename T, typename std::enable_if<!PointerTraits<T>::is_pointer::value && is_builtin_data_scalar<T>::value, int>::type = 0>
|
|
|
VariableDefinition* GetDefinitionDetail()
|
|
|
{
|
|
|
FamilyId id = Family<T>::Id();
|
|
|
@@ -189,9 +242,9 @@ private:
|
|
|
return definition.get();
|
|
|
}
|
|
|
|
|
|
- // Get definition for non-scalar types.
|
|
|
+ // Get definition for types that are not a built-in scalar.
|
|
|
// These must already have been registered by the user.
|
|
|
- template<typename T, typename std::enable_if<!PointerTraits<T>::is_pointer::value && !is_valid_data_scalar<T>::value, int>::type = 0>
|
|
|
+ template<typename T, typename std::enable_if<!PointerTraits<T>::is_pointer::value && !is_builtin_data_scalar<T>::value, int>::type = 0>
|
|
|
VariableDefinition* GetDefinitionDetail()
|
|
|
{
|
|
|
FamilyId id = Family<T>::Id();
|
|
|
@@ -240,63 +293,139 @@ private:
|
|
|
TransformFuncRegister transform_register;
|
|
|
};
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename MemberType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, MemberType Object::* member_object_ptr)
|
|
|
+{
|
|
|
+ return CreateMemberObjectDefinition(name, member_object_ptr);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename ReturnType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, ReturnType& (Object::* member_get_func_ptr)())
|
|
|
+{
|
|
|
+ return CreateMemberGetFuncDefinition<ReturnType>(name, member_get_func_ptr);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename ReturnType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, ReturnType& (Object::* member_get_func_ptr)() const)
|
|
|
+{
|
|
|
+ return CreateMemberGetFuncDefinition<ReturnType>(name, member_get_func_ptr);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename ReturnType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, ReturnType* (Object::* member_get_func_ptr)())
|
|
|
+{
|
|
|
+ return CreateMemberGetFuncDefinition<ReturnType>(name, member_get_func_ptr);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename ReturnType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, ReturnType* (Object::* member_get_func_ptr)() const)
|
|
|
+{
|
|
|
+ return CreateMemberGetFuncDefinition<ReturnType>(name, member_get_func_ptr);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename ReturnType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, ReturnType(Object::* member_get_func_ptr)())
|
|
|
+{
|
|
|
+ using BasicReturnType = typename std::remove_cv<typename std::remove_reference<ReturnType>::type>::type;
|
|
|
+ using SetType = std::nullptr_t Object::*;
|
|
|
+ return CreateMemberScalarGetSetFuncDefinition<BasicReturnType>(name, member_get_func_ptr, SetType{});
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename ReturnType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, ReturnType(Object::* member_get_func_ptr)() const)
|
|
|
+{
|
|
|
+ using BasicReturnType = typename std::remove_cv<typename std::remove_reference<ReturnType>::type>::type;
|
|
|
+ using SetType = std::nullptr_t Object::*;
|
|
|
+ return CreateMemberScalarGetSetFuncDefinition<BasicReturnType>(name, member_get_func_ptr, SetType{});
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename ReturnType, typename AssignType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, ReturnType(Object::* member_get_func_ptr)(), void(Object::* member_set_func_ptr)(AssignType))
|
|
|
+{
|
|
|
+ using BasicReturnType = typename std::remove_cv<typename std::remove_reference<ReturnType>::type>::type;
|
|
|
+ using BasicAssignType = typename std::remove_cv<typename std::remove_reference<AssignType>::type>::type;
|
|
|
+ using UnderlyingType = typename std::conditional<std::is_null_pointer<BasicReturnType>::value, BasicAssignType, BasicReturnType>::type;
|
|
|
+
|
|
|
+ static_assert(std::is_null_pointer<ReturnType>::value || std::is_null_pointer<AssignType>::value || std::is_same<BasicReturnType, BasicAssignType>::value, "Provided getter and setter functions must get and set the same type.");
|
|
|
+
|
|
|
+ return CreateMemberScalarGetSetFuncDefinition<UnderlyingType>(name, member_get_func_ptr, member_set_func_ptr);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Object>
|
|
|
+template <typename ReturnType, typename AssignType>
|
|
|
+bool StructHandle<Object>::RegisterMemberDetail(const String& name, ReturnType(Object::* member_get_func_ptr)() const, void(Object::* member_set_func_ptr)(AssignType))
|
|
|
+{
|
|
|
+ using BasicReturnType = typename std::remove_cv<typename std::remove_reference<ReturnType>::type>::type;
|
|
|
+ using BasicAssignType = typename std::remove_cv<typename std::remove_reference<AssignType>::type>::type;
|
|
|
+ using UnderlyingType = typename std::conditional<std::is_null_pointer<BasicReturnType>::value, BasicAssignType, BasicReturnType>::type;
|
|
|
+
|
|
|
+ static_assert(std::is_null_pointer<ReturnType>::value || std::is_null_pointer<AssignType>::value || std::is_same<BasicReturnType, BasicAssignType>::value, "Provided getter and setter functions must get and set the same type.");
|
|
|
+
|
|
|
+ return CreateMemberScalarGetSetFuncDefinition<UnderlyingType>(name, member_get_func_ptr, member_set_func_ptr);
|
|
|
+}
|
|
|
+
|
|
|
template<typename Object>
|
|
|
template<typename MemberType>
|
|
|
-inline StructHandle<Object>& StructHandle<Object>::RegisterMember(const String& name, MemberType Object::* member_ptr)
|
|
|
+bool StructHandle<Object>::CreateMemberObjectDefinition(const String& name, MemberType Object::* member_ptr)
|
|
|
{
|
|
|
- if (VariableDefinition* member_definition = type_register->GetDefinition<MemberType>())
|
|
|
- {
|
|
|
- struct_definition->AddMember(
|
|
|
- name,
|
|
|
- MakeUnique<MemberObjectPointerDefinition<Object, MemberType>>(member_definition, member_ptr)
|
|
|
- );
|
|
|
- }
|
|
|
- return *this;
|
|
|
+ VariableDefinition* underlying_definition = type_register->GetDefinition<MemberType>();
|
|
|
+ if (!underlying_definition)
|
|
|
+ return false;
|
|
|
+ struct_definition->AddMember(
|
|
|
+ name,
|
|
|
+ MakeUnique<MemberObjectDefinition<Object, MemberType>>(underlying_definition, member_ptr)
|
|
|
+ );
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
template<typename Object>
|
|
|
-template<typename ReturnType>
|
|
|
-inline StructHandle<Object>& StructHandle<Object>::RegisterMember(const String& name, ReturnType(Object::*member_get_func_ptr)())
|
|
|
+template<typename BasicReturnType, typename MemberType>
|
|
|
+bool StructHandle<Object>::CreateMemberGetFuncDefinition(const String& name, MemberType Object::* member_get_func_ptr)
|
|
|
{
|
|
|
- using BasicReturnType = typename std::remove_pointer<typename std::remove_reference<ReturnType>::type>::type;
|
|
|
- static_assert(!std::is_same<ReturnType, BasicReturnType>::value, "Struct member getter function must return value by reference or raw pointer.");
|
|
|
-
|
|
|
VariableDefinition* underlying_definition = type_register->GetDefinition<BasicReturnType>();
|
|
|
+ if (!underlying_definition)
|
|
|
+ return false;
|
|
|
+
|
|
|
struct_definition->AddMember(
|
|
|
name,
|
|
|
- MakeUnique<MemberFunctionPointerDefinition<Object, ReturnType, BasicReturnType>>(underlying_definition, member_get_func_ptr)
|
|
|
+ MakeUnique<MemberGetFuncDefinition<Object, MemberType, BasicReturnType>>(underlying_definition, member_get_func_ptr)
|
|
|
);
|
|
|
- return *this;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
template<typename Object>
|
|
|
-template<typename ReturnType, typename AssignType>
|
|
|
-inline StructHandle<Object>& StructHandle<Object>::RegisterMemberScalar(const String& name, ReturnType(Object::* member_get_func_ptr)(), void(Object::* member_set_func_ptr)(AssignType))
|
|
|
+template<typename UnderlyingType, typename MemberGetType, typename MemberSetType>
|
|
|
+bool StructHandle<Object>::CreateMemberScalarGetSetFuncDefinition(const String& name, MemberGetType Object::* member_get_func_ptr, MemberSetType Object::* member_set_func_ptr)
|
|
|
{
|
|
|
- using BasicReturnType = typename std::remove_cv<typename std::remove_reference<ReturnType>::type>::type;
|
|
|
- using BasicAssignType = typename std::remove_cv<typename std::remove_reference<AssignType>::type>::type;
|
|
|
- using UnderlyingType = typename std::conditional<std::is_null_pointer<BasicReturnType>::value, BasicAssignType, BasicReturnType>::type;
|
|
|
-
|
|
|
- static_assert(std::is_null_pointer<ReturnType>::value || std::is_null_pointer<AssignType>::value || std::is_same<BasicReturnType, BasicAssignType>::value, "Provided getter and setter functions must get and set the same type.");
|
|
|
- static_assert(std::is_copy_assignable<UnderlyingType>::value, "Struct member getter and setter functions must return/assign a type that is copy assignable.");
|
|
|
- static_assert(std::is_default_constructible<UnderlyingType>::value, "Struct member getter and setter functions must return/assign a type that is default constructible.");
|
|
|
+ static_assert(std::is_copy_assignable<UnderlyingType>::value, "Struct member getter/setter functions must return/assign a type that is copy assignable.");
|
|
|
+ static_assert(std::is_default_constructible<UnderlyingType>::value, "Struct member getter/setter functions must return/assign a type that is default constructible.");
|
|
|
|
|
|
VariableDefinition* underlying_definition = type_register->GetDefinition<UnderlyingType>();
|
|
|
if (!underlying_definition)
|
|
|
- return *this;
|
|
|
+ return false;
|
|
|
|
|
|
- DataVariableType type = underlying_definition->Type();
|
|
|
- if (!(type == DataVariableType::Scalar || type == DataVariableType::Function))
|
|
|
+ if (underlying_definition->Type() != DataVariableType::Scalar)
|
|
|
{
|
|
|
- RMLUI_LOG_TYPE_ERROR(UnderlyingType, "A getter/setter member function must return and assign a scalar data variable type.");
|
|
|
- return *this;
|
|
|
+ RMLUI_LOG_TYPE_ERROR(UnderlyingType, "Non-scalar data variable member registered, but only scalar data variables are allowed here: A getter function returning by value, or a getter/setter function pair.");
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
struct_definition->AddMember(
|
|
|
name,
|
|
|
- MakeUnique<MemberScalarFunctionPointerDefinition<Object, ReturnType, AssignType, UnderlyingType>>(underlying_definition, member_get_func_ptr, member_set_func_ptr)
|
|
|
+ MakeUnique<MemberScalarGetSetFuncDefinition<Object, MemberGetType, MemberSetType, UnderlyingType>>(underlying_definition, member_get_func_ptr, member_set_func_ptr)
|
|
|
);
|
|
|
- return *this;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
} // namespace Rml
|