Improve inheritance system in gdnative pluginscript
This commit is contained in:
parent
05b1843818
commit
0de61998e4
4 changed files with 29 additions and 28 deletions
|
@ -84,8 +84,9 @@ Variant PluginScriptInstance::call(const StringName &p_method, const Variant **p
|
||||||
godot_variant ret = _desc->call_method(
|
godot_variant ret = _desc->call_method(
|
||||||
_data, (godot_string_name *)&p_method, (const godot_variant **)p_args,
|
_data, (godot_string_name *)&p_method, (const godot_variant **)p_args,
|
||||||
p_argcount, (godot_variant_call_error *)&r_error);
|
p_argcount, (godot_variant_call_error *)&r_error);
|
||||||
Variant *var_ret = (Variant *)&ret;
|
Variant var_ret = *(Variant *)&ret;
|
||||||
return *var_ret;
|
godot_variant_destroy(&ret);
|
||||||
|
return var_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // TODO: Don't rely on default implementations provided by ScriptInstance ?
|
#if 0 // TODO: Don't rely on default implementations provided by ScriptInstance ?
|
||||||
|
|
|
@ -103,6 +103,7 @@ Ref<Script> PluginScriptLanguage::get_template(const String &p_class_name, const
|
||||||
if (_desc.get_template_source_code) {
|
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);
|
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);
|
script->set_source_code(*(String *)&src);
|
||||||
|
godot_string_destroy(&src);
|
||||||
}
|
}
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,13 +131,10 @@ ScriptInstance *PluginScript::instance_create(Object *p_this) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginScript *top = this;
|
StringName base_type = get_instance_base_type();
|
||||||
// TODO: can be optimized by storing a PluginScript::_base_parent direct pointer
|
if (base_type) {
|
||||||
while (top->_ref_base_parent.is_valid())
|
if (!ClassDB::is_parent_class(p_this->get_class_name(), base_type)) {
|
||||||
top = top->_ref_base_parent.ptr();
|
String msg = "Script inherits from native type '" + String(base_type) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'";
|
||||||
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() + "'";
|
|
||||||
// TODO: implement PluginscriptLanguage::debug_break_parse
|
// TODO: implement PluginscriptLanguage::debug_break_parse
|
||||||
// if (ScriptDebugger::get_singleton()) {
|
// if (ScriptDebugger::get_singleton()) {
|
||||||
// _language->debug_break_parse(get_path(), 0, msg);
|
// _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
|
// TODO: GDscript uses `ScriptDebugger` here to jump into the parsing error
|
||||||
return err;
|
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;
|
_valid = true;
|
||||||
// Use the manifest to configure this script object
|
// Use the manifest to configure this script object
|
||||||
_data = manifest.data;
|
_data = manifest.data;
|
||||||
_name = *(StringName *)&manifest.name;
|
_name = *(StringName *)&manifest.name;
|
||||||
_tool = manifest.is_tool;
|
_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;
|
Dictionary *members = (Dictionary *)&manifest.member_lines;
|
||||||
for (const Variant *key = members->next(); key != NULL; key = members->next(key)) {
|
for (const Variant *key = members->next(); key != NULL; key = members->next(key)) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ private:
|
||||||
bool _tool;
|
bool _tool;
|
||||||
bool _valid;
|
bool _valid;
|
||||||
|
|
||||||
Ref<PluginScript> _ref_base_parent;
|
Ref<Script> _ref_base_parent;
|
||||||
StringName _native_parent;
|
StringName _native_parent;
|
||||||
SelfList<PluginScript> _script_list;
|
SelfList<PluginScript> _script_list;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue