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