diff options
Diffstat (limited to 'modules/gdscript/gdscript.cpp')
-rw-r--r-- | modules/gdscript/gdscript.cpp | 184 |
1 files changed, 98 insertions, 86 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 57a29cc81e..6b325d6451 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gdscript.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/**************************************************************************/ #include "gdscript.h" @@ -248,6 +248,10 @@ Ref<Script> GDScript::get_base_script() const { } } +StringName GDScript::get_global_name() const { + return name; +} + StringName GDScript::get_instance_base_type() const { if (native.is_valid()) { return native->get_name(); @@ -629,6 +633,10 @@ void GDScript::_update_doc() { } } + for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) { + E.value->_update_doc(); + } + _add_doc(doc); } #endif @@ -1003,17 +1011,6 @@ void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const { void GDScript::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &GDScript::_new, MethodInfo("new")); - - ClassDB::bind_method(D_METHOD("get_as_byte_code"), &GDScript::get_as_byte_code); -} - -Vector<uint8_t> GDScript::get_as_byte_code() const { - return Vector<uint8_t>(); -}; - -// TODO: Fully remove this. There's not this kind of "bytecode" anymore. -Error GDScript::load_byte_code(const String &p_path) { - return ERR_COMPILATION_FAILED; } void GDScript::set_path(const String &p_path, bool p_take_over) { @@ -1033,7 +1030,7 @@ String GDScript::get_script_path() const { } Error GDScript::load_source_code(const String &p_path) { - if (p_path.is_empty() || ResourceLoader::get_resource_type(p_path.get_slice("::", 0)) == "PackedScene") { + if (p_path.is_empty() || p_path.begins_with("gdscript://") || ResourceLoader::get_resource_type(p_path.get_slice("::", 0)) == "PackedScene") { return OK; } @@ -1303,7 +1300,7 @@ GDScript *GDScript::_get_gdscript_from_variant(const Variant &p_variant) { } void GDScript::_get_dependencies(RBSet<GDScript *> &p_dependencies, const GDScript *p_except) { - if (skip_dependencies || p_dependencies.has(this)) { + if (p_dependencies.has(this)) { return; } p_dependencies.insert(this); @@ -1359,9 +1356,11 @@ GDScript::GDScript() : GDScriptLanguage::get_singleton()->script_list.add(&script_list); } + + path = vformat("gdscript://%d.gd", get_instance_id()); } -void GDScript::_save_orphaned_subclasses() { +void GDScript::_save_orphaned_subclasses(GDScript::ClearData *p_clear_data) { struct ClassRefWithName { ObjectID id; String fully_qualified_name; @@ -1377,8 +1376,17 @@ void GDScript::_save_orphaned_subclasses() { } // clear subclasses to allow unused subclasses to be deleted + for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) { + p_clear_data->scripts.insert(E.value); + } subclasses.clear(); // subclasses are also held by constants, clear those as well + for (KeyValue<StringName, Variant> &E : constants) { + GDScript *gdscr = _get_gdscript_from_variant(E.value); + if (gdscr != nullptr) { + p_clear_data->scripts.insert(gdscr); + } + } constants.clear(); // keep orphan subclass only for subclasses that are still in use @@ -1409,60 +1417,50 @@ void GDScript::_init_rpc_methods_properties() { } } -void GDScript::clear() { +void GDScript::clear(GDScript::ClearData *p_clear_data) { if (clearing) { return; } clearing = true; - RBSet<GDScript *> must_clear_dependencies = get_must_clear_dependencies(); - HashMap<GDScript *, ObjectID> must_clear_dependencies_objectids; + GDScript::ClearData data; + GDScript::ClearData *clear_data = p_clear_data; + bool is_root = false; - // Log the objectids before clearing, as a cascade of clear could - // remove instances that are still in the clear loop - for (GDScript *E : must_clear_dependencies) { - must_clear_dependencies_objectids.insert(E, E->get_instance_id()); + // If `clear_data` is `nullptr`, it means that it's the root. + // The root is in charge to clear functions and scripts of itself and its dependencies + if (clear_data == nullptr) { + clear_data = &data; + is_root = true; } + RBSet<GDScript *> must_clear_dependencies = get_must_clear_dependencies(); for (GDScript *E : must_clear_dependencies) { - Object *obj = ObjectDB::get_instance(must_clear_dependencies_objectids[E]); - if (obj == nullptr) { - continue; - } - - E->skip_dependencies = true; - E->clear(); - E->skip_dependencies = false; - GDScriptCache::remove_script(E->get_path()); + clear_data->scripts.insert(E); + E->clear(clear_data); } - RBSet<StringName> member_function_names; for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) { - member_function_names.insert(E.key); - } - for (const StringName &E : member_function_names) { - if (member_functions.has(E)) { - memdelete(member_functions[E]); - } + clear_data->functions.insert(E.value); } - member_function_names.clear(); member_functions.clear(); for (KeyValue<StringName, GDScript::MemberInfo> &E : member_indices) { + clear_data->scripts.insert(E.value.data_type.script_type_ref); E.value.data_type.script_type_ref = Ref<Script>(); } if (implicit_initializer) { - memdelete(implicit_initializer); + clear_data->functions.insert(implicit_initializer); + implicit_initializer = nullptr; } - implicit_initializer = nullptr; if (implicit_ready) { - memdelete(implicit_ready); + clear_data->functions.insert(implicit_ready); + implicit_ready = nullptr; } - implicit_ready = nullptr; - _save_orphaned_subclasses(); + _save_orphaned_subclasses(clear_data); #ifdef TOOLS_ENABLED // Clearing inner class doc, script doc only cleared when the script source deleted. @@ -1470,7 +1468,21 @@ void GDScript::clear() { _clear_doc(); } #endif - clearing = false; + + // If it's not the root, skip clearing the data + if (is_root) { + // All dependencies have been accounted for + for (GDScriptFunction *E : clear_data->functions) { + memdelete(E); + } + for (Ref<Script> &E : clear_data->scripts) { + Ref<GDScript> gdscr = E; + if (gdscr.is_valid()) { + GDScriptCache::remove_script(gdscr->get_path()); + } + } + clear_data->clear(); + } } GDScript::~GDScript() { @@ -1966,6 +1978,16 @@ void GDScriptLanguage::add_named_global_constant(const StringName &p_name, const named_globals[p_name] = p_value; } +Variant GDScriptLanguage::get_any_global_constant(const StringName &p_name) { + if (named_globals.has(p_name)) { + return named_globals[p_name]; + } + if (globals.has(p_name)) { + return _global_array[globals[p_name]]; + } + ERR_FAIL_V_MSG(Variant(), vformat("Could not find any global constant with name: %s.", p_name)); +} + void GDScriptLanguage::remove_named_global_constant(const StringName &p_name) { ERR_FAIL_COND(!named_globals.has(p_name)); named_globals.erase(p_name); @@ -2540,8 +2562,7 @@ GDScriptLanguage::GDScriptLanguage() { script_frame_time = 0; _debug_call_stack_pos = 0; - int dmcs = GLOBAL_DEF("debug/settings/gdscript/max_call_stack", 1024); - ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/gdscript/max_call_stack", PropertyInfo(Variant::INT, "debug/settings/gdscript/max_call_stack", PROPERTY_HINT_RANGE, "1024,4096,1,or_greater")); //minimum is 1024 + int dmcs = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/settings/gdscript/max_call_stack", PROPERTY_HINT_RANGE, "1024,4096,1,or_greater"), 1024); if (EngineDebugger::is_active()) { //debugging enabled! @@ -2562,10 +2583,7 @@ GDScriptLanguage::GDScriptLanguage() { GDScriptWarning::Code code = (GDScriptWarning::Code)i; Variant default_enabled = GDScriptWarning::get_default_value(code); String path = GDScriptWarning::get_settings_path_from_code(code); - GLOBAL_DEF(path, default_enabled); - - PropertyInfo property_info = GDScriptWarning::get_property_info(code); - ProjectSettings::get_singleton()->set_custom_property_info(path, property_info); + GLOBAL_DEF(GDScriptWarning::get_property_info(code), default_enabled); } #endif // DEBUG_ENABLED } @@ -2622,8 +2640,6 @@ Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const Str Error err; Ref<GDScript> scr = GDScriptCache::get_full_script(p_path, err, "", p_cache_mode == CACHE_MODE_IGNORE); - // TODO: Reintroduce binary and encrypted scripts. - if (scr.is_null()) { // Don't fail loading because of parsing error. scr.instantiate(); @@ -2638,9 +2654,6 @@ Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const Str void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("gd"); - // TODO: Reintroduce binary and encrypted scripts. - // p_extensions->push_back("gdc"); - // p_extensions->push_back("gde"); } bool ResourceFormatLoaderGDScript::handles_type(const String &p_type) const { @@ -2649,8 +2662,7 @@ bool ResourceFormatLoaderGDScript::handles_type(const String &p_type) const { String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const { String el = p_path.get_extension().to_lower(); - // TODO: Reintroduce binary and encrypted scripts. - if (el == "gd" /*|| el == "gdc" || el == "gde"*/) { + if (el == "gd") { return "GDScript"; } return ""; |