Переглянути джерело

Use godot_object_cast_to instead of TagDB to cast engine types

sheepandshepherd 5 роки тому
батько
коміт
33f9de16e4
2 змінених файлів з 30 додано та 13 видалено
  1. 12 0
      binding_generator.py
  2. 18 13
      include/core/Godot.hpp

+ 12 - 0
binding_generator.py

@@ -146,10 +146,14 @@ def generate_class_header(used_classes, c):
 
     source.append("\t};")
     source.append("\tstatic ___method_bindings ___mb;")
+    source.append("\tstatic void *_detail_class_tag;")
     source.append("")
     source.append("public:")
     source.append("\tstatic void ___init_method_bindings();")
 
+    # class id from core engine for casting
+    source.append("\tinline static size_t ___get_id() { return (size_t)_detail_class_tag; }")
+
     source.append("")
 
 
@@ -355,11 +359,19 @@ def generate_class_implementation(icalls, used_classes, c):
     source.append(class_name + "::___method_bindings " + class_name + "::___mb = {};")
     source.append("")
 
+    source.append("void *" + class_name + "::_detail_class_tag = nullptr;")
+    source.append("")
+
     source.append("void " + class_name + "::___init_method_bindings() {")
 
     for method in c["methods"]:
         source.append("\t___mb.mb_" + method["name"] + " = godot::api->godot_method_bind_get_method(\"" + c["name"] + "\", \"" + method["name"] + "\");")
 
+    source.append("\tgodot_string_name class_name;")
+    source.append("\tgodot::api->godot_string_name_new_data(&class_name, \"" + c["name"] + "\");")
+    source.append("\t_detail_class_tag = godot::core_1_2_api->godot_get_class_tag(&class_name);")
+    source.append("\tgodot::api->godot_string_name_destroy(&class_name);")
+
     source.append("}")
     source.append("")
 

+ 18 - 13
include/core/Godot.hpp

@@ -100,7 +100,7 @@ public:
 		return godot::detail::create_custom_class_instance<Name>();                         \
 	}                                                                                       \
 	inline static size_t ___get_id() { return typeid(Name).hash_code(); }                   \
-	inline static size_t ___get_base_id() { return typeid(Base).hash_code(); }              \
+	inline static size_t ___get_base_id() { return Base::___get_id(); }                     \
 	inline static const char *___get_base_type_name() { return Base::___get_class_name(); } \
 	inline static godot::Object *___get_from_variant(godot::Variant a) {                    \
 		return (godot::Object *)godot::detail::get_custom_class_instance<Name>(             \
@@ -513,23 +513,28 @@ T *Object::cast_to(const Object *obj) {
 	if (!obj)
 		return nullptr;
 
-	size_t have_tag = (size_t)godot::nativescript_1_1_api->godot_nativescript_get_type_tag(obj->_owner);
-
-	if (have_tag) {
-		if (!godot::_TagDB::is_type_known((size_t)have_tag)) {
-			have_tag = 0;
+	if (T::___CLASS_IS_SCRIPT) {
+		size_t have_tag = (size_t)godot::nativescript_1_1_api->godot_nativescript_get_type_tag(obj->_owner);
+		if (have_tag) {
+			if (!godot::_TagDB::is_type_known((size_t)have_tag)) {
+				have_tag = 0;
+			}
 		}
-	}
 
-	if (!have_tag) {
-		have_tag = obj->_type_tag;
-	}
+		if (!have_tag) {
+			have_tag = obj->_type_tag;
+		}
 
-	if (godot::_TagDB::is_type_compatible(typeid(T).hash_code(), have_tag)) {
-		return (T::___CLASS_IS_SCRIPT) ? detail::get_custom_class_instance<T>(obj) : (T *)obj;
+		if (godot::_TagDB::is_type_compatible(T::___get_id(), have_tag)) {
+			return detail::get_custom_class_instance<T>(obj);
+		}
 	} else {
-		return nullptr;
+		if (godot::core_1_2_api->godot_object_cast_to(obj->_owner, (void *)T::___get_id())) {
+			return (T *)obj;
+		}
 	}
+
+	return nullptr;
 }
 #endif