diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 7e96735d676..3f9585c03c9 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -144,6 +144,12 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { props.erase(p_name); + if (p_name.operator String().begins_with("autoload/")) { + String node_name = p_name.operator String().split("/")[1]; + if (autoloads.has(node_name)) { + remove_autoload(node_name); + } + } } else { if (p_name == CoreStringNames::get_singleton()->_custom_features) { Vector custom_feature_array = String(p_value).split(","); @@ -181,6 +187,19 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { } else { props[p_name] = VariantContainer(p_value, last_order++); } + if (p_name.operator String().begins_with("autoload/")) { + String node_name = p_name.operator String().split("/")[1]; + AutoloadInfo autoload; + autoload.name = node_name; + String path = p_value; + if (path.begins_with("*")) { + autoload.is_singleton = true; + autoload.path = path.substr(1); + } else { + autoload.path = path; + } + add_autoload(autoload); + } } return true; @@ -945,6 +964,29 @@ bool ProjectSettings::has_custom_feature(const String &p_feature) const { return custom_features.has(p_feature); } +Map ProjectSettings::get_autoload_list() const { + return autoloads; +} + +void ProjectSettings::add_autoload(const AutoloadInfo &p_autoload) { + ERR_FAIL_COND_MSG(p_autoload.name == StringName(), "Trying to add autoload with no name."); + autoloads[p_autoload.name] = p_autoload; +} + +void ProjectSettings::remove_autoload(const StringName &p_autoload) { + ERR_FAIL_COND_MSG(!autoloads.has(p_autoload), "Trying to remove non-existent autoload."); + autoloads.erase(p_autoload); +} + +bool ProjectSettings::has_autoload(const StringName &p_autoload) const { + return autoloads.has(p_autoload); +} + +ProjectSettings::AutoloadInfo ProjectSettings::get_autoload(const StringName &p_name) const { + ERR_FAIL_COND_V_MSG(!autoloads.has(p_name), AutoloadInfo(), "Trying to get non-existent autoload."); + return autoloads[p_name]; +} + void ProjectSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting); ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting); diff --git a/core/project_settings.h b/core/project_settings.h index 3ed80738a1d..4aceafe3c0e 100644 --- a/core/project_settings.h +++ b/core/project_settings.h @@ -47,6 +47,12 @@ public: NO_BUILTIN_ORDER_BASE = 1 << 16 }; + struct AutoloadInfo { + StringName name; + String path; + bool is_singleton = false; + }; + protected: struct VariantContainer { int order = 0; @@ -79,6 +85,8 @@ protected: Set custom_features; Map feature_overrides; + Map autoloads; + bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List *p_list) const; @@ -148,6 +156,12 @@ public: bool has_custom_feature(const String &p_feature) const; + Map get_autoload_list() const; + void add_autoload(const AutoloadInfo &p_autoload); + void remove_autoload(const StringName &p_autoload); + bool has_autoload(const StringName &p_autoload) const; + AutoloadInfo get_autoload(const StringName &p_name) const; + ProjectSettings(); ~ProjectSettings(); }; diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index da0ff9f18f8..4cd4f68fa27 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -477,6 +477,8 @@ void EditorAutoloadSettings::update_autoload() { info.node->queue_delete(); info.node = nullptr; } + + ProjectSettings::get_singleton()->remove_autoload(info.name); } // Load new/changed autoloads @@ -503,6 +505,12 @@ void EditorAutoloadSettings::update_autoload() { } } + ProjectSettings::AutoloadInfo prop_info; + prop_info.name = info->name; + prop_info.path = info->path; + prop_info.is_singleton = info->is_singleton; + ProjectSettings::get_singleton()->add_autoload(prop_info); + if (!info->in_editor && !info->is_singleton) { // No reason to keep this node memdelete(info->node); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 1c9dadc0dd8..9304683d778 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -343,16 +343,11 @@ void ScriptTextEditor::_set_theme_for_script() { } //colorize singleton autoloads (as types, just as engine singletons are) - List props; - ProjectSettings::get_singleton()->get_property_list(&props); - for (List::Element *E = props.front(); E; E = E->next()) { - String s = E->get().name; - if (!s.begins_with("autoload/")) { - continue; - } - String path = ProjectSettings::get_singleton()->get(s); - if (path.begins_with("*")) { - text_edit->add_keyword_color(s.get_slice("/", 1), colors_cache.usertype_color); + Map autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + for (Map::Element *E = autoloads.front(); E; E = E->next()) { + const ProjectSettings::AutoloadInfo &info = E->value(); + if (info.is_singleton) { + text_edit->add_keyword_color(info.name, colors_cache.usertype_color); } } @@ -942,12 +937,11 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c emit_signal("go_to_help", "class_global:" + result.class_name + ":" + result.class_member); } break; } - } else if (ProjectSettings::get_singleton()->has_setting("autoload/" + p_symbol)) { - //check for Autoload scenes - String path = ProjectSettings::get_singleton()->get("autoload/" + p_symbol); - if (path.begins_with("*")) { - path = path.substr(1, path.length()); - EditorNode::get_singleton()->load_scene(path); + } else if (ProjectSettings::get_singleton()->has_autoload(p_symbol)) { + // Check for Autoload scenes. + const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(p_symbol); + if (info.is_singleton) { + EditorNode::get_singleton()->load_scene(info.path); } } else if (p_symbol.is_rel_path()) { // Every symbol other than absolute path is relative path so keep this condition at last. @@ -974,7 +968,7 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) { } ScriptLanguage::LookupResult result; - if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || ProjectSettings::get_singleton()->has_setting("autoload/" + p_symbol)) { + if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) { text_edit->set_highlighted_word(p_symbol); } else if (p_symbol.is_rel_path()) { String path = _get_absolute_path(p_symbol); diff --git a/main/main.cpp b/main/main.cpp index 608b4a7c4d8..4ea11cfaeb2 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1792,46 +1792,26 @@ bool Main::start() { if (!project_manager && !editor) { // game if (game_path != "" || script != "") { //autoload - List props; - ProjectSettings::get_singleton()->get_property_list(&props); + Map autoloads = ProjectSettings::get_singleton()->get_autoload_list(); //first pass, add the constants so they exist before any script is loaded - for (List::Element *E = props.front(); E; E = E->next()) { - String s = E->get().name; - if (!s.begins_with("autoload/")) { - continue; - } - String name = s.get_slicec('/', 1); - String path = ProjectSettings::get_singleton()->get(s); - bool global_var = false; - if (path.begins_with("*")) { - global_var = true; - } + for (Map::Element *E = autoloads.front(); E; E = E->next()) { + const ProjectSettings::AutoloadInfo &info = E->get(); - if (global_var) { + if (info.is_singleton) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { - ScriptServer::get_language(i)->add_global_constant(name, Variant()); + ScriptServer::get_language(i)->add_global_constant(info.name, Variant()); } } } //second pass, load into global constants List to_add; - for (List::Element *E = props.front(); E; E = E->next()) { - String s = E->get().name; - if (!s.begins_with("autoload/")) { - continue; - } - String name = s.get_slicec('/', 1); - String path = ProjectSettings::get_singleton()->get(s); - bool global_var = false; - if (path.begins_with("*")) { - global_var = true; - path = path.substr(1, path.length() - 1); - } + for (Map::Element *E = autoloads.front(); E; E = E->next()) { + const ProjectSettings::AutoloadInfo &info = E->get(); - RES res = ResourceLoader::load(path); - ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + path); + RES res = ResourceLoader::load(info.path); + ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path); Node *n = nullptr; if (res->is_class("PackedScene")) { Ref ps = res; @@ -1840,7 +1820,7 @@ bool Main::start() { Ref