summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/AcceptDialog.xml4
-rw-r--r--doc/classes/ConfirmationDialog.xml3
-rw-r--r--doc/classes/EditorFileDialog.xml6
-rw-r--r--doc/classes/FileDialog.xml7
-rw-r--r--doc/classes/ProjectSettings.xml3
-rw-r--r--doc/classes/ScriptCreateDialog.xml1
-rw-r--r--editor/animation_track_editor.cpp8
-rw-r--r--editor/connections_dialog.cpp4
-rw-r--r--editor/create_dialog.cpp4
-rw-r--r--editor/debugger/editor_debugger_tree.cpp2
-rw-r--r--editor/dependency_editor.cpp8
-rw-r--r--editor/editor_asset_installer.cpp2
-rw-r--r--editor/editor_audio_buses.cpp2
-rw-r--r--editor/editor_dir_dialog.cpp2
-rw-r--r--editor/editor_feature_profile.cpp6
-rw-r--r--editor/editor_file_dialog.cpp30
-rw-r--r--editor/editor_file_dialog.h2
-rw-r--r--editor/editor_help_search.cpp2
-rw-r--r--editor/editor_inspector.cpp57
-rw-r--r--editor/editor_inspector.h13
-rw-r--r--editor/editor_locale_dialog.cpp2
-rw-r--r--editor/editor_node.cpp50
-rw-r--r--editor/editor_properties.cpp2
-rw-r--r--editor/editor_resource_picker.cpp2
-rw-r--r--editor/editor_settings_dialog.cpp2
-rw-r--r--editor/export_template_manager.cpp4
-rw-r--r--editor/filesystem_dock.cpp8
-rw-r--r--editor/groups_editor.cpp2
-rw-r--r--editor/icons/CopyNodePath.svg2
-rw-r--r--editor/import/dynamic_font_import_settings.cpp4
-rw-r--r--editor/import/scene_import_settings.cpp14
-rw-r--r--editor/import_dock.cpp2
-rw-r--r--editor/inspector_dock.cpp4
-rw-r--r--editor/plugin_config_dialog.cpp2
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp4
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp12
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.cpp10
-rw-r--r--editor/plugins/lightmap_gi_editor_plugin.cpp2
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp4
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/occluder_instance_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/replication_editor_plugin.cpp2
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp4
-rw-r--r--editor/plugins/script_editor_plugin.cpp12
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp8
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp8
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp2
-rw-r--r--editor/plugins/theme_editor_plugin.cpp10
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp6
-rw-r--r--editor/project_export.cpp12
-rw-r--r--editor/project_manager.cpp28
-rw-r--r--editor/project_settings_editor.cpp2
-rw-r--r--editor/property_editor.cpp6
-rw-r--r--editor/property_selector.cpp2
-rw-r--r--editor/quick_open.cpp2
-rw-r--r--editor/rename_dialog.cpp2
-rw-r--r--editor/reparent_dialog.cpp2
-rw-r--r--editor/scene_create_dialog.cpp2
-rw-r--r--editor/scene_tree_dock.cpp4
-rw-r--r--editor/script_create_dialog.cpp8
-rw-r--r--editor/shader_create_dialog.cpp12
-rw-r--r--main/main.cpp16
-rwxr-xr-xmisc/scripts/install_vulkan_sdk_macos.sh13
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml31
-rw-r--r--modules/gdscript/gdscript_parser.cpp241
-rw-r--r--modules/gdscript/gdscript_parser.h17
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp4
-rw-r--r--modules/visual_script/editor/visual_script_editor.cpp6
-rw-r--r--modules/visual_script/editor/visual_script_property_selector.cpp2
-rw-r--r--platform/iphone/display_server_iphone.mm1
-rw-r--r--platform/windows/display_server_windows.cpp12
-rw-r--r--platform/windows/display_server_windows.h2
-rw-r--r--scene/gui/dialogs.cpp28
-rw-r--r--scene/gui/dialogs.h7
-rw-r--r--scene/gui/file_dialog.cpp26
-rw-r--r--scene/gui/file_dialog.h2
-rw-r--r--scene/gui/rich_text_label.cpp65
-rw-r--r--scene/gui/rich_text_label.h1
-rw-r--r--scene/gui/text_edit.cpp4
-rw-r--r--scene/gui/tree.cpp3
-rw-r--r--servers/rendering/renderer_rd/shaders/taa_resolve.glsl3
89 files changed, 616 insertions, 320 deletions
diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml
index c1e28ffba3..0009c82548 100644
--- a/doc/classes/AcceptDialog.xml
+++ b/doc/classes/AcceptDialog.xml
@@ -62,6 +62,7 @@
Sets autowrapping for the text in the dialog.
</member>
<member name="dialog_close_on_escape" type="bool" setter="set_close_on_escape" getter="get_close_on_escape" default="true">
+ If [code]true[/code], the dialog will be hidden when the escape key ([constant @GlobalScope.KEY_ESCAPE]) is pressed.
</member>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" default="true">
If [code]true[/code], the dialog is hidden when the OK button is pressed. You can set it to [code]false[/code] if you want to do e.g. input validation when receiving the [signal confirmed] signal, and handle hiding the dialog in your own logic.
@@ -71,6 +72,9 @@
The text displayed by the dialog.
</member>
<member name="exclusive" type="bool" setter="set_exclusive" getter="is_exclusive" overrides="Window" default="true" />
+ <member name="ok_button_text" type="String" setter="set_ok_button_text" getter="get_ok_button_text" default="&quot;OK&quot;">
+ The text displayed by the OK button (see [method get_ok_button]).
+ </member>
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default="&quot;Alert!&quot;" />
<member name="transient" type="bool" setter="set_transient" getter="is_transient" overrides="Window" default="true" />
<member name="visible" type="bool" setter="set_visible" getter="is_visible" overrides="Window" default="false" />
diff --git a/doc/classes/ConfirmationDialog.xml b/doc/classes/ConfirmationDialog.xml
index 2316e32b5d..d4c503857d 100644
--- a/doc/classes/ConfirmationDialog.xml
+++ b/doc/classes/ConfirmationDialog.xml
@@ -27,6 +27,9 @@
</method>
</methods>
<members>
+ <member name="cancel_button_text" type="String" setter="set_cancel_button_text" getter="get_cancel_button_text" default="&quot;Cancel&quot;">
+ The text displayed by the cancel button (see [method get_cancel_button]).
+ </member>
<member name="min_size" type="Vector2i" setter="set_min_size" getter="get_min_size" overrides="Window" default="Vector2i(200, 70)" />
<member name="size" type="Vector2i" setter="set_size" getter="get_size" overrides="Window" default="Vector2i(200, 100)" />
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default="&quot;Please Confirm...&quot;" />
diff --git a/doc/classes/EditorFileDialog.xml b/doc/classes/EditorFileDialog.xml
index b1fd7b4e76..6fd5abe369 100644
--- a/doc/classes/EditorFileDialog.xml
+++ b/doc/classes/EditorFileDialog.xml
@@ -11,9 +11,11 @@
<method name="add_filter">
<return type="void" />
<argument index="0" name="filter" type="String" />
+ <argument index="1" name="description" type="String" default="&quot;&quot;" />
<description>
- Adds a comma-delimited file extension filter option to the [EditorFileDialog] with an optional semi-colon-delimited label.
- For example, [code]"*.tscn, *.scn; Scenes"[/code] results in filter text "Scenes (*.tscn, *.scn)".
+ Adds a comma-delimited file name [code]filter[/code] option to the [EditorFileDialog] with an optional [code]description[/code], which restricts what files can be picked.
+ A [code]filter[/code] should be of the form [code]"filename.extension"[/code], where filename and extension can be [code]*[/code] to match any string. Filters starting with [code].[/code] (i.e. empty filenames) are not allowed.
+ For example, a [code]filter[/code] of [code]"*.tscn, *.scn"[/code] and a [code]description[/code] of [code]"Scenes"[/code] results in filter text "Scenes (*.tscn, *.scn)".
</description>
</method>
<method name="clear_filters">
diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml
index 903f36d0ce..f45031cea8 100644
--- a/doc/classes/FileDialog.xml
+++ b/doc/classes/FileDialog.xml
@@ -12,10 +12,11 @@
<method name="add_filter">
<return type="void" />
<argument index="0" name="filter" type="String" />
+ <argument index="1" name="description" type="String" default="&quot;&quot;" />
<description>
- Adds [code]filter[/code] to the list of filters, which restricts what files can be picked.
- A [code]filter[/code] should be of the form [code]"filename.extension ; Description"[/code], where filename and extension can be [code]*[/code] to match any string. Filters starting with [code].[/code] (i.e. empty filenames) are not allowed.
- Example filters: [code]"*.png ; PNG Images"[/code], [code]"project.godot ; Godot Project"[/code].
+ Adds a comma-delimited file name [code]filter[/code] option to the [FileDialog] with an optional [code]description[/code], which restricts what files can be picked.
+ A [code]filter[/code] should be of the form [code]"filename.extension"[/code], where filename and extension can be [code]*[/code] to match any string. Filters starting with [code].[/code] (i.e. empty filenames) are not allowed.
+ For example, a [code]filter[/code] of [code]"*.png, *.jpg"[/code] and a [code]description[/code] of [code]"Images"[/code] results in filter text "Images (*.png, *.jpg)".
</description>
</method>
<method name="clear_filters">
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 7c378f33fe..2a47d4af25 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -203,6 +203,9 @@
Path to an image used as the boot splash. If left empty, the default Godot Engine splash will be displayed instead.
[b]Note:[/b] Only effective if [member application/boot_splash/show_image] is [code]true[/code].
</member>
+ <member name="application/boot_splash/minimum_display_time" type="int" setter="" getter="" default="0">
+ Minimum boot splash display time (in milliseconds). It is not recommended to set too high values for this setting.
+ </member>
<member name="application/boot_splash/show_image" type="bool" setter="" getter="" default="true">
If [code]true[/code], displays the image specified in [member application/boot_splash/image] when the engine starts. If [code]false[/code], only displays the plain color specified in [member application/boot_splash/bg_color].
</member>
diff --git a/doc/classes/ScriptCreateDialog.xml b/doc/classes/ScriptCreateDialog.xml
index e21fac2d32..79ee95719d 100644
--- a/doc/classes/ScriptCreateDialog.xml
+++ b/doc/classes/ScriptCreateDialog.xml
@@ -40,6 +40,7 @@
</methods>
<members>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" />
+ <member name="ok_button_text" type="String" setter="set_ok_button_text" getter="get_ok_button_text" overrides="AcceptDialog" default="&quot;Create&quot;" />
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default="&quot;Attach Node Script&quot;" />
</members>
<signals>
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 500a3df127..19b259489f 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -3696,7 +3696,7 @@ void AnimationTrackEditor::commit_insert_queue() {
insert_confirm_bezier->set_visible(all_bezier);
insert_confirm_reset->set_visible(reset_allowed);
- insert_confirm->get_ok_button()->set_text(TTR("Create"));
+ insert_confirm->set_ok_button_text(TTR("Create"));
insert_confirm->popup_centered();
} else {
_insert_track(reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
@@ -6473,7 +6473,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
optimize_max_angle->set_step(0.1);
optimize_max_angle->set_value(22);
- optimize_dialog->get_ok_button()->set_text(TTR("Optimize"));
+ optimize_dialog->set_ok_button_text(TTR("Optimize"));
optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_OPTIMIZE_ANIMATION_CONFIRM));
//
@@ -6498,7 +6498,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
cleanup_vb->add_child(cleanup_all);
cleanup_dialog->set_title(TTR("Clean-Up Animation(s) (NO UNDO!)"));
- cleanup_dialog->get_ok_button()->set_text(TTR("Clean-Up"));
+ cleanup_dialog->set_ok_button_text(TTR("Clean-Up"));
cleanup_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_CLEAN_UP_ANIMATION_CONFIRM));
@@ -6518,7 +6518,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
track_copy_dialog = memnew(ConfirmationDialog);
add_child(track_copy_dialog);
track_copy_dialog->set_title(TTR("Select Tracks to Copy"));
- track_copy_dialog->get_ok_button()->set_text(TTR("Copy"));
+ track_copy_dialog->set_ok_button_text(TTR("Copy"));
VBoxContainer *track_vbox = memnew(VBoxContainer);
track_copy_dialog->add_child(track_vbox);
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 74fea03fee..ce94edd583 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -494,8 +494,8 @@ ConnectDialog::ConnectDialog() {
error = memnew(AcceptDialog);
add_child(error);
error->set_title(TTR("Cannot connect signal"));
- error->get_ok_button()->set_text(TTR("Close"));
- get_ok_button()->set_text(TTR("Connect"));
+ error->set_ok_button_text(TTR("Close"));
+ set_ok_button_text(TTR("Connect"));
}
ConnectDialog::~ConnectDialog() {
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 31c169a0fb..c41eeb520a 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -57,10 +57,10 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const St
if (p_replace_mode) {
set_title(vformat(TTR("Change %s Type"), base_type));
- get_ok_button()->set_text(TTR("Change"));
+ set_ok_button_text(TTR("Change"));
} else {
set_title(vformat(TTR("Create New %s"), base_type));
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
}
_load_favorites_and_history();
diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp
index 023204b74a..bdab1cfecb 100644
--- a/editor/debugger/editor_debugger_tree.cpp
+++ b/editor/debugger/editor_debugger_tree.cpp
@@ -258,7 +258,7 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) {
ResourceSaver::get_recognized_extensions(sd, &extensions);
file_dialog->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
}
file_dialog->popup_file_dialog();
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 9a1b2b5ff5..aa03b7e252 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -575,7 +575,7 @@ void DependencyRemoveDialog::_bind_methods() {
}
DependencyRemoveDialog::DependencyRemoveDialog() {
- get_ok_button()->set_text(TTR("Remove"));
+ set_ok_button_text(TTR("Remove"));
VBoxContainer *vb = memnew(VBoxContainer);
add_child(vb);
@@ -641,8 +641,8 @@ DependencyErrorDialog::DependencyErrorDialog() {
files->set_v_size_flags(Control::SIZE_EXPAND_FILL);
set_min_size(Size2(500, 220) * EDSCALE);
- get_ok_button()->set_text(TTR("Open Anyway"));
- get_cancel_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Open Anyway"));
+ set_cancel_button_text(TTR("Close"));
text = memnew(Label);
vb->add_child(text);
@@ -780,7 +780,7 @@ void OrphanResourcesDialog::_bind_methods() {
OrphanResourcesDialog::OrphanResourcesDialog() {
set_title(TTR("Orphan Resource Explorer"));
delete_confirm = memnew(ConfirmationDialog);
- get_ok_button()->set_text(TTR("Delete"));
+ set_ok_button_text(TTR("Delete"));
add_child(delete_confirm);
dep_edit = memnew(DependencyEditor);
add_child(dep_edit);
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index ef29448854..3d4bee4b4e 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -355,7 +355,7 @@ EditorAssetInstaller::EditorAssetInstaller() {
error = memnew(AcceptDialog);
add_child(error);
- get_ok_button()->set_text(TTR("Install"));
+ set_ok_button_text(TTR("Install"));
set_title(TTR("Asset Installer"));
set_hide_on_ok(true);
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index fd121e73ab..fa365c4368 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -1332,7 +1332,7 @@ EditorAudioBuses::EditorAudioBuses() {
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("AudioBusLayout", &ext);
for (const String &E : ext) {
- file_dialog->add_filter(vformat("*.%s; %s", E, TTR("Audio Bus Layout")));
+ file_dialog->add_filter("*." + E, TTR("Audio Bus Layout"));
}
add_child(file_dialog);
file_dialog->connect("file_selected", callable_mp(this, &EditorAudioBuses::_file_dialog_callback));
diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp
index 8494991892..4cbc0cf25d 100644
--- a/editor/editor_dir_dialog.cpp
+++ b/editor/editor_dir_dialog.cpp
@@ -211,5 +211,5 @@ EditorDirDialog::EditorDirDialog() {
mkdirerr->set_text(TTR("Could not create folder."));
add_child(mkdirerr);
- get_ok_button()->set_text(TTR("Choose"));
+ set_ok_button_text(TTR("Choose"));
}
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index f8fc28c31c..9e2d56b2b9 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -983,7 +983,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
add_child(new_profile_dialog);
new_profile_dialog->connect("confirmed", callable_mp(this, &EditorFeatureProfileManager::_create_new_profile));
new_profile_dialog->register_text_enter(new_profile_name);
- new_profile_dialog->get_ok_button()->set_text(TTR("Create"));
+ new_profile_dialog->set_ok_button_text(TTR("Create"));
erase_profile_dialog = memnew(ConfirmationDialog);
add_child(erase_profile_dialog);
@@ -993,7 +993,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
import_profiles = memnew(EditorFileDialog);
add_child(import_profiles);
import_profiles->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES);
- import_profiles->add_filter("*.profile; " + TTR("Godot Feature Profile"));
+ import_profiles->add_filter("*.profile", TTR("Godot Feature Profile"));
import_profiles->connect("files_selected", callable_mp(this, &EditorFeatureProfileManager::_import_profiles));
import_profiles->set_title(TTR("Import Profile(s)"));
import_profiles->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
@@ -1001,7 +1001,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
export_profile = memnew(EditorFileDialog);
add_child(export_profile);
export_profile->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- export_profile->add_filter("*.profile; " + TTR("Godot Feature Profile"));
+ export_profile->add_filter("*.profile", TTR("Godot Feature Profile"));
export_profile->connect("file_selected", callable_mp(this, &EditorFeatureProfileManager::_export_profile));
export_profile->set_title(TTR("Export Profile"));
export_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index af1345b205..9f446ab38f 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -227,10 +227,10 @@ void EditorFileDialog::update_dir() {
switch (mode) {
case FILE_MODE_OPEN_FILE:
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(TTR("Select Current Folder"));
+ set_ok_button_text(TTR("Select Current Folder"));
break;
case FILE_MODE_OPEN_ANY:
case FILE_MODE_SAVE_FILE:
@@ -507,7 +507,7 @@ void EditorFileDialog::_item_selected(int p_item) {
file->set_text(d["name"]);
_request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
} else if (mode == FILE_MODE_OPEN_DIR) {
- get_ok_button()->set_text(TTR("Select This Folder"));
+ set_ok_button_text(TTR("Select This Folder"));
}
get_ok_button()->set_disabled(_is_open_should_be_disabled());
@@ -540,13 +540,13 @@ void EditorFileDialog::_items_clear_selection(const Vector2 &p_pos, MouseButton
switch (mode) {
case FILE_MODE_OPEN_FILE:
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
get_ok_button()->set_disabled(!item_list->is_anything_selected());
break;
case FILE_MODE_OPEN_DIR:
get_ok_button()->set_disabled(false);
- get_ok_button()->set_text(TTR("Select Current Folder"));
+ set_ok_button_text(TTR("Select Current Folder"));
break;
case FILE_MODE_OPEN_ANY:
@@ -976,8 +976,12 @@ void EditorFileDialog::clear_filters() {
invalidate();
}
-void EditorFileDialog::add_filter(const String &p_filter) {
- filters.push_back(p_filter);
+void EditorFileDialog::add_filter(const String &p_filter, const String &p_description) {
+ if (p_description.is_empty()) {
+ filters.push_back(p_filter);
+ } else {
+ filters.push_back(vformat("%s ; %s", p_filter, p_description));
+ }
update_filters();
invalidate();
}
@@ -1033,27 +1037,27 @@ void EditorFileDialog::set_file_mode(FileMode p_mode) {
mode = p_mode;
switch (mode) {
case FILE_MODE_OPEN_FILE:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_title(TTR("Open a File"));
can_create_dir = false;
break;
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_title(TTR("Open File(s)"));
can_create_dir = false;
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_title(TTR("Open a Directory"));
can_create_dir = true;
break;
case FILE_MODE_OPEN_ANY:
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_title(TTR("Open a File or Directory"));
can_create_dir = true;
break;
case FILE_MODE_SAVE_FILE:
- get_ok_button()->set_text(TTR("Save"));
+ set_ok_button_text(TTR("Save"));
set_title(TTR("Save a File"));
can_create_dir = true;
break;
@@ -1481,7 +1485,7 @@ void EditorFileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_cancel_pressed"), &EditorFileDialog::_cancel_pressed);
ClassDB::bind_method(D_METHOD("clear_filters"), &EditorFileDialog::clear_filters);
- ClassDB::bind_method(D_METHOD("add_filter", "filter"), &EditorFileDialog::add_filter);
+ ClassDB::bind_method(D_METHOD("add_filter", "filter", "description"), &EditorFileDialog::add_filter, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_current_dir"), &EditorFileDialog::get_current_dir);
ClassDB::bind_method(D_METHOD("get_current_file"), &EditorFileDialog::get_current_file);
ClassDB::bind_method(D_METHOD("get_current_path"), &EditorFileDialog::get_current_path);
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 5f2e29b690..51629f2682 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -212,7 +212,7 @@ protected:
public:
void popup_file_dialog();
void clear_filters();
- void add_filter(const String &p_filter);
+ void add_filter(const String &p_filter, const String &p_description = "");
void set_enable_multiple_selection(bool p_enable);
Vector<String> get_selected_files() const;
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index f454ba2c41..c48b443a0b 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -185,7 +185,7 @@ EditorHelpSearch::EditorHelpSearch() {
set_title(TTR("Search Help"));
get_ok_button()->set_disabled(true);
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
// Split search and results area.
VBoxContainer *vbox = memnew(VBoxContainer);
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index dc47719f0a..1711b23547 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -39,6 +39,7 @@
#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/plugins/script_editor_plugin.h"
#include "multi_node_edit.h"
#include "scene/gui/center_container.h"
#include "scene/property_utils.h"
@@ -410,6 +411,10 @@ StringName EditorProperty::get_edited_property() const {
return property;
}
+void EditorProperty::set_doc_path(const String &p_doc_path) {
+ doc_path = p_doc_path;
+}
+
void EditorProperty::update_property() {
GDVIRTUAL_CALL(_update_property);
}
@@ -906,6 +911,10 @@ void EditorProperty::menu_option(int p_option) {
emit_signal(SNAME("property_pinned"), property, !pinned);
update();
} break;
+ case MENU_OPEN_DOCUMENTATION: {
+ ScriptEditor::get_singleton()->goto_help(doc_path);
+ EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
+ } break;
}
}
@@ -985,20 +994,25 @@ void EditorProperty::_update_popup() {
add_child(menu);
menu->connect("id_pressed", callable_mp(this, &EditorProperty::menu_option));
}
- menu->add_shortcut(ED_GET_SHORTCUT("property_editor/copy_property"), MENU_COPY_PROPERTY);
- menu->add_shortcut(ED_GET_SHORTCUT("property_editor/paste_property"), MENU_PASTE_PROPERTY);
- menu->add_shortcut(ED_GET_SHORTCUT("property_editor/copy_property_path"), MENU_COPY_PROPERTY_PATH);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/copy_property"), MENU_COPY_PROPERTY);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/paste_property"), MENU_PASTE_PROPERTY);
+ menu->add_icon_shortcut(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), ED_GET_SHORTCUT("property_editor/copy_property_path"), MENU_COPY_PROPERTY_PATH);
menu->set_item_disabled(MENU_PASTE_PROPERTY, is_read_only());
if (!pin_hidden) {
menu->add_separator();
if (can_pin) {
- menu->add_check_item(TTR("Pin value"), MENU_PIN_VALUE);
+ menu->add_icon_check_item(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")), TTR("Pin Value"), MENU_PIN_VALUE);
menu->set_item_checked(menu->get_item_index(MENU_PIN_VALUE), pinned);
- menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default."));
} else {
- menu->add_check_item(vformat(TTR("Pin value [Disabled because '%s' is editor-only]"), property), MENU_PIN_VALUE);
+ menu->add_icon_check_item(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")), vformat(TTR("Pin Value [Disabled because '%s' is editor-only]"), property), MENU_PIN_VALUE);
menu->set_item_disabled(menu->get_item_index(MENU_PIN_VALUE), true);
}
+ menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default."));
+ }
+
+ if (!doc_path.is_empty()) {
+ menu->add_separator();
+ menu->add_icon_item(get_theme_icon(SNAME("Help"), SNAME("EditorIcons")), TTR("Open Documentation"), MENU_OPEN_DOCUMENTATION);
}
}
@@ -2844,7 +2858,7 @@ void EditorInspector::update_tree() {
restart_request_props.insert(p.name);
}
- String doc_hint;
+ PropertyDocInfo doc_info;
if (use_doc_hints) {
// Build the doc hint, to use as tooltip.
@@ -2856,16 +2870,15 @@ void EditorInspector::update_tree() {
}
StringName propname = property_prefix + p.name;
- String descr;
bool found = false;
// Search for the property description in the cache.
- HashMap<StringName, HashMap<StringName, String>>::Iterator E = descr_cache.find(classname);
+ HashMap<StringName, HashMap<StringName, PropertyDocInfo>>::Iterator E = doc_info_cache.find(classname);
if (E) {
- HashMap<StringName, String>::Iterator F = E->value.find(propname);
+ HashMap<StringName, PropertyDocInfo>::Iterator F = E->value.find(propname);
if (F) {
found = true;
- descr = F->value;
+ doc_info = F->value;
}
}
@@ -2873,10 +2886,11 @@ void EditorInspector::update_tree() {
// Build the property description String and add it to the cache.
DocTools *dd = EditorHelp::get_doc_data();
HashMap<String, DocData::ClassDoc>::Iterator F = dd->class_list.find(classname);
- while (F && descr.is_empty()) {
+ while (F && doc_info.description.is_empty()) {
for (int i = 0; i < F->value.properties.size(); i++) {
if (F->value.properties[i].name == propname.operator String()) {
- descr = DTR(F->value.properties[i].description);
+ doc_info.description = DTR(F->value.properties[i].description);
+ doc_info.path = "class_property:" + F->value.name + ":" + F->value.properties[i].name;
break;
}
}
@@ -2885,7 +2899,8 @@ void EditorInspector::update_tree() {
if (slices.size() == 2 && slices[0].begins_with("theme_override_")) {
for (int i = 0; i < F->value.theme_properties.size(); i++) {
if (F->value.theme_properties[i].name == slices[1]) {
- descr = DTR(F->value.theme_properties[i].description);
+ doc_info.description = DTR(F->value.theme_properties[i].description);
+ doc_info.path = "class_theme_item:" + F->value.name + ":" + F->value.theme_properties[i].name;
break;
}
}
@@ -2897,10 +2912,9 @@ void EditorInspector::update_tree() {
break;
}
}
- descr_cache[classname][propname] = descr;
- }
- doc_hint = descr;
+ doc_info_cache[classname][propname] = doc_info;
+ }
}
Vector<EditorInspectorPlugin::AddedEditor> editors;
@@ -2983,11 +2997,12 @@ void EditorInspector::update_tree() {
ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed));
ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED);
ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), varray(), CONNECT_DEFERRED);
- if (!doc_hint.is_empty()) {
- ep->set_tooltip(property_prefix + p.name + "::" + doc_hint);
+ if (!doc_info.description.is_empty()) {
+ ep->set_tooltip(property_prefix + p.name + "::" + doc_info.description);
} else {
ep->set_tooltip(property_prefix + p.name);
}
+ ep->set_doc_path(doc_info.path);
ep->update_property();
ep->_update_pin_flags();
ep->update_revert_and_pin_status();
@@ -3473,7 +3488,7 @@ void EditorInspector::_property_pinned(const String &p_path, bool p_pinned) {
void EditorInspector::_property_selected(const String &p_path, int p_focusable) {
property_selected = p_path;
property_focusable = p_focusable;
- //deselect the others
+ // Deselect the others.
for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) {
if (F.key == property_selected) {
continue;
@@ -3781,7 +3796,7 @@ void EditorInspector::_show_add_meta_dialog() {
add_meta_type->add_icon_item(get_theme_icon(type, "EditorIcons"), type, i);
}
hbc->add_child(add_meta_type);
- add_meta_dialog->get_ok_button()->set_text(TTR("Add"));
+ add_meta_dialog->set_ok_button_text(TTR("Add"));
add_child(add_meta_dialog);
add_meta_dialog->register_text_enter(add_meta_name);
add_meta_dialog->connect("confirmed", callable_mp(this, &EditorInspector::_add_meta_confirm));
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index d70d06c48b..9542f102cb 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -62,6 +62,7 @@ public:
MENU_PASTE_PROPERTY,
MENU_COPY_PROPERTY_PATH,
MENU_PIN_VALUE,
+ MENU_OPEN_DOCUMENTATION,
};
private:
@@ -71,6 +72,7 @@ private:
Object *object = nullptr;
StringName property;
String property_path;
+ String doc_path;
int property_usage;
@@ -148,6 +150,8 @@ public:
Object *get_edited_object();
StringName get_edited_property() const;
+ void set_doc_path(const String &p_doc_path);
+
virtual void update_property();
void update_revert_and_pin_status();
@@ -439,7 +443,7 @@ class EditorInspector : public ScrollContainer {
VBoxContainer *main_vbox = nullptr;
- //map use to cache the instantiated editors
+ // Map used to cache the instantiated editors.
HashMap<StringName, List<EditorProperty *>> editor_property_map;
List<EditorInspectorSection *> sections;
HashSet<StringName> pending;
@@ -473,7 +477,12 @@ class EditorInspector : public ScrollContainer {
int property_focusable;
int update_scroll_request;
- HashMap<StringName, HashMap<StringName, String>> descr_cache;
+ struct PropertyDocInfo {
+ String description;
+ String path;
+ };
+
+ HashMap<StringName, HashMap<StringName, PropertyDocInfo>> doc_info_cache;
HashMap<StringName, String> class_descr_cache;
HashSet<StringName> restart_request_props;
diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp
index abef0dc353..cd8150d235 100644
--- a/editor/editor_locale_dialog.cpp
+++ b/editor/editor_locale_dialog.cpp
@@ -552,5 +552,5 @@ EditorLocaleDialog::EditorLocaleDialog() {
add_child(vb);
_update_tree();
- get_ok_button()->set_text(TTR("Select"));
+ set_ok_button_text(TTR("Select"));
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 64665833df..abe431221c 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -1259,7 +1259,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String
// This serves no purpose and confused people.
continue;
}
- file->add_filter("*." + E + " ; " + E.to_upper());
+ file->add_filter("*." + E, E.to_upper());
preferred.push_back(E);
}
// Lowest priority extension.
@@ -2471,7 +2471,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions);
file->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file->add_filter("*." + extensions[i], extensions[i].to_upper());
}
Node *scene = editor_data.get_edited_scene_root();
@@ -2541,10 +2541,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (scene_root) {
String scene_filename = scene_root->get_scene_file_path();
if (p_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Reload"));
+ save_confirmation->set_ok_button_text(TTR("Save & Reload"));
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before reloading?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene"));
} else {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Quit"));
+ save_confirmation->set_ok_button_text(TTR("Save & Quit"));
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene"));
}
save_confirmation->popup_centered();
@@ -2617,7 +2617,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
ResourceSaver::get_recognized_extensions(sd, &extensions);
file->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file->add_filter("*." + extensions[i], extensions[i].to_upper());
}
if (!scene->get_scene_file_path().is_empty()) {
@@ -2660,7 +2660,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case FILE_EXTERNAL_OPEN_SCENE: {
if (unsaved_cache && !p_confirmed) {
- confirmation->get_ok_button()->set_text(TTR("Open"));
+ confirmation->set_ok_button_text(TTR("Open"));
confirmation->set_text(TTR("Current scene not saved. Open anyway?"));
confirmation->popup_centered();
break;
@@ -2716,7 +2716,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
if (unsaved_cache && !p_confirmed) {
- confirmation->get_ok_button()->set_text(TTR("Reload Saved Scene"));
+ confirmation->set_ok_button_text(TTR("Reload Saved Scene"));
confirmation->set_text(
TTR("The current scene has unsaved changes.\nReload the saved scene anyway? This action cannot be undone."));
confirmation->popup_centered();
@@ -2838,10 +2838,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
i = _next_unsaved_scene(true, ++i);
}
if (p_option == RELOAD_CURRENT_PROJECT) {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Reload"));
+ save_confirmation->set_ok_button_text(TTR("Save & Reload"));
save_confirmation->set_text(TTR("Save changes to the following scene(s) before reloading?") + unsaved_scenes);
} else {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Quit"));
+ save_confirmation->set_ok_button_text(TTR("Save & Quit"));
save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes to the following scene(s) before opening Project Manager?")) + unsaved_scenes);
}
save_confirmation->popup_centered();
@@ -2903,7 +2903,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions);
file->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file->add_filter("*." + extensions[i], extensions[i].to_upper());
}
Node *scene = editor_data.get_edited_scene_root();
@@ -4272,14 +4272,14 @@ Error EditorNode::export_preset(const String &p_preset, const String &p_path, bo
void EditorNode::show_accept(const String &p_text, const String &p_title) {
current_menu_option = -1;
- accept->get_ok_button()->set_text(p_title);
+ accept->set_ok_button_text(p_title);
accept->set_text(p_text);
accept->popup_centered();
}
void EditorNode::show_save_accept(const String &p_text, const String &p_title) {
current_menu_option = -1;
- save_accept->get_ok_button()->set_text(p_title);
+ save_accept->set_ok_button_text(p_title);
save_accept->set_text(p_text);
save_accept->popup_centered();
}
@@ -4957,8 +4957,8 @@ void EditorNode::_immediate_dialog_confirmed() {
bool EditorNode::immediate_confirmation_dialog(const String &p_text, const String &p_ok_text, const String &p_cancel_text) {
ConfirmationDialog *cd = memnew(ConfirmationDialog);
cd->set_text(p_text);
- cd->get_ok_button()->set_text(p_ok_text);
- cd->get_cancel_button()->set_text(p_cancel_text);
+ cd->set_ok_button_text(p_ok_text);
+ cd->set_cancel_button_text(p_cancel_text);
cd->connect("confirmed", callable_mp(singleton, &EditorNode::_immediate_dialog_confirmed));
singleton->gui_base->add_child(cd);
@@ -5020,14 +5020,14 @@ void EditorNode::_layout_menu_option(int p_id) {
case SETTINGS_LAYOUT_SAVE: {
current_menu_option = p_id;
layout_dialog->set_title(TTR("Save Layout"));
- layout_dialog->get_ok_button()->set_text(TTR("Save"));
+ layout_dialog->set_ok_button_text(TTR("Save"));
layout_dialog->popup_centered();
layout_dialog->set_name_line_enabled(true);
} break;
case SETTINGS_LAYOUT_DELETE: {
current_menu_option = p_id;
layout_dialog->set_title(TTR("Delete Layout"));
- layout_dialog->get_ok_button()->set_text(TTR("Delete"));
+ layout_dialog->set_ok_button_text(TTR("Delete"));
layout_dialog->popup_centered();
layout_dialog->set_name_line_enabled(false);
} break;
@@ -5069,7 +5069,7 @@ void EditorNode::_scene_tab_closed(int p_tab, int option) {
? saved_version != editor_data.get_undo_redo().get_version()
: editor_data.get_scene_version(p_tab) != 0;
if (unsaved) {
- save_confirmation->get_ok_button()->set_text(TTR("Save & Close"));
+ save_confirmation->set_ok_button_text(TTR("Save & Close"));
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene->get_scene_file_path().is_empty() ? scene->get_scene_file_path() : "unsaved scene"));
save_confirmation->popup_centered();
} else {
@@ -6769,7 +6769,7 @@ EditorNode::EditorNode() {
video_restart_dialog = memnew(ConfirmationDialog);
video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor."));
- video_restart_dialog->get_ok_button()->set_text(TTR("Save & Restart"));
+ video_restart_dialog->set_ok_button_text(TTR("Save & Restart"));
video_restart_dialog->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SET_RENDERING_DRIVER_SAVE_AND_RESTART));
gui_base->add_child(video_restart_dialog);
@@ -6938,7 +6938,7 @@ EditorNode::EditorNode() {
custom_build_manage_templates = memnew(ConfirmationDialog);
custom_build_manage_templates->set_text(TTR("Android build template is missing, please install relevant templates."));
- custom_build_manage_templates->get_ok_button()->set_text(TTR("Manage Templates"));
+ custom_build_manage_templates->set_ok_button_text(TTR("Manage Templates"));
custom_build_manage_templates->add_button(TTR("Install from file"))->connect("pressed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE));
custom_build_manage_templates->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_MANAGE_EXPORT_TEMPLATES));
gui_base->add_child(custom_build_manage_templates);
@@ -6953,13 +6953,13 @@ EditorNode::EditorNode() {
install_android_build_template = memnew(ConfirmationDialog);
install_android_build_template->set_text(TTR("This will set up your project for custom Android builds by installing the source template to \"res://android/build\".\nYou can then apply modifications and build your own custom APK on export (adding modules, changing the AndroidManifest.xml, etc.).\nNote that in order to make custom builds instead of using pre-built APKs, the \"Use Custom Build\" option should be enabled in the Android export preset."));
- install_android_build_template->get_ok_button()->set_text(TTR("Install"));
+ install_android_build_template->set_ok_button_text(TTR("Install"));
install_android_build_template->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current));
gui_base->add_child(install_android_build_template);
remove_android_build_template = memnew(ConfirmationDialog);
remove_android_build_template->set_text(TTR("The Android build template is already installed in this project and it won't be overwritten.\nRemove the \"res://android/build\" directory manually before attempting this operation again."));
- remove_android_build_template->get_ok_button()->set_text(TTR("Show in File Manager"));
+ remove_android_build_template->set_ok_button_text(TTR("Show in File Manager"));
remove_android_build_template->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES));
gui_base->add_child(remove_android_build_template);
@@ -6970,7 +6970,7 @@ EditorNode::EditorNode() {
file_templates->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
file_templates->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
file_templates->clear_filters();
- file_templates->add_filter("*.tpz ; " + TTR("Template Package"));
+ file_templates->add_filter("*.tpz", TTR("Template Package"));
file = memnew(EditorFileDialog);
gui_base->add_child(file);
@@ -7034,7 +7034,7 @@ EditorNode::EditorNode() {
disk_changed->connect("confirmed", callable_mp(this, &EditorNode::_reload_modified_scenes));
disk_changed->connect("confirmed", callable_mp(this, &EditorNode::_reload_project_settings));
- disk_changed->get_ok_button()->set_text(TTR("Reload"));
+ disk_changed->set_ok_button_text(TTR("Reload"));
disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
disk_changed->connect("custom_action", callable_mp(this, &EditorNode::_resave_scenes));
@@ -7208,7 +7208,7 @@ EditorNode::EditorNode() {
set_process(true);
open_imported = memnew(ConfirmationDialog);
- open_imported->get_ok_button()->set_text(TTR("Open Anyway"));
+ open_imported->set_ok_button_text(TTR("Open Anyway"));
new_inherited_button = open_imported->add_button(TTR("New Inherited"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "inherit");
open_imported->connect("confirmed", callable_mp(this, &EditorNode::_open_imported));
open_imported->connect("custom_action", callable_mp(this, &EditorNode::_inherit_imported));
@@ -7249,7 +7249,7 @@ EditorNode::EditorNode() {
pick_main_scene = memnew(ConfirmationDialog);
gui_base->add_child(pick_main_scene);
- pick_main_scene->get_ok_button()->set_text(TTR("Select"));
+ pick_main_scene->set_ok_button_text(TTR("Select"));
pick_main_scene->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_PICK_MAIN_SCENE));
select_current_scene_button = pick_main_scene->add_button(TTR("Select Current"), true, "select_current");
pick_main_scene->connect("custom_action", callable_mp(this, &EditorNode::_pick_main_scene_custom_action));
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index d06d22ae5b..aaa518362c 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -836,7 +836,7 @@ EditorPropertyLayersGrid::EditorPropertyLayersGrid() {
rename_dialog->add_child(rename_dialog_vb);
rename_dialog_text = memnew(LineEdit);
rename_dialog_vb->add_margin_child(TTR("Name:"), rename_dialog_text);
- rename_dialog->get_ok_button()->set_text(TTR("Rename"));
+ rename_dialog->set_ok_button_text(TTR("Rename"));
add_child(rename_dialog);
rename_dialog->register_text_enter(rename_dialog_text);
rename_dialog->connect("confirmed", callable_mp(this, &EditorPropertyLayersGrid::_rename_operation_confirm));
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 16ebecb8be..2e78b58e11 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -254,7 +254,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
file_dialog->clear_filters();
for (const String &E : valid_extensions) {
- file_dialog->add_filter("*." + E + " ; " + E.to_upper());
+ file_dialog->add_filter("*." + E, E.to_upper());
}
file_dialog->popup_file_dialog();
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index 3eb7d7ffbd..08ff63551f 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -772,7 +772,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
timer->set_one_shot(true);
add_child(timer);
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &EditorSettingsDialog::_settings_changed));
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
}
EditorSettingsDialog::~EditorSettingsDialog() {
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 4ca2e1fdbf..af9c918360 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -810,7 +810,7 @@ void ExportTemplateManager::_bind_methods() {
ExportTemplateManager::ExportTemplateManager() {
set_title(TTR("Export Template Manager"));
set_hide_on_ok(false);
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
// Downloadable export templates are only available for stable and official alpha/beta/RC builds
// (which always have a number following their status, e.g. "alpha1").
@@ -990,7 +990,7 @@ ExportTemplateManager::ExportTemplateManager() {
install_file_dialog->set_title(TTR("Select Template File"));
install_file_dialog->set_access(FileDialog::ACCESS_FILESYSTEM);
install_file_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE);
- install_file_dialog->add_filter("*.tpz ; " + TTR("Godot Export Templates"));
+ install_file_dialog->add_filter("*.tpz", TTR("Godot Export Templates"));
install_file_dialog->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_file_selected), varray(false));
add_child(install_file_dialog);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 2d6ec0c63a..fe6e6044a4 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -3145,7 +3145,7 @@ FileSystemDock::FileSystemDock() {
add_child(remove_dialog);
move_dialog = memnew(EditorDirDialog);
- move_dialog->get_ok_button()->set_text(TTR("Move"));
+ move_dialog->set_ok_button_text(TTR("Move"));
add_child(move_dialog);
move_dialog->connect("dir_selected", callable_mp(this, &FileSystemDock::_move_operation_confirm), make_binds(false));
@@ -3155,13 +3155,13 @@ FileSystemDock::FileSystemDock() {
rename_dialog_text = memnew(LineEdit);
rename_dialog_vb->add_margin_child(TTR("Name:"), rename_dialog_text);
- rename_dialog->get_ok_button()->set_text(TTR("Rename"));
+ rename_dialog->set_ok_button_text(TTR("Rename"));
add_child(rename_dialog);
rename_dialog->register_text_enter(rename_dialog_text);
rename_dialog->connect("confirmed", callable_mp(this, &FileSystemDock::_rename_operation_confirm));
overwrite_dialog = memnew(ConfirmationDialog);
- overwrite_dialog->get_ok_button()->set_text(TTR("Overwrite"));
+ overwrite_dialog->set_ok_button_text(TTR("Overwrite"));
add_child(overwrite_dialog);
overwrite_dialog->connect("confirmed", callable_mp(this, &FileSystemDock::_move_with_overwrite));
@@ -3171,7 +3171,7 @@ FileSystemDock::FileSystemDock() {
duplicate_dialog_text = memnew(LineEdit);
duplicate_dialog_vb->add_margin_child(TTR("Name:"), duplicate_dialog_text);
- duplicate_dialog->get_ok_button()->set_text(TTR("Duplicate"));
+ duplicate_dialog->set_ok_button_text(TTR("Duplicate"));
add_child(duplicate_dialog);
duplicate_dialog->register_text_enter(duplicate_dialog_text);
duplicate_dialog->connect("confirmed", callable_mp(this, &FileSystemDock::_duplicate_operation_confirm));
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 5dc81f623d..bca8c95574 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -568,7 +568,7 @@ GroupDialog::GroupDialog() {
error = memnew(ConfirmationDialog);
add_child(error);
- error->get_ok_button()->set_text(TTR("Close"));
+ error->set_ok_button_text(TTR("Close"));
_add_group_text_changed("");
}
diff --git a/editor/icons/CopyNodePath.svg b/editor/icons/CopyNodePath.svg
index 1adec4ade3..12d03843e0 100644
--- a/editor/icons/CopyNodePath.svg
+++ b/editor/icons/CopyNodePath.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><circle cx="3" cy="1048.4"/><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10zm3 5-2 4h2l2-4zm4 0-2 4h2l2-4z" fill-opacity=".78431" transform="translate(0 1036.4)"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><circle cx="3" cy="1048.4"/><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10zm3 5-2 4h2l2-4zm4 0-2 4h2l2-4z" transform="translate(0 1036.4)"/></g></svg>
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index fa261496f0..ee13a1a9c1 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -1363,6 +1363,6 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
import_settings_data.instantiate();
import_settings_data->owner = this;
- get_ok_button()->set_text(TTR("Reimport"));
- get_cancel_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Reimport"));
+ set_cancel_button_text(TTR("Close"));
}
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index b682407307..0e2967dc42 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -1059,7 +1059,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
}
external_paths->set_title(TTR("Extract Materials to Resource Files"));
- external_paths->get_ok_button()->set_text(TTR("Extract"));
+ external_paths->set_ok_button_text(TTR("Extract"));
} break;
case ACTION_CHOOSE_MESH_SAVE_PATHS: {
for (const KeyValue<String, MeshData> &E : mesh_map) {
@@ -1112,7 +1112,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
}
external_paths->set_title(TTR("Set paths to save meshes as resource files on Reimport"));
- external_paths->get_ok_button()->set_text(TTR("Set Paths"));
+ external_paths->set_ok_button_text(TTR("Set Paths"));
} break;
case ACTION_CHOOSE_ANIMATION_SAVE_PATHS: {
for (const KeyValue<String, AnimationData> &E : animation_map) {
@@ -1158,7 +1158,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) {
}
external_paths->set_title(TTR("Set paths to save animations as resource files on Reimport"));
- external_paths->get_ok_button()->set_text(TTR("Set Paths"));
+ external_paths->set_ok_button_text(TTR("Set Paths"));
} break;
}
@@ -1347,8 +1347,8 @@ SceneImportSettings::SceneImportSettings() {
scene_import_settings_data = memnew(SceneImportSettingsData);
- get_ok_button()->set_text(TTR("Reimport"));
- get_cancel_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Reimport"));
+ set_cancel_button_text(TTR("Close"));
external_paths = memnew(ConfirmationDialog);
add_child(external_paths);
@@ -1382,8 +1382,8 @@ SceneImportSettings::SceneImportSettings() {
item_save_path = memnew(EditorFileDialog);
item_save_path->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- item_save_path->add_filter("*.tres; " + TTR("Text Resource"));
- item_save_path->add_filter("*.res; " + TTR("Binary Resource"));
+ item_save_path->add_filter("*.tres", TTR("Text Resource"));
+ item_save_path->add_filter("*.res", TTR("Binary Resource"));
add_child(item_save_path);
item_save_path->connect("file_selected", callable_mp(this, &SceneImportSettings::_save_path_changed));
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 6bb71ff491..f9e5885f9d 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -671,7 +671,7 @@ ImportDock::ImportDock() {
advanced->connect("pressed", callable_mp(this, &ImportDock::_advanced_options));
reimport_confirm = memnew(ConfirmationDialog);
- reimport_confirm->get_ok_button()->set_text(TTR("Save Scenes, Re-Import, and Restart"));
+ reimport_confirm->set_ok_button_text(TTR("Save Scenes, Re-Import, and Restart"));
content->add_child(reimport_confirm);
reimport_confirm->connect("confirmed", callable_mp(this, &ImportDock::_reimport_and_restart));
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index ad92911810..a509cf3d8f 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -219,12 +219,12 @@ void InspectorDock::_load_resource(const String &p_type) {
load_resource_dialog->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- load_resource_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ load_resource_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
}
const Vector<String> textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false);
for (int i = 0; i < textfile_ext.size(); i++) {
- load_resource_dialog->add_filter("*." + textfile_ext[i] + " ; " + textfile_ext[i].to_upper());
+ load_resource_dialog->add_filter("*." + textfile_ext[i], textfile_ext[i].to_upper());
}
load_resource_dialog->popup_file_dialog();
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index 77e4905341..7061204832 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -200,7 +200,7 @@ void PluginConfigDialog::config(const String &p_config_path) {
_on_required_text_changed("");
get_ok_button()->set_disabled(!_edit_mode);
- get_ok_button()->set_text(_edit_mode ? TTR("Update") : TTR("Create"));
+ set_ok_button_text(_edit_mode ? TTR("Update") : TTR("Create"));
}
void PluginConfigDialog::_bind_methods() {
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index affe46aaae..a5ca55f6df 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -733,7 +733,7 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(bool p_wip_destructive) {
create_resource = memnew(ConfirmationDialog);
add_child(create_resource);
- create_resource->get_ok_button()->set_text(TTR("Create"));
+ create_resource->set_ok_button_text(TTR("Create"));
}
void AbstractPolygon2DEditorPlugin::edit(Object *p_object) {
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 8d1755d260..3d4701a54a 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -1688,7 +1688,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
name_dialog->register_text_enter(name);
error_dialog = memnew(ConfirmationDialog);
- error_dialog->get_ok_button()->set_text(TTR("Close"));
+ error_dialog->set_ok_button_text(TTR("Close"));
error_dialog->set_title(TTR("Error!"));
add_child(error_dialog);
@@ -1696,7 +1696,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
blend_editor.dialog = memnew(AcceptDialog);
add_child(blend_editor.dialog);
- blend_editor.dialog->get_ok_button()->set_text(TTR("Close"));
+ blend_editor.dialog->set_ok_button_text(TTR("Close"));
blend_editor.dialog->set_hide_on_ok(true);
VBoxContainer *blend_vb = memnew(VBoxContainer);
blend_editor.dialog->add_child(blend_vb);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 12ab9e3b61..bc95624dd5 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -307,8 +307,8 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
preview_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
previews->add_child(preview_hb);
- get_ok_button()->set_text(TTR("Download"));
- get_cancel_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Download"));
+ set_cancel_button_text(TTR("Close"));
}
///////////////////////////////////////////////////////////////////////////////////
@@ -1293,14 +1293,14 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
EditorAssetLibraryItemDownload *download_item = _get_asset_in_progress(description->get_asset_id());
if (download_item) {
if (download_item->can_install()) {
- description->get_ok_button()->set_text(TTR("Install"));
+ description->set_ok_button_text(TTR("Install"));
description->get_ok_button()->set_disabled(false);
} else {
- description->get_ok_button()->set_text(TTR("Downloading..."));
+ description->set_ok_button_text(TTR("Downloading..."));
description->get_ok_button()->set_disabled(true);
}
} else {
- description->get_ok_button()->set_text(TTR("Download"));
+ description->set_ok_button_text(TTR("Download"));
description->get_ok_button()->set_disabled(false);
}
@@ -1584,7 +1584,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
asset_open = memnew(EditorFileDialog);
asset_open->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- asset_open->add_filter("*.zip ; " + TTR("Assets ZIP File"));
+ asset_open->add_filter("*.zip", TTR("Assets ZIP File"));
asset_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
add_child(asset_open);
asset_open->connect("file_selected", callable_mp(this, &EditorAssetLibrary::_asset_file_selected));
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index 79025041d3..a7c3c32120 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -257,7 +257,7 @@ CPUParticles2DEditorPlugin::CPUParticles2DEditorPlugin() {
List<String> ext;
ImageLoader::get_recognized_extensions(&ext);
for (const String &E : ext) {
- file->add_filter("*." + E + "; " + E.to_upper());
+ file->add_filter("*." + E, E.to_upper());
}
file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
toolbar->add_child(file);
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index a255c12ed4..8e6687c836 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -380,7 +380,7 @@ GPUParticles2DEditorPlugin::GPUParticles2DEditorPlugin() {
List<String> ext;
ImageLoader::get_recognized_extensions(&ext);
for (const String &E : ext) {
- file->add_filter("*." + E + "; " + E.to_upper());
+ file->add_filter("*." + E, E.to_upper());
}
file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
toolbar->add_child(file);
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 5461fda58b..6750f1aa9c 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -215,7 +215,7 @@ GPUParticles3DEditorBase::GPUParticles3DEditorBase() {
emission_fill->add_item(TTR("Volume"));
emd_vb->add_margin_child(TTR("Emission Source:"), emission_fill);
- emission_dialog->get_ok_button()->set_text(TTR("Create"));
+ emission_dialog->set_ok_button_text(TTR("Create"));
emission_dialog->connect("confirmed", callable_mp(this, &GPUParticles3DEditorBase::_generate_emission_points));
emission_tree_dialog = memnew(SceneTreeDialog);
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
index e97c611e96..df45d6c290 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
@@ -117,17 +117,15 @@ void GradientTexture2DEditorRect::_notification(int p_what) {
const Ref<Texture2D> fill_to_icon = get_theme_icon(SNAME("EditorPathSharpHandle"), SNAME("EditorIcons"));
handle_size = fill_from_icon->get_size();
- const int MAX_HEIGHT = 250 * EDSCALE;
Size2 rect_size = get_size();
// Get the size and position to draw the texture and handles at.
- size = Size2(texture->get_width() * MAX_HEIGHT / texture->get_height(), MAX_HEIGHT);
+ size = Size2(texture->get_width() * rect_size.height / texture->get_height(), rect_size.height);
if (size.width > rect_size.width) {
size.width = rect_size.width;
- size.height = texture->get_height() * rect_size.width / texture->get_width();
+ size.height = texture->get_height() * size.width / texture->get_width();
}
- offset = Point2(Math::round((rect_size.width - size.width) / 2), 0) + handle_size / 2;
- set_custom_minimum_size(Size2(0, size.height));
+ offset = ((rect_size - size + handle_size) / 2).round();
size -= handle_size;
checkerboard->set_rect(Rect2(offset, size));
@@ -183,6 +181,8 @@ GradientTexture2DEditorRect::GradientTexture2DEditorRect() {
checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
checkerboard->set_draw_behind_parent(true);
add_child(checkerboard);
+
+ set_custom_minimum_size(Size2(0, 250 * EDSCALE));
}
///////////////////////
diff --git a/editor/plugins/lightmap_gi_editor_plugin.cpp b/editor/plugins/lightmap_gi_editor_plugin.cpp
index aef97f059a..8413c5e875 100644
--- a/editor/plugins/lightmap_gi_editor_plugin.cpp
+++ b/editor/plugins/lightmap_gi_editor_plugin.cpp
@@ -138,7 +138,7 @@ LightmapGIEditorPlugin::LightmapGIEditorPlugin() {
file_dialog = memnew(EditorFileDialog);
file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- file_dialog->add_filter("*.lmbake ; " + TTR("LightMap Bake"));
+ file_dialog->add_filter("*.lmbake", TTR("LightMap Bake"));
file_dialog->set_title(TTR("Select lightmap bake file:"));
file_dialog->connect("file_selected", callable_mp(this, &LightmapGIEditorPlugin::_bake_select_file));
bake->add_child(file_dialog);
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index d1f858315c..5fb885ad1f 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -519,7 +519,7 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
outline_dialog = memnew(ConfirmationDialog);
outline_dialog->set_title(TTR("Create Outline Mesh"));
- outline_dialog->get_ok_button()->set_text(TTR("Create"));
+ outline_dialog->set_ok_button_text(TTR("Create"));
VBoxContainer *outline_dialog_vbc = memnew(VBoxContainer);
outline_dialog->add_child(outline_dialog_vbc);
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 914ccb54c1..72bfc05270 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -263,7 +263,7 @@ MeshLibraryEditor::MeshLibraryEditor() {
file->clear_filters();
file->set_title(TTR("Import Scene"));
for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file->add_filter("*." + extensions[i], extensions[i].to_upper());
}
add_child(file);
file->connect("file_selected", callable_mp(this, &MeshLibraryEditor::_import_scene_cbk));
@@ -288,7 +288,7 @@ MeshLibraryEditor::MeshLibraryEditor() {
cd_remove->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_remove_confirm));
cd_update = memnew(ConfirmationDialog);
add_child(cd_update);
- cd_update->get_ok_button()->set_text(TTR("Apply without Transforms"));
+ cd_update->set_ok_button_text(TTR("Apply without Transforms"));
cd_update->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(false));
cd_update->add_button(TTR("Apply with Transforms"))->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(true));
}
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index 0fab3aed0d..7207390922 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -347,7 +347,7 @@ MultiMeshEditor::MultiMeshEditor() {
populate_amount->set_value(128);
vbc->add_margin_child(TTR("Amount:"), populate_amount);
- populate_dialog->get_ok_button()->set_text(TTR("Populate"));
+ populate_dialog->set_ok_button_text(TTR("Populate"));
populate_dialog->get_ok_button()->connect("pressed", callable_mp(this, &MultiMeshEditor::_populate));
std = memnew(SceneTreeDialog);
diff --git a/editor/plugins/occluder_instance_3d_editor_plugin.cpp b/editor/plugins/occluder_instance_3d_editor_plugin.cpp
index d5fc51aea4..365f74d7a3 100644
--- a/editor/plugins/occluder_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/occluder_instance_3d_editor_plugin.cpp
@@ -113,7 +113,7 @@ OccluderInstance3DEditorPlugin::OccluderInstance3DEditorPlugin() {
file_dialog = memnew(EditorFileDialog);
file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
- file_dialog->add_filter("*.occ ; Occluder3D");
+ file_dialog->add_filter("*.occ", "Occluder3D");
file_dialog->set_title(TTR("Select occluder bake file:"));
file_dialog->connect("file_selected", callable_mp(this, &OccluderInstance3DEditorPlugin::_bake_select_file));
bake->add_child(file_dialog);
diff --git a/editor/plugins/replication_editor_plugin.cpp b/editor/plugins/replication_editor_plugin.cpp
index 72fe3c5f20..9e495c3aa3 100644
--- a/editor/plugins/replication_editor_plugin.cpp
+++ b/editor/plugins/replication_editor_plugin.cpp
@@ -171,7 +171,7 @@ ReplicationEditor::ReplicationEditor() {
add_child(delete_dialog);
error_dialog = memnew(AcceptDialog);
- error_dialog->get_ok_button()->set_text(TTR("Close"));
+ error_dialog->set_ok_button_text(TTR("Close"));
error_dialog->set_title(TTR("Error!"));
add_child(error_dialog);
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index 79fc304242..4e528ef066 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -57,7 +57,7 @@ void ResourcePreloaderEditor::_files_load_request(const Vector<String> &p_paths)
dialog->set_text(TTR("ERROR: Couldn't load resource!"));
dialog->set_title(TTR("Error!"));
//dialog->get_cancel()->set_text("Close");
- dialog->get_ok_button()->set_text(TTR("Close"));
+ dialog->set_ok_button_text(TTR("Close"));
dialog->popup_centered();
return; ///beh should show an error i guess
}
@@ -139,7 +139,7 @@ void ResourcePreloaderEditor::_paste_pressed() {
if (!r.is_valid()) {
dialog->set_text(TTR("Resource clipboard is empty!"));
dialog->set_title(TTR("Error!"));
- dialog->get_ok_button()->set_text(TTR("Close"));
+ dialog->set_ok_button_text(TTR("Close"));
dialog->popup_centered();
return; ///beh should show an error i guess
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 6ab2366a44..f4d42ff456 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -377,7 +377,7 @@ ScriptEditorQuickOpen::ScriptEditorQuickOpen() {
search_box->connect("gui_input", callable_mp(this, &ScriptEditorQuickOpen::_sbox_input));
search_options = memnew(Tree);
vbc->add_margin_child(TTR("Matches:"), search_options, true);
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
get_ok_button()->set_disabled(true);
register_text_enter(search_box);
set_hide_on_ok(false);
@@ -1188,7 +1188,7 @@ void ScriptEditor::_menu_option(int p_option) {
file_dialog->clear_filters();
for (const String &E : textfile_extensions) {
- file_dialog->add_filter("*." + E + " ; " + E.to_upper());
+ file_dialog->add_filter("*." + E, E.to_upper());
}
file_dialog->popup_file_dialog();
file_dialog->set_title(TTR("New Text File..."));
@@ -1203,11 +1203,11 @@ void ScriptEditor::_menu_option(int p_option) {
ResourceLoader::get_recognized_extensions_for_type("Script", &extensions);
file_dialog->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ file_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
}
for (const String &E : textfile_extensions) {
- file_dialog->add_filter("*." + E + " ; " + E.to_upper());
+ file_dialog->add_filter("*." + E, E.to_upper());
}
file_dialog->popup_file_dialog();
@@ -3883,7 +3883,7 @@ ScriptEditor::ScriptEditor() {
tab_container->connect("tab_changed", callable_mp(this, &ScriptEditor::_tab_changed));
erase_tab_confirm = memnew(ConfirmationDialog);
- erase_tab_confirm->get_ok_button()->set_text(TTR("Save"));
+ erase_tab_confirm->set_ok_button_text(TTR("Save"));
erase_tab_confirm->add_button(TTR("Discard"), DisplayServer::get_singleton()->get_swap_cancel_ok(), "discard");
erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab), varray(true));
erase_tab_confirm->connect("custom_action", callable_mp(this, &ScriptEditor::_close_discard_current_tab));
@@ -3916,7 +3916,7 @@ ScriptEditor::ScriptEditor() {
disk_changed_list->set_v_size_flags(SIZE_EXPAND_FILL);
disk_changed->connect("confirmed", callable_mp(this, &ScriptEditor::_reload_scripts));
- disk_changed->get_ok_button()->set_text(TTR("Reload"));
+ disk_changed->set_ok_button_text(TTR("Reload"));
disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
disk_changed->connect("custom_action", callable_mp(this, &ScriptEditor::_resave_scripts));
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 04b407ce65..85a39b1c9c 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -830,7 +830,7 @@ ShaderEditor::ShaderEditor() {
vbc->add_child(dl);
disk_changed->connect("confirmed", callable_mp(this, &ShaderEditor::_reload_shader_from_disk));
- disk_changed->get_ok_button()->set_text(TTR("Reload"));
+ disk_changed->set_ok_button_text(TTR("Reload"));
disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
disk_changed->connect("custom_action", callable_mp(this, &ShaderEditor::save_external_data));
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index ad817f9a41..3323d865c2 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -122,7 +122,7 @@ void Sprite2DEditor::_menu_option(int p_option) {
switch (p_option) {
case MENU_OPTION_CONVERT_TO_MESH_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create MeshInstance2D"));
+ debug_uv_dialog->set_ok_button_text(TTR("Create MeshInstance2D"));
debug_uv_dialog->set_title(TTR("MeshInstance2D Preview"));
_update_mesh_data();
@@ -131,7 +131,7 @@ void Sprite2DEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CONVERT_TO_POLYGON_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create Polygon2D"));
+ debug_uv_dialog->set_ok_button_text(TTR("Create Polygon2D"));
debug_uv_dialog->set_title(TTR("Polygon2D Preview"));
_update_mesh_data();
@@ -139,7 +139,7 @@ void Sprite2DEditor::_menu_option(int p_option) {
debug_uv->update();
} break;
case MENU_OPTION_CREATE_COLLISION_POLY_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create CollisionPolygon2D"));
+ debug_uv_dialog->set_ok_button_text(TTR("Create CollisionPolygon2D"));
debug_uv_dialog->set_title(TTR("CollisionPolygon2D Preview"));
_update_mesh_data();
@@ -148,7 +148,7 @@ void Sprite2DEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create LightOccluder2D"));
+ debug_uv_dialog->set_ok_button_text(TTR("Create LightOccluder2D"));
debug_uv_dialog->set_title(TTR("LightOccluder2D Preview"));
_update_mesh_data();
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 8a40ffbe38..edd900f7d8 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -119,7 +119,7 @@ void SpriteFramesEditor::_sheet_preview_draw() {
if (frames_selected.size() == 0) {
split_sheet_dialog->get_ok_button()->set_disabled(true);
- split_sheet_dialog->get_ok_button()->set_text(TTR("No Frames Selected"));
+ split_sheet_dialog->set_ok_button_text(TTR("No Frames Selected"));
return;
}
@@ -140,7 +140,7 @@ void SpriteFramesEditor::_sheet_preview_draw() {
}
split_sheet_dialog->get_ok_button()->set_disabled(false);
- split_sheet_dialog->get_ok_button()->set_text(vformat(TTR("Add %d Frame(s)"), frames_selected.size()));
+ split_sheet_dialog->set_ok_button_text(vformat(TTR("Add %d Frame(s)"), frames_selected.size()));
}
void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
@@ -449,7 +449,7 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
dialog->set_title(TTR("Error!"));
//dialog->get_cancel()->set_text("Close");
- dialog->get_ok_button()->set_text(TTR("Close"));
+ dialog->set_ok_button_text(TTR("Close"));
dialog->popup_centered();
return; ///beh should show an error i guess
}
@@ -516,7 +516,7 @@ void SpriteFramesEditor::_paste_pressed() {
dialog->set_text(TTR("Resource clipboard is empty or not a texture!"));
dialog->set_title(TTR("Error!"));
//dialog->get_cancel()->set_text("Close");
- dialog->get_ok_button()->set_text(TTR("Close"));
+ dialog->set_ok_button_text(TTR("Close"));
dialog->popup_centered();
return; ///beh should show an error i guess
}
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 3f4f9a4f4d..dd98247428 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -989,7 +989,7 @@ Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const {
}
TextureRegionEditor::TextureRegionEditor() {
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
VBoxContainer *vb = memnew(VBoxContainer);
add_child(vb);
node_sprite_2d = nullptr;
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index b01b90cd08..129af1bb1d 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -1883,7 +1883,7 @@ void ThemeItemEditorDialog::set_edited_theme(const Ref<Theme> &p_theme) {
ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_editor) {
set_title(TTR("Manage Theme Items"));
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
set_hide_on_ok(false); // Closing may require a confirmation in some cases.
theme_type_editor = p_theme_type_editor;
@@ -2080,7 +2080,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("Theme", &ext);
for (const String &E : ext) {
- import_another_theme_dialog->add_filter(vformat("*.%s; %s", E, TTR("Theme Resource")));
+ import_another_theme_dialog->add_filter("*." + E, TTR("Theme Resource"));
}
import_another_file_hb->add_child(import_another_theme_dialog);
import_another_theme_dialog->connect("file_selected", callable_mp(this, &ThemeItemEditorDialog::_select_another_theme_cbk));
@@ -2733,7 +2733,7 @@ void ThemeTypeEditor::_list_type_selected(int p_index) {
void ThemeTypeEditor::_add_type_button_cbk() {
add_type_mode = ADD_THEME_TYPE;
add_type_dialog->set_title(TTR("Add Item Type"));
- add_type_dialog->get_ok_button()->set_text(TTR("Add Type"));
+ add_type_dialog->set_ok_button_text(TTR("Add Type"));
add_type_dialog->set_include_own_types(false);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
}
@@ -3269,7 +3269,7 @@ void ThemeTypeEditor::_type_variation_changed(const String p_value) {
void ThemeTypeEditor::_add_type_variation_cbk() {
add_type_mode = ADD_VARIATION_BASE;
add_type_dialog->set_title(TTR("Set Variation Base Type"));
- add_type_dialog->get_ok_button()->set_text(TTR("Set Base Type"));
+ add_type_dialog->set_ok_button_text(TTR("Set Base Type"));
add_type_dialog->set_include_own_types(true);
add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE);
}
@@ -3663,7 +3663,7 @@ ThemeEditor::ThemeEditor() {
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &ext);
for (const String &E : ext) {
- preview_scene_dialog->add_filter(vformat("*.%s; %s", E, TTR("Scene")));
+ preview_scene_dialog->add_filter("*." + E, TTR("Scene"));
}
main_hs->add_child(preview_scene_dialog);
preview_scene_dialog->connect("file_selected", callable_mp(this, &ThemeEditor::_preview_scene_dialog_cbk));
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
index 02fe65378d..3fe6778f48 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.cpp
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -256,7 +256,7 @@ AtlasMergingDialog::AtlasMergingDialog() {
set_hide_on_ok(false);
// Ok buttons
- get_ok_button()->set_text(TTR("Merge (Keep original Atlases)"));
+ set_ok_button_text(TTR("Merge (Keep original Atlases)"));
get_ok_button()->set_disabled(true);
merge_button = add_button(TTR("Merge"), true, "merge");
merge_button->set_disabled(true);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 37ccc6ad45..deffa48615 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -2405,7 +2405,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
confirm_auto_create_tiles = memnew(AcceptDialog);
confirm_auto_create_tiles->set_title(TTR("Auto Create Tiles in Non-Transparent Texture Regions?"));
confirm_auto_create_tiles->set_text(TTR("The atlas's texture was modified.\nWould you like to automatically create tiles in the atlas?"));
- confirm_auto_create_tiles->get_ok_button()->set_text(TTR("Yes"));
+ confirm_auto_create_tiles->set_ok_button_text(TTR("Yes"));
confirm_auto_create_tiles->add_cancel_button()->set_text(TTR("No"));
confirm_auto_create_tiles->connect("confirmed", callable_mp(this, &TileSetAtlasSourceEditor::_auto_create_tiles));
add_child(confirm_auto_create_tiles);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 8c72a886ea..94073daeda 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -4911,7 +4911,7 @@ VisualShaderEditor::VisualShaderEditor() {
members_dialog->set_title(TTR("Create Shader Node"));
members_dialog->set_exclusive(false);
members_dialog->add_child(members_vb);
- members_dialog->get_ok_button()->set_text(TTR("Create"));
+ members_dialog->set_ok_button_text(TTR("Create"));
members_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualShaderEditor::_member_create));
members_dialog->get_ok_button()->set_disabled(true);
members_dialog->connect("cancelled", callable_mp(this, &VisualShaderEditor::_member_cancel));
@@ -4922,7 +4922,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_varying_dialog = memnew(ConfirmationDialog);
add_varying_dialog->set_title(TTR("Create Shader Varying"));
add_varying_dialog->set_exclusive(false);
- add_varying_dialog->get_ok_button()->set_text(TTR("Create"));
+ add_varying_dialog->set_ok_button_text(TTR("Create"));
add_varying_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualShaderEditor::_varying_create));
add_varying_dialog->get_ok_button()->set_disabled(true);
add_child(add_varying_dialog);
@@ -4966,7 +4966,7 @@ VisualShaderEditor::VisualShaderEditor() {
remove_varying_dialog = memnew(ConfirmationDialog);
remove_varying_dialog->set_title(TTR("Delete Shader Varying"));
remove_varying_dialog->set_exclusive(false);
- remove_varying_dialog->get_ok_button()->set_text(TTR("Delete"));
+ remove_varying_dialog->set_ok_button_text(TTR("Delete"));
remove_varying_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualShaderEditor::_varying_deleted));
add_child(remove_varying_dialog);
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index ac32027219..209c997d58 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -892,7 +892,7 @@ void ProjectExportDialog::_export_project() {
List<String> extension_list = platform->get_binary_extensions(current);
for (int i = 0; i < extension_list.size(); i++) {
// TRANSLATORS: This is the name of a project export file format. %s will be replaced by the platform name.
- export_project->add_filter(vformat("*.%s; %s", extension_list[i], vformat(TTR("%s Export"), platform->get_name())));
+ export_project->add_filter("*." + extension_list[i], vformat(TTR("%s Export"), platform->get_name()));
}
if (!current->get_export_path().is_empty()) {
@@ -1195,13 +1195,13 @@ ProjectExportDialog::ProjectExportDialog() {
delete_confirm = memnew(ConfirmationDialog);
add_child(delete_confirm);
- delete_confirm->get_ok_button()->set_text(TTR("Delete"));
+ delete_confirm->set_ok_button_text(TTR("Delete"));
delete_confirm->connect("confirmed", callable_mp(this, &ProjectExportDialog::_delete_preset_confirm));
// Export buttons, dialogs and errors.
- get_cancel_button()->set_text(TTR("Close"));
- get_ok_button()->set_text(TTR("Export PCK/ZIP..."));
+ set_cancel_button_text(TTR("Close"));
+ set_ok_button_text(TTR("Export PCK/ZIP..."));
export_button = add_button(TTR("Export Project..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
export_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_project));
// Disable initially before we select a valid preset
@@ -1222,8 +1222,8 @@ ProjectExportDialog::ProjectExportDialog() {
export_all_button->set_disabled(true);
export_pck_zip = memnew(EditorFileDialog);
- export_pck_zip->add_filter("*.zip ; " + TTR("ZIP File"));
- export_pck_zip->add_filter("*.pck ; " + TTR("Godot Project Pack"));
+ export_pck_zip->add_filter("*.zip", TTR("ZIP File"));
+ export_pck_zip->add_filter("*.pck", TTR("Godot Project Pack"));
export_pck_zip->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
export_pck_zip->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
add_child(export_pck_zip);
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index d1aa1ceae6..f7ef574205 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -362,8 +362,8 @@ private:
if (mode == MODE_IMPORT) {
fdialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
fdialog->clear_filters();
- fdialog->add_filter(vformat("project.godot ; %s %s", VERSION_NAME, TTR("Project")));
- fdialog->add_filter("*.zip ; " + TTR("ZIP File"));
+ fdialog->add_filter("project.godot", vformat("%s %s", VERSION_NAME, TTR("Project")));
+ fdialog->add_filter("*.zip", TTR("ZIP File"));
} else {
fdialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR);
}
@@ -681,7 +681,7 @@ public:
install_browse->hide();
set_title(TTR("Rename Project"));
- get_ok_button()->set_text(TTR("Rename"));
+ set_ok_button_text(TTR("Rename"));
name_container->show();
status_rect->hide();
msg->hide();
@@ -735,7 +735,7 @@ public:
if (mode == MODE_IMPORT) {
set_title(TTR("Import Existing Project"));
- get_ok_button()->set_text(TTR("Import & Edit"));
+ set_ok_button_text(TTR("Import & Edit"));
name_container->hide();
install_path_container->hide();
rasterizer_container->hide();
@@ -744,7 +744,7 @@ public:
} else if (mode == MODE_NEW) {
set_title(TTR("Create New Project"));
- get_ok_button()->set_text(TTR("Create & Edit"));
+ set_ok_button_text(TTR("Create & Edit"));
name_container->show();
install_path_container->hide();
rasterizer_container->show();
@@ -754,7 +754,7 @@ public:
} else if (mode == MODE_INSTALL) {
set_title(TTR("Install Project:") + " " + zip_title);
- get_ok_button()->set_text(TTR("Install & Edit"));
+ set_ok_button_text(TTR("Install & Edit"));
project_name->set_text(zip_title);
name_container->show();
install_path_container->hide();
@@ -2801,9 +2801,9 @@ ProjectManager::ProjectManager() {
{
// Dialogs
language_restart_ask = memnew(ConfirmationDialog);
- language_restart_ask->get_ok_button()->set_text(TTR("Restart Now"));
+ language_restart_ask->set_ok_button_text(TTR("Restart Now"));
language_restart_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_restart_confirm));
- language_restart_ask->get_cancel_button()->set_text(TTR("Continue"));
+ language_restart_ask->set_cancel_button_text(TTR("Continue"));
add_child(language_restart_ask);
scan_dir = memnew(EditorFileDialog);
@@ -2816,12 +2816,12 @@ ProjectManager::ProjectManager() {
scan_dir->connect("dir_selected", callable_mp(this, &ProjectManager::_scan_begin));
erase_missing_ask = memnew(ConfirmationDialog);
- erase_missing_ask->get_ok_button()->set_text(TTR("Remove All"));
+ erase_missing_ask->set_ok_button_text(TTR("Remove All"));
erase_missing_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_erase_missing_projects_confirm));
add_child(erase_missing_ask);
erase_ask = memnew(ConfirmationDialog);
- erase_ask->get_ok_button()->set_text(TTR("Remove"));
+ erase_ask->set_ok_button_text(TTR("Remove"));
erase_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_erase_project_confirm));
add_child(erase_ask);
@@ -2836,17 +2836,17 @@ ProjectManager::ProjectManager() {
erase_ask_vb->add_child(delete_project_contents);
multi_open_ask = memnew(ConfirmationDialog);
- multi_open_ask->get_ok_button()->set_text(TTR("Edit"));
+ multi_open_ask->set_ok_button_text(TTR("Edit"));
multi_open_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_open_selected_projects));
add_child(multi_open_ask);
multi_run_ask = memnew(ConfirmationDialog);
- multi_run_ask->get_ok_button()->set_text(TTR("Run"));
+ multi_run_ask->set_ok_button_text(TTR("Run"));
multi_run_ask->get_ok_button()->connect("pressed", callable_mp(this, &ProjectManager::_run_project_confirm));
add_child(multi_run_ask);
multi_scan_ask = memnew(ConfirmationDialog);
- multi_scan_ask->get_ok_button()->set_text(TTR("Scan"));
+ multi_scan_ask->set_ok_button_text(TTR("Scan"));
add_child(multi_scan_ask);
ask_update_settings = memnew(ConfirmationDialog);
@@ -2868,7 +2868,7 @@ ProjectManager::ProjectManager() {
if (asset_library) {
open_templates = memnew(ConfirmationDialog);
open_templates->set_text(TTR("You currently don't have any projects.\nWould you like to explore official example projects in the Asset Library?"));
- open_templates->get_ok_button()->set_text(TTR("Open Asset Library"));
+ open_templates->set_ok_button_text(TTR("Open Asset Library"));
open_templates->connect("confirmed", callable_mp(this, &ProjectManager::_open_asset_library));
add_child(open_templates);
}
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 1524993bd0..49707355a0 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -685,7 +685,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
timer->set_one_shot(true);
add_child(timer);
- get_ok_button()->set_text(TTR("Close"));
+ set_ok_button_text(TTR("Close"));
set_hide_on_ok(true);
bool use_advanced = EditorSettings::get_singleton()->get_project_metadata("project_settings", "advanced_mode", false);
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 9f13a9d520..277ae14e0e 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -145,7 +145,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
file->clear_filters();
for (const String &E : valid_extensions) {
- file->add_filter("*." + E + " ; " + E.to_upper());
+ file->add_filter("*." + E, E.to_upper());
}
file->popup_file_dialog();
@@ -1223,7 +1223,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
filter = "*." + extensions[i];
}
- file->add_filter(filter + " ; " + extensions[i].to_upper());
+ file->add_filter(filter, extensions[i].to_upper());
}
}
file->popup_file_dialog();
@@ -1307,7 +1307,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
ResourceLoader::get_recognized_extensions_for_type(type, &extensions);
file->clear_filters();
for (const String &E : extensions) {
- file->add_filter("*." + E + " ; " + E.to_upper());
+ file->add_filter("*." + E, E.to_upper());
}
file->popup_file_dialog();
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index c136eae1bc..841c3ff3b1 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -581,7 +581,7 @@ PropertySelector::PropertySelector() {
search_box->connect("gui_input", callable_mp(this, &PropertySelector::_sbox_input));
search_options = memnew(Tree);
vbc->add_margin_child(TTR("Matches:"), search_options, true);
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
get_ok_button()->set_disabled(true);
register_text_enter(search_box);
set_hide_on_ok(false);
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
index 4938699fc4..4f7f9fc78c 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -263,6 +263,6 @@ EditorQuickOpen::EditorQuickOpen() {
search_options->add_theme_constant_override("draw_guides", 1);
vbc->add_margin_child(TTR("Matches:"), search_options, true);
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
set_hide_on_ok(false);
}
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
index a8278b9aab..255187e4ed 100644
--- a/editor/rename_dialog.cpp
+++ b/editor/rename_dialog.cpp
@@ -289,7 +289,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
// ---- Dialog related
set_min_size(Size2(383, 0));
- get_ok_button()->set_text(TTR("Rename"));
+ set_ok_button_text(TTR("Rename"));
Button *but_reset = add_button(TTR("Reset"));
eh.errfunc = _error_handler;
diff --git a/editor/reparent_dialog.cpp b/editor/reparent_dialog.cpp
index 5a8fe24518..75098b25b1 100644
--- a/editor/reparent_dialog.cpp
+++ b/editor/reparent_dialog.cpp
@@ -89,7 +89,7 @@ ReparentDialog::ReparentDialog() {
//cancel->connect("pressed", this,"_cancel");
- get_ok_button()->set_text(TTR("Reparent"));
+ set_ok_button_text(TTR("Reparent"));
}
ReparentDialog::~ReparentDialog() {
diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp
index 64aea54c5f..6a35b22210 100644
--- a/editor/scene_create_dialog.cpp
+++ b/editor/scene_create_dialog.cpp
@@ -76,7 +76,7 @@ void SceneCreateDialog::accept_create() {
void SceneCreateDialog::browse_types() {
select_node_dialog->popup_create(true);
select_node_dialog->set_title(TTR("Pick Root Node Type"));
- select_node_dialog->get_ok_button()->set_text(TTR("Pick"));
+ select_node_dialog->set_ok_button_text(TTR("Pick"));
}
void SceneCreateDialog::on_type_picked() {
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 2e1090e6c0..fb8be5db81 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -910,7 +910,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
ResourceSaver::get_recognized_extensions(sd, &extensions);
new_scene_from_dialog->clear_filters();
for (int i = 0; i < extensions.size(); i++) {
- new_scene_from_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ new_scene_from_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
}
String existing;
@@ -3535,7 +3535,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
clear_inherit_confirm = memnew(ConfirmationDialog);
clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)"));
- clear_inherit_confirm->get_ok_button()->set_text(TTR("Clear"));
+ clear_inherit_confirm->set_ok_button_text(TTR("Clear"));
add_child(clear_inherit_confirm);
set_process_input(true);
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index e8561de19c..f2eabdd208 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -481,7 +481,7 @@ void ScriptCreateDialog::_browse_path(bool browse_parent, bool p_save) {
if (p_save) {
file_browse->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
file_browse->set_title(TTR("Open Script / Choose Location"));
- file_browse->get_ok_button()->set_text(TTR("Open"));
+ file_browse->set_ok_button_text(TTR("Open"));
} else {
file_browse->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
file_browse->set_title(TTR("Open Script"));
@@ -528,7 +528,7 @@ void ScriptCreateDialog::_browse_class_in_tree() {
select_class->set_base_type(base_type);
select_class->popup_create(true);
select_class->set_title(vformat(TTR("Inherit %s"), base_type));
- select_class->get_ok_button()->set_text(TTR("Inherit"));
+ select_class->set_ok_button_text(TTR("Inherit"));
}
void ScriptCreateDialog::_path_changed(const String &p_path) {
@@ -750,7 +750,7 @@ void ScriptCreateDialog::_update_dialog() {
parent_browse_button->set_disabled(!is_new_file || !can_inherit_from_file);
template_inactive_message = "";
String button_text = is_new_file ? TTR("Create") : TTR("Load");
- get_ok_button()->set_text(button_text);
+ set_ok_button_text(button_text);
if (is_new_file) {
if (is_built_in) {
@@ -1088,7 +1088,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
file_browse->connect("file_selected", callable_mp(this, &ScriptCreateDialog::_file_selected));
file_browse->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
add_child(file_browse);
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
alert = memnew(AcceptDialog);
alert->get_label()->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
alert->get_label()->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp
index f70c46c8d8..28e1e9bf22 100644
--- a/editor/shader_create_dialog.cpp
+++ b/editor/shader_create_dialog.cpp
@@ -270,7 +270,7 @@ void ShaderCreateDialog::_built_in_toggled(bool p_enabled) {
void ShaderCreateDialog::_browse_path() {
file_browse->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
file_browse->set_title(TTR("Open Shader / Choose Location"));
- file_browse->get_ok_button()->set_text(TTR("Open"));
+ file_browse->set_ok_button_text(TTR("Open"));
file_browse->set_disable_overwrite_warning(true);
file_browse->clear_filters();
@@ -469,20 +469,20 @@ void ShaderCreateDialog::_update_dialog() {
builtin_warning_label->set_visible(is_built_in);
if (is_built_in) {
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
_msg_path_valid(true, TTR("Built-in shader (into scene file)."));
} else if (is_new_shader_created) {
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
if (is_path_valid) {
_msg_path_valid(true, TTR("Will create a new shader file."));
}
} else if (load_enabled) {
- get_ok_button()->set_text(TTR("Load"));
+ set_ok_button_text(TTR("Load"));
if (is_path_valid) {
_msg_path_valid(true, TTR("Will load an existing shader file."));
}
} else {
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
_msg_path_valid(false, TTR("Shader file already exists."));
shader_ok = false;
@@ -638,7 +638,7 @@ ShaderCreateDialog::ShaderCreateDialog() {
alert->get_label()->set_custom_minimum_size(Size2(325, 60) * EDSCALE);
add_child(alert);
- get_ok_button()->set_text(TTR("Create"));
+ set_ok_button_text(TTR("Create"));
set_hide_on_ok(false);
set_title(TTR("Create Shader"));
diff --git a/main/main.cpp b/main/main.cpp
index eb401cd9ef..2bb67f17f1 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2198,6 +2198,13 @@ bool Main::start() {
#endif
}
+ uint64_t minimum_time_msec = GLOBAL_DEF("application/boot_splash/minimum_display_time", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("application/boot_splash/minimum_display_time",
+ PropertyInfo(Variant::INT,
+ "application/boot_splash/minimum_display_time",
+ PROPERTY_HINT_RANGE,
+ "0,100,1,or_greater,suffix:ms")); // No negative numbers.
+
#ifdef TOOLS_ENABLED
if (!doc_tool_path.is_empty()) {
// Needed to instance editor-only classes for their default values
@@ -2718,6 +2725,15 @@ bool Main::start() {
if (movie_writer) {
movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, write_movie_path);
}
+
+ if (minimum_time_msec) {
+ uint64_t minimum_time = 1000 * minimum_time_msec;
+ uint64_t elapsed_time = OS::get_singleton()->get_ticks_usec();
+ if (elapsed_time < minimum_time) {
+ OS::get_singleton()->delay_usec(minimum_time - elapsed_time);
+ }
+ }
+
return true;
}
diff --git a/misc/scripts/install_vulkan_sdk_macos.sh b/misc/scripts/install_vulkan_sdk_macos.sh
new file mode 100755
index 0000000000..e03a907749
--- /dev/null
+++ b/misc/scripts/install_vulkan_sdk_macos.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+IFS=$'\n\t'
+
+# Download and install the Vulkan SDK.
+curl -LO "https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.dmg"
+hdiutil attach vulkan-sdk.dmg -mountpoint /Volumes/vulkan-sdk
+/Volumes/vulkan-sdk/InstallVulkan.app/Contents/MacOS/InstallVulkan \
+ --accept-licenses --default-answer --confirm-command install
+hdiutil detach /Volumes/vulkan-sdk
+
+echo 'Vulkan SDK installed successfully! You can now build Godot by running "scons".'
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 049be47ca8..e995cce651 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -285,16 +285,15 @@
<description>
</description>
</annotation>
- <annotation name="@export_exp_easing">
+ <annotation name="@export_exp_easing" qualifiers="vararg">
<return type="void" />
- <argument index="0" name="hint1" type="String" default="null" />
- <argument index="1" name="hint2" type="String" default="null" />
+ <argument index="0" name="hints" type="String" default="&quot;&quot;" />
<description>
</description>
</annotation>
<annotation name="@export_file" qualifiers="vararg">
<return type="void" />
- <argument index="0" name="filter" type="String" default="null" />
+ <argument index="0" name="filter" type="String" default="&quot;&quot;" />
<description>
</description>
</annotation>
@@ -341,14 +340,14 @@
</annotation>
<annotation name="@export_global_file" qualifiers="vararg">
<return type="void" />
- <argument index="0" name="filter" type="String" default="null" />
+ <argument index="0" name="filter" type="String" default="&quot;&quot;" />
<description>
</description>
</annotation>
<annotation name="@export_group">
<return type="void" />
<argument index="0" name="name" type="String" />
- <argument index="1" name="prefix" type="String" default="null" />
+ <argument index="1" name="prefix" type="String" default="&quot;&quot;" />
<description>
</description>
</annotation>
@@ -359,7 +358,7 @@
</annotation>
<annotation name="@export_node_path" qualifiers="vararg">
<return type="void" />
- <argument index="0" name="type" type="String" default="null" />
+ <argument index="0" name="type" type="String" default="&quot;&quot;" />
<description>
</description>
</annotation>
@@ -368,21 +367,19 @@
<description>
</description>
</annotation>
- <annotation name="@export_range">
+ <annotation name="@export_range" qualifiers="vararg">
<return type="void" />
<argument index="0" name="min" type="float" />
<argument index="1" name="max" type="float" />
- <argument index="2" name="step" type="float" default="null" />
- <argument index="3" name="slider1" type="String" default="null" />
- <argument index="4" name="slider2" type="String" default="null" />
- <argument index="5" name="slider3" type="String" default="null" />
+ <argument index="2" name="step" type="float" default="1.0" />
+ <argument index="3" name="extra_hints" type="String" default="&quot;&quot;" />
<description>
</description>
</annotation>
<annotation name="@export_subgroup">
<return type="void" />
<argument index="0" name="name" type="String" />
- <argument index="1" name="prefix" type="String" default="null" />
+ <argument index="1" name="prefix" type="String" default="&quot;&quot;" />
<description>
</description>
</annotation>
@@ -399,10 +396,10 @@
</annotation>
<annotation name="@rpc" qualifiers="vararg">
<return type="void" />
- <argument index="0" name="mode" type="String" default="null" />
- <argument index="1" name="sync" type="String" default="null" />
- <argument index="2" name="transfer_mode" type="String" default="null" />
- <argument index="3" name="transfer_channel" type="int" default="null" />
+ <argument index="0" name="mode" type="String" default="&quot;&quot;" />
+ <argument index="1" name="sync" type="String" default="&quot;&quot;" />
+ <argument index="2" name="transfer_mode" type="String" default="&quot;&quot;" />
+ <argument index="3" name="transfer_channel" type="int" default="0" />
<description>
</description>
</annotation>
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 233da87aee..6c5d416cf1 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -117,18 +117,18 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation);
// Export annotations.
register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>);
- register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::INT>, 0, true);
- register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, 1, true);
+ register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::INT>, varray(), true);
+ register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, varray(""), true);
register_annotation(MethodInfo("@export_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_DIR, Variant::STRING>);
- register_annotation(MethodInfo("@export_global_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_FILE, Variant::STRING>, 1, true);
+ register_annotation(MethodInfo("@export_global_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_FILE, Variant::STRING>, varray(""), true);
register_annotation(MethodInfo("@export_global_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_DIR, Variant::STRING>);
register_annotation(MethodInfo("@export_multiline"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_MULTILINE_TEXT, Variant::STRING>);
register_annotation(MethodInfo("@export_placeholder"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_PLACEHOLDER_TEXT, Variant::STRING>);
- register_annotation(MethodInfo("@export_range", PropertyInfo(Variant::FLOAT, "min"), PropertyInfo(Variant::FLOAT, "max"), PropertyInfo(Variant::FLOAT, "step"), PropertyInfo(Variant::STRING, "slider1"), PropertyInfo(Variant::STRING, "slider2"), PropertyInfo(Variant::STRING, "slider3")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_RANGE, Variant::FLOAT>, 4);
- register_annotation(MethodInfo("@export_exp_easing", PropertyInfo(Variant::STRING, "hint1"), PropertyInfo(Variant::STRING, "hint2")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_EXP_EASING, Variant::FLOAT>, 2);
+ register_annotation(MethodInfo("@export_range", PropertyInfo(Variant::FLOAT, "min"), PropertyInfo(Variant::FLOAT, "max"), PropertyInfo(Variant::FLOAT, "step"), PropertyInfo(Variant::STRING, "extra_hints")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_RANGE, Variant::FLOAT>, varray(1.0, ""), true);
+ register_annotation(MethodInfo("@export_exp_easing", PropertyInfo(Variant::STRING, "hints")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_EXP_EASING, Variant::FLOAT>, varray(""), true);
register_annotation(MethodInfo("@export_color_no_alpha"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_COLOR_NO_ALPHA, Variant::COLOR>);
- register_annotation(MethodInfo("@export_node_path", PropertyInfo(Variant::STRING, "type")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NODE_PATH_VALID_TYPES, Variant::NODE_PATH>, 1, true);
- register_annotation(MethodInfo("@export_flags", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, 0, true);
+ register_annotation(MethodInfo("@export_node_path", PropertyInfo(Variant::STRING, "type")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NODE_PATH_VALID_TYPES, Variant::NODE_PATH>, varray(""), true);
+ register_annotation(MethodInfo("@export_flags", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, varray(), true);
register_annotation(MethodInfo("@export_flags_2d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_RENDER, Variant::INT>);
register_annotation(MethodInfo("@export_flags_2d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_PHYSICS, Variant::INT>);
register_annotation(MethodInfo("@export_flags_2d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_NAVIGATION, Variant::INT>);
@@ -137,12 +137,12 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>);
// Export grouping annotations.
register_annotation(MethodInfo("@export_category", PropertyInfo(Variant::STRING, "name")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_CATEGORY>);
- register_annotation(MethodInfo("@export_group", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_GROUP>, 1);
- register_annotation(MethodInfo("@export_subgroup", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_SUBGROUP>, 1);
+ register_annotation(MethodInfo("@export_group", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_GROUP>, varray(""));
+ register_annotation(MethodInfo("@export_subgroup", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_SUBGROUP>, varray(""));
// Warning annotations.
- register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, 0, true);
+ register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, varray(), true);
// Networking.
- register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<Multiplayer::RPC_MODE_AUTHORITY>, 4, true);
+ register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<Multiplayer::RPC_MODE_AUTHORITY>, varray("", "", "", 0), true);
}
GDScriptParser::~GDScriptParser() {
@@ -162,6 +162,7 @@ void GDScriptParser::clear() {
for_completion = false;
errors.clear();
multiline_stack.clear();
+ nodes_in_progress.clear();
}
void GDScriptParser::push_error(const String &p_message, const Node *p_origin) {
@@ -413,6 +414,9 @@ GDScriptTokenizer::Token GDScriptParser::advance() {
push_error(current.literal);
current = tokenizer.scan();
}
+ for (Node *n : nodes_in_progress) {
+ update_extents(n);
+ }
return previous;
}
@@ -609,6 +613,7 @@ void GDScriptParser::parse_program() {
}
parse_class_body(true);
+ complete_extents(head);
#ifdef TOOLS_ENABLED
for (const KeyValue<int, GDScriptTokenizer::CommentData> &E : tokenizer.get_comments()) {
@@ -649,6 +654,7 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
if (multiline && !consume(GDScriptTokenizer::Token::INDENT, R"(Expected indented block after class declaration.)")) {
current_class = previous_class;
+ complete_extents(n_class);
return n_class;
}
@@ -661,6 +667,7 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
}
parse_class_body(multiline);
+ complete_extents(n_class);
if (multiline) {
consume(GDScriptTokenizer::Token::DEDENT, R"(Missing unindent at the end of the class body.)");
@@ -870,11 +877,13 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable() {
}
GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_property) {
+ VariableNode *variable = alloc_node<VariableNode>();
+
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected variable name after "var".)")) {
+ complete_extents(variable);
return nullptr;
}
- VariableNode *variable = alloc_node<VariableNode>();
variable->identifier = parse_identifier();
variable->export_info.name = variable->identifier->name;
@@ -882,10 +891,10 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper
if (check(GDScriptTokenizer::Token::NEWLINE)) {
if (p_allow_property) {
advance();
-
return parse_property(variable, true);
} else {
push_error(R"(Expected type after ":")");
+ complete_extents(variable);
return nullptr;
}
} else if (check((GDScriptTokenizer::Token::EQUAL))) {
@@ -924,6 +933,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper
}
}
+ complete_extents(variable);
end_statement("variable declaration");
return variable;
@@ -932,6 +942,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper
GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_variable, bool p_need_indent) {
if (p_need_indent) {
if (!consume(GDScriptTokenizer::Token::INDENT, R"(Expected indented block for property after ":".)")) {
+ complete_extents(p_variable);
return nullptr;
}
}
@@ -941,6 +952,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var
make_completion_context(COMPLETION_PROPERTY_DECLARATION, property);
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected "get" or "set" for property declaration.)")) {
+ complete_extents(p_variable);
return nullptr;
}
@@ -997,6 +1009,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var
}
function = parse_identifier();
}
+ complete_extents(p_variable);
if (p_variable->property == VariableNode::PROP_SETGET) {
end_statement("property declaration");
@@ -1011,37 +1024,37 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var
void GDScriptParser::parse_property_setter(VariableNode *p_variable) {
switch (p_variable->property) {
case VariableNode::PROP_INLINE: {
- consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after "set".)");
- if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected parameter name after "(".)")) {
- p_variable->setter_parameter = parse_identifier();
- }
- consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after parameter name.)*");
- consume(GDScriptTokenizer::Token::COLON, R"*(Expected ":" after ")".)*");
-
+ FunctionNode *function = alloc_node<FunctionNode>();
IdentifierNode *identifier = alloc_node<IdentifierNode>();
+ complete_extents(identifier);
identifier->name = "@" + p_variable->identifier->name + "_setter";
-
- FunctionNode *function = alloc_node<FunctionNode>();
function->identifier = identifier;
- FunctionNode *previous_function = current_function;
- current_function = function;
+ consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after "set".)");
ParameterNode *parameter = alloc_node<ParameterNode>();
- parameter->identifier = p_variable->setter_parameter;
-
- if (parameter->identifier != nullptr) {
+ if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected parameter name after "(".)")) {
+ reset_extents(parameter, previous);
+ p_variable->setter_parameter = parse_identifier();
+ parameter->identifier = p_variable->setter_parameter;
function->parameters_indices[parameter->identifier->name] = 0;
function->parameters.push_back(parameter);
+ }
+ complete_extents(parameter);
+ consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after parameter name.)*");
+ consume(GDScriptTokenizer::Token::COLON, R"*(Expected ":" after ")".)*");
+
+ FunctionNode *previous_function = current_function;
+ current_function = function;
+ if (p_variable->setter_parameter != nullptr) {
SuiteNode *body = alloc_node<SuiteNode>();
body->add_local(parameter, function);
-
function->body = parse_suite("setter declaration", body);
p_variable->setter = function;
}
-
current_function = previous_function;
+ complete_extents(function);
break;
}
case VariableNode::PROP_SETGET:
@@ -1059,12 +1072,13 @@ void GDScriptParser::parse_property_setter(VariableNode *p_variable) {
void GDScriptParser::parse_property_getter(VariableNode *p_variable) {
switch (p_variable->property) {
case VariableNode::PROP_INLINE: {
+ FunctionNode *function = alloc_node<FunctionNode>();
+
consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "get".)");
IdentifierNode *identifier = alloc_node<IdentifierNode>();
+ complete_extents(identifier);
identifier->name = "@" + p_variable->identifier->name + "_getter";
-
- FunctionNode *function = alloc_node<FunctionNode>();
function->identifier = identifier;
FunctionNode *previous_function = current_function;
@@ -1072,9 +1086,10 @@ void GDScriptParser::parse_property_getter(VariableNode *p_variable) {
SuiteNode *body = alloc_node<SuiteNode>();
function->body = parse_suite("getter declaration", body);
-
p_variable->getter = function;
+
current_function = previous_function;
+ complete_extents(function);
break;
}
case VariableNode::PROP_SETGET:
@@ -1090,11 +1105,12 @@ void GDScriptParser::parse_property_getter(VariableNode *p_variable) {
}
GDScriptParser::ConstantNode *GDScriptParser::parse_constant() {
+ ConstantNode *constant = alloc_node<ConstantNode>();
+
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected constant name after "const".)")) {
return nullptr;
}
- ConstantNode *constant = alloc_node<ConstantNode>();
constant->identifier = parse_identifier();
if (match(GDScriptTokenizer::Token::COLON)) {
@@ -1113,12 +1129,15 @@ GDScriptParser::ConstantNode *GDScriptParser::parse_constant() {
if (constant->initializer == nullptr) {
push_error(R"(Expected initializer expression for constant.)");
+ complete_extents(constant);
return nullptr;
}
} else {
+ complete_extents(constant);
return nullptr;
}
+ complete_extents(constant);
end_statement("constant declaration");
return constant;
@@ -1148,15 +1167,18 @@ GDScriptParser::ParameterNode *GDScriptParser::parse_parameter() {
parameter->default_value = parse_expression(false);
}
+ complete_extents(parameter);
return parameter;
}
GDScriptParser::SignalNode *GDScriptParser::parse_signal() {
+ SignalNode *signal = alloc_node<SignalNode>();
+
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected signal name after "signal".)")) {
+ complete_extents(signal);
return nullptr;
}
- SignalNode *signal = alloc_node<SignalNode>();
signal->identifier = parse_identifier();
if (check(GDScriptTokenizer::Token::PARENTHESIS_OPEN)) {
@@ -1188,6 +1210,7 @@ GDScriptParser::SignalNode *GDScriptParser::parse_signal() {
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected closing ")" after signal parameters.)*");
}
+ complete_extents(signal);
end_statement("signal declaration");
return signal;
@@ -1299,6 +1322,7 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() {
}
#endif // TOOLS_ENABLED
+ complete_extents(enum_node);
end_statement("enum");
return enum_node;
@@ -1350,19 +1374,22 @@ void GDScriptParser::parse_function_signature(FunctionNode *p_function, SuiteNod
}
GDScriptParser::FunctionNode *GDScriptParser::parse_function() {
+ FunctionNode *function = alloc_node<FunctionNode>();
+
bool _static = false;
if (previous.type == GDScriptTokenizer::Token::STATIC) {
// TODO: Improve message if user uses "static" with "var" or "const"
if (!consume(GDScriptTokenizer::Token::FUNC, R"(Expected "func" after "static".)")) {
+ complete_extents(function);
return nullptr;
}
_static = true;
}
- FunctionNode *function = alloc_node<FunctionNode>();
make_completion_context(COMPLETION_OVERRIDE_METHOD, function);
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected function name after "func".)")) {
+ complete_extents(function);
return nullptr;
}
@@ -1384,6 +1411,7 @@ GDScriptParser::FunctionNode *GDScriptParser::parse_function() {
function->body = parse_suite("function declaration", body);
current_function = previous_function;
+ complete_extents(function);
return function;
}
@@ -1431,6 +1459,7 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali
}
pop_completion_call();
}
+ complete_extents(annotation);
match(GDScriptTokenizer::Token::NEWLINE); // Newline after annotation is optional.
@@ -1449,12 +1478,12 @@ void GDScriptParser::clear_unused_annotations() {
annotation_stack.clear();
}
-bool GDScriptParser::register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, int p_optional_arguments, bool p_is_vararg) {
+bool GDScriptParser::register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments, bool p_is_vararg) {
ERR_FAIL_COND_V_MSG(valid_annotations.has(p_info.name), false, vformat(R"(Annotation "%s" already registered.)", p_info.name));
AnnotationInfo new_annotation;
new_annotation.info = p_info;
- new_annotation.info.default_arguments.resize(p_optional_arguments);
+ new_annotation.info.default_arguments = p_default_arguments;
if (p_is_vararg) {
new_annotation.info.flags |= METHOD_FLAG_VARARG;
}
@@ -1480,9 +1509,11 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
if (multiline) {
if (!consume(GDScriptTokenizer::Token::INDENT, vformat(R"(Expected indented block after %s.)", p_context))) {
current_suite = suite->parent_block;
+ complete_extents(suite);
return suite;
}
}
+ reset_extents(suite, current);
int error_count = 0;
@@ -1532,6 +1563,8 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
} while ((multiline || previous.type == GDScriptTokenizer::Token::SEMICOLON) && !check(GDScriptTokenizer::Token::DEDENT) && !lambda_ended && !is_at_end());
+ complete_extents(suite);
+
if (multiline) {
if (!lambda_ended) {
consume(GDScriptTokenizer::Token::DEDENT, vformat(R"(Missing unindent at the end of %s.)", p_context));
@@ -1562,6 +1595,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
case GDScriptTokenizer::Token::PASS:
advance();
result = alloc_node<PassNode>();
+ complete_extents(result);
end_statement(R"("pass")");
break;
case GDScriptTokenizer::Token::VAR:
@@ -1609,6 +1643,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
// If this fails the expression will be nullptr, but that's the same as no return, so it's fine.
n_return->return_value = parse_expression(false);
}
+ complete_extents(n_return);
result = n_return;
current_suite->has_return = true;
@@ -1619,6 +1654,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
case GDScriptTokenizer::Token::BREAKPOINT:
advance();
result = alloc_node<BreakpointNode>();
+ complete_extents(result);
end_statement(R"("breakpoint")");
break;
case GDScriptTokenizer::Token::ASSERT:
@@ -1644,10 +1680,12 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
lambda_ended = true;
has_ended_lambda = true;
} else {
+ advance();
push_error(vformat(R"(Expected statement, found "%s" instead.)", previous.get_name()));
}
+ } else {
+ end_statement("expression");
}
- end_statement("expression");
lambda_ended = lambda_ended || has_ended_lambda;
result = expression;
@@ -1710,6 +1748,7 @@ GDScriptParser::AssertNode *GDScriptParser::parse_assert() {
assert->condition = parse_expression(false);
if (assert->condition == nullptr) {
push_error("Expected expression to assert.");
+ complete_extents(assert);
return nullptr;
}
@@ -1718,12 +1757,14 @@ GDScriptParser::AssertNode *GDScriptParser::parse_assert() {
assert->message = parse_expression(false);
if (assert->message == nullptr) {
push_error(R"(Expected error message for assert after ",".)");
+ complete_extents(assert);
return nullptr;
}
}
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after assert expression.)*");
+ complete_extents(assert);
end_statement(R"("assert")");
return assert;
@@ -1733,8 +1774,10 @@ GDScriptParser::BreakNode *GDScriptParser::parse_break() {
if (!can_break) {
push_error(R"(Cannot use "break" outside of a loop.)");
}
+ BreakNode *break_node = alloc_node<BreakNode>();
+ complete_extents(break_node);
end_statement(R"("break")");
- return alloc_node<BreakNode>();
+ return break_node;
}
GDScriptParser::ContinueNode *GDScriptParser::parse_continue() {
@@ -1742,9 +1785,10 @@ GDScriptParser::ContinueNode *GDScriptParser::parse_continue() {
push_error(R"(Cannot use "continue" outside of a loop or pattern matching block.)");
}
current_suite->has_continue = true;
- end_statement(R"("continue")");
ContinueNode *cont = alloc_node<ContinueNode>();
cont->is_for_match = is_continue_match;
+ complete_extents(cont);
+ end_statement(R"("continue")");
return cont;
}
@@ -1786,6 +1830,7 @@ GDScriptParser::ForNode *GDScriptParser::parse_for() {
suite->parent_for = n_for;
n_for->loop = parse_suite(R"("for" block)", suite);
+ complete_extents(n_for);
// Reset break/continue state.
can_break = could_break;
@@ -1813,15 +1858,16 @@ GDScriptParser::IfNode *GDScriptParser::parse_if(const String &p_token) {
}
if (match(GDScriptTokenizer::Token::ELIF)) {
- IfNode *elif = parse_if("elif");
-
SuiteNode *else_block = alloc_node<SuiteNode>();
+ IfNode *elif = parse_if("elif");
else_block->statements.push_back(elif);
+ complete_extents(else_block);
n_if->false_block = else_block;
} else if (match(GDScriptTokenizer::Token::ELSE)) {
consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "else".)");
n_if->false_block = parse_suite(R"("else" block)");
}
+ complete_extents(n_if);
if (n_if->false_block != nullptr && n_if->false_block->has_return && n_if->true_block->has_return) {
current_suite->has_return = true;
@@ -1845,6 +1891,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
consume(GDScriptTokenizer::Token::NEWLINE, R"(Expected a newline after "match" statement.)");
if (!consume(GDScriptTokenizer::Token::INDENT, R"(Expected an indented block after "match" statement.)")) {
+ complete_extents(match);
return match;
}
@@ -1862,7 +1909,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
}
#ifdef DEBUG_ENABLED
- if (have_wildcard_without_continue) {
+ if (have_wildcard_without_continue && !branch->patterns.is_empty()) {
push_warning(branch->patterns[0], GDScriptWarning::UNREACHABLE_PATTERN);
}
@@ -1878,6 +1925,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
#endif
match->branches.push_back(branch);
}
+ complete_extents(match);
consume(GDScriptTokenizer::Token::DEDENT, R"(Expected an indented block after "match" statement.)");
@@ -1892,6 +1940,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
MatchBranchNode *branch = alloc_node<MatchBranchNode>();
+ reset_extents(branch, current);
bool has_bind = false;
@@ -1919,6 +1968,7 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
}
if (!consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "match" patterns.)")) {
+ complete_extents(branch);
return nullptr;
}
@@ -1939,6 +1989,7 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
}
branch->block = parse_suite("match pattern block", suite);
+ complete_extents(branch);
// Restore continue state.
can_continue = could_continue;
@@ -1949,12 +2000,14 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_root_pattern) {
PatternNode *pattern = alloc_node<PatternNode>();
+ reset_extents(pattern, current);
switch (current.type) {
case GDScriptTokenizer::Token::VAR: {
// Bind.
advance();
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected bind name after "var".)")) {
+ complete_extents(pattern);
return nullptr;
}
pattern->pattern_type = PatternNode::PT_BIND;
@@ -1965,12 +2018,14 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
if (p_root_pattern != nullptr) {
if (p_root_pattern->has_bind(pattern->bind->name)) {
push_error(vformat(R"(Bind variable name "%s" was already used in this pattern.)", pattern->bind->name));
+ complete_extents(pattern);
return nullptr;
}
}
if (current_suite->has_local(pattern->bind->name)) {
push_error(vformat(R"(There's already a %s named "%s" in this scope.)", current_suite->get_local(pattern->bind->name).get_name(), pattern->bind->name));
+ complete_extents(pattern);
return nullptr;
}
@@ -2023,6 +2078,7 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
push_error(R"(The ".." pattern must be the last element in the pattern dictionary.)");
} else {
PatternNode *sub_pattern = alloc_node<PatternNode>();
+ complete_extents(sub_pattern);
sub_pattern->pattern_type = PatternNode::PT_REST;
pattern->dictionary.push_back({ nullptr, sub_pattern });
pattern->rest_used = true;
@@ -2071,6 +2127,7 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
break;
}
}
+ complete_extents(pattern);
return pattern;
}
@@ -2104,6 +2161,7 @@ GDScriptParser::WhileNode *GDScriptParser::parse_while() {
is_continue_match = false;
n_while->loop = parse_suite(R"("while" block)");
+ complete_extents(n_while);
// Reset break/continue state.
can_break = could_break;
@@ -2176,6 +2234,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_identifier(ExpressionNode
ERR_FAIL_V_MSG(nullptr, "Parser bug: parsing literal node without literal token.");
}
IdentifierNode *identifier = alloc_node<IdentifierNode>();
+ complete_extents(identifier);
identifier->name = previous.get_identifier();
if (current_suite != nullptr && current_suite->has_local(identifier->name)) {
@@ -2227,6 +2286,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_literal(ExpressionNode *p_
}
LiteralNode *literal = alloc_node<LiteralNode>();
+ complete_extents(literal);
literal->value = previous.literal;
return literal;
}
@@ -2236,6 +2296,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_self(ExpressionNode *p_pre
push_error(R"(Cannot use "self" inside a static function.)");
}
SelfNode *self = alloc_node<SelfNode>();
+ complete_extents(self);
self->current_class = current_class;
return self;
}
@@ -2243,6 +2304,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_self(ExpressionNode *p_pre
GDScriptParser::ExpressionNode *GDScriptParser::parse_builtin_constant(ExpressionNode *p_previous_operand, bool p_can_assign) {
GDScriptTokenizer::Token::Type op_type = previous.type;
LiteralNode *constant = alloc_node<LiteralNode>();
+ complete_extents(constant);
switch (op_type) {
case GDScriptTokenizer::Token::CONST_PI:
@@ -2303,30 +2365,38 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_unary_operator(ExpressionN
}
break;
default:
+ complete_extents(operation);
return nullptr; // Unreachable.
}
+ complete_extents(operation);
return operation;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_not_in_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
// check that NOT is followed by IN by consuming it before calling parse_binary_operator which will only receive a plain IN
+ UnaryOpNode *operation = alloc_node<UnaryOpNode>();
+ reset_extents(operation, p_previous_operand);
+ update_extents(operation);
consume(GDScriptTokenizer::Token::IN, R"(Expected "in" after "not" in content-test operator.)");
ExpressionNode *in_operation = parse_binary_operator(p_previous_operand, p_can_assign);
- UnaryOpNode *operation = alloc_node<UnaryOpNode>();
operation->operation = UnaryOpNode::OP_LOGIC_NOT;
operation->variant_op = Variant::OP_NOT;
operation->operand = in_operation;
+ complete_extents(operation);
return operation;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
GDScriptTokenizer::Token op = previous;
BinaryOpNode *operation = alloc_node<BinaryOpNode>();
+ reset_extents(operation, p_previous_operand);
+ update_extents(operation);
Precedence precedence = (Precedence)(get_rule(op.type)->precedence + 1);
operation->left_operand = p_previous_operand;
operation->right_operand = parse_precedence(precedence, false);
+ complete_extents(operation);
if (operation->right_operand == nullptr) {
push_error(vformat(R"(Expected expression after "%s" operator.")", op.get_name()));
@@ -2429,8 +2499,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(Expression
GDScriptParser::ExpressionNode *GDScriptParser::parse_ternary_operator(ExpressionNode *p_previous_operand, bool p_can_assign) {
// Only one ternary operation exists, so no abstraction here.
TernaryOpNode *operation = alloc_node<TernaryOpNode>();
- operation->true_expr = p_previous_operand;
+ reset_extents(operation, p_previous_operand);
+ update_extents(operation);
+ operation->true_expr = p_previous_operand;
operation->condition = parse_precedence(PREC_TERNARY, false);
if (operation->condition == nullptr) {
@@ -2445,6 +2517,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_ternary_operator(Expressio
push_error(R"(Expected expression after "else".)");
}
+ complete_extents(operation);
return operation;
}
@@ -2497,6 +2570,9 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode
}
AssignmentNode *assignment = alloc_node<AssignmentNode>();
+ reset_extents(assignment, p_previous_operand);
+ update_extents(assignment);
+
make_completion_context(COMPLETION_ASSIGN, assignment);
#ifdef DEBUG_ENABLED
bool has_operator = true;
@@ -2561,6 +2637,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode
if (assignment->assigned_value == nullptr) {
push_error(R"(Expected an expression after "=".)");
}
+ complete_extents(assignment);
#ifdef DEBUG_ENABLED
if (source_variable != nullptr) {
@@ -2582,6 +2659,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_await(ExpressionNode *p_pr
push_error(R"(Expected signal or coroutine after "await".)");
}
await->to_await = element;
+ complete_extents(await);
if (current_function) { // Might be null in a getter or setter.
current_function->is_coroutine = true;
@@ -2610,6 +2688,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_array(ExpressionNode *p_pr
}
pop_multiline();
consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected closing "]" after array elements.)");
+ complete_extents(array);
return array;
}
@@ -2701,6 +2780,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode
}
pop_multiline();
consume(GDScriptTokenizer::Token::BRACE_CLOSE, R"(Expected closing "}" after dictionary elements.)");
+ complete_extents(dictionary);
return dictionary;
}
@@ -2718,6 +2798,8 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_grouping(ExpressionNode *p
GDScriptParser::ExpressionNode *GDScriptParser::parse_attribute(ExpressionNode *p_previous_operand, bool p_can_assign) {
SubscriptNode *attribute = alloc_node<SubscriptNode>();
+ reset_extents(attribute, p_previous_operand);
+ update_extents(attribute);
if (for_completion) {
bool is_builtin = false;
@@ -2737,17 +2819,21 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_attribute(ExpressionNode *
attribute->base = p_previous_operand;
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier after "." for attribute access.)")) {
+ complete_extents(attribute);
return attribute;
}
attribute->is_attribute = true;
attribute->attribute = parse_identifier();
+ complete_extents(attribute);
return attribute;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_subscript(ExpressionNode *p_previous_operand, bool p_can_assign) {
SubscriptNode *subscript = alloc_node<SubscriptNode>();
+ reset_extents(subscript, p_previous_operand);
+ update_extents(subscript);
make_completion_context(COMPLETION_SUBSCRIPT, subscript);
@@ -2760,15 +2846,19 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_subscript(ExpressionNode *
pop_multiline();
consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected "]" after subscription index.)");
+ complete_extents(subscript);
return subscript;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_cast(ExpressionNode *p_previous_operand, bool p_can_assign) {
CastNode *cast = alloc_node<CastNode>();
+ reset_extents(cast, p_previous_operand);
+ update_extents(cast);
cast->operand = p_previous_operand;
cast->cast_type = parse_type();
+ complete_extents(cast);
if (cast->cast_type == nullptr) {
push_error(R"(Expected type specifier after "as".)");
@@ -2780,6 +2870,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_cast(ExpressionNode *p_pre
GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_previous_operand, bool p_can_assign) {
CallNode *call = alloc_node<CallNode>();
+ reset_extents(call, p_previous_operand);
if (previous.type == GDScriptTokenizer::Token::SUPER) {
// Super call.
@@ -2790,6 +2881,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
if (current_function == nullptr) {
push_error(R"(Cannot use implicit "super" call outside of a function.)");
pop_multiline();
+ complete_extents(call);
return nullptr;
}
if (current_function->identifier) {
@@ -2802,6 +2894,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
make_completion_context(COMPLETION_SUPER_METHOD, call, true);
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected function name after ".".)")) {
pop_multiline();
+ complete_extents(call);
return nullptr;
}
IdentifierNode *identifier = parse_identifier();
@@ -2858,6 +2951,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
pop_multiline();
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected closing ")" after call arguments.)*");
+ complete_extents(call);
return call;
}
@@ -2901,6 +2995,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
if (previous.type == GDScriptTokenizer::Token::PERCENT) {
if (path_state != PATH_STATE_START && path_state != PATH_STATE_SLASH) {
push_error(R"("%" is only valid in the beginning of a node name (either after "$" or after "/"))");
+ complete_extents(get_node);
return nullptr;
}
get_node->full_path += "%";
@@ -2909,6 +3004,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
} else if (previous.type == GDScriptTokenizer::Token::SLASH) {
if (path_state != PATH_STATE_START && path_state != PATH_STATE_NODE_NAME) {
push_error(R"("/" is only valid at the beginning of the path or after a node name.)");
+ complete_extents(get_node);
return nullptr;
}
@@ -2936,6 +3032,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
break;
}
push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous_token));
+ complete_extents(get_node);
return nullptr;
}
@@ -2949,10 +3046,12 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
path_state = PATH_STATE_NODE_NAME;
} else if (!check(GDScriptTokenizer::Token::SLASH) && !check(GDScriptTokenizer::Token::PERCENT)) {
push_error(vformat(R"(Unexpected "%s" in node path.)", current.get_name()));
+ complete_extents(get_node);
return nullptr;
}
} while (match(GDScriptTokenizer::Token::SLASH) || match(GDScriptTokenizer::Token::PERCENT));
+ complete_extents(get_node);
return get_node;
}
@@ -2976,6 +3075,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_preload(ExpressionNode *p_
pop_multiline();
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after preload path.)*");
+ complete_extents(preload);
return preload;
}
@@ -3025,6 +3125,8 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_lambda(ExpressionNode *p_p
in_lambda = true;
function->body = parse_suite("lambda declaration", body, true);
+ complete_extents(function);
+ complete_extents(lambda);
pop_multiline();
@@ -3069,13 +3171,15 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) {
if (!match(GDScriptTokenizer::Token::IDENTIFIER)) {
if (match(GDScriptTokenizer::Token::VOID)) {
if (p_allow_void) {
- TypeNode *void_type = alloc_node<TypeNode>();
+ complete_extents(type);
+ TypeNode *void_type = type;
return void_type;
} else {
push_error(R"("void" is only allowed for a function return type.)");
}
}
// Leave error message to the caller who knows the context.
+ complete_extents(type);
return nullptr;
}
@@ -3088,11 +3192,15 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) {
type->container_type = parse_type(false); // Don't allow void for array element type.
if (type->container_type == nullptr) {
push_error(R"(Expected type for collection after "[".)");
+ complete_extents(type);
type = nullptr;
} else if (type->container_type->container_type != nullptr) {
push_error("Nested typed collections are not supported.");
}
consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected closing "]" after collection type.)");
+ if (type != nullptr) {
+ complete_extents(type);
+ }
return type;
}
@@ -3105,6 +3213,7 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) {
}
}
+ complete_extents(type);
return type;
}
@@ -3922,6 +4031,46 @@ GDScriptParser::DataType GDScriptParser::DataType::get_typed_container_type() co
return type;
}
+void GDScriptParser::complete_extents(Node *p_node) {
+ while (!nodes_in_progress.is_empty() && nodes_in_progress.back()->get() != p_node) {
+ ERR_PRINT("Parser bug: Mismatch in extents tracking stack.");
+ nodes_in_progress.pop_back();
+ }
+ if (nodes_in_progress.is_empty()) {
+ ERR_PRINT("Parser bug: Extents tracking stack is empty.");
+ } else {
+ nodes_in_progress.pop_back();
+ }
+}
+
+void GDScriptParser::update_extents(Node *p_node) {
+ p_node->end_line = previous.end_line;
+ p_node->end_column = previous.end_column;
+ p_node->leftmost_column = MIN(p_node->leftmost_column, previous.leftmost_column);
+ p_node->rightmost_column = MAX(p_node->rightmost_column, previous.rightmost_column);
+}
+
+void GDScriptParser::reset_extents(Node *p_node, GDScriptTokenizer::Token p_token) {
+ p_node->start_line = p_token.start_line;
+ p_node->end_line = p_token.end_line;
+ p_node->start_column = p_token.start_column;
+ p_node->end_column = p_token.end_column;
+ p_node->leftmost_column = p_token.leftmost_column;
+ p_node->rightmost_column = p_token.rightmost_column;
+}
+
+void GDScriptParser::reset_extents(Node *p_node, Node *p_from) {
+ if (p_from == nullptr) {
+ return;
+ }
+ p_node->start_line = p_from->start_line;
+ p_node->end_line = p_from->end_line;
+ p_node->start_column = p_from->start_column;
+ p_node->end_column = p_from->end_column;
+ p_node->leftmost_column = p_from->leftmost_column;
+ p_node->rightmost_column = p_from->rightmost_column;
+}
+
/*---------- PRETTY PRINT FOR DEBUG ----------*/
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 8d3295f25b..9c97f98fbc 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -1301,6 +1301,12 @@ private:
};
static ParseRule *get_rule(GDScriptTokenizer::Token::Type p_token_type);
+ List<Node *> nodes_in_progress;
+ void complete_extents(Node *p_node);
+ void update_extents(Node *p_node);
+ void reset_extents(Node *p_node, GDScriptTokenizer::Token p_token);
+ void reset_extents(Node *p_node, Node *p_from);
+
template <class T>
T *alloc_node() {
T *node = memnew(T);
@@ -1308,13 +1314,8 @@ private:
node->next = list;
list = node;
- // TODO: Properly set positions for all nodes.
- node->start_line = previous.start_line;
- node->end_line = previous.end_line;
- node->start_column = previous.start_column;
- node->end_column = previous.end_column;
- node->leftmost_column = previous.leftmost_column;
- node->rightmost_column = previous.rightmost_column;
+ reset_extents(node, previous);
+ nodes_in_progress.push_back(node);
return node;
}
@@ -1359,7 +1360,7 @@ private:
SuiteNode *parse_suite(const String &p_context, SuiteNode *p_suite = nullptr, bool p_for_lambda = false);
// Annotations
AnnotationNode *parse_annotation(uint32_t p_valid_targets);
- bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, int p_optional_arguments = 0, bool p_is_vararg = false);
+ bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments = Vector<Variant>(), bool p_is_vararg = false);
bool validate_annotation_arguments(AnnotationNode *p_annotation);
void clear_unused_annotations();
bool tool_annotation(const AnnotationNode *p_annotation, Node *p_target);
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index 676862ea5a..033591a0b9 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -449,8 +449,8 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() {
EditorNode::get_singleton()->get_gui_base()->add_child(configure_blender_dialog);
- configure_blender_dialog->get_ok_button()->set_text(TTR("Confirm Path"));
- configure_blender_dialog->get_cancel_button()->set_text(TTR("Disable '.blend' Import"));
+ configure_blender_dialog->set_ok_button_text(TTR("Confirm Path"));
+ configure_blender_dialog->set_cancel_button_text(TTR("Disable '.blend' Import"));
configure_blender_dialog->get_cancel_button()->set_tooltip(TTR("Disables Blender '.blend' files import for this project. Can be re-enabled in Project Settings."));
configure_blender_dialog->connect("confirmed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_path_confirmed));
diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp
index ceea0eaf1d..d9419292ba 100644
--- a/modules/visual_script/editor/visual_script_editor.cpp
+++ b/modules/visual_script/editor/visual_script_editor.cpp
@@ -4717,7 +4717,7 @@ VisualScriptEditor::VisualScriptEditor() {
function_create_dialog = memnew(ConfirmationDialog);
function_create_dialog->set_title(TTR("Create Function"));
function_create_dialog->add_child(function_vb);
- function_create_dialog->get_ok_button()->set_text(TTR("Create"));
+ function_create_dialog->set_ok_button_text(TTR("Create"));
function_create_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualScriptEditor::_create_function));
add_child(function_create_dialog);
@@ -4761,7 +4761,7 @@ VisualScriptEditor::VisualScriptEditor() {
graph->connect("connection_to_empty", callable_mp(this, &VisualScriptEditor::_graph_connect_to_empty));
edit_signal_dialog = memnew(AcceptDialog);
- edit_signal_dialog->get_ok_button()->set_text(TTR("Close"));
+ edit_signal_dialog->set_ok_button_text(TTR("Close"));
add_child(edit_signal_dialog);
signal_editor = memnew(VisualScriptEditorSignalEdit);
@@ -4771,7 +4771,7 @@ VisualScriptEditor::VisualScriptEditor() {
edit_signal_edit->edit(signal_editor);
edit_variable_dialog = memnew(AcceptDialog);
- edit_variable_dialog->get_ok_button()->set_text(TTR("Close"));
+ edit_variable_dialog->set_ok_button_text(TTR("Close"));
add_child(edit_variable_dialog);
variable_editor = memnew(VisualScriptEditorVariableEdit);
diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp
index ae30655301..f98ce5bb26 100644
--- a/modules/visual_script/editor/visual_script_property_selector.cpp
+++ b/modules/visual_script/editor/visual_script_property_selector.cpp
@@ -533,7 +533,7 @@ VisualScriptPropertySelector::VisualScriptPropertySelector() {
scroller->add_child(help_bit);
help_bit->connect("request_hide", callable_mp(this, &VisualScriptPropertySelector::_hide_requested));
- get_ok_button()->set_text(TTR("Open"));
+ set_ok_button_text(TTR("Open"));
get_ok_button()->set_disabled(true);
set_hide_on_ok(false);
}
diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm
index 573ee9b7a8..28ffc9595e 100644
--- a/platform/iphone/display_server_iphone.mm
+++ b/platform/iphone/display_server_iphone.mm
@@ -195,6 +195,7 @@ void DisplayServerIPhone::window_set_drop_files_callback(const Callable &p_calla
}
void DisplayServerIPhone::process_events() {
+ Input::get_singleton()->flush_buffered_events();
}
void DisplayServerIPhone::_dispatch_input_events(const Ref<InputEvent> &p_event) {
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index e66fa142a7..91e0fbe0dc 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -2382,7 +2382,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
case WM_MOUSELEAVE: {
old_invalid = true;
- outside = true;
+ windows[window_id].mouse_outside = true;
_send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT);
@@ -2612,7 +2612,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- if (outside) {
+ if (windows[window_id].mouse_outside) {
// Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
@@ -2622,7 +2622,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
CursorShape c = cursor_shape;
cursor_shape = CURSOR_MAX;
cursor_set_shape(c);
- outside = false;
+ windows[window_id].mouse_outside = false;
// Once-off notification, must call again.
track_mouse_leave_event(hWnd);
@@ -2713,7 +2713,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- if (outside) {
+ if (windows[window_id].mouse_outside) {
// Mouse enter.
if (mouse_mode != MOUSE_MODE_CAPTURED) {
@@ -2723,7 +2723,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
CursorShape c = cursor_shape;
cursor_shape = CURSOR_MAX;
cursor_set_shape(c);
- outside = false;
+ windows[window_id].mouse_outside = false;
// Once-off notification, must call again.
track_mouse_leave_event(hWnd);
@@ -3608,8 +3608,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
old_invalid = true;
mouse_mode = MOUSE_MODE_VISIBLE;
- outside = true;
-
rendering_driver = p_rendering_driver;
// Init TTS
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 0429bed3a0..ddbf674c64 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -313,7 +313,6 @@ class DisplayServerWindows : public DisplayServer {
int key_event_pos;
bool old_invalid;
- bool outside;
int old_x, old_y;
Point2i center;
@@ -387,6 +386,7 @@ class DisplayServerWindows : public DisplayServer {
Size2 window_rect;
Point2 last_pos;
+ bool mouse_outside = true;
ObjectID instance_id;
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index a2b05ee50d..44e2bb89eb 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -161,6 +161,14 @@ bool AcceptDialog::has_autowrap() {
return label->get_autowrap_mode() != TextServer::AUTOWRAP_OFF;
}
+void AcceptDialog::set_ok_button_text(String p_ok_button_text) {
+ ok->set_text(p_ok_button_text);
+}
+
+String AcceptDialog::get_ok_button_text() const {
+ return ok->get_text();
+}
+
void AcceptDialog::register_text_enter(Control *p_line_edit) {
ERR_FAIL_NULL(p_line_edit);
LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit);
@@ -262,7 +270,7 @@ Button *AcceptDialog::add_button(const String &p_text, bool p_right, const Strin
Button *AcceptDialog::add_cancel_button(const String &p_cancel) {
String c = p_cancel;
if (p_cancel.is_empty()) {
- c = RTR("Cancel");
+ c = "Cancel";
}
Button *b = swap_cancel_ok ? add_button(c, true) : add_button(c);
b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
@@ -306,11 +314,15 @@ void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text"), &AcceptDialog::get_text);
ClassDB::bind_method(D_METHOD("set_autowrap", "autowrap"), &AcceptDialog::set_autowrap);
ClassDB::bind_method(D_METHOD("has_autowrap"), &AcceptDialog::has_autowrap);
+ ClassDB::bind_method(D_METHOD("set_ok_button_text", "text"), &AcceptDialog::set_ok_button_text);
+ ClassDB::bind_method(D_METHOD("get_ok_button_text"), &AcceptDialog::get_ok_button_text);
ADD_SIGNAL(MethodInfo("confirmed"));
ADD_SIGNAL(MethodInfo("cancelled"));
ADD_SIGNAL(MethodInfo("custom_action", PropertyInfo(Variant::STRING_NAME, "action")));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "ok_button_text"), "set_ok_button_text", "get_ok_button_text");
+
ADD_GROUP("Dialog", "dialog");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "dialog_text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"), "set_hide_on_ok", "get_hide_on_ok");
@@ -349,7 +361,7 @@ AcceptDialog::AcceptDialog() {
hbc->add_spacer();
ok = memnew(Button);
- ok->set_text(RTR("OK"));
+ ok->set_text("OK");
hbc->add_child(ok);
hbc->add_spacer();
@@ -365,8 +377,20 @@ AcceptDialog::~AcceptDialog() {
// ConfirmationDialog
+void ConfirmationDialog::set_cancel_button_text(String p_cancel_button_text) {
+ cancel->set_text(p_cancel_button_text);
+}
+
+String ConfirmationDialog::get_cancel_button_text() const {
+ return cancel->get_text();
+}
+
void ConfirmationDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cancel_button"), &ConfirmationDialog::get_cancel_button);
+ ClassDB::bind_method(D_METHOD("set_cancel_button_text"), &ConfirmationDialog::set_cancel_button_text);
+ ClassDB::bind_method(D_METHOD("get_cancel_button_text"), &ConfirmationDialog::get_cancel_button_text);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "cancel_button_text"), "set_cancel_button_text", "get_cancel_button_text");
}
Button *ConfirmationDialog::get_cancel_button() {
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index 41fd9c0a10..711361de88 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -97,6 +97,9 @@ public:
void set_autowrap(bool p_autowrap);
bool has_autowrap();
+ void set_ok_button_text(String p_ok_button_text);
+ String get_ok_button_text() const;
+
AcceptDialog();
~AcceptDialog();
};
@@ -110,6 +113,10 @@ protected:
public:
Button *get_cancel_button();
+
+ void set_cancel_button_text(String p_cancel_button_text);
+ String get_cancel_button_text() const;
+
ConfirmationDialog();
};
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 6bb4ac9c6f..8ec930b753 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -419,10 +419,10 @@ void FileDialog::deselect_all() {
switch (mode) {
case FILE_MODE_OPEN_FILE:
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(RTR("Open"));
+ set_ok_button_text(RTR("Open"));
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(RTR("Select Current Folder"));
+ set_ok_button_text(RTR("Select Current Folder"));
break;
case FILE_MODE_OPEN_ANY:
case FILE_MODE_SAVE_FILE:
@@ -446,7 +446,7 @@ void FileDialog::_tree_selected() {
if (!d["dir"]) {
file->set_text(d["name"]);
} else if (mode == FILE_MODE_OPEN_DIR) {
- get_ok_button()->set_text(RTR("Select This Folder"));
+ set_ok_button_text(RTR("Select This Folder"));
}
get_ok_button()->set_disabled(_is_open_should_be_disabled());
@@ -673,9 +673,13 @@ void FileDialog::clear_filters() {
invalidate();
}
-void FileDialog::add_filter(const String &p_filter) {
+void FileDialog::add_filter(const String &p_filter, const String &p_description) {
ERR_FAIL_COND_MSG(p_filter.begins_with("."), "Filter must be \"filename.extension\", can't start with dot.");
- filters.push_back(p_filter);
+ if (p_description.is_empty()) {
+ filters.push_back(p_filter);
+ } else {
+ filters.push_back(vformat("%s ; %s", p_filter, p_description));
+ }
update_filters();
invalidate();
}
@@ -764,35 +768,35 @@ void FileDialog::set_file_mode(FileMode p_mode) {
mode = p_mode;
switch (mode) {
case FILE_MODE_OPEN_FILE:
- get_ok_button()->set_text(RTR("Open"));
+ set_ok_button_text(RTR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open a File"));
}
makedir->hide();
break;
case FILE_MODE_OPEN_FILES:
- get_ok_button()->set_text(RTR("Open"));
+ set_ok_button_text(RTR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open File(s)"));
}
makedir->hide();
break;
case FILE_MODE_OPEN_DIR:
- get_ok_button()->set_text(RTR("Select Current Folder"));
+ set_ok_button_text(RTR("Select Current Folder"));
if (mode_overrides_title) {
set_title(TTRC("Open a Directory"));
}
makedir->show();
break;
case FILE_MODE_OPEN_ANY:
- get_ok_button()->set_text(RTR("Open"));
+ set_ok_button_text(RTR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open a File or Directory"));
}
makedir->show();
break;
case FILE_MODE_SAVE_FILE:
- get_ok_button()->set_text(RTR("Save"));
+ set_ok_button_text(RTR("Save"));
if (mode_overrides_title) {
set_title(TTRC("Save a File"));
}
@@ -919,7 +923,7 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_cancel_pressed"), &FileDialog::_cancel_pressed);
ClassDB::bind_method(D_METHOD("clear_filters"), &FileDialog::clear_filters);
- ClassDB::bind_method(D_METHOD("add_filter", "filter"), &FileDialog::add_filter);
+ ClassDB::bind_method(D_METHOD("add_filter", "filter", "description"), &FileDialog::add_filter, DEFVAL(""));
ClassDB::bind_method(D_METHOD("set_filters", "filters"), &FileDialog::set_filters);
ClassDB::bind_method(D_METHOD("get_filters"), &FileDialog::get_filters);
ClassDB::bind_method(D_METHOD("get_current_dir"), &FileDialog::get_current_dir);
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 8b8d93920c..017c9d8d4f 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -151,7 +151,7 @@ protected:
public:
void popup_file_dialog();
void clear_filters();
- void add_filter(const String &p_filter);
+ void add_filter(const String &p_filter, const String &p_description = "");
void set_filters(const Vector<String> &p_filters);
Vector<String> get_filters() const;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 05824d54f1..f5ff274683 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -149,7 +149,12 @@ RichTextLabel::Item *RichTextLabel::_get_item_at_pos(RichTextLabel::Item *p_item
return it;
}
} break;
- case ITEM_NEWLINE:
+ case ITEM_NEWLINE: {
+ offset += 1;
+ if (offset == p_position) {
+ return it;
+ }
+ } break;
case ITEM_IMAGE:
case ITEM_TABLE: {
offset += 1;
@@ -1344,6 +1349,8 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Point2i &p_click, ItemFrame **r_click_frame, int *r_click_line, Item **r_click_item, int *r_click_char, bool p_table) {
Vector2 off;
+ bool line_clicked = false;
+ float text_rect_begin = 0.0;
int char_pos = -1;
Line &l = p_frame->lines[p_line];
MutexLock lock(l.text_buf->get_mutex());
@@ -1469,7 +1476,11 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
}
if (p_click.y >= rect.position.y && p_click.y <= rect.position.y + rect.size.y) {
- char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x);
+ if ((!rtl && p_click.x >= rect.position.x) || (rtl && p_click.x <= rect.position.x + rect.size.x)) {
+ char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x);
+ }
+ line_clicked = true;
+ text_rect_begin = rtl ? rect.position.x + rect.size.x : rect.position.x;
}
// If table hit was detected, and line hit is in the table bounds use table hit.
@@ -1496,23 +1507,38 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
}
// Text line hit.
- if (char_pos >= 0) {
+ if (line_clicked) {
// Find item.
if (r_click_item != nullptr) {
Item *it = p_frame->lines[p_line].from;
Item *it_to = (p_line + 1 < (int)p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr;
- if (char_pos == p_frame->lines[p_line].char_count) {
- // Selection after the end of line, select last item.
- if (it_to != nullptr) {
- *r_click_item = _get_prev_item(it_to);
- } else {
- for (Item *i = it; i; i = _get_next_item(i)) {
- *r_click_item = i;
+ if (char_pos >= 0) {
+ *r_click_item = _get_item_at_pos(it, it_to, char_pos);
+ } else {
+ int stop = text_rect_begin;
+ *r_click_item = _find_indentable(it);
+ while (*r_click_item) {
+ Ref<Font> font = _find_font(*r_click_item);
+ if (!font.is_valid()) {
+ font = get_theme_font(SNAME("normal_font"));
+ }
+ int font_size = _find_font_size(*r_click_item);
+ if (font_size == -1) {
+ font_size = get_theme_font_size(SNAME("normal_font_size"));
+ }
+ if (rtl) {
+ stop += tab_size * font->get_char_size(' ', font_size).width;
+ if (stop > p_click.x) {
+ break;
+ }
+ } else {
+ stop -= tab_size * font->get_char_size(' ', font_size).width;
+ if (stop < p_click.x) {
+ break;
+ }
}
+ *r_click_item = _find_indentable((*r_click_item)->parent);
}
- } else {
- // Selection in the line.
- *r_click_item = _get_item_at_pos(it, it_to, char_pos);
}
}
@@ -2069,6 +2095,19 @@ void RichTextLabel::_find_frame(Item *p_item, ItemFrame **r_frame, int *r_line)
}
}
+RichTextLabel::Item *RichTextLabel::_find_indentable(Item *p_item) {
+ Item *indentable = p_item;
+
+ while (indentable) {
+ if (indentable->type == ITEM_INDENT || indentable->type == ITEM_LIST) {
+ return indentable;
+ }
+ indentable = indentable->parent;
+ }
+
+ return indentable;
+}
+
Ref<Font> RichTextLabel::_find_font(Item *p_item) {
Item *fontitem = p_item;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 3b6175e9cf..c123f38c01 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -459,6 +459,7 @@ private:
String _roman(int p_num, bool p_capitalize) const;
String _letters(int p_num, bool p_capitalize) const;
+ Item *_find_indentable(Item *p_item);
Item *_get_item_at_pos(Item *p_item_from, Item *p_item_to, int p_position);
void _find_frame(Item *p_item, ItemFrame **r_frame, int *r_line);
int _find_font_size(Item *p_item);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 9c6cd6bdb2..06553cd0f6 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1217,7 +1217,7 @@ void TextEdit::_notification(int p_what) {
if (brace_open_mismatch) {
current_color = brace_mismatch_color;
}
- Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, font->get_underline_thickness(font_size));
+ Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, MAX(font->get_underline_thickness(font_size) * get_theme_default_base_scale(), 1));
draw_rect(rect, current_color);
}
@@ -1226,7 +1226,7 @@ void TextEdit::_notification(int p_what) {
if (brace_close_mismatch) {
current_color = brace_mismatch_color;
}
- Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, font->get_underline_thickness(font_size));
+ Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, MAX(font->get_underline_thickness(font_size) * get_theme_default_base_scale(), 1));
draw_rect(rect, current_color);
}
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 4bb8208679..f43a91b85f 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2815,6 +2815,9 @@ void Tree::value_editor_changed(double p_value) {
TreeItem::Cell &c = popup_edited_item->cells.write[popup_edited_item_col];
c.val = p_value;
+
+ text_editor->set_text(String::num(c.val, Math::range_step_decimals(c.step)));
+
item_edited(popup_edited_item_col, popup_edited_item);
update();
}
diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
index a1a77b95aa..ddd984ad83 100644
--- a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
@@ -29,7 +29,8 @@
#VERSION_DEFINES
-// Based on Spartan Engine's TAA implementation https://github.com/PanosK92/SpartanEngine/blob/master/Data/shaders/temporal_antialiasing.hlsl
+// Based on Spartan Engine's TAA implementation (without TAA upscale).
+// <https://github.com/PanosK92/SpartanEngine/blob/a8338d0609b85dc32f3732a5c27fb4463816a3b9/Data/shaders/temporal_antialiasing.hlsl>
#define USE_SUBGROUPS