Browse Source

Merge pull request #101449 from dsnopek/gdextension-virtual-method-compat-merged-hash

Use `MethodInfo::get_compatibility_hash()` to generate the hash for `MethodBind::get_hash()` and other GDExtension hash clean up
Rémi Verschelde 7 months ago
parent
commit
23e05b7c2f

+ 10 - 2
core/extension/gdextension_special_compat_hashes.cpp

@@ -255,7 +255,8 @@ void GDExtensionSpecialCompatHashes::initialize() {
 #endif
 	});
 	mappings.insert("DirAccess", {
-		{ "list_dir_begin", 2018049411, 2610976713 },
+		{ "list_dir_begin", 2018049411, 166280745 },
+		{ "list_dir_begin", 2610976713, 166280745 },
 		{ "copy", 198434953, 1063198817 },
 		{ "copy_absolute", 198434953, 1063198817 },
 	});
@@ -277,7 +278,8 @@ void GDExtensionSpecialCompatHashes::initialize() {
 		{ "global_menu_add_multistate_item", 3431222859, 3297554655 },
 		{ "global_menu_add_separator", 1041533178, 3214812433 },
 		{ "tts_speak", 3741216677, 903992738 },
-		{ "is_touchscreen_available", 4162880507, 3323674545 },
+		{ "is_touchscreen_available", 4162880507, 36873697 },
+		{ "is_touchscreen_available", 3323674545, 36873697 },
 		{ "screen_set_orientation", 2629526904, 2211511631 },
 		{ "window_get_native_handle", 2709193271, 1096425680 },
 		{ "window_set_title", 3043792800, 441246282 },
@@ -548,6 +550,9 @@ void GDExtensionSpecialCompatHashes::initialize() {
 		{ "tr", 2475554935, 1195764410 },
 		{ "tr_n", 4021311862, 162698058 },
 	});
+	mappings.insert("OpenXRAPIExtension", {
+		{ "transform_from_pose", 3255299855, 2963875352 },
+	});
 	mappings.insert("OptionButton", {
 		{ "add_item", 3043792800, 2697778442 },
 		{ "add_icon_item", 3944051090, 3781678508 },
@@ -912,6 +917,9 @@ void GDExtensionSpecialCompatHashes::initialize() {
 		{ "set_cells_terrain_path", 3072115677, 3578627656 },
 		{ "get_used_cells_by_id", 4152068407, 2931012785 },
 	});
+	mappings.insert("TileMapLayer", {
+		{ "notify_runtime_tile_data_update", 2275361663, 3218959716 },
+	});
 	mappings.insert("TileMapPattern", {
 		{ "set_cell", 634000503, 2224802556 },
 	});

+ 1 - 1
core/io/dir_access.cpp

@@ -631,7 +631,7 @@ void DirAccess::_bind_methods() {
 	ClassDB::bind_static_method("DirAccess", D_METHOD("get_open_error"), &DirAccess::get_open_error);
 	ClassDB::bind_static_method("DirAccess", D_METHOD("create_temp", "prefix", "keep"), &DirAccess::_create_temp, DEFVAL(""), DEFVAL(false));
 
-	ClassDB::bind_method(D_METHOD("list_dir_begin"), &DirAccess::list_dir_begin, DEFVAL(false), DEFVAL(false));
+	ClassDB::bind_method(D_METHOD("list_dir_begin"), &DirAccess::list_dir_begin);
 	ClassDB::bind_method(D_METHOD("get_next"), &DirAccess::_get_next);
 	ClassDB::bind_method(D_METHOD("current_is_dir"), &DirAccess::current_is_dir);
 	ClassDB::bind_method(D_METHOD("list_dir_end"), &DirAccess::list_dir_end);

+ 5 - 0
core/object/class_db.cpp

@@ -1959,6 +1959,11 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_
 		ERR_FAIL_V_MSG(nullptr, vformat("Method definition provides more arguments than the method actually has '%s::%s'.", instance_type, mdname));
 	}
 
+	if (p_defcount > p_bind->get_argument_count()) {
+		memdelete(p_bind);
+		ERR_FAIL_V_MSG(nullptr, vformat("Method definition for '%s::%s' provides more default arguments than the method has arguments.", instance_type, mdname));
+	}
+
 	p_bind->set_argument_names(method_name.args);
 
 	if (!p_compatibility) {

+ 6 - 20
core/object/method_bind.cpp

@@ -35,29 +35,15 @@
 #include "method_bind.h"
 
 uint32_t MethodBind::get_hash() const {
-	uint32_t hash = hash_murmur3_one_32(has_return() ? 1 : 0);
-	hash = hash_murmur3_one_32(get_argument_count(), hash);
-
-	for (int i = (has_return() ? -1 : 0); i < get_argument_count(); i++) {
-		PropertyInfo pi = i == -1 ? get_return_info() : get_argument_info(i);
-		hash = hash_murmur3_one_32(get_argument_type(i), hash);
-		if (pi.class_name != StringName()) {
-			hash = hash_murmur3_one_32(pi.class_name.operator String().hash(), hash);
-		}
-	}
-
-	hash = hash_murmur3_one_32(get_default_argument_count(), hash);
+	MethodInfo mi;
+	mi.return_val = get_return_info();
+	mi.flags = get_hint_flags();
 	for (int i = 0; i < get_argument_count(); i++) {
-		if (has_default_argument(i)) {
-			Variant v = get_default_argument(i);
-			hash = hash_murmur3_one_32(v.hash(), hash);
-		}
+		mi.arguments.push_back(get_argument_info(i));
 	}
+	mi.default_arguments = default_arguments;
 
-	hash = hash_murmur3_one_32(is_const(), hash);
-	hash = hash_murmur3_one_32(is_vararg(), hash);
-
-	return hash_fmix32(hash);
+	return mi.get_compatibility_hash();
 }
 
 PropertyInfo MethodBind::get_argument_info(int p_argument) const {

+ 0 - 1
core/object/object.cpp

@@ -165,7 +165,6 @@ MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) {
 	return mi;
 }
 
-// This was copied from MethodBind::get_hash() so that the compatibility hashes for virtual and non-virtual methods would be the same.
 uint32_t MethodInfo::get_compatibility_hash() const {
 	bool has_return = (return_val.type != Variant::NIL) || (return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT);
 

+ 2 - 2
core/variant/native_ptr.h

@@ -121,7 +121,7 @@ struct GDExtensionPtr {
 
 template <typename T>
 struct GetTypeInfo<GDExtensionConstPtr<T>> {
-	static const Variant::Type VARIANT_TYPE = Variant::NIL;
+	static const Variant::Type VARIANT_TYPE = Variant::INT;
 	static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
 	static inline PropertyInfo get_class_info() {
 		return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDExtensionConstPtr<T>::get_name());
@@ -130,7 +130,7 @@ struct GetTypeInfo<GDExtensionConstPtr<T>> {
 
 template <typename T>
 struct GetTypeInfo<GDExtensionPtr<T>> {
-	static const Variant::Type VARIANT_TYPE = Variant::NIL;
+	static const Variant::Type VARIANT_TYPE = Variant::INT;
 	static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
 	static inline PropertyInfo get_class_info() {
 		return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDExtensionPtr<T>::get_name());

+ 1 - 1
scene/2d/tile_map_layer.cpp

@@ -1834,7 +1834,7 @@ void TileMapLayer::_bind_methods() {
 
 	// --- Runtime ---
 	ClassDB::bind_method(D_METHOD("update_internals"), &TileMapLayer::update_internals);
-	ClassDB::bind_method(D_METHOD("notify_runtime_tile_data_update"), &TileMapLayer::notify_runtime_tile_data_update, DEFVAL(-1));
+	ClassDB::bind_method(D_METHOD("notify_runtime_tile_data_update"), &TileMapLayer::notify_runtime_tile_data_update);
 
 	// --- Shortcuts to methods defined in TileSet ---
 	ClassDB::bind_method(D_METHOD("map_pattern", "position_in_tilemap", "coords_in_pattern", "pattern"), &TileMapLayer::map_pattern);

+ 1 - 1
servers/display_server.cpp

@@ -917,7 +917,7 @@ void DisplayServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("screen_get_usable_rect", "screen"), &DisplayServer::screen_get_usable_rect, DEFVAL(SCREEN_OF_MAIN_WINDOW));
 	ClassDB::bind_method(D_METHOD("screen_get_dpi", "screen"), &DisplayServer::screen_get_dpi, DEFVAL(SCREEN_OF_MAIN_WINDOW));
 	ClassDB::bind_method(D_METHOD("screen_get_scale", "screen"), &DisplayServer::screen_get_scale, DEFVAL(SCREEN_OF_MAIN_WINDOW));
-	ClassDB::bind_method(D_METHOD("is_touchscreen_available"), &DisplayServer::is_touchscreen_available, DEFVAL(SCREEN_OF_MAIN_WINDOW));
+	ClassDB::bind_method(D_METHOD("is_touchscreen_available"), &DisplayServer::is_touchscreen_available);
 	ClassDB::bind_method(D_METHOD("screen_get_max_scale"), &DisplayServer::screen_get_max_scale);
 	ClassDB::bind_method(D_METHOD("screen_get_refresh_rate", "screen"), &DisplayServer::screen_get_refresh_rate, DEFVAL(SCREEN_OF_MAIN_WINDOW));
 	ClassDB::bind_method(D_METHOD("screen_get_pixel", "position"), &DisplayServer::screen_get_pixel);