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.
This commit is contained in:
George Marques 2022-06-20 13:05:11 -03:00
parent 81cac4907f
commit cf015673d3
No known key found for this signature in database
GPG key ID: 046BD46A3201E43D
3 changed files with 31 additions and 13 deletions

View file

@ -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<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method);
if (E) {

View file

@ -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;

View file

@ -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) {