From 81cac4907fb605e4a55712c0a835b7e83660bc04 Mon Sep 17 00:00:00 2001 From: George Marques Date: Fri, 17 Jun 2022 14:48:07 -0300 Subject: [PATCH 1/2] GDScript: Don't add implicit constructor to the list of functions So it's not shown on docs or when listing the methods. This also avoids being able to call it using the `call()` function. --- modules/gdscript/gdscript.cpp | 4 ++++ modules/gdscript/gdscript_compiler.cpp | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 617db883f8a..874e0f22c5e 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1254,6 +1254,10 @@ GDScript::~GDScript() { memdelete(E.value); } + if (implicit_initializer) { + memdelete(implicit_initializer); + } + if (GDScriptCache::singleton) { // Cache may have been already destroyed at engine shutdown. GDScriptCache::remove_script(get_path()); } diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 25454030b17..ca4995152ec 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2140,7 +2140,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ #endif } - if (!p_for_lambda) { + if (!is_implicit_initializer && !p_for_lambda) { p_script->member_functions[func_name] = gd_function; } @@ -2208,11 +2208,15 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar for (const KeyValue &E : p_script->member_functions) { memdelete(E.value); } + if (p_script->implicit_initializer) { + memdelete(p_script->implicit_initializer); + } 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->tool = parser->is_tool(); p_script->name = p_class->identifier ? p_class->identifier->name : ""; From cf015673d3556afe4f56d70235e684a398bbaf01 Mon Sep 17 00:00:00 2001 From: George Marques Date: Mon, 20 Jun 2022 13:05:11 -0300 Subject: [PATCH 2/2] GDScript: Use implicit method for @onready variables Initialize them with the implicit method so they're not related to the overriding of the `_ready` method of the script but instead are always set. --- modules/gdscript/gdscript.cpp | 16 +++++++++++++++ modules/gdscript/gdscript.h | 1 + modules/gdscript/gdscript_compiler.cpp | 27 +++++++++++++------------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 874e0f22c5e..e6aeef2fd1b 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1258,6 +1258,10 @@ GDScript::~GDScript() { 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()); } @@ -1545,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::Iterator E = sptr->member_functions.find(p_method); if (E) { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 0057962d5ef..feb0a237df4 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 instances; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index ca4995152ec..16a0b17d615 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 (!is_implicit_initializer && !p_for_lambda) { + if (!is_implicit_initializer && !is_implicit_ready && !p_for_lambda) { p_script->member_functions[func_name] = gd_function; } @@ -2211,12 +2213,16 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar 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 : ""; @@ -2460,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) { @@ -2502,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) {