| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  script_language.cpp                                                  */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2022-01-13 09:45:09 +01:00
										 |  |  | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "script_language.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-09 22:07:40 -07:00
										 |  |  | #include "core/core_string_names.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/project_settings.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES]; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | int ScriptServer::_language_count = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool ScriptServer::scripting_enabled = true; | 
					
						
							|  |  |  | bool ScriptServer::reload_scripts_on_save = false; | 
					
						
							| 
									
										
										
										
											2019-02-04 20:39:02 +01:00
										 |  |  | bool ScriptServer::languages_finished = false; | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | ScriptEditRequestFunction ScriptServer::edit_request_func = nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void Script::_notification(int p_what) { | 
					
						
							|  |  |  | 	if (p_what == NOTIFICATION_POSTINITIALIZE) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (ScriptDebugger::get_singleton()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			ScriptDebugger::get_singleton()->set_break_language(get_language()); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-01 14:13:40 -05:00
										 |  |  | Variant Script::_get_property_default_value(const StringName &p_property) { | 
					
						
							|  |  |  | 	Variant ret; | 
					
						
							|  |  |  | 	get_property_default_value(p_property, ret); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Array Script::_get_script_property_list() { | 
					
						
							|  |  |  | 	Array ret; | 
					
						
							|  |  |  | 	List<PropertyInfo> list; | 
					
						
							|  |  |  | 	get_script_property_list(&list); | 
					
						
							|  |  |  | 	for (List<PropertyInfo>::Element *E = list.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		ret.append(E->get().operator Dictionary()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Array Script::_get_script_method_list() { | 
					
						
							|  |  |  | 	Array ret; | 
					
						
							|  |  |  | 	List<MethodInfo> list; | 
					
						
							|  |  |  | 	get_script_method_list(&list); | 
					
						
							|  |  |  | 	for (List<MethodInfo>::Element *E = list.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		ret.append(E->get().operator Dictionary()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Array Script::_get_script_signal_list() { | 
					
						
							|  |  |  | 	Array ret; | 
					
						
							|  |  |  | 	List<MethodInfo> list; | 
					
						
							|  |  |  | 	get_script_signal_list(&list); | 
					
						
							|  |  |  | 	for (List<MethodInfo>::Element *E = list.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		ret.append(E->get().operator Dictionary()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Dictionary Script::_get_script_constant_map() { | 
					
						
							|  |  |  | 	Dictionary ret; | 
					
						
							|  |  |  | 	Map<StringName, Variant> map; | 
					
						
							|  |  |  | 	get_constants(&map); | 
					
						
							|  |  |  | 	for (Map<StringName, Variant>::Element *E = map.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		ret[E->key()] = E->value(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void Script::_bind_methods() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("can_instance"), &Script::can_instance); | 
					
						
							| 
									
										
										
										
											2017-02-13 12:47:24 +01:00
										 |  |  | 	//ClassDB::bind_method(D_METHOD("instance_create","base_object"),&Script::instance_create);
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("instance_has", "base_object"), &Script::instance_has); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("has_source_code"), &Script::has_source_code); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_source_code"), &Script::get_source_code); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_source_code", "source"), &Script::set_source_code); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("reload", "keep_state"), &Script::reload, DEFVAL(false)); | 
					
						
							| 
									
										
										
										
											2017-12-19 06:55:55 -06:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_base_script"), &Script::get_base_script); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_instance_base_type"), &Script::get_instance_base_type); | 
					
						
							| 
									
										
										
										
											2017-08-29 14:33:27 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("has_script_signal", "signal_name"), &Script::has_script_signal); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-01 14:13:40 -05:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_script_property_list"), &Script::_get_script_property_list); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_script_method_list"), &Script::_get_script_method_list); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_script_signal_list"), &Script::_get_script_signal_list); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_script_constant_map"), &Script::_get_script_constant_map); | 
					
						
							| 
									
										
										
										
											2019-09-24 11:44:48 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_property_default_value", "property"), &Script::_get_property_default_value); | 
					
						
							| 
									
										
										
										
											2019-08-01 14:13:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 14:33:27 -03:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("is_tool"), &Script::is_tool); | 
					
						
							| 
									
										
										
										
											2018-01-12 00:35:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_code", PROPERTY_HINT_NONE, "", 0), "set_source_code", "get_source_code"); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptServer::set_scripting_enabled(bool p_enabled) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	scripting_enabled = p_enabled; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ScriptServer::is_scripting_enabled() { | 
					
						
							|  |  |  | 	return scripting_enabled; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | ScriptLanguage *ScriptServer::get_language(int p_idx) { | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, _language_count, nullptr); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return _languages[p_idx]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptServer::register_language(ScriptLanguage *p_language) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_COND(_language_count >= MAX_LANGUAGES); | 
					
						
							|  |  |  | 	_languages[_language_count++] = p_language; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-26 10:53:34 -03:00
										 |  |  | void ScriptServer::unregister_language(ScriptLanguage *p_language) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < _language_count; i++) { | 
					
						
							|  |  |  | 		if (_languages[i] == p_language) { | 
					
						
							| 
									
										
										
										
											2016-06-26 10:53:34 -03:00
										 |  |  | 			_language_count--; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			if (i < _language_count) { | 
					
						
							|  |  |  | 				SWAP(_languages[i], _languages[_language_count]); | 
					
						
							| 
									
										
										
										
											2016-06-26 10:53:34 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-13 00:53:12 -03:00
										 |  |  | void ScriptServer::init_languages() { | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | 	{ //load global classes
 | 
					
						
							|  |  |  | 		global_classes_clear(); | 
					
						
							|  |  |  | 		if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) { | 
					
						
							|  |  |  | 			Array script_classes = ProjectSettings::get_singleton()->get("_global_script_classes"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (int i = 0; i < script_classes.size(); i++) { | 
					
						
							|  |  |  | 				Dictionary c = script_classes[i]; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 				if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) { | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | 				add_global_class(c["class"], c["base"], c["language"], c["path"]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < _language_count; i++) { | 
					
						
							| 
									
										
										
										
											2014-11-13 00:53:12 -03:00
										 |  |  | 		_languages[i]->init(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-22 16:11:04 -03:00
										 |  |  | void ScriptServer::finish_languages() { | 
					
						
							|  |  |  | 	for (int i = 0; i < _language_count; i++) { | 
					
						
							|  |  |  | 		_languages[i]->finish(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | 	global_classes_clear(); | 
					
						
							| 
									
										
										
										
											2019-02-04 20:39:02 +01:00
										 |  |  | 	languages_finished = true; | 
					
						
							| 
									
										
										
										
											2017-07-22 16:11:04 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-13 10:58:32 -03:00
										 |  |  | void ScriptServer::set_reload_scripts_on_save(bool p_enable) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	reload_scripts_on_save = p_enable; | 
					
						
							| 
									
										
										
										
											2016-06-13 10:58:32 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ScriptServer::is_reload_scripts_on_save_enabled() { | 
					
						
							|  |  |  | 	return reload_scripts_on_save; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-25 10:40:33 -03:00
										 |  |  | void ScriptServer::thread_enter() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < _language_count; i++) { | 
					
						
							| 
									
										
										
										
											2016-06-25 10:40:33 -03:00
										 |  |  | 		_languages[i]->thread_enter(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptServer::thread_exit() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < _language_count; i++) { | 
					
						
							| 
									
										
										
										
											2016-06-25 10:40:33 -03:00
										 |  |  | 		_languages[i]->thread_exit(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | HashMap<StringName, ScriptServer::GlobalScriptClass> ScriptServer::global_classes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptServer::global_classes_clear() { | 
					
						
							|  |  |  | 	global_classes.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptServer::add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path) { | 
					
						
							| 
									
										
										
										
											2019-10-07 12:05:39 +02:00
										 |  |  | 	ERR_FAIL_COND_MSG(p_class == p_base || (global_classes.has(p_base) && get_global_class_native_base(p_base) == p_class), "Cyclic inheritance in script class."); | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | 	GlobalScriptClass g; | 
					
						
							|  |  |  | 	g.language = p_language; | 
					
						
							|  |  |  | 	g.path = p_path; | 
					
						
							|  |  |  | 	g.base = p_base; | 
					
						
							|  |  |  | 	global_classes[p_class] = g; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void ScriptServer::remove_global_class(const StringName &p_class) { | 
					
						
							|  |  |  | 	global_classes.erase(p_class); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool ScriptServer::is_global_class(const StringName &p_class) { | 
					
						
							|  |  |  | 	return global_classes.has(p_class); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | StringName ScriptServer::get_global_class_language(const StringName &p_class) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!global_classes.has(p_class), StringName()); | 
					
						
							|  |  |  | 	return global_classes[p_class].language; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | String ScriptServer::get_global_class_path(const String &p_class) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!global_classes.has(p_class), String()); | 
					
						
							|  |  |  | 	return global_classes[p_class].path; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StringName ScriptServer::get_global_class_base(const String &p_class) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!global_classes.has(p_class), String()); | 
					
						
							|  |  |  | 	return global_classes[p_class].base; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-03-09 00:47:27 -03:00
										 |  |  | StringName ScriptServer::get_global_class_native_base(const String &p_class) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!global_classes.has(p_class), String()); | 
					
						
							|  |  |  | 	String base = global_classes[p_class].base; | 
					
						
							|  |  |  | 	while (global_classes.has(base)) { | 
					
						
							|  |  |  | 		base = global_classes[base].base; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return base; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) { | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	const StringName *K = nullptr; | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | 	List<StringName> classes; | 
					
						
							|  |  |  | 	while ((K = global_classes.next(K))) { | 
					
						
							|  |  |  | 		classes.push_back(*K); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	classes.sort_custom<StringName::AlphCompare>(); | 
					
						
							|  |  |  | 	for (List<StringName>::Element *E = classes.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		r_global_classes->push_back(E->get()); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void ScriptServer::save_global_classes() { | 
					
						
							|  |  |  | 	List<StringName> gc; | 
					
						
							|  |  |  | 	get_global_class_list(&gc); | 
					
						
							|  |  |  | 	Array gcarr; | 
					
						
							|  |  |  | 	for (List<StringName>::Element *E = gc.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		Dictionary d; | 
					
						
							|  |  |  | 		d["class"] = E->get(); | 
					
						
							|  |  |  | 		d["language"] = global_classes[E->get()].language; | 
					
						
							|  |  |  | 		d["path"] = global_classes[E->get()].path; | 
					
						
							|  |  |  | 		d["base"] = global_classes[E->get()].base; | 
					
						
							|  |  |  | 		gcarr.push_back(d); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-13 18:40:58 +01:00
										 |  |  | 	Array old; | 
					
						
							|  |  |  | 	if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) { | 
					
						
							|  |  |  | 		old = ProjectSettings::get_singleton()->get("_global_script_classes"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((!old.empty() || gcarr.empty()) && gcarr.hash() == old.hash()) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-03 04:36:07 -04:00
										 |  |  | 	if (gcarr.empty()) { | 
					
						
							| 
									
										
										
										
											2020-10-05 15:45:54 -04:00
										 |  |  | 		if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) { | 
					
						
							|  |  |  | 			ProjectSettings::get_singleton()->clear("_global_script_classes"); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-03 04:36:07 -04:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		ProjectSettings::get_singleton()->set("_global_script_classes", gcarr); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-15 19:29:00 -03:00
										 |  |  | 	ProjectSettings::get_singleton()->save(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////
 | 
					
						
							| 
									
										
										
										
											2021-05-04 14:20:36 +02:00
										 |  |  | void ScriptInstance::get_property_state(List<Pair<StringName, Variant>> &state) { | 
					
						
							| 
									
										
										
										
											2016-01-23 21:42:15 -03:00
										 |  |  | 	List<PropertyInfo> pinfo; | 
					
						
							|  |  |  | 	get_property_list(&pinfo); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		if (E->get().usage & PROPERTY_USAGE_STORAGE) { | 
					
						
							|  |  |  | 			Pair<StringName, Variant> p; | 
					
						
							|  |  |  | 			p.first = E->get().name; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 			if (get(p.first, p.second)) { | 
					
						
							| 
									
										
										
										
											2016-01-23 21:42:15 -03:00
										 |  |  | 				state.push_back(p); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-01-23 21:42:15 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Variant ScriptInstance::call(const StringName &p_method, VARIANT_ARG_DECLARE) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	VARIANT_ARGPTRS; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int argc = 0; | 
					
						
							|  |  |  | 	for (int i = 0; i < VARIANT_ARG_MAX; i++) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (argptr[i]->get_type() == Variant::NIL) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		argc++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Variant::CallError error; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	return call(p_method, argptr, argc, error); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void ScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Variant::CallError ce; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	call(p_method, p_args, p_argcount, ce); // script may not support multilevel calls
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void ScriptInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Variant::CallError ce; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	call(p_method, p_args, p_argcount, ce); // script may not support multilevel calls
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | void ScriptInstance::property_set_fallback(const StringName &, const Variant &, bool *r_valid) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (r_valid) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		*r_valid = false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variant ScriptInstance::property_get_fallback(const StringName &, bool *r_valid) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (r_valid) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		*r_valid = false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 	return Variant(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void ScriptInstance::call_multilevel(const StringName &p_method, VARIANT_ARG_DECLARE) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	VARIANT_ARGPTRS; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int argc = 0; | 
					
						
							|  |  |  | 	for (int i = 0; i < VARIANT_ARG_MAX; i++) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (argptr[i]->get_type() == Variant::NIL) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		argc++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	call_multilevel(p_method, argptr, argc); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ScriptInstance::~ScriptInstance() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | ScriptCodeCompletionCache *ScriptCodeCompletionCache::singleton = nullptr; | 
					
						
							| 
									
										
										
										
											2015-06-26 01:14:31 -03:00
										 |  |  | ScriptCodeCompletionCache::ScriptCodeCompletionCache() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	singleton = this; | 
					
						
							| 
									
										
										
										
											2015-06-26 01:14:31 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void ScriptLanguage::frame() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | ScriptDebugger *ScriptDebugger::singleton = nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebugger::set_lines_left(int p_left) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	lines_left = p_left; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ScriptDebugger::get_lines_left() const { | 
					
						
							|  |  |  | 	return lines_left; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebugger::set_depth(int p_depth) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	depth = p_depth; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ScriptDebugger::get_depth() const { | 
					
						
							|  |  |  | 	return depth; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void ScriptDebugger::insert_breakpoint(int p_line, const StringName &p_source) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (!breakpoints.has(p_line)) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		breakpoints[p_line] = Set<StringName>(); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	breakpoints[p_line].insert(p_source); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void ScriptDebugger::remove_breakpoint(int p_line, const StringName &p_source) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (!breakpoints.has(p_line)) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	breakpoints[p_line].erase(p_source); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (breakpoints[p_line].size() == 0) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		breakpoints.erase(p_line); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool ScriptDebugger::is_breakpoint(int p_line, const StringName &p_source) const { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (!breakpoints.has(p_line)) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return breakpoints[p_line].has(p_source); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool ScriptDebugger::is_breakpoint_line(int p_line) const { | 
					
						
							|  |  |  | 	return breakpoints.has(p_line); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | String ScriptDebugger::breakpoint_find_source(const String &p_source) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return p_source; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebugger::clear_breakpoints() { | 
					
						
							|  |  |  | 	breakpoints.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebugger::idle_poll() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebugger::line_poll() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ScriptDebugger::set_break_language(ScriptLanguage *p_lang) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	break_lang = p_lang; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | ScriptLanguage *ScriptDebugger::get_break_language() const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return break_lang; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ScriptDebugger::ScriptDebugger() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	singleton = this; | 
					
						
							|  |  |  | 	lines_left = -1; | 
					
						
							|  |  |  | 	depth = -1; | 
					
						
							| 
									
										
										
										
											2021-05-04 16:00:45 +02:00
										 |  |  | 	break_lang = nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (script->is_placeholder_fallback_enabled()) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (values.has(p_name)) { | 
					
						
							| 
									
										
										
										
											2017-08-06 09:32:52 -03:00
										 |  |  | 		Variant defval; | 
					
						
							|  |  |  | 		if (script->get_property_default_value(p_name, defval)) { | 
					
						
							|  |  |  | 			if (defval == p_value) { | 
					
						
							|  |  |  | 				values.erase(p_name); | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		values[p_name] = p_value; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2017-08-06 09:32:52 -03:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		Variant defval; | 
					
						
							|  |  |  | 		if (script->get_property_default_value(p_name, defval)) { | 
					
						
							|  |  |  | 			if (defval != p_value) { | 
					
						
							|  |  |  | 				values[p_name] = p_value; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool PlaceHolderScriptInstance::get(const StringName &p_name, Variant &r_ret) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (values.has(p_name)) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		r_ret = values[p_name]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-06 09:32:52 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-05 23:19:02 +02:00
										 |  |  | 	if (constants.has(p_name)) { | 
					
						
							|  |  |  | 		r_ret = constants[p_name]; | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 00:26:00 +01:00
										 |  |  | 	if (!script->is_placeholder_fallback_enabled()) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		Variant defval; | 
					
						
							|  |  |  | 		if (script->get_property_default_value(p_name, defval)) { | 
					
						
							|  |  |  | 			r_ret = defval; | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-06 09:32:52 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { | 
					
						
							| 
									
										
										
										
											2019-01-10 00:26:00 +01:00
										 |  |  | 	if (script->is_placeholder_fallback_enabled()) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 			p_properties->push_back(E->get()); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 			PropertyInfo pinfo = E->get(); | 
					
						
							|  |  |  | 			if (!values.has(pinfo.name)) { | 
					
						
							|  |  |  | 				pinfo.usage |= PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			p_properties->push_back(E->get()); | 
					
						
							| 
									
										
										
										
											2017-08-06 09:32:52 -03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Variant::Type PlaceHolderScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { | 
					
						
							|  |  |  | 	if (values.has(p_name)) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (r_is_valid) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			*r_is_valid = true; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-05 14:18:22 -03:00
										 |  |  | 		return values[p_name].get_type(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-05 23:19:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (constants.has(p_name)) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (r_is_valid) { | 
					
						
							| 
									
										
										
										
											2019-03-05 23:19:02 +02:00
										 |  |  | 			*r_is_valid = true; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-05 23:19:02 +02:00
										 |  |  | 		return constants[p_name].get_type(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (r_is_valid) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		*r_is_valid = false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-05 14:18:22 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return Variant::NIL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-30 19:58:37 -03:00
										 |  |  | void PlaceHolderScriptInstance::get_method_list(List<MethodInfo> *p_list) const { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (script->is_placeholder_fallback_enabled()) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-30 19:58:37 -03:00
										 |  |  | 	if (script.is_valid()) { | 
					
						
							|  |  |  | 		script->get_script_method_list(p_list); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool PlaceHolderScriptInstance::has_method(const StringName &p_method) const { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (script->is_placeholder_fallback_enabled()) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-30 19:58:37 -03:00
										 |  |  | 	if (script.is_valid()) { | 
					
						
							|  |  |  | 		return script->has_method(p_method); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, const Map<StringName, Variant> &p_values) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Set<StringName> new_values; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (const List<PropertyInfo>::Element *E = p_properties.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		StringName n = E->get().name; | 
					
						
							|  |  |  | 		new_values.insert(n); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (!values.has(n) || values[n].get_type() != E->get().type) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 			if (p_values.has(n)) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				values[n] = p_values[n]; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	properties = p_properties; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	List<StringName> to_remove; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (Map<StringName, Variant>::Element *E = values.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		if (!new_values.has(E->key())) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			to_remove.push_back(E->key()); | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-06 09:32:52 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Variant defval; | 
					
						
							|  |  |  | 		if (script->get_property_default_value(E->key(), defval)) { | 
					
						
							|  |  |  | 			//remove because it's the same as the default value
 | 
					
						
							|  |  |  | 			if (defval == E->get()) { | 
					
						
							|  |  |  | 				to_remove.push_back(E->key()); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (to_remove.size()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		values.erase(to_remove.front()->get()); | 
					
						
							|  |  |  | 		to_remove.pop_front(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (owner && owner->get_script_instance() == this) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		owner->_change_notify(); | 
					
						
							| 
									
										
										
										
											2014-09-22 00:50:48 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	//change notify
 | 
					
						
							| 
									
										
										
										
											2019-03-05 23:19:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	constants.clear(); | 
					
						
							|  |  |  | 	script->get_constants(&constants); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) { | 
					
						
							| 
									
										
										
										
											2019-01-10 00:26:00 +01:00
										 |  |  | 	if (script->is_placeholder_fallback_enabled()) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		Map<StringName, Variant>::Element *E = values.find(p_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (E) { | 
					
						
							|  |  |  | 			E->value() = p_value; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			values.insert(p_name, p_value); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bool found = false; | 
					
						
							| 
									
										
										
										
											2019-02-12 21:10:08 +01:00
										 |  |  | 		for (const List<PropertyInfo>::Element *F = properties.front(); F; F = F->next()) { | 
					
						
							|  |  |  | 			if (F->get().name == p_name) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 				found = true; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!found) { | 
					
						
							|  |  |  | 			properties.push_back(PropertyInfo(p_value.get_type(), p_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (r_valid) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		*r_valid = false; // Cannot change the value in either case
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_name, bool *r_valid) { | 
					
						
							| 
									
										
										
										
											2019-01-10 00:26:00 +01:00
										 |  |  | 	if (script->is_placeholder_fallback_enabled()) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		const Map<StringName, Variant>::Element *E = values.find(p_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (E) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 			if (r_valid) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 				*r_valid = true; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 			return E->value(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-05 23:19:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		E = constants.find(p_name); | 
					
						
							|  |  |  | 		if (E) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 			if (r_valid) { | 
					
						
							| 
									
										
										
										
											2019-03-05 23:19:02 +02:00
										 |  |  | 				*r_valid = true; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-03-05 23:19:02 +02:00
										 |  |  | 			return E->value(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	if (r_valid) { | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 		*r_valid = false; | 
					
						
							| 
									
										
										
										
											2021-05-05 12:44:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-29 22:40:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return Variant(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-06 21:36:34 +01:00
										 |  |  | PlaceHolderScriptInstance::PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner) : | 
					
						
							|  |  |  | 		owner(p_owner), | 
					
						
							|  |  |  | 		language(p_language), | 
					
						
							| 
									
										
										
										
											2019-01-10 00:26:00 +01:00
										 |  |  | 		script(p_script) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PlaceHolderScriptInstance::~PlaceHolderScriptInstance() { | 
					
						
							|  |  |  | 	if (script.is_valid()) { | 
					
						
							|  |  |  | 		script->_placeholder_erased(this); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |