2
0
Эх сурвалжийг харах

Add support for BitField hint, sync API files.

bruvzg 3 жил өмнө
parent
commit
713b122b84

+ 38 - 9
binding_generator.py

@@ -1064,7 +1064,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
 
 
     if "enums" in class_api and class_name != "Object":
     if "enums" in class_api and class_name != "Object":
         for enum_api in class_api["enums"]:
         for enum_api in class_api["enums"]:
-            result.append(f'VARIANT_ENUM_CAST({class_name}, {class_name}::{enum_api["name"]});')
+            if enum_api["is_bitfield"]:
+                result.append(f'VARIANT_BITFIELD_CAST({class_name}, {class_name}::{enum_api["name"]});')
+            else:
+                result.append(f'VARIANT_ENUM_CAST({class_name}, {class_name}::{enum_api["name"]});')
         result.append("")
         result.append("")
 
 
     result.append(f"#endif // ! {header_guard}")
     result.append(f"#endif // ! {header_guard}")
@@ -1194,7 +1197,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
             result.append(method_call)
             result.append(method_call)
 
 
             if vararg and ("return_value" in method and method["return_value"]["type"] != "void"):
             if vararg and ("return_value" in method and method["return_value"]["type"] != "void"):
-                return_type = method["return_value"]["type"].replace("enum::", "")
+                return_type = get_enum_fullname(method["return_value"]["type"])
                 if return_type != "Variant":
                 if return_type != "Variant":
                     result.append(f"\treturn VariantCaster<{return_type}>::cast(ret);")
                     result.append(f"\treturn VariantCaster<{return_type}>::cast(ret);")
                 else:
                 else:
@@ -1712,18 +1715,35 @@ def needs_copy_instead_of_move(type_name):
 
 
 
 
 def is_enum(type_name):
 def is_enum(type_name):
-    return type_name.startswith("enum::")
+    return type_name.startswith("enum::") or type_name.startswith("bitfield::")
+
+
+def is_bitfield(type_name):
+    return type_name.startswith("bitfield::")
 
 
 
 
 def get_enum_class(enum_name: str):
 def get_enum_class(enum_name: str):
     if "." in enum_name:
     if "." in enum_name:
-        return enum_name.replace("enum::", "").split(".")[0]
+        if is_bitfield(enum_name):
+            return enum_name.replace("bitfield::", "").split(".")[0]
+        else:
+            return enum_name.replace("enum::", "").split(".")[0]
     else:
     else:
         return "GlobalConstants"
         return "GlobalConstants"
 
 
 
 
+def get_enum_fullname(enum_name: str):
+    if is_bitfield(enum_name):
+        return enum_name.replace("bitfield::", "BitField<") + ">"
+    else:
+        return enum_name.replace("enum::", "")
+
+
 def get_enum_name(enum_name: str):
 def get_enum_name(enum_name: str):
-    return enum_name.replace("enum::", "").split(".")[-1]
+    if is_bitfield(enum_name):
+        return enum_name.replace("bitfield::", "").split(".")[-1]
+    else:
+        return enum_name.replace("enum::", "").split(".")[-1]
 
 
 
 
 def is_variant(type_name):
 def is_variant(type_name):
@@ -1781,10 +1801,16 @@ def correct_type(type_name, meta=None):
     if type_name in type_conversion:
     if type_name in type_conversion:
         return type_conversion[type_name]
         return type_conversion[type_name]
     if is_enum(type_name):
     if is_enum(type_name):
-        base_class = get_enum_class(type_name)
-        if base_class == "GlobalConstants":
-            return f"{get_enum_name(type_name)}"
-        return f"{base_class}::{get_enum_name(type_name)}"
+        if is_bitfield(type_name):
+            base_class = get_enum_class(type_name)
+            if base_class == "GlobalConstants":
+                return f"BitField<{get_enum_name(type_name)}>"
+            return f"BitField<{base_class}::{get_enum_name(type_name)}>"
+        else:
+            base_class = get_enum_class(type_name)
+            if base_class == "GlobalConstants":
+                return f"{get_enum_name(type_name)}"
+            return f"{base_class}::{get_enum_name(type_name)}"
     if is_refcounted(type_name):
     if is_refcounted(type_name):
         return f"Ref<{type_name}>"
         return f"Ref<{type_name}>"
     if type_name == "Object" or is_engine_class(type_name):
     if type_name == "Object" or is_engine_class(type_name):
@@ -1807,6 +1833,9 @@ def get_gdnative_type(type_name):
         "float": "double",
         "float": "double",
     }
     }
 
 
+    if type_name.startswith("BitField<"):
+        return "int64_t"
+
     if type_name in type_conversion_map:
     if type_name in type_conversion_map:
         return type_conversion_map[type_name]
         return type_conversion_map[type_name]
     return type_name
     return type_name

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 349 - 228
godot-headers/extension_api.json


+ 1 - 1
godot-headers/godot/gdnative_interface.h

@@ -540,7 +540,7 @@ typedef struct {
 
 
 	void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
 	void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
 	void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
 	void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
-	void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
+	void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, bool p_is_bitfield);
 	void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
 	void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
 	void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
 	void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
 	void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
 	void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);

+ 21 - 0
include/godot_cpp/core/binder_common.hpp

@@ -62,6 +62,27 @@ namespace godot {
 	};                                                                                \
 	};                                                                                \
 	}
 	}
 
 
+#define VARIANT_BITFIELD_CAST(m_class, m_enum)                                                  \
+	namespace godot {                                                                           \
+	MAKE_BITFIELD_TYPE_INFO(m_class, m_enum)                                                    \
+	template <>                                                                                 \
+	struct VariantCaster<BitField<m_class::m_enum>> {                                           \
+		static _FORCE_INLINE_ BitField<m_class::m_enum> cast(const Variant &p_variant) {        \
+			return BitField<m_class::m_enum>(p_variant.operator int64_t());                     \
+		}                                                                                       \
+	};                                                                                          \
+	template <>                                                                                 \
+	struct PtrToArg<BitField<m_class::m_enum>> {                                                \
+		_FORCE_INLINE_ static BitField<m_class::m_enum> convert(const void *p_ptr) {            \
+			return BitField<m_class::m_enum>(*reinterpret_cast<const int64_t *>(p_ptr));        \
+		}                                                                                       \
+		typedef int64_t EncodeT;                                                                \
+		_FORCE_INLINE_ static void encode(BitField<m_class::m_enum> p_val, const void *p_ptr) { \
+			*(int64_t *)p_ptr = p_val;                                                          \
+		}                                                                                       \
+	};                                                                                          \
+	}
+
 template <class T>
 template <class T>
 struct VariantCaster {
 struct VariantCaster {
 	static _FORCE_INLINE_ T cast(const Variant &p_variant) {
 	static _FORCE_INLINE_ T cast(const Variant &p_variant) {

+ 4 - 1
include/godot_cpp/core/class_db.hpp

@@ -116,7 +116,7 @@ public:
 	static void add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix);
 	static void add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix);
 	static void add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index = -1);
 	static void add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index = -1);
 	static void add_signal(const char *p_class, const MethodInfo &p_signal);
 	static void add_signal(const char *p_class, const MethodInfo &p_signal);
-	static void bind_integer_constant(const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
+	static void bind_integer_constant(const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, bool p_is_bitfield = false);
 	static void bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call);
 	static void bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call);
 
 
 	static MethodBind *get_method(const char *p_class, const char *p_method);
 	static MethodBind *get_method(const char *p_class, const char *p_method);
@@ -133,6 +133,9 @@ public:
 #define BIND_ENUM_CONSTANT(m_constant) \
 #define BIND_ENUM_CONSTANT(m_constant) \
 	godot::ClassDB::bind_integer_constant(get_class_static(), godot::__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
 	godot::ClassDB::bind_integer_constant(get_class_static(), godot::__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
 
 
+#define BIND_BITFIELD_FLAG(m_constant) \
+	godot::ClassDB::bind_integer_constant(get_class_static(), godot::__constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true);
+
 #define BIND_VIRTUAL_METHOD(m_class, m_method)                                                                                    \
 #define BIND_VIRTUAL_METHOD(m_class, m_method)                                                                                    \
 	{                                                                                                                             \
 	{                                                                                                                             \
 		auto ___call##m_method = [](GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) -> void { \
 		auto ___call##m_method = [](GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) -> void { \

+ 47 - 0
include/godot_cpp/core/type_info.hpp

@@ -219,6 +219,53 @@ inline const char *__constant_get_enum_name(T param, const char *p_constant) {
 	return GetTypeInfo<T>::get_class_info().class_name;
 	return GetTypeInfo<T>::get_class_info().class_name;
 }
 }
 
 
+template <class T>
+class BitField {
+	uint32_t value = 0;
+
+public:
+	_FORCE_INLINE_ void set_flag(T p_flag) { value |= p_flag; }
+	_FORCE_INLINE_ bool has_flag(T p_flag) const { return value & p_flag; }
+	_FORCE_INLINE_ void clear_flag(T p_flag) { return value &= ~p_flag; }
+	_FORCE_INLINE_ BitField(uint32_t p_value) { value = p_value; }
+	_FORCE_INLINE_ operator uint32_t() const { return value; }
+	_FORCE_INLINE_ operator Variant() const { return value; }
+};
+
+#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_class, m_enum, m_impl)                                                                                    \
+	template <>                                                                                                                                   \
+	struct GetTypeInfo<m_impl> {                                                                                                                  \
+		static const Variant::Type VARIANT_TYPE = Variant::INT;                                                                                   \
+		static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;                    \
+		static inline GDNativePropertyInfo get_class_info() {                                                                                     \
+			return PropertyInfo(GDNATIVE_VARIANT_TYPE_INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
+					#m_class "." #m_enum);                                                                                                        \
+		}                                                                                                                                         \
+	};                                                                                                                                            \
+	template <>                                                                                                                                   \
+	struct GetTypeInfo<BitField<m_impl>> {                                                                                                        \
+		static const Variant::Type VARIANT_TYPE = Variant::INT;                                                                                   \
+		static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;                    \
+		static inline GDNativePropertyInfo get_class_info() {                                                                                     \
+			return PropertyInfo(GDNATIVE_VARIANT_TYPE_INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
+					#m_class "." #m_enum);                                                                                                        \
+		}                                                                                                                                         \
+	};
+
+#define MAKE_BITFIELD_TYPE_INFO(m_class, m_enum)                 \
+	TEMPL_MAKE_BITFIELD_TYPE_INFO(m_class, m_enum, m_enum)       \
+	TEMPL_MAKE_BITFIELD_TYPE_INFO(m_class, m_enum, m_enum const) \
+	TEMPL_MAKE_BITFIELD_TYPE_INFO(m_class, m_enum, m_enum &)     \
+	TEMPL_MAKE_BITFIELD_TYPE_INFO(m_class, m_enum, const m_enum &)
+
+template <typename T>
+inline const char *__constant_get_bitfield_name(T param, const char *p_constant) {
+	if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) {
+		ERR_PRINT(("Missing VARIANT_ENUM_CAST for constant's bitfield: " + String(p_constant)).utf8().get_data());
+	}
+	return GetTypeInfo<BitField<T>>::get_class_info().class_name;
+}
+
 #define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
 #define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
 
 
 } // namespace godot
 } // namespace godot

+ 2 - 2
src/core/class_db.cpp

@@ -249,7 +249,7 @@ void ClassDB::add_signal(const char *p_class, const MethodInfo &p_signal) {
 	internal::gdn_interface->classdb_register_extension_class_signal(internal::library, cl.name, p_signal.name, parameters.data(), parameters.size());
 	internal::gdn_interface->classdb_register_extension_class_signal(internal::library, cl.name, p_signal.name, parameters.data(), parameters.size());
 }
 }
 
 
-void ClassDB::bind_integer_constant(const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value) {
+void ClassDB::bind_integer_constant(const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, bool p_is_bitfield) {
 	std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(p_class_name);
 	std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(p_class_name);
 
 
 	ERR_FAIL_COND_MSG(type_it == classes.end(), "Class doesn't exist.");
 	ERR_FAIL_COND_MSG(type_it == classes.end(), "Class doesn't exist.");
@@ -263,7 +263,7 @@ void ClassDB::bind_integer_constant(const char *p_class_name, const char *p_enum
 	type.constant_names.insert(p_constant_name);
 	type.constant_names.insert(p_constant_name);
 
 
 	// Register it with Godot
 	// Register it with Godot
-	internal::gdn_interface->classdb_register_extension_class_integer_constant(internal::library, p_class_name, p_enum_name, p_constant_name, p_constant_value);
+	internal::gdn_interface->classdb_register_extension_class_integer_constant(internal::library, p_class_name, p_enum_name, p_constant_name, p_constant_value, p_is_bitfield);
 }
 }
 
 
 GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, const char *p_name) {
 GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, const char *p_name) {

+ 1 - 1
test/demo/project.godot

@@ -12,8 +12,8 @@ config_version=5
 
 
 config/name="GDExtension Test Project"
 config/name="GDExtension Test Project"
 run/main_scene="res://main.tscn"
 run/main_scene="res://main.tscn"
-config/icon="res://icon.png"
 config/features=PackedStringArray("4.0")
 config/features=PackedStringArray("4.0")
+config/icon="res://icon.png"
 
 
 [native_extensions]
 [native_extensions]
 
 

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно