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

Merge pull request #15761 from touilleMan/pluginscript-improve-inheritance

[GDnative] Improve inheritance system in gdnative pluginscript
Rémi Verschelde 7 жил өмнө
parent
commit
1699978e24

+ 3 - 2
modules/gdnative/pluginscript/pluginscript_instance.cpp

@@ -84,8 +84,9 @@ Variant PluginScriptInstance::call(const StringName &p_method, const Variant **p
 	godot_variant ret = _desc->call_method(
 			_data, (godot_string_name *)&p_method, (const godot_variant **)p_args,
 			p_argcount, (godot_variant_call_error *)&r_error);
-	Variant *var_ret = (Variant *)&ret;
-	return *var_ret;
+	Variant var_ret = *(Variant *)&ret;
+	godot_variant_destroy(&ret);
+	return var_ret;
 }
 
 #if 0 // TODO: Don't rely on default implementations provided by ScriptInstance ?

+ 1 - 0
modules/gdnative/pluginscript/pluginscript_language.cpp

@@ -103,6 +103,7 @@ Ref<Script> PluginScriptLanguage::get_template(const String &p_class_name, const
 	if (_desc.get_template_source_code) {
 		godot_string src = _desc.get_template_source_code(_data, (godot_string *)&p_class_name, (godot_string *)&p_base_class_name);
 		script->set_source_code(*(String *)&src);
+		godot_string_destroy(&src);
 	}
 	return script;
 }

+ 24 - 25
modules/gdnative/pluginscript/pluginscript_script.cpp

@@ -131,13 +131,10 @@ ScriptInstance *PluginScript::instance_create(Object *p_this) {
 #endif
 	}
 
-	PluginScript *top = this;
-	// TODO: can be optimized by storing a PluginScript::_base_parent direct pointer
-	while (top->_ref_base_parent.is_valid())
-		top = top->_ref_base_parent.ptr();
-	if (top->_native_parent) {
-		if (!ClassDB::is_parent_class(p_this->get_class_name(), top->_native_parent)) {
-			String msg = "Script inherits from native type '" + String(top->_native_parent) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'";
+	StringName base_type = get_instance_base_type();
+	if (base_type) {
+		if (!ClassDB::is_parent_class(p_this->get_class_name(), base_type)) {
+			String msg = "Script inherits from native type '" + String(base_type) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'";
 			// TODO: implement PluginscriptLanguage::debug_break_parse
 			// if (ScriptDebugger::get_singleton()) {
 			// 	_language->debug_break_parse(get_path(), 0, msg);
@@ -210,29 +207,31 @@ Error PluginScript::reload(bool p_keep_state) {
 		// TODO: GDscript uses `ScriptDebugger` here to jump into the parsing error
 		return err;
 	}
+
+	// Script's parent is passed as base_name which can make reference to a
+	// ClassDB name (i.e. `Node2D`) or a ressource path (i.e. `res://foo/bar.gd`)
+	StringName *base_name = (StringName *)&manifest.base;
+	if (*base_name) {
+
+		if (ClassDB::class_exists(*base_name)) {
+			_native_parent = *base_name;
+		} else {
+			Ref<Script> res = ResourceLoader::load(*base_name);
+			if (res.is_valid()) {
+				_ref_base_parent = res;
+			} else {
+				String name = *(StringName *)&manifest.name;
+				ERR_EXPLAIN(_path + ": Script '" + name + "' has an invalid parent '" + *base_name + "'.");
+				ERR_FAIL_V(ERR_PARSE_ERROR);
+			}
+		}
+	}
+
 	_valid = true;
 	// Use the manifest to configure this script object
 	_data = manifest.data;
 	_name = *(StringName *)&manifest.name;
 	_tool = manifest.is_tool;
-	// Base name is either another PluginScript or a regular class accessible
-	// through ClassDB
-	StringName *base_name = (StringName *)&manifest.base;
-	for (SelfList<PluginScript> *e = _language->_script_list.first(); e != NULL; e = e->next()) {
-		if (e->self()->_name == *base_name) {
-			// Found you, base is a PluginScript !
-			_ref_base_parent = Ref<PluginScript>(e->self());
-			break;
-		}
-	}
-	if (!_ref_base_parent.is_valid()) {
-		// Base is a native ClassDB
-		if (!ClassDB::class_exists(*base_name)) {
-			ERR_EXPLAIN("Unknown script '" + String(_name) + "' parent '" + String(*base_name) + "'.");
-			ERR_FAIL_V(ERR_PARSE_ERROR);
-		}
-		_native_parent = *base_name;
-	}
 
 	Dictionary *members = (Dictionary *)&manifest.member_lines;
 	for (const Variant *key = members->next(); key != NULL; key = members->next(key)) {

+ 1 - 1
modules/gdnative/pluginscript/pluginscript_script.h

@@ -53,7 +53,7 @@ private:
 	bool _tool;
 	bool _valid;
 
-	Ref<PluginScript> _ref_base_parent;
+	Ref<Script> _ref_base_parent;
 	StringName _native_parent;
 	SelfList<PluginScript> _script_list;