summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/project_settings.cpp42
-rw-r--r--core/project_settings.h14
-rw-r--r--doc/classes/EditorInterface.xml44
-rw-r--r--editor/code_editor.cpp33
-rw-r--r--editor/create_dialog.cpp1
-rw-r--r--editor/editor_autoload_settings.cpp8
-rw-r--r--editor/editor_node.cpp57
-rw-r--r--editor/editor_node.h4
-rw-r--r--editor/editor_plugin.cpp30
-rw-r--r--editor/editor_plugin.h7
-rw-r--r--editor/editor_run.cpp9
-rw-r--r--editor/editor_run.h2
-rw-r--r--editor/plugins/script_text_editor.cpp28
-rw-r--r--main/main.cpp48
-rw-r--r--modules/bullet/area_bullet.cpp1
-rw-r--r--modules/gdscript/gdscript.cpp62
-rw-r--r--modules/gdscript/gdscript_parser.cpp3
-rw-r--r--modules/gdscript/register_types.cpp8
-rw-r--r--modules/mono/editor/code_completion.cpp13
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)));
}
}