diff options
-rw-r--r-- | modules/gdscript/gdscript.cpp | 20 | ||||
-rw-r--r-- | modules/gdscript/gdscript.h | 1 | ||||
-rw-r--r-- | modules/gdscript/gdscript_compiler.cpp | 31 |
3 files changed, 39 insertions, 13 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 617db883f8..e6aeef2fd1 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1254,6 +1254,14 @@ GDScript::~GDScript() { memdelete(E.value); } + if (implicit_initializer) { + memdelete(implicit_initializer); + } + + if (implicit_ready) { + memdelete(implicit_ready); + } + if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown. GDScriptCache::remove_script(get_path()); } @@ -1541,6 +1549,18 @@ bool GDScriptInstance::has_method(const StringName &p_method) const { Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { GDScript *sptr = script.ptr(); + if (unlikely(p_method == SNAME("_ready"))) { + // Call implicit ready first, including for the super classes. + while (sptr) { + if (sptr->implicit_ready) { + sptr->implicit_ready->call(this, nullptr, 0, r_error); + } + sptr = sptr->_base; + } + + // Reset this back for the regular call. + sptr = script.ptr(); + } while (sptr) { HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method); if (E) { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 0057962d5e..feb0a237df 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -120,6 +120,7 @@ class GDScript : public Script { GDScriptFunction *implicit_initializer = nullptr; GDScriptFunction *initializer = nullptr; //direct pointer to new , faster to locate + GDScriptFunction *implicit_ready = nullptr; int subclass_count = 0; RBSet<Object *> instances; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 25454030b1..16a0b17d61 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1990,18 +1990,18 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ // Parse initializer if applies. bool is_implicit_initializer = !p_for_ready && !p_func && !p_for_lambda; - bool is_initializer = p_func && !p_for_lambda && String(p_func->identifier->name) == GDScriptLanguage::get_singleton()->strings._init; - bool is_for_ready = p_for_ready || (p_func && !p_for_lambda && String(p_func->identifier->name) == "_ready"); + bool is_initializer = p_func && !p_for_lambda && p_func->identifier->name == GDScriptLanguage::get_singleton()->strings._init; + bool is_implicit_ready = !p_func && p_for_ready; - if (!p_for_lambda && (is_implicit_initializer || is_for_ready)) { + if (!p_for_lambda && (is_implicit_initializer || is_implicit_ready)) { // Initialize class fields. for (int i = 0; i < p_class->members.size(); i++) { if (p_class->members[i].type != GDScriptParser::ClassNode::Member::VARIABLE) { continue; } const GDScriptParser::VariableNode *field = p_class->members[i].variable; - if (field->onready != is_for_ready) { - // Only initialize in _ready. + if (field->onready != is_implicit_ready) { + // Only initialize in @implicit_ready. continue; } @@ -2123,6 +2123,8 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ p_script->initializer = gd_function; } else if (is_implicit_initializer) { p_script->implicit_initializer = gd_function; + } else if (is_implicit_ready) { + p_script->implicit_ready = gd_function; } if (p_func) { @@ -2140,7 +2142,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ #endif } - if (!p_for_lambda) { + if (!is_implicit_initializer && !is_implicit_ready && !p_for_lambda) { p_script->member_functions[func_name] = gd_function; } @@ -2208,11 +2210,19 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar for (const KeyValue<StringName, GDScriptFunction *> &E : p_script->member_functions) { memdelete(E.value); } + if (p_script->implicit_initializer) { + memdelete(p_script->implicit_initializer); + } + if (p_script->implicit_ready) { + memdelete(p_script->implicit_ready); + } p_script->member_functions.clear(); p_script->member_indices.clear(); p_script->member_info.clear(); p_script->_signals.clear(); p_script->initializer = nullptr; + p_script->implicit_initializer = nullptr; + p_script->implicit_ready = nullptr; p_script->tool = parser->is_tool(); p_script->name = p_class->identifier ? p_class->identifier->name : ""; @@ -2456,15 +2466,10 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { //parse methods - bool has_ready = false; - for (int i = 0; i < p_class->members.size(); i++) { const GDScriptParser::ClassNode::Member &member = p_class->members[i]; if (member.type == member.FUNCTION) { const GDScriptParser::FunctionNode *function = member.function; - if (!has_ready && function->identifier->name == "_ready") { - has_ready = true; - } Error err = OK; _parse_function(err, p_script, p_class, function); if (err) { @@ -2498,8 +2503,8 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa } } - if (!has_ready && p_class->onready_used) { - //create a _ready constructor + if (p_class->onready_used) { + // Create an implicit_ready constructor. Error err = OK; _parse_function(err, p_script, p_class, nullptr, true); if (err) { |