diff options
-rw-r--r-- | core/project_settings.cpp | 42 | ||||
-rw-r--r-- | core/project_settings.h | 14 | ||||
-rw-r--r-- | doc/classes/EditorInterface.xml | 44 | ||||
-rw-r--r-- | editor/code_editor.cpp | 33 | ||||
-rw-r--r-- | editor/create_dialog.cpp | 1 | ||||
-rw-r--r-- | editor/editor_autoload_settings.cpp | 8 | ||||
-rw-r--r-- | editor/editor_node.cpp | 57 | ||||
-rw-r--r-- | editor/editor_node.h | 4 | ||||
-rw-r--r-- | editor/editor_plugin.cpp | 30 | ||||
-rw-r--r-- | editor/editor_plugin.h | 7 | ||||
-rw-r--r-- | editor/editor_run.cpp | 9 | ||||
-rw-r--r-- | editor/editor_run.h | 2 | ||||
-rw-r--r-- | editor/plugins/script_text_editor.cpp | 28 | ||||
-rw-r--r-- | main/main.cpp | 48 | ||||
-rw-r--r-- | modules/bullet/area_bullet.cpp | 1 | ||||
-rw-r--r-- | modules/gdscript/gdscript.cpp | 62 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 3 | ||||
-rw-r--r-- | modules/gdscript/register_types.cpp | 8 | ||||
-rw-r--r-- | modules/mono/editor/code_completion.cpp | 13 |
19 files changed, 291 insertions, 123 deletions
diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 7e96735d67..3f9585c03c 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<String> 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<StringName, ProjectSettings::AutoloadInfo> 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 3ed80738a1..4aceafe3c0 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<String> custom_features; Map<StringName, StringName> feature_overrides; + Map<StringName, AutoloadInfo> 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<PropertyInfo> *p_list) const; @@ -148,6 +156,12 @@ public: bool has_custom_feature(const String &p_feature) const; + Map<StringName, AutoloadInfo> 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/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index c2c73a8b83..1d877e632e 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -72,6 +72,13 @@ Returns an [Array] with the file paths of the currently opened scenes. </description> </method> + <method name="get_playing_scene" qualifiers="const"> + <return type="String"> + </return> + <description> + Returns the name of the scene that is being played. If no scene is currently being played, returns an empty string. + </description> + </method> <method name="get_resource_filesystem"> <return type="EditorFileSystem"> </return> @@ -117,6 +124,13 @@ Shows the given property on the given [code]object[/code] in the Editor's Inspector dock. </description> </method> + <method name="is_playing_scene" qualifiers="const"> + <return type="bool"> + </return> + <description> + Returns [code]true[/code], if a scene is currently being played; [code]false[/code] otherwise. Paused scenes are considered as being played. + </description> + </method> <method name="is_plugin_enabled" qualifiers="const"> <return type="bool"> </return> @@ -146,6 +160,29 @@ Opens the scene at the given path. </description> </method> + <method name="play_current_scene"> + <return type="void"> + </return> + <description> + Plays the currently active scene. + </description> + </method> + <method name="play_custom_scene"> + <return type="void"> + </return> + <argument index="0" name="scene_filepath" type="String"> + </argument> + <description> + Plays the scene specified by its filepath. + </description> + </method> + <method name="play_main_scene"> + <return type="void"> + </return> + <description> + Plays the main scene. + </description> + </method> <method name="reload_scene_from_path"> <return type="void"> </return> @@ -201,6 +238,13 @@ Sets the enabled status of a plugin. The plugin name is the same as its directory name. </description> </method> + <method name="stop_playing_scene"> + <return type="void"> + </return> + <description> + Stops the scene that is currently playing. + </description> + </method> </methods> <members> <member name="distraction_free_mode" type="bool" setter="set_distraction_free_mode" getter="is_distraction_free_mode_enabled"> diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index b73a27214d..70747b4956 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -108,22 +108,25 @@ void FindReplaceBar::_notification(int p_what) { void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (k.is_valid()) { - if (k->is_pressed() && (text_edit->has_focus() || vbc_lineedit->is_a_parent_of(get_focus_owner()))) { - bool accepted = true; - - switch (k->get_keycode()) { - case KEY_ESCAPE: { - _hide_bar(); - } break; - default: { - accepted = false; - } break; - } + if (!k.is_valid() || !k->is_pressed()) { + return; + } - if (accepted) { - accept_event(); - } + Control *focus_owner = get_focus_owner(); + if (text_edit->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) { + bool accepted = true; + + switch (k->get_keycode()) { + case KEY_ESCAPE: { + _hide_bar(); + } break; + default: { + accepted = false; + } break; + } + + if (accepted) { + accept_event(); } } } diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index a1bc7a9522..99a2a73a75 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -425,7 +425,6 @@ Object *CreateDialog::instance_selected() { if (n) { n->set_name(custom); } - obj = n; } else { obj = EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom); } diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index da0ff9f18f..4cd4f68fa2 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/editor_node.cpp b/editor/editor_node.cpp index a4a53d8a92..454170647f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1225,20 +1225,25 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { _find_node_types(editor_data.get_edited_scene_root(), c2d, c3d); - bool is2d; - if (c3d < c2d) { - is2d = true; - } else { - is2d = false; - } save.step(TTR("Creating Thumbnail"), 1); //current view? Ref<Image> img; - if (is2d) { + // If neither 3D or 2D nodes are present, make a 1x1 black texture. + // We cannot fallback on the 2D editor, because it may not have been used yet, + // which would result in an invalid texture. + if (c3d == 0 && c2d == 0) { + img.instance(); + img->create(1, 1, 0, Image::FORMAT_RGB8); + } else if (c3d < c2d) { img = scene_root->get_texture()->get_data(); } else { - img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data(); + // The 3D editor may be disabled as a feature, but scenes can still be opened. + // This check prevents the preview from regenerating in case those scenes are then saved. + Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile(); + if (!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)) { + img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data(); + } } if (img.is_valid()) { @@ -2043,7 +2048,6 @@ void EditorNode::_run(bool p_current, const String &p_custom) { play_custom_scene_button->set_pressed(false); play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons")); - String main_scene; String run_filename; String args; bool skip_breakpoints; @@ -2464,8 +2468,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_PLAY: { - _menu_option_confirm(RUN_STOP, true); - _run(false); + run_play(); } break; case RUN_PLAY_CUSTOM_SCENE: { @@ -2476,8 +2479,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { play_custom_scene_button->set_pressed(false); } else { String last_custom_scene = run_custom_filename; - _menu_option_confirm(RUN_STOP, true); - _run(false, last_custom_scene); + run_play_custom(last_custom_scene); } } break; @@ -2517,9 +2519,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_PLAY_SCENE: { - _save_default_environment(); - _menu_option_confirm(RUN_STOP, true); - _run(true); + run_play_current(); } break; case RUN_SCENE_SETTINGS: { @@ -4524,10 +4524,35 @@ void EditorNode::run_play() { _run(false); } +void EditorNode::run_play_current() { + _save_default_environment(); + _menu_option_confirm(RUN_STOP, true); + _run(true); +} + +void EditorNode::run_play_custom(const String &p_custom) { + _menu_option_confirm(RUN_STOP, true); + _run(false, p_custom); +} + void EditorNode::run_stop() { _menu_option_confirm(RUN_STOP, false); } +bool EditorNode::is_run_playing() const { + EditorRun::Status status = editor_run.get_status(); + return (status == EditorRun::STATUS_PLAY || status == EditorRun::STATUS_PAUSED); +} + +String EditorNode::get_run_playing_scene() const { + String run_filename = editor_run.get_running_scene(); + if (run_filename == "" && is_run_playing()) { + run_filename = GLOBAL_DEF("application/run/main_scene", ""); // Must be the main scene then. + } + + return run_filename; +} + int EditorNode::get_current_tab() { return scene_tabs->get_current_tab(); } diff --git a/editor/editor_node.h b/editor/editor_node.h index f6cae466ff..dec28b0d2b 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -865,7 +865,11 @@ public: bool ensure_main_scene(bool p_from_native); void run_play(); + void run_play_current(); + void run_play_custom(const String &p_custom); void run_stop(); + bool is_run_playing() const; + String get_run_playing_scene() const; }; struct EditorProgress { diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index af1b426327..da0a0827d2 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -176,6 +176,30 @@ void EditorInterface::reload_scene_from_path(const String &scene_path) { EditorNode::get_singleton()->reload_scene(scene_path); } +void EditorInterface::play_main_scene() { + EditorNode::get_singleton()->run_play(); +} + +void EditorInterface::play_current_scene() { + EditorNode::get_singleton()->run_play_current(); +} + +void EditorInterface::play_custom_scene(const String &scene_path) { + EditorNode::get_singleton()->run_play_custom(scene_path); +} + +void EditorInterface::stop_playing_scene() { + EditorNode::get_singleton()->run_stop(); +} + +bool EditorInterface::is_playing_scene() const { + return EditorNode::get_singleton()->is_run_playing(); +} + +String EditorInterface::get_playing_scene() const { + return EditorNode::get_singleton()->get_run_playing_scene(); +} + Node *EditorInterface::get_edited_scene_root() { return EditorNode::get_singleton()->get_edited_scene(); } @@ -285,6 +309,12 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("edit_resource", "resource"), &EditorInterface::edit_resource); ClassDB::bind_method(D_METHOD("open_scene_from_path", "scene_filepath"), &EditorInterface::open_scene_from_path); ClassDB::bind_method(D_METHOD("reload_scene_from_path", "scene_filepath"), &EditorInterface::reload_scene_from_path); + ClassDB::bind_method(D_METHOD("play_main_scene"), &EditorInterface::play_main_scene); + ClassDB::bind_method(D_METHOD("play_current_scene"), &EditorInterface::play_current_scene); + ClassDB::bind_method(D_METHOD("play_custom_scene", "scene_filepath"), &EditorInterface::play_custom_scene); + ClassDB::bind_method(D_METHOD("stop_playing_scene"), &EditorInterface::stop_playing_scene); + ClassDB::bind_method(D_METHOD("is_playing_scene"), &EditorInterface::is_playing_scene); + ClassDB::bind_method(D_METHOD("get_playing_scene"), &EditorInterface::get_playing_scene); ClassDB::bind_method(D_METHOD("get_open_scenes"), &EditorInterface::get_open_scenes); ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &EditorInterface::get_edited_scene_root); ClassDB::bind_method(D_METHOD("get_resource_previewer"), &EditorInterface::get_resource_previewer); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 52ff7f04f8..685f69bf3f 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -73,6 +73,13 @@ public: void open_scene_from_path(const String &scene_path); void reload_scene_from_path(const String &scene_path); + void play_main_scene(); + void play_current_scene(); + void play_custom_scene(const String &scene_path); + void stop_playing_scene(); + bool is_playing_scene() const; + String get_playing_scene() const; + Node *get_edited_scene_root(); Array get_open_scenes() const; ScriptEditor *get_script_editor(); diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index 6a73e6c072..b49c50fa31 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -38,6 +38,10 @@ EditorRun::Status EditorRun::get_status() const { return status; } +String EditorRun::get_running_scene() const { + return running_scene; +} + Error EditorRun::run(const String &p_scene, const String &p_custom_args, const List<String> &p_breakpoints, const bool &p_skip_breakpoints) { List<String> args; @@ -203,6 +207,9 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L } status = STATUS_PLAY; + if (p_scene != "") { + running_scene = p_scene; + } return OK; } @@ -231,8 +238,10 @@ void EditorRun::stop() { } status = STATUS_STOP; + running_scene = ""; } EditorRun::EditorRun() { status = STATUS_STOP; + running_scene = ""; } diff --git a/editor/editor_run.h b/editor/editor_run.h index 06050436a9..a15d65d91b 100644 --- a/editor/editor_run.h +++ b/editor/editor_run.h @@ -46,9 +46,11 @@ public: private: Status status; + String running_scene; public: Status get_status() const; + String get_running_scene() const; Error run(const String &p_scene, const String &p_custom_args, const List<String> &p_breakpoints, const bool &p_skip_breakpoints = false); void run_native_notify() { status = STATUS_PLAY; } void stop(); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 1c9dadc0dd..9304683d77 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<PropertyInfo> props; - ProjectSettings::get_singleton()->get_property_list(&props); - for (List<PropertyInfo>::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<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + for (Map<StringName, ProjectSettings::AutoloadInfo>::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 608b4a7c4d..4ea11cfaeb 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<PropertyInfo> props; - ProjectSettings::get_singleton()->get_property_list(&props); + Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); //first pass, add the constants so they exist before any script is loaded - for (List<PropertyInfo>::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<StringName, ProjectSettings::AutoloadInfo>::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<Node *> to_add; - for (List<PropertyInfo>::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<StringName, ProjectSettings::AutoloadInfo>::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<PackedScene> ps = res; @@ -1840,7 +1820,7 @@ bool Main::start() { Ref<Script> script_res = res; StringName ibt = script_res->get_instance_base_type(); bool valid_type = ClassDB::is_parent_class(ibt, "Node"); - ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + path); + ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + info.path); Object *obj = ClassDB::instance(ibt); @@ -1850,15 +1830,15 @@ bool Main::start() { n->set_script(script_res); } - ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + path); - n->set_name(name); + ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + info.path); + n->set_name(info.name); //defer so references are all valid on _ready() to_add.push_back(n); - 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, n); + ScriptServer::get_language(i)->add_global_constant(info.name, n); } } } diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp index 79d8e252f0..e5e5f81d2a 100644 --- a/modules/bullet/area_bullet.cpp +++ b/modules/bullet/area_bullet.cpp @@ -174,6 +174,7 @@ void AreaBullet::reload_body() { void AreaBullet::set_space(SpaceBullet *p_space) { // Clear the old space if there is one if (space) { + overlappingObjects.clear(); isScratched = false; // Remove this object form the physics world diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 632407c61f..01af562327 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -2001,114 +2001,116 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b String GDScriptWarning::get_message() const { #define CHECK_SYMBOLS(m_amount) ERR_FAIL_COND_V(symbols.size() < m_amount, String()); + String msg; + switch (code) { case UNASSIGNED_VARIABLE_OP_ASSIGN: { CHECK_SYMBOLS(1); - return "Using assignment with operation but the variable '" + symbols[0] + "' was not previously assigned a value."; + msg = "Using assignment with operation but the variable '" + symbols[0] + "' was not previously assigned a value."; } break; case UNASSIGNED_VARIABLE: { CHECK_SYMBOLS(1); - return "The variable '" + symbols[0] + "' was used but never assigned a value."; + msg = "The variable '" + symbols[0] + "' was used but never assigned a value."; } break; case UNUSED_VARIABLE: { CHECK_SYMBOLS(1); - return "The local variable '" + symbols[0] + "' is declared but never used in the block. If this is intended, prefix it with an underscore: '_" + symbols[0] + "'"; + msg = "The local variable '" + symbols[0] + "' is declared but never used in the block. If this is intended, prefix it with an underscore: '_" + symbols[0] + "'"; } break; case SHADOWED_VARIABLE: { CHECK_SYMBOLS(2); - return "The local variable '" + symbols[0] + "' is shadowing an already-defined variable at line " + symbols[1] + "."; + msg = "The local variable '" + symbols[0] + "' is shadowing an already-defined variable at line " + symbols[1] + "."; } break; case UNUSED_CLASS_VARIABLE: { CHECK_SYMBOLS(1); - return "The class variable '" + symbols[0] + "' is declared but never used in the script."; + msg = "The class variable '" + symbols[0] + "' is declared but never used in the script."; } break; case UNUSED_ARGUMENT: { CHECK_SYMBOLS(2); - return "The argument '" + symbols[1] + "' is never used in the function '" + symbols[0] + "'. If this is intended, prefix it with an underscore: '_" + symbols[1] + "'"; + msg = "The argument '" + symbols[1] + "' is never used in the function '" + symbols[0] + "'. If this is intended, prefix it with an underscore: '_" + symbols[1] + "'"; } break; case UNREACHABLE_CODE: { CHECK_SYMBOLS(1); - return "Unreachable code (statement after return) in function '" + symbols[0] + "()'."; + msg = "Unreachable code (statement after return) in function '" + symbols[0] + "()'."; } break; case STANDALONE_EXPRESSION: { - return "Standalone expression (the line has no effect)."; + msg = "Standalone expression (the line has no effect)."; } break; case VOID_ASSIGNMENT: { CHECK_SYMBOLS(1); - return "Assignment operation, but the function '" + symbols[0] + "()' returns void."; + msg = "Assignment operation, but the function '" + symbols[0] + "()' returns void."; } break; case NARROWING_CONVERSION: { - return "Narrowing conversion (float is converted to int and loses precision)."; + msg = "Narrowing conversion (float is converted to int and loses precision)."; } break; case FUNCTION_MAY_YIELD: { CHECK_SYMBOLS(1); - return "Assigned variable is typed but the function '" + symbols[0] + "()' may yield and return a GDScriptFunctionState instead."; + msg = "Assigned variable is typed but the function '" + symbols[0] + "()' may yield and return a GDScriptFunctionState instead."; } break; case VARIABLE_CONFLICTS_FUNCTION: { CHECK_SYMBOLS(1); - return "Variable declaration of '" + symbols[0] + "' conflicts with a function of the same name."; + msg = "Variable declaration of '" + symbols[0] + "' conflicts with a function of the same name."; } break; case FUNCTION_CONFLICTS_VARIABLE: { CHECK_SYMBOLS(1); - return "Function declaration of '" + symbols[0] + "()' conflicts with a variable of the same name."; + msg = "Function declaration of '" + symbols[0] + "()' conflicts with a variable of the same name."; } break; case FUNCTION_CONFLICTS_CONSTANT: { CHECK_SYMBOLS(1); - return "Function declaration of '" + symbols[0] + "()' conflicts with a constant of the same name."; + msg = "Function declaration of '" + symbols[0] + "()' conflicts with a constant of the same name."; } break; case INCOMPATIBLE_TERNARY: { - return "Values of the ternary conditional are not mutually compatible."; + msg = "Values of the ternary conditional are not mutually compatible."; } break; case UNUSED_SIGNAL: { CHECK_SYMBOLS(1); - return "The signal '" + symbols[0] + "' is declared but never emitted."; + msg = "The signal '" + symbols[0] + "' is declared but never emitted."; } break; case RETURN_VALUE_DISCARDED: { CHECK_SYMBOLS(1); - return "The function '" + symbols[0] + "()' returns a value, but this value is never used."; + msg = "The function '" + symbols[0] + "()' returns a value, but this value is never used."; } break; case PROPERTY_USED_AS_FUNCTION: { CHECK_SYMBOLS(2); - return "The method '" + symbols[0] + "()' was not found in base '" + symbols[1] + "' but there's a property with the same name. Did you mean to access it?"; + msg = "The method '" + symbols[0] + "()' was not found in base '" + symbols[1] + "' but there's a property with the same name. Did you mean to access it?"; } break; case CONSTANT_USED_AS_FUNCTION: { CHECK_SYMBOLS(2); - return "The method '" + symbols[0] + "()' was not found in base '" + symbols[1] + "' but there's a constant with the same name. Did you mean to access it?"; + msg = "The method '" + symbols[0] + "()' was not found in base '" + symbols[1] + "' but there's a constant with the same name. Did you mean to access it?"; } break; case FUNCTION_USED_AS_PROPERTY: { CHECK_SYMBOLS(2); - return "The property '" + symbols[0] + "' was not found in base '" + symbols[1] + "' but there's a method with the same name. Did you mean to call it?"; + msg = "The property '" + symbols[0] + "' was not found in base '" + symbols[1] + "' but there's a method with the same name. Did you mean to call it?"; } break; case INTEGER_DIVISION: { - return "Integer division, decimal part will be discarded."; + msg = "Integer division, decimal part will be discarded."; } break; case UNSAFE_PROPERTY_ACCESS: { CHECK_SYMBOLS(2); - return "The property '" + symbols[0] + "' is not present on the inferred type '" + symbols[1] + "' (but may be present on a subtype)."; + msg = "The property '" + symbols[0] + "' is not present on the inferred type '" + symbols[1] + "' (but may be present on a subtype)."; } break; case UNSAFE_METHOD_ACCESS: { CHECK_SYMBOLS(2); - return "The method '" + symbols[0] + "' is not present on the inferred type '" + symbols[1] + "' (but may be present on a subtype)."; + msg = "The method '" + symbols[0] + "' is not present on the inferred type '" + symbols[1] + "' (but may be present on a subtype)."; } break; case UNSAFE_CAST: { CHECK_SYMBOLS(1); - return "The value is cast to '" + symbols[0] + "' but has an unknown type."; + msg = "The value is cast to '" + symbols[0] + "' but has an unknown type."; } break; case UNSAFE_CALL_ARGUMENT: { CHECK_SYMBOLS(4); - return "The argument '" + symbols[0] + "' of the function '" + symbols[1] + "' requires a the subtype '" + symbols[2] + "' but the supertype '" + symbols[3] + "' was provided"; + msg = "The argument '" + symbols[0] + "' of the function '" + symbols[1] + "' requires a the subtype '" + symbols[2] + "' but the supertype '" + symbols[3] + "' was provided"; } break; case DEPRECATED_KEYWORD: { CHECK_SYMBOLS(2); - return "The '" + symbols[0] + "' keyword is deprecated and will be removed in a future release, please replace its uses by '" + symbols[1] + "'."; + msg = "The '" + symbols[0] + "' keyword is deprecated and will be removed in a future release, please replace its uses by '" + symbols[1] + "'."; } break; case STANDALONE_TERNARY: { - return "Standalone ternary conditional operator: the return value is being discarded."; - } + msg = "Standalone ternary conditional operator: the return value is being discarded."; + } break; case WARNING_MAX: - break; // Can't happen, but silences warning + ERR_FAIL_V_MSG(String(), "Invalid GDScript warning code: " + get_name_from_code(code) + "."); } - ERR_FAIL_V_MSG(String(), "Invalid GDScript warning code: " + get_name_from_code(code) + "."); + return msg + " [" + get_name() + "]"; #undef CHECK_SYMBOLS } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index ca452bf008..63da849723 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -4072,6 +4072,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { while (true) { current_function = function; Node *arg = _parse_and_reduce_expression(p_class, _static); + if (!arg) { + return; + } current_function = nullptr; cparent->arguments.push_back(arg); diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 53e760ffa7..388df63dba 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -55,6 +55,8 @@ Ref<ResourceFormatSaverGDScript> resource_saver_gd; #include "language_server/gdscript_language_server.h" #endif // !GDSCRIPT_NO_LSP +Ref<GDScriptEditorTranslationParserPlugin> gdscript_translation_parser_plugin; + class EditorExportGDScript : public EditorExportPlugin { GDCLASS(EditorExportGDScript, EditorExportPlugin); @@ -167,7 +169,6 @@ void register_gdscript_types() { ScriptEditor::register_create_syntax_highlighter_function(GDScriptSyntaxHighlighter::create); EditorNode::add_init_callback(_editor_init); - Ref<GDScriptEditorTranslationParserPlugin> gdscript_translation_parser_plugin; gdscript_translation_parser_plugin.instance(); EditorTranslationParser::get_singleton()->add_parser(gdscript_translation_parser_plugin, EditorTranslationParser::STANDARD); #endif // TOOLS_ENABLED @@ -185,4 +186,9 @@ void unregister_gdscript_types() { ResourceSaver::remove_resource_format_saver(resource_saver_gd); resource_saver_gd.unref(); + +#ifdef TOOLS_ENABLED + EditorTranslationParser::get_singleton()->remove_parser(gdscript_translation_parser_plugin, EditorTranslationParser::STANDARD); + gdscript_translation_parser_plugin.unref(); +#endif // TOOLS_ENABLED } diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp index df1547607d..942c6d26a6 100644 --- a/modules/mono/editor/code_completion.cpp +++ b/modules/mono/editor/code_completion.cpp @@ -123,16 +123,11 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr case CompletionKind::NODE_PATHS: { { // AutoLoads - List<PropertyInfo> props; - ProjectSettings::get_singleton()->get_property_list(&props); + Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - String s = E->get().name; - if (!s.begins_with("autoload/")) { - continue; - } - String name = s.get_slice("/", 1); - suggestions.push_back(quoted("/root/" + name)); + for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) { + const ProjectSettings::AutoloadInfo &info = E->value(); + suggestions.push_back(quoted("/root/" + String(info.name))); } } |