diff options
Diffstat (limited to 'editor')
45 files changed, 714 insertions, 182 deletions
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index fe1401bdf9..7ed603410d 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -1123,6 +1123,7 @@ ActionMapEditor::ActionMapEditor() { action_tree->set_hide_root(true); action_tree->set_column_titles_visible(true); action_tree->set_column_title(0, TTR("Action")); + action_tree->set_column_clip_content(0, true); action_tree->set_column_title(1, TTR("Deadzone")); action_tree->set_column_expand(1, false); action_tree->set_column_custom_minimum_width(1, 80 * EDSCALE); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 7090572b0f..05945a8ae2 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -4450,7 +4450,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) { } if (node == AnimationPlayerEditor::singleton->get_player()) { - EditorNode::get_singleton()->show_warning(TTR("An animation player can't animate itself, only other players.")); + EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players.")); return; } @@ -5334,7 +5334,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { } break; case EDIT_PASTE_TRACKS: { if (track_clipboard.size() == 0) { - EditorNode::get_singleton()->show_warning(TTR("Clipboard is empty")); + EditorNode::get_singleton()->show_warning(TTR("Clipboard is empty!")); break; } diff --git a/editor/audio_stream_preview.h b/editor/audio_stream_preview.h index 61567598ed..9cf47fd51a 100644 --- a/editor/audio_stream_preview.h +++ b/editor/audio_stream_preview.h @@ -75,6 +75,15 @@ class AudioStreamPreviewGenerator : public Node { thread = p_rhs.thread; return *this; } + Preview(const Preview &p_rhs) { + preview = p_rhs.preview; + base_stream = p_rhs.base_stream; + playback = p_rhs.playback; + generating.set_to(generating.is_set()); + id = p_rhs.id; + thread = p_rhs.thread; + } + Preview() {} }; Map<ObjectID, Preview> previews; diff --git a/editor/debugger/editor_network_profiler.cpp b/editor/debugger/editor_network_profiler.cpp index af83baeff8..1c781c4d98 100644 --- a/editor/debugger/editor_network_profiler.cpp +++ b/editor/debugger/editor_network_profiler.cpp @@ -178,18 +178,23 @@ EditorNetworkProfiler::EditorNetworkProfiler() { counters_display->set_column_titles_visible(true); counters_display->set_column_title(0, TTR("Node")); counters_display->set_column_expand(0, true); + counters_display->set_column_clip_content(0, true); counters_display->set_column_custom_minimum_width(0, 60 * EDSCALE); counters_display->set_column_title(1, TTR("Incoming RPC")); counters_display->set_column_expand(1, false); + counters_display->set_column_clip_content(1, true); counters_display->set_column_custom_minimum_width(1, 120 * EDSCALE); counters_display->set_column_title(2, TTR("Incoming RSET")); counters_display->set_column_expand(2, false); + counters_display->set_column_clip_content(2, true); counters_display->set_column_custom_minimum_width(2, 120 * EDSCALE); counters_display->set_column_title(3, TTR("Outgoing RPC")); counters_display->set_column_expand(3, false); + counters_display->set_column_clip_content(3, true); counters_display->set_column_custom_minimum_width(3, 120 * EDSCALE); counters_display->set_column_title(4, TTR("Outgoing RSET")); counters_display->set_column_expand(4, false); + counters_display->set_column_clip_content(4, true); counters_display->set_column_custom_minimum_width(4, 120 * EDSCALE); add_child(counters_display); diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index ba84040b0c..5f4d1b6f36 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -631,13 +631,16 @@ EditorProfiler::EditorProfiler() { variables->set_column_titles_visible(true); variables->set_column_title(0, TTR("Name")); variables->set_column_expand(0, true); - variables->set_column_custom_minimum_width(0, 60 * EDSCALE); + variables->set_column_clip_content(0, true); + variables->set_column_expand_ratio(0, 60); variables->set_column_title(1, TTR("Time")); variables->set_column_expand(1, false); - variables->set_column_custom_minimum_width(1, 100 * EDSCALE); + variables->set_column_clip_content(1, true); + variables->set_column_expand_ratio(1, 100); variables->set_column_title(2, TTR("Calls")); variables->set_column_expand(2, false); - variables->set_column_custom_minimum_width(2, 60 * EDSCALE); + variables->set_column_clip_content(2, true); + variables->set_column_expand_ratio(2, 60); variables->connect("item_edited", callable_mp(this, &EditorProfiler::_item_edited)); graph = memnew(TextureRect); diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index 171d0574e0..a0e8a3bd35 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -773,12 +773,15 @@ EditorVisualProfiler::EditorVisualProfiler() { variables->set_column_titles_visible(true); variables->set_column_title(0, TTR("Name")); variables->set_column_expand(0, true); + variables->set_column_clip_content(0, true); variables->set_column_custom_minimum_width(0, 60); variables->set_column_title(1, TTR("CPU")); variables->set_column_expand(1, false); + variables->set_column_clip_content(1, true); variables->set_column_custom_minimum_width(1, 60 * EDSCALE); variables->set_column_title(2, TTR("GPU")); variables->set_column_expand(2, false); + variables->set_column_clip_content(2, true); variables->set_column_custom_minimum_width(2, 60 * EDSCALE); variables->connect("cell_selected", callable_mp(this, &EditorVisualProfiler::_item_selected)); diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index e283043a4f..508b984b91 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -1644,8 +1644,10 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { error_tree->set_column_expand(0, false); error_tree->set_column_custom_minimum_width(0, 140); + error_tree->set_column_clip_content(0, true); error_tree->set_column_expand(1, true); + error_tree->set_column_clip_content(1, true); error_tree->set_select_mode(Tree::SELECT_ROW); error_tree->set_hide_root(true); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 74a8ad9077..ef571e5c7a 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -226,7 +226,11 @@ DependencyEditor::DependencyEditor() { tree->set_columns(2); tree->set_column_titles_visible(true); tree->set_column_title(0, TTR("Resource")); + tree->set_column_clip_content(0, true); + tree->set_column_expand_ratio(0, 2); tree->set_column_title(1, TTR("Path")); + tree->set_column_clip_content(1, true); + tree->set_column_expand_ratio(1, 1); tree->set_hide_root(true); tree->connect("button_pressed", callable_mp(this, &DependencyEditor::_load_pressed)); @@ -769,9 +773,11 @@ OrphanResourcesDialog::OrphanResourcesDialog() { files = memnew(Tree); files->set_columns(2); files->set_column_titles_visible(true); - files->set_column_custom_minimum_width(1, 100); + files->set_column_custom_minimum_width(1, 100 * EDSCALE); files->set_column_expand(0, true); + files->set_column_clip_content(0, true); files->set_column_expand(1, false); + files->set_column_clip_content(1, true); files->set_column_title(0, TTR("Resource")); files->set_column_title(1, TTR("Owns")); files->set_hide_root(true); diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 83319ee5a5..dc90f26d48 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -112,7 +112,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { unzFile pkg = unzOpen2(p_path.utf8().get_data(), &io); if (!pkg) { - error->set_text(TTR("Error opening package file, not in ZIP format.")); + error->set_text(vformat(TTR("Error opening asset file for \"%s\" (not in ZIP format)."), asset_name)); return; } @@ -196,6 +196,8 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { root->set_editable(0, true); Map<String, TreeItem *> dir_map; + int num_file_conflicts = 0; + for (Set<String>::Element *E = files_sorted.front(); E; E = E->next()) { String path = E->get(); int depth = p_depth; @@ -254,8 +256,9 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { String res_path = "res://" + path; if (FileAccess::exists(res_path)) { + num_file_conflicts += 1; ti->set_custom_color(0, tree->get_theme_color("error_color", "Editor")); - ti->set_tooltip(0, vformat(TTR("%s (Already Exists)"), res_path)); + ti->set_tooltip(0, vformat(TTR("%s (already exists)"), res_path)); ti->set_checked(0, false); } else { ti->set_tooltip(0, res_path); @@ -266,6 +269,13 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { status_map[E->get()] = ti; } + + if (num_file_conflicts >= 1) { + asset_contents->set_text(vformat(TTR("Contents of asset \"%s\" - %d file(s) conflict with your project:"), asset_name, num_file_conflicts)); + } else { + asset_contents->set_text(vformat(TTR("Contents of asset \"%s\" - No files conflict with your project:"), asset_name)); + } + popup_centered_ratio(); updating = false; } @@ -276,7 +286,7 @@ void EditorAssetInstaller::ok_pressed() { unzFile pkg = unzOpen2(package_path.utf8().get_data(), &io); if (!pkg) { - error->set_text(TTR("Error opening package file, not in ZIP format.")); + error->set_text(vformat(TTR("Error opening asset file for \"%s\" (not in ZIP format)."), asset_name)); return; } @@ -343,10 +353,10 @@ void EditorAssetInstaller::ok_pressed() { unzClose(pkg); if (failed_files.size()) { - String msg = TTR("The following files failed extraction from package:") + "\n\n"; + String msg = vformat(TTR("The following files failed extraction from asset \"%s\":"), asset_name) + "\n\n"; for (int i = 0; i < failed_files.size(); i++) { if (i > 15) { - msg += "\n" + vformat(TTR("And %s more files."), itos(failed_files.size() - i)); + msg += "\n" + vformat(TTR("(and %s more files)"), itos(failed_files.size() - i)); break; } msg += failed_files[i]; @@ -356,12 +366,20 @@ void EditorAssetInstaller::ok_pressed() { } } else { if (EditorNode::get_singleton() != nullptr) { - EditorNode::get_singleton()->show_warning(TTR("Package installed successfully!"), TTR("Success!")); + EditorNode::get_singleton()->show_warning(vformat(TTR("Asset \"%s\" installed successfully!"), asset_name), TTR("Success!")); } } EditorFileSystem::get_singleton()->scan_changes(); } +void EditorAssetInstaller::set_asset_name(const String &p_asset_name) { + asset_name = p_asset_name; +} + +String EditorAssetInstaller::get_asset_name() const { + return asset_name; +} + void EditorAssetInstaller::_bind_methods() { } @@ -369,14 +387,18 @@ EditorAssetInstaller::EditorAssetInstaller() { VBoxContainer *vb = memnew(VBoxContainer); add_child(vb); + asset_contents = memnew(Label); + vb->add_child(asset_contents); + tree = memnew(Tree); - vb->add_margin_child(TTR("Package Contents:"), tree, true); + tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_edited)); + vb->add_child(tree); error = memnew(AcceptDialog); add_child(error); get_ok_button()->set_text(TTR("Install")); - set_title(TTR("Package Installer")); + set_title(TTR("Asset Installer")); updating = false; diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h index d9233a5ce8..9fafe2792a 100644 --- a/editor/editor_asset_installer.h +++ b/editor/editor_asset_installer.h @@ -37,7 +37,9 @@ class EditorAssetInstaller : public ConfirmationDialog { GDCLASS(EditorAssetInstaller, ConfirmationDialog); Tree *tree; + Label *asset_contents; String package_path; + String asset_name; AcceptDialog *error; Map<String, TreeItem *> status_map; bool updating; @@ -51,6 +53,10 @@ protected: public: void open(const String &p_path, int p_depth = 0); + + void set_asset_name(const String &p_asset_name); + String get_asset_name() const; + EditorAssetInstaller(); }; diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 306a88047a..12ae55fbc1 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -882,19 +882,17 @@ EditorAutoloadSettings::EditorAutoloadSettings() { tree->set_column_title(0, TTR("Name")); tree->set_column_expand(0, true); - tree->set_column_custom_minimum_width(0, 100 * EDSCALE); + tree->set_column_expand_ratio(0, 1); tree->set_column_title(1, TTR("Path")); tree->set_column_expand(1, true); - tree->set_column_custom_minimum_width(1, 100 * EDSCALE); + tree->set_column_clip_content(1, true); + tree->set_column_expand_ratio(1, 2); tree->set_column_title(2, TTR("Global Variable")); tree->set_column_expand(2, false); - // Reserve enough space for translations of "Global Variable" which may be longer. - tree->set_column_custom_minimum_width(2, 150 * EDSCALE); tree->set_column_expand(3, false); - tree->set_column_custom_minimum_width(3, 120 * EDSCALE); tree->connect("cell_selected", callable_mp(this, &EditorAutoloadSettings::_autoload_selected)); tree->connect("item_edited", callable_mp(this, &EditorAutoloadSettings::_autoload_edited)); diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 57ddc64e95..a9bbb92079 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -237,9 +237,11 @@ EditorHelpSearch::EditorHelpSearch() { results_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); results_tree->set_columns(2); results_tree->set_column_title(0, TTR("Name")); + results_tree->set_column_clip_content(0, true); results_tree->set_column_title(1, TTR("Member Type")); results_tree->set_column_expand(1, false); results_tree->set_column_custom_minimum_width(1, 150 * EDSCALE); + results_tree->set_column_clip_content(1, true); results_tree->set_custom_minimum_size(Size2(0, 100) * EDSCALE); results_tree->set_hide_root(true); results_tree->set_select_mode(Tree::SELECT_ROW); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 7d6021b0f6..4cfa2d7338 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -137,6 +137,7 @@ #include "editor/plugins/gpu_particles_3d_editor_plugin.h" #include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h" #include "editor/plugins/gradient_editor_plugin.h" +#include "editor/plugins/input_event_editor_plugin.h" #include "editor/plugins/item_list_editor_plugin.h" #include "editor/plugins/light_occluder_2d_editor_plugin.h" #include "editor/plugins/lightmap_gi_editor_plugin.h" @@ -2712,7 +2713,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } save_confirmation->get_ok_button()->set_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 the following scene(s) before opening Project Manager?")) + unsaved_scenes); + 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(); } } @@ -3874,6 +3875,21 @@ Ref<ImageTexture> EditorNode::_load_custom_class_icon(const String &p_path) cons return nullptr; } +void EditorNode::_pick_main_scene_custom_action(const String &p_custom_action_name) { + if (p_custom_action_name == "select_current") { + Node *scene = editor_data.get_edited_scene_root(); + + if (!scene) { + show_accept(TTR("There is no defined scene to run."), TTR("OK")); + return; + } + + pick_main_scene->hide(); + current_option = SETTINGS_PICK_MAIN_SCENE; + _dialog_action(scene->get_filename()); + } +} + Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String &p_fallback) const { ERR_FAIL_COND_V(!p_object || !gui_base, nullptr); @@ -4668,6 +4684,14 @@ bool EditorNode::ensure_main_scene(bool p_from_native) { current_option = -1; pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in \"Project Settings\" under the 'application' category.")); pick_main_scene->popup_centered(); + + if (editor_data.get_edited_scene_root()) { + select_current_scene_button->set_disabled(false); + select_current_scene_button->grab_focus(); + } else { + select_current_scene_button->set_disabled(true); + } + return false; } @@ -6816,6 +6840,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(MeshEditorPlugin(this))); add_editor_plugin(memnew(MaterialEditorPlugin(this))); add_editor_plugin(memnew(GPUParticlesCollisionSDFEditorPlugin(this))); + add_editor_plugin(memnew(InputEventEditorPlugin(this))); for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) { add_editor_plugin(EditorPlugins::create(i, this)); @@ -6944,6 +6969,8 @@ EditorNode::EditorNode() { gui_base->add_child(pick_main_scene); pick_main_scene->get_ok_button()->set_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)); for (int i = 0; i < _init_callbacks.size(); i++) { _init_callbacks[i](); diff --git a/editor/editor_node.h b/editor/editor_node.h index dcb6ad6e94..07bed6999b 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -301,6 +301,7 @@ private: ConfirmationDialog *save_confirmation; ConfirmationDialog *import_confirmation; ConfirmationDialog *pick_main_scene; + Button *select_current_scene_button; AcceptDialog *accept; EditorAbout *about; AcceptDialog *warning; @@ -663,6 +664,8 @@ private: bool _is_class_editor_disabled_by_feature_profile(const StringName &p_class); Ref<ImageTexture> _load_custom_class_icon(const String &p_path) const; + void _pick_main_scene_custom_action(const String &p_custom_action_name); + protected: void _notification(int p_what); diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index 62fbad7bcf..b4e5a58c21 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -212,10 +212,15 @@ EditorPluginSettings::EditorPluginSettings() { plugin_list->set_column_title(3, TTR("Status:")); plugin_list->set_column_title(4, TTR("Edit:")); plugin_list->set_column_expand(0, true); + plugin_list->set_column_clip_content(0, true); plugin_list->set_column_expand(1, false); + plugin_list->set_column_clip_content(1, true); plugin_list->set_column_expand(2, false); + plugin_list->set_column_clip_content(2, true); plugin_list->set_column_expand(3, false); + plugin_list->set_column_clip_content(3, true); plugin_list->set_column_expand(4, false); + plugin_list->set_column_clip_content(4, true); plugin_list->set_column_custom_minimum_width(1, 100 * EDSCALE); plugin_list->set_column_custom_minimum_width(2, 250 * EDSCALE); plugin_list->set_column_custom_minimum_width(3, 80 * EDSCALE); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 6004427c0f..080563f375 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -631,6 +631,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("editors/3d/navigation/zoom_style", 0); hints["editors/3d/navigation/zoom_style"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_style", PROPERTY_HINT_ENUM, "Vertical, Horizontal"); + _initial_set("editors/3d/navigation/emulate_numpad", false); _initial_set("editors/3d/navigation/emulate_3_button_mouse", false); _initial_set("editors/3d/navigation/orbit_modifier", 0); hints["editors/3d/navigation/orbit_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/orbit_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl"); diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h index af952eaffc..52ab6d68ee 100644 --- a/editor/editor_vcs_interface.h +++ b/editor/editor_vcs_interface.h @@ -46,16 +46,16 @@ protected: static void _bind_methods(); // Implemented by addons as end points for the proxy functions - bool _initialize(String p_project_root_path); - bool _is_vcs_initialized(); - Dictionary _get_modified_files_data(); - void _stage_file(String p_file_path); - void _unstage_file(String p_file_path); - void _commit(String p_msg); - Array _get_file_diff(String p_file_path); - bool _shut_down(); - String _get_project_name(); - String _get_vcs_name(); + virtual bool _initialize(String p_project_root_path); + virtual bool _is_vcs_initialized(); + virtual Dictionary _get_modified_files_data(); + virtual void _stage_file(String p_file_path); + virtual void _unstage_file(String p_file_path); + virtual void _commit(String p_msg); + virtual Array _get_file_diff(String p_file_path); + virtual bool _shut_down(); + virtual String _get_project_name(); + virtual String _get_vcs_name(); public: static EditorVCSInterface *get_singleton(); diff --git a/editor/editor_zoom_widget.cpp b/editor/editor_zoom_widget.cpp index f9be829493..44751a480a 100644 --- a/editor/editor_zoom_widget.cpp +++ b/editor/editor_zoom_widget.cpp @@ -51,17 +51,17 @@ void EditorZoomWidget::_update_zoom_label() { } void EditorZoomWidget::_button_zoom_minus() { - set_zoom_by_increments(-6); + set_zoom_by_increments(-6, Input::get_singleton()->is_key_pressed(KEY_ALT)); emit_signal("zoom_changed", zoom); } void EditorZoomWidget::_button_zoom_reset() { - set_zoom(1.0); + set_zoom(1.0 * MAX(1, EDSCALE)); emit_signal("zoom_changed", zoom); } void EditorZoomWidget::_button_zoom_plus() { - set_zoom_by_increments(6); + set_zoom_by_increments(6, Input::get_singleton()->is_key_pressed(KEY_ALT)); emit_signal("zoom_changed", zoom); } @@ -76,31 +76,69 @@ void EditorZoomWidget::set_zoom(float p_zoom) { } } -void EditorZoomWidget::set_zoom_by_increments(int p_increment_count) { - // Base increment factor defined as the twelveth root of two. - // This allow a smooth geometric evolution of the zoom, with the advantage of - // visiting all integer power of two scale factors. - // note: this is analogous to the 'semitones' interval in the music world - // In order to avoid numerical imprecisions, we compute and edit a zoom index - // with the following relation: zoom = 2 ^ (index / 12) - - if (zoom < CMP_EPSILON || p_increment_count == 0) { - return; - } +void EditorZoomWidget::set_zoom_by_increments(int p_increment_count, bool p_integer_only) { + // Remove editor scale from the index computation. + const float zoom_noscale = zoom / MAX(1, EDSCALE); + + if (p_integer_only) { + // Only visit integer scaling factors above 100%, and fractions with an integer denominator below 100% + // (1/2 = 50%, 1/3 = 33.33%, 1/4 = 25%, …). + // This is useful when working on pixel art projects to avoid distortion. + // This algorithm is designed to handle fractional start zoom values correctly + // (e.g. 190% will zoom up to 200% and down to 100%). + if (zoom_noscale + p_increment_count * 0.001 >= 1.0 - CMP_EPSILON) { + // New zoom is certain to be above 100%. + if (p_increment_count >= 1) { + // Zooming. + set_zoom(Math::floor(zoom_noscale + p_increment_count) * MAX(1, EDSCALE)); + } else { + // Dezooming. + set_zoom(Math::ceil(zoom_noscale + p_increment_count) * MAX(1, EDSCALE)); + } + } else { + if (p_increment_count >= 1) { + // Zooming. Convert the current zoom into a denominator. + float new_zoom = 1.0 / Math::ceil(1.0 / zoom_noscale - p_increment_count); + if (Math::is_equal_approx(zoom_noscale, new_zoom)) { + // New zoom is identical to the old zoom, so try again. + // This can happen due to floating-point precision issues. + new_zoom = 1.0 / Math::ceil(1.0 / zoom_noscale - p_increment_count - 1); + } + set_zoom(new_zoom * MAX(1, EDSCALE)); + } else { + // Dezooming. Convert the current zoom into a denominator. + float new_zoom = 1.0 / Math::floor(1.0 / zoom_noscale - p_increment_count); + if (Math::is_equal_approx(zoom_noscale, new_zoom)) { + // New zoom is identical to the old zoom, so try again. + // This can happen due to floating-point precision issues. + new_zoom = 1.0 / Math::floor(1.0 / zoom_noscale - p_increment_count + 1); + } + set_zoom(new_zoom * MAX(1, EDSCALE)); + } + } + } else { + // Base increment factor defined as the twelveth root of two. + // This allow a smooth geometric evolution of the zoom, with the advantage of + // visiting all integer power of two scale factors. + // note: this is analogous to the 'semitones' interval in the music world + // In order to avoid numerical imprecisions, we compute and edit a zoom index + // with the following relation: zoom = 2 ^ (index / 12) - // Remove Editor scale from the index computation - float zoom_noscale = zoom / MAX(1, EDSCALE); + if (zoom < CMP_EPSILON || p_increment_count == 0) { + return; + } - // zoom = 2**(index/12) => log2(zoom) = index/12 - float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f)); + // zoom = 2**(index/12) => log2(zoom) = index/12 + float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f)); - float new_zoom_index = closest_zoom_index + p_increment_count; - float new_zoom = Math::pow(2.f, new_zoom_index / 12.f); + float new_zoom_index = closest_zoom_index + p_increment_count; + float new_zoom = Math::pow(2.f, new_zoom_index / 12.f); - // Restore Editor scale transformation - new_zoom *= MAX(1, EDSCALE); + // Restore Editor scale transformation + new_zoom *= MAX(1, EDSCALE); - set_zoom(new_zoom); + set_zoom(new_zoom); + } } void EditorZoomWidget::_notification(int p_what) { @@ -118,7 +156,7 @@ void EditorZoomWidget::_notification(int p_what) { void EditorZoomWidget::_bind_methods() { ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &EditorZoomWidget::set_zoom); ClassDB::bind_method(D_METHOD("get_zoom"), &EditorZoomWidget::get_zoom); - ClassDB::bind_method(D_METHOD("set_zoom_by_increments", "increment"), &EditorZoomWidget::set_zoom_by_increments); + ClassDB::bind_method(D_METHOD("set_zoom_by_increments", "increment", "integer_only"), &EditorZoomWidget::set_zoom_by_increments); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "zoom"), "set_zoom", "get_zoom"); diff --git a/editor/editor_zoom_widget.h b/editor/editor_zoom_widget.h index 4e95018e52..c35faeefe7 100644 --- a/editor/editor_zoom_widget.h +++ b/editor/editor_zoom_widget.h @@ -56,7 +56,7 @@ public: float get_zoom(); void set_zoom(float p_zoom); - void set_zoom_by_increments(int p_increment_count); + void set_zoom_by_increments(int p_increment_count, bool p_integer_only = false); }; #endif // EDITOR_ZOOM_WIDGET_H diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 527ffc86df..3dc854d6bd 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -815,7 +815,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { if (searched_string.length() > 0) { // Display the search results. - _search(EditorFileSystem::get_singleton()->get_filesystem(), &file_list, 128); + // Limit the number of results displayed to avoid an infinite loop. + _search(EditorFileSystem::get_singleton()->get_filesystem(), &file_list, 10000); } else { if (display_mode == DISPLAY_MODE_TREE_ONLY || always_show_folders) { // Display folders in the list. diff --git a/editor/icons/ImmediateMesh.svg b/editor/icons/ImmediateMesh.svg new file mode 100644 index 0000000000..9521530876 --- /dev/null +++ b/editor/icons/ImmediateMesh.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 2v2h5v-2zm5 2v3h2v-3zm2-2v2h5v-2zm-2 7v3h2v-3zm-5 3v2h5v-2zm7 0v2h5v-2z" fill="#ffca5f" transform="scale(.93749994)"/></svg> diff --git a/editor/icons/ORMMaterial3D.svg b/editor/icons/ORMMaterial3D.svg index 3d6db6910d..e09208155d 100644 --- a/editor/icons/ORMMaterial3D.svg +++ b/editor/icons/ORMMaterial3D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5.0534707 10.652714q0 .729229-.4538398 1.253141-.4538403.516832-1.0868283.516832h-1.1943162q-.6389592 0-1.1047425-.509753-.47175502-.509751-.47175502-1.26022v-5.5223119q0-.7575473.47175502-1.2672998.4717549-.5097517 1.1047425-.5097517h1.1943162q.6270165 0 1.0868283.516832.4538398.5168313.4538398 1.2602195zm-1.0808559-.233636v-5.0550395q0-.5734707-.3344086-.8141867-.1074887-.0849591-.2567782-.0778788h-.9912826q-.2567779 0-.4120391.2690357-.1552611.2690357-.1552611.6230298v5.0550395q0 .559311.3164938.807108.1074885.08496.2508064.08496h.9912826q.2746925 0 .4359254-.276116.1552614-.276115.1552614-.61595z" fill="#f00"/><path d="m9.9872948 12.451006h-1.0427362l-1.4698137-3.9222572h-.7931457v3.9222572h-1.0094573v-9.076416h2.739956q.5435541 0 .9318066.4601926.3882524.4601933.3882524 1.1540217v2.1239667q0 1.0053443-.6766682 1.3168588-.2107668.099119-.4659043.099119zm-1.2590481-5.64267v-1.5858953q0-.4743524-.2884169-.6867495-.088743-.070798-.2052192-.063719h-1.5530114v2.9452329h1.7194053q.2828702-.00708.3161488-.389394.011093-.1132781.011093-.2194752z" fill="#008000"/><path d="m10.201004 3.7285848q0-.4106342.529158-.3681546.126777.014161.209458.014161v.00708h.115753l1.692202 4.9205216 1.697714-4.9205216h.06063v-.00708h.463013q.198434 0 .297651.212397.03307.063719.03307.1415978v8.694102h-1.01422v-5.6001914l-1.058314 3.2284284h-.953584l-1.058315-2.9310723v5.3028353h-1.014218z" fill="#00f"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3.1191406-3.7636719 1.8808594 3.7636719 1.8828125 3.763672-1.8828125z" fill="#80ff45"/><path d="m3 6.6191406v2.3808594 1.382812l1.234375.617188 2.765625 1.382812v-1.382812-2-.3808594l-3.2382812-1.6191406z" fill="#ff4545"/><path d="m13 6.6191406-.761719.3808594-3.238281 1.6191406v3.7636714l2.765625-1.382812 1.234375-.617188v-1.382812z" fill="#45d7ff"/></svg> diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp index ce78166d1e..f8e93df382 100644 --- a/editor/import/scene_importer_mesh.cpp +++ b/editor/import/scene_importer_mesh.cpp @@ -506,7 +506,7 @@ Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose() const { const Vector<Face3> faces = get_faces(); - Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces); + Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces, -1); Vector<Ref<Shape3D>> ret; diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index 91a15f1131..208d4437d3 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -728,7 +728,9 @@ LocalizationEditor::LocalizationEditor() { translation_remap_options->set_column_title(1, TTR("Locale")); translation_remap_options->set_column_titles_visible(true); translation_remap_options->set_column_expand(0, true); + translation_remap_options->set_column_clip_content(0, true); translation_remap_options->set_column_expand(1, false); + translation_remap_options->set_column_clip_content(1, true); translation_remap_options->set_column_custom_minimum_width(1, 200); translation_remap_options->connect("item_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_changed)); translation_remap_options->connect("button_pressed", callable_mp(this, &LocalizationEditor::_translation_res_option_delete)); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 48d7cfdee2..2b92943f7e 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -569,8 +569,10 @@ void AnimationPlayerEditor::_animation_blend() { blend_editor.dialog->popup_centered(Size2(400, 400) * EDSCALE); blend_editor.tree->set_hide_root(true); - blend_editor.tree->set_column_custom_minimum_width(0, 10); - blend_editor.tree->set_column_custom_minimum_width(1, 3); + blend_editor.tree->set_column_expand_ratio(0, 10); + blend_editor.tree->set_column_clip_content(0, true); + blend_editor.tree->set_column_expand_ratio(1, 3); + blend_editor.tree->set_column_clip_content(1, true); List<StringName> anims; player->get_animation_list(&anims); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index cd61ebd418..596b2a6527 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -369,6 +369,9 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int progress->set_modulate(Color(0, 0, 0, 0)); set_process(false); + + // Automatically prompt for installation once the download is completed. + _install(); } void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asset_id, const Ref<Texture2D> &p_preview, const String &p_download_url, const String &p_sha256_hash) { @@ -456,6 +459,7 @@ void EditorAssetLibraryItemDownload::_install() { return; } + asset_installer->set_asset_name(title->get_text()); asset_installer->open(file, 1); } @@ -1296,6 +1300,7 @@ void EditorAssetLibrary::_asset_file_selected(const String &p_file) { } asset_installer = memnew(EditorAssetInstaller); + asset_installer->set_asset_name(p_file.get_basename()); add_child(asset_installer); asset_installer->open(p_file); } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 7282475ddf..94cd8ce17d 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1149,8 +1149,9 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); } else { - zoom_widget->set_zoom_by_increments(-1); - if (b->get_factor() != 1.f) { + zoom_widget->set_zoom_by_increments(-1, Input::get_singleton()->is_key_pressed(KEY_ALT)); + if (!Math::is_equal_approx(b->get_factor(), 1.0f)) { + // Handle high-precision (analog) scrolling. zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f)); } _zoom_on_position(zoom_widget->get_zoom(), b->get_position()); @@ -1164,8 +1165,9 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); } else { - zoom_widget->set_zoom_by_increments(1); - if (b->get_factor() != 1.f) { + zoom_widget->set_zoom_by_increments(1, Input::get_singleton()->is_key_pressed(KEY_ALT)); + if (!Math::is_equal_approx(b->get_factor(), 1.0f)) { + // Handle high-precision (analog) scrolling. zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f)); } _zoom_on_position(zoom_widget->get_zoom(), b->get_position()); @@ -1194,6 +1196,20 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo Ref<InputEventKey> k = p_event; if (k.is_valid()) { + if (k->is_pressed()) { + if (ED_GET_SHORTCUT("canvas_item_editor/zoom_100_percent")->is_shortcut(p_event)) { + _update_zoom(1.0 * MAX(1, EDSCALE)); + } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_200_percent")->is_shortcut(p_event)) { + _update_zoom(2.0 * MAX(1, EDSCALE)); + } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_400_percent")->is_shortcut(p_event)) { + _update_zoom(4.0 * MAX(1, EDSCALE)); + } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_800_percent")->is_shortcut(p_event)) { + _update_zoom(8.0 * MAX(1, EDSCALE)); + } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_1600_percent")->is_shortcut(p_event)) { + _update_zoom(16.0 * MAX(1, EDSCALE)); + } + } + bool is_pan_key = pan_view_shortcut.is_valid() && pan_view_shortcut->is_shortcut(p_event); if (is_pan_key && (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || drag_type != DRAG_NONE)) { @@ -5610,6 +5626,16 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); singleton = this; + // To ensure that scripts can parse the list of shortcuts correctly, we have to define + // those shortcuts one by one. + // Resetting zoom to 100% is a duplicate shortcut of `canvas_item_editor/reset_zoom`, + // but it ensures both 1 and Ctrl + 0 can be used to reset zoom. + ED_SHORTCUT("canvas_item_editor/zoom_100_percent", TTR("Zoom To 100%"), KEY_1); + ED_SHORTCUT("canvas_item_editor/zoom_200_percent", TTR("Zoom To 200%"), KEY_2); + ED_SHORTCUT("canvas_item_editor/zoom_400_percent", TTR("Zoom To 400%"), KEY_3); + ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom To 800%"), KEY_4); + ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom To 1600%"), KEY_5); + set_process_unhandled_key_input(true); // Update the menus' checkboxes diff --git a/editor/plugins/input_event_editor_plugin.cpp b/editor/plugins/input_event_editor_plugin.cpp new file mode 100644 index 0000000000..f1aa10844b --- /dev/null +++ b/editor/plugins/input_event_editor_plugin.cpp @@ -0,0 +1,122 @@ +/*************************************************************************/ +/* input_event_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "input_event_editor_plugin.h" + +void InputEventConfigContainer::_bind_methods() { +} + +void InputEventConfigContainer::_configure_pressed() { + config_dialog->popup_and_configure(input_event); +} + +void InputEventConfigContainer::_event_changed() { + input_event_text->set_text(input_event->as_text()); +} + +void InputEventConfigContainer::_config_dialog_confirmed() { + Ref<InputEvent> ie = config_dialog->get_event(); + input_event->copy_from(ie); + _event_changed(); +} + +Size2 InputEventConfigContainer::get_minimum_size() const { + // Don't bother with a minimum x size for the control - we don't want the inspector + // to jump in size if a long text is placed in the label (e.g. Joypad Axis description) + return Size2(0, HBoxContainer::get_minimum_size().y); +} + +void InputEventConfigContainer::set_event(const Ref<InputEvent> &p_event) { + Ref<InputEventKey> k = p_event; + Ref<InputEventMouseButton> m = p_event; + Ref<InputEventJoypadButton> jb = p_event; + Ref<InputEventJoypadMotion> jm = p_event; + + if (k.is_valid()) { + config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_KEY); + } else if (m.is_valid()) { + config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_MOUSE_BUTTON); + } else if (jb.is_valid()) { + config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_JOY_BUTTON); + } else if (jm.is_valid()) { + config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_JOY_MOTION); + } + + input_event = p_event; + _event_changed(); + input_event->connect("changed", callable_mp(this, &InputEventConfigContainer::_event_changed)); +} + +InputEventConfigContainer::InputEventConfigContainer() { + MarginContainer *mc = memnew(MarginContainer); + mc->add_theme_constant_override("margin_left", 10); + mc->add_theme_constant_override("margin_right", 10); + mc->add_theme_constant_override("margin_top", 10); + mc->add_theme_constant_override("margin_bottom", 10); + add_child(mc); + + HBoxContainer *hb = memnew(HBoxContainer); + mc->add_child(hb); + + open_config_button = memnew(Button); + open_config_button->set_text("Configure"); + open_config_button->connect("pressed", callable_mp(this, &InputEventConfigContainer::_configure_pressed)); + hb->add_child(open_config_button); + + input_event_text = memnew(Label); + hb->add_child(input_event_text); + + config_dialog = memnew(InputEventConfigurationDialog); + config_dialog->connect("confirmed", callable_mp(this, &InputEventConfigContainer::_config_dialog_confirmed)); + add_child(config_dialog); +} + +bool EditorInspectorPluginInputEvent::can_handle(Object *p_object) { + Ref<InputEventKey> k = Ref<InputEventKey>(p_object); + Ref<InputEventMouseButton> m = Ref<InputEventMouseButton>(p_object); + Ref<InputEventJoypadButton> jb = Ref<InputEventJoypadButton>(p_object); + Ref<InputEventJoypadMotion> jm = Ref<InputEventJoypadMotion>(p_object); + + return k.is_valid() || m.is_valid() || jb.is_valid() || jm.is_valid(); +} + +void EditorInspectorPluginInputEvent::parse_begin(Object *p_object) { + Ref<InputEvent> ie = Ref<InputEvent>(p_object); + + InputEventConfigContainer *picker_controls = memnew(InputEventConfigContainer); + picker_controls->set_event(ie); + add_custom_control(picker_controls); +} + +InputEventEditorPlugin::InputEventEditorPlugin(EditorNode *p_node) { + Ref<EditorInspectorPluginInputEvent> plugin; + plugin.instantiate(); + add_inspector_plugin(plugin); +} diff --git a/editor/plugins/input_event_editor_plugin.h b/editor/plugins/input_event_editor_plugin.h new file mode 100644 index 0000000000..bc8293c9e5 --- /dev/null +++ b/editor/plugins/input_event_editor_plugin.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* input_event_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef INPUT_EVENT_EDITOR_PLUGIN_H +#define INPUT_EVENT_EDITOR_PLUGIN_H + +#include "editor/action_map_editor.h" +#include "editor/editor_inspector.h" +#include "editor/editor_node.h" + +class InputEventConfigContainer : public HBoxContainer { + GDCLASS(InputEventConfigContainer, HBoxContainer); + + Label *input_event_text; + Button *open_config_button; + + Ref<InputEvent> input_event; + InputEventConfigurationDialog *config_dialog; + + void _config_dialog_confirmed(); + void _configure_pressed(); + + void _event_changed(); + +protected: + static void _bind_methods(); + +public: + virtual Size2 get_minimum_size() const override; + void set_event(const Ref<InputEvent> &p_event); + + InputEventConfigContainer(); +}; + +class EditorInspectorPluginInputEvent : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginInputEvent, EditorInspectorPlugin); + +public: + virtual bool can_handle(Object *p_object) override; + virtual void parse_begin(Object *p_object) override; +}; + +class InputEventEditorPlugin : public EditorPlugin { + GDCLASS(InputEventEditorPlugin, EditorPlugin); + +public: + virtual String get_name() const override { return "InputEvent"; } + + InputEventEditorPlugin(EditorNode *p_node); +}; + +#endif // INPUT_EVENT_EDITOR_PLUGIN_H diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 0d2b2ea2f5..7434accc1a 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -153,14 +153,18 @@ void MeshInstance3DEditor::_menu_option(int p_option) { ur->add_undo_method(node->get_parent(), "remove_child", cshape); ur->commit_action(); } break; - case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE: { + + case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE: + case MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE: { if (node == get_tree()->get_edited_scene_root()) { err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root.")); err_dialog->popup_centered(); return; } - Ref<Shape3D> shape = mesh->create_convex_shape(); + bool simplify = (p_option == MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE); + + Ref<Shape3D> shape = mesh->create_convex_shape(true, simplify); if (shape.is_null()) { err_dialog->set_text(TTR("Couldn't create a single convex collision shape.")); @@ -169,7 +173,11 @@ void MeshInstance3DEditor::_menu_option(int p_option) { } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Create Single Convex Shape")); + if (simplify) { + ur->create_action(TTR("Create Simplified Convex Shape")); + } else { + ur->create_action(TTR("Create Single Convex Shape")); + } CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); @@ -186,6 +194,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { ur->commit_action(); } break; + case MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES: { if (node == get_tree()->get_edited_scene_root()) { err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root.")); @@ -441,8 +450,10 @@ MeshInstance3DEditor::MeshInstance3DEditor() { options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection.")); options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE); options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection.")); + options->get_popup()->add_item(TTR("Create Simplified Convex Collision Sibling"), MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE); + options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy.")); options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES); - options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between the two above options.")); + options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision.")); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH); options->get_popup()->add_separator(); diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h index 69f494de7f..98b667c978 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.h +++ b/editor/plugins/mesh_instance_3d_editor_plugin.h @@ -43,6 +43,7 @@ class MeshInstance3DEditor : public Control { MENU_OPTION_CREATE_STATIC_TRIMESH_BODY, MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE, MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE, + MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE, MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES, MENU_OPTION_CREATE_NAVMESH, MENU_OPTION_CREATE_OUTLINE_MESH, diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 5a4d79cdc8..72a63539b3 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -467,22 +467,31 @@ void Node3DEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_ } void Node3DEditorViewport::_select(Node *p_node, bool p_append, bool p_single) { - if (!p_append) { - editor_selection->clear(); - } - - if (editor_selection->is_selected(p_node)) { - //erase - editor_selection->remove_node(p_node); + // Add or remove a single node from the selection + if (p_append && p_single) { + if (editor_selection->is_selected(p_node)) { + // Already in the selection, remove it from the selected nodes + editor_selection->remove_node(p_node); + } else { + // Add the item to the selection + editor_selection->add_node(p_node); + } + } else if (p_append && !p_single) { + // Add the item to the selection + editor_selection->add_node(p_node); } else { + // No append; single select + editor_selection->clear(); editor_selection->add_node(p_node); - } - - if (p_single) { + // Reselect if (Engine::get_singleton()->is_editor_hint()) { editor->call("edit_node", p_node); } } + + if (editor_selection->get_selected_node_list().size() == 1) { + editor->push_item(editor_selection->get_selected_node_list()[0]); + } } ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle, bool p_alt_select) { @@ -1967,6 +1976,13 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { return; } + if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_numpad")) { + const uint32_t code = k->get_keycode(); + if (code >= KEY_0 && code <= KEY_9) { + k->set_keycode(code - KEY_0 + KEY_KP_0); + } + } + if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) { if (_edit.mode != TRANSFORM_NONE) { _edit.snap = !_edit.snap; @@ -2504,15 +2520,15 @@ void Node3DEditorViewport::_notification(int p_what) { } if (show_info) { + const String viewport_size = vformat(String::utf8("%d × %d"), viewport->get_size().x, viewport->get_size().y); String text; text += vformat(TTR("X: %s\n"), rtos(current_camera->get_position().x).pad_decimals(1)); text += vformat(TTR("Y: %s\n"), rtos(current_camera->get_position().y).pad_decimals(1)); text += vformat(TTR("Z: %s\n"), rtos(current_camera->get_position().z).pad_decimals(1)); text += "\n"; text += vformat( - TTR("Size: %dx%d (%.1fMP)\n"), - viewport->get_size().x, - viewport->get_size().y, + TTR("Size: %s (%.1fMP)\n"), + viewport_size, viewport->get_size().x * viewport->get_size().y * 0.000001); text += "\n"; @@ -3250,14 +3266,12 @@ void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) { if (!preview) { preview_camera->hide(); } - view_menu->set_disabled(false); surface->update(); } else { previewing = preview; previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), preview->get_camera()); //replace - view_menu->set_disabled(true); surface->update(); } } @@ -3504,7 +3518,6 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) { previewing = Object::cast_to<Camera3D>(pv); previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), previewing->get_camera()); //replace - view_menu->set_disabled(true); surface->update(); preview_camera->set_pressed(true); preview_camera->show(); @@ -6214,31 +6227,47 @@ void Node3DEditor::_sun_environ_settings_pressed() { sun_environ_popup->popup(); } -void Node3DEditor::_add_sun_to_scene() { +void Node3DEditor::_add_sun_to_scene(bool p_already_added_environment) { sun_environ_popup->hide(); + if (!p_already_added_environment && world_env_count == 0 && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + // Prevent infinite feedback loop between the sun and environment methods. + _add_environment_to_scene(true); + } + Node *base = get_tree()->get_edited_scene_root(); if (!base) { - EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation")); - return; + // Create a root node so we can add child nodes to it. + EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D)); + base = get_tree()->get_edited_scene_root(); } ERR_FAIL_COND(!base); Node *new_sun = preview_sun->duplicate(); undo_redo->create_action("Add Preview Sun to Scene"); undo_redo->add_do_method(base, "add_child", new_sun); + // Move to the beginning of the scene tree since more "global" nodes + // generally look better when placed at the top. + undo_redo->add_do_method(base, "move_child", new_sun, 0); undo_redo->add_do_method(new_sun, "set_owner", base); undo_redo->add_undo_method(base, "remove_child", new_sun); undo_redo->add_do_reference(new_sun); undo_redo->commit_action(); } -void Node3DEditor::_add_environment_to_scene() { + +void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) { sun_environ_popup->hide(); + if (!p_already_added_sun && directional_light_count == 0 && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + // Prevent infinite feedback loop between the sun and environment methods. + _add_sun_to_scene(true); + } + Node *base = get_tree()->get_edited_scene_root(); if (!base) { - EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation")); - return; + // Create a root node so we can add child nodes to it. + EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D)); + base = get_tree()->get_edited_scene_root(); } ERR_FAIL_COND(!base); @@ -6247,6 +6276,9 @@ void Node3DEditor::_add_environment_to_scene() { undo_redo->create_action("Add Preview Environment to Scene"); undo_redo->add_do_method(base, "add_child", new_env); + // Move to the beginning of the scene tree since more "global" nodes + // generally look better when placed at the top. + undo_redo->add_do_method(base, "move_child", new_env, 0); undo_redo->add_do_method(new_env, "set_owner", base); undo_redo->add_undo_method(base, "remove_child", new_env); undo_redo->add_do_reference(new_env); @@ -7174,7 +7206,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { sun_add_to_scene = memnew(Button); sun_add_to_scene->set_text(TTR("Add Sun to Scene")); - sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene)); + sun_add_to_scene->set_tooltip(TTR("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene.")); + sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene), varray(false)); sun_vb->add_spacer(); sun_vb->add_child(sun_add_to_scene); @@ -7238,7 +7271,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { environ_add_to_scene = memnew(Button); environ_add_to_scene->set_text(TTR("Add Environment to Scene")); - environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene)); + environ_add_to_scene->set_tooltip(TTR("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene.")); + environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene), varray(false)); environ_vb->add_spacer(); environ_vb->add_child(environ_add_to_scene); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index ac0b2e1859..a195a0eee0 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -805,8 +805,8 @@ private: void _preview_settings_changed(); void _sun_environ_settings_pressed(); - void _add_sun_to_scene(); - void _add_environment_to_scene(); + void _add_sun_to_scene(bool p_already_added_environment = false); + void _add_environment_to_scene(bool p_already_added_sun = false); protected: void _notification(int p_what); diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index a7c11f8521..488aa8c861 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -367,8 +367,10 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { tree = memnew(Tree); tree->connect("button_pressed", callable_mp(this, &ResourcePreloaderEditor::_cell_button_pressed)); tree->set_columns(2); - tree->set_column_custom_minimum_width(0, 2); - tree->set_column_custom_minimum_width(1, 3); + tree->set_column_expand_ratio(0, 2); + tree->set_column_clip_content(0, true); + tree->set_column_expand_ratio(1, 3); + tree->set_column_clip_content(1, true); tree->set_column_expand(0, true); tree->set_column_expand(1, true); tree->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index b8f1c0197e..5523333fa5 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -930,11 +930,14 @@ ThemeItemImportTree::ThemeItemImportTree() { import_items_tree->set_column_title(IMPORT_ITEM, TTR("Import")); import_items_tree->set_column_title(IMPORT_ITEM_DATA, TTR("With Data")); import_items_tree->set_column_expand(0, true); + import_items_tree->set_column_clip_content(0, true); import_items_tree->set_column_expand(IMPORT_ITEM, false); import_items_tree->set_column_expand(IMPORT_ITEM_DATA, false); import_items_tree->set_column_custom_minimum_width(0, 160 * EDSCALE); import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM, 80 * EDSCALE); import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM_DATA, 80 * EDSCALE); + import_items_tree->set_column_clip_content(1, true); + import_items_tree->set_column_clip_content(2, true); ScrollContainer *import_bulk_sc = memnew(ScrollContainer); import_bulk_sc->set_custom_minimum_size(Size2(260.0, 0.0) * EDSCALE); diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 75a944e910..10679ad6f2 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -476,6 +476,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { version_control_dock = memnew(PanelContainer); version_control_dock->set_v_size_flags(Control::SIZE_EXPAND_FILL); + version_control_dock->set_custom_minimum_size(Size2(0, 300) * EDSCALE); version_control_dock->hide(); diff_vbc = memnew(VBoxContainer); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index bf6cff6d8b..f438d9bab8 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -110,6 +110,7 @@ void VisualShaderGraphPlugin::_bind_methods() { ClassDB::bind_method("set_uniform_name", &VisualShaderGraphPlugin::set_uniform_name); ClassDB::bind_method("set_expression", &VisualShaderGraphPlugin::set_expression); ClassDB::bind_method("update_curve", &VisualShaderGraphPlugin::update_curve); + ClassDB::bind_method("update_curve3", &VisualShaderGraphPlugin::update_curve3); ClassDB::bind_method("update_constant", &VisualShaderGraphPlugin::update_constant); } @@ -211,9 +212,19 @@ void VisualShaderGraphPlugin::set_uniform_name(VisualShader::Type p_type, int p_ } void VisualShaderGraphPlugin::update_curve(int p_node_id) { - if (links.has(p_node_id) && links[p_node_id].curve_editor) { + if (links.has(p_node_id) && links[p_node_id].curve_editors[0]) { if (((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) { - links[p_node_id].curve_editor->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve()); + links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve()); + } + } +} + +void VisualShaderGraphPlugin::update_curve3(int p_node_id) { + if (links.has(p_node_id) && links[p_node_id].curve_editors[0] && links[p_node_id].curve_editors[1] && links[p_node_id].curve_editors[2]) { + if (((VisualShaderNodeCurve3Texture *)links[p_node_id].visual_node)->get_texture().is_valid()) { + links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurve3Texture *)links[p_node_id].visual_node)->get_texture()->get_curve_x()); + links[p_node_id].curve_editors[1]->set_curve(((VisualShaderNodeCurve3Texture *)links[p_node_id].visual_node)->get_texture()->get_curve_y()); + links[p_node_id].curve_editors[2]->set_curve(((VisualShaderNodeCurve3Texture *)links[p_node_id].visual_node)->get_texture()->get_curve_z()); } } } @@ -265,8 +276,8 @@ void VisualShaderGraphPlugin::register_expression_edit(int p_node_id, CodeEdit * links[p_node_id].expression_edit = p_expression_edit; } -void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, CurveEditor *p_curve_editor) { - links[p_node_id].curve_editor = p_curve_editor; +void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor) { + links[p_node_id].curve_editors[p_index] = p_curve_editor; } void VisualShaderGraphPlugin::update_uniform_refs() { @@ -312,7 +323,7 @@ void VisualShaderGraphPlugin::make_dirty(bool p_enabled) { } void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) { - links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, nullptr, nullptr }); + links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } }); } void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) { @@ -472,6 +483,18 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { custom_editor = hbox; } + Ref<VisualShaderNodeCurve3Texture> curve3 = vsnode; + if (curve3.is_valid()) { + if (curve3->get_texture().is_valid() && !curve3->get_texture()->is_connected("changed", callable_mp(VisualShaderEditor::get_singleton()->get_graph_plugin(), &VisualShaderGraphPlugin::update_curve3))) { + curve3->get_texture()->connect("changed", callable_mp(VisualShaderEditor::get_singleton()->get_graph_plugin(), &VisualShaderGraphPlugin::update_curve3), varray(p_id)); + } + + HBoxContainer *hbox = memnew(HBoxContainer); + custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + hbox->add_child(custom_editor); + custom_editor = hbox; + } + Ref<VisualShaderNodeFloatConstant> float_const = vsnode; if (float_const.is_valid()) { HBoxContainer *hbox = memnew(HBoxContainer); @@ -495,19 +518,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { port_offset++; node->add_child(custom_editor); - if (curve.is_valid()) { + bool is_curve = curve.is_valid() || curve3.is_valid(); + + if (is_curve) { VisualShaderEditor::get_singleton()->graph->add_child(node); VisualShaderEditor::get_singleton()->_update_created_node(node); - CurveEditor *curve_editor = memnew(CurveEditor); - node->add_child(curve_editor); - register_curve_editor(p_id, curve_editor); - curve_editor->set_custom_minimum_size(Size2(300, 0)); - curve_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); - if (curve->get_texture().is_valid()) { - curve_editor->set_curve(curve->get_texture()->get_curve()); - } - TextureButton *preview = memnew(TextureButton); preview->set_toggle_mode(true); preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons")); @@ -519,12 +535,59 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, 0), CONNECT_DEFERRED); custom_editor->add_child(preview); + if (vsnode->get_output_port_for_preview() >= 0) { + show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview()); + } + } + + if (curve.is_valid()) { + CurveEditor *curve_editor = memnew(CurveEditor); + node->add_child(curve_editor); + register_curve_editor(p_id, 0, curve_editor); + curve_editor->set_custom_minimum_size(Size2(300, 0)); + curve_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + if (curve->get_texture().is_valid()) { + curve_editor->set_curve(curve->get_texture()->get_curve()); + } + } + + if (curve3.is_valid()) { + CurveEditor *curve_editor_x = memnew(CurveEditor); + node->add_child(curve_editor_x); + register_curve_editor(p_id, 0, curve_editor_x); + curve_editor_x->set_custom_minimum_size(Size2(300, 0)); + curve_editor_x->set_h_size_flags(Control::SIZE_EXPAND_FILL); + if (curve3->get_texture().is_valid()) { + curve_editor_x->set_curve(curve3->get_texture()->get_curve_x()); + } + + CurveEditor *curve_editor_y = memnew(CurveEditor); + node->add_child(curve_editor_y); + register_curve_editor(p_id, 1, curve_editor_y); + curve_editor_y->set_custom_minimum_size(Size2(300, 0)); + curve_editor_y->set_h_size_flags(Control::SIZE_EXPAND_FILL); + if (curve3->get_texture().is_valid()) { + curve_editor_y->set_curve(curve3->get_texture()->get_curve_y()); + } + + CurveEditor *curve_editor_z = memnew(CurveEditor); + node->add_child(curve_editor_z); + register_curve_editor(p_id, 2, curve_editor_z); + curve_editor_z->set_custom_minimum_size(Size2(300, 0)); + curve_editor_z->set_h_size_flags(Control::SIZE_EXPAND_FILL); + if (curve3->get_texture().is_valid()) { + curve_editor_z->set_curve(curve3->get_texture()->get_curve_z()); + } + } + + if (is_curve) { VisualShaderNode::PortType port_left = vsnode->get_input_port_type(0); VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); node->set_slot(0, true, port_left, type_color[port_left], true, port_right, type_color[port_right]); VisualShaderEditor::get_singleton()->call_deferred("_set_node_size", (int)p_type, p_id, size); } + if (vsnode->is_use_prop_slots()) { return; } @@ -888,6 +951,7 @@ void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id) { void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { if (visual_shader->get_shader_type() == p_type) { VisualShaderEditor::get_singleton()->graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); + connections.push_back({ p_from_node, p_from_port, p_to_node, p_to_port }); if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr) { links[p_to_node].input_ports[p_to_port].default_input_button->hide(); } @@ -897,6 +961,12 @@ void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_fro void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { if (visual_shader->get_shader_type() == p_type) { VisualShaderEditor::get_singleton()->graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); + for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { + if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { + connections.erase(E); + break; + } + } if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr && links[p_to_node].visual_node->get_input_port_default_value(p_to_port).get_type() != Variant::NIL) { links[p_to_node].input_ports[p_to_port].default_input_button->show(); set_input_port_default_value(p_type, p_to_node, p_to_port, links[p_to_node].visual_node->get_input_port_default_value(p_to_port)); @@ -2204,6 +2274,8 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, int p_op_idx) { void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_path, int p_node_idx) { ERR_FAIL_INDEX(p_idx, add_options.size()); + VisualShader::Type type = get_current_shader_type(); + Ref<VisualShaderNode> vsnode; bool is_custom = add_options[p_idx].is_custom; @@ -2230,6 +2302,29 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa } } + VisualShaderNodeUniformRef *uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(vsn); + + if (uniform_ref && to_node != -1 && to_slot != -1) { + VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot); + bool success = false; + + for (int i = 0; i < uniform_ref->get_uniforms_count(); i++) { + if (uniform_ref->get_port_type_by_index(i) == input_port_type) { + uniform_ref->set_uniform_name(uniform_ref->get_uniform_name_by_index(i)); + success = true; + break; + } + } + if (!success) { + for (int i = 0; i < uniform_ref->get_uniforms_count(); i++) { + if (visual_shader->is_port_types_compatible(uniform_ref->get_port_type_by_index(i), input_port_type)) { + uniform_ref->set_uniform_name(uniform_ref->get_uniform_name_by_index(i)); + break; + } + } + } + } + vsnode = Ref<VisualShaderNode>(vsn); } else { ERR_FAIL_COND(add_options[p_idx].script.is_null()); @@ -2250,8 +2345,6 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa } saved_node_pos_dirty = false; - VisualShader::Type type = get_current_shader_type(); - int id_to_use = visual_shader->get_valid_node_id(type); if (p_resource_path.is_empty()) { @@ -2380,6 +2473,11 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa graph_plugin->call_deferred("update_curve", id_to_use); } + VisualShaderNodeCurve3Texture *curve3 = Object::cast_to<VisualShaderNodeCurve3Texture>(vsnode.ptr()); + if (curve3) { + graph_plugin->call_deferred("update_curve3", id_to_use); + } + if (p_resource_path.is_empty()) { undo_redo->commit_action(); } else { @@ -2388,7 +2486,7 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa VisualShaderNodeTexture *texture2d = Object::cast_to<VisualShaderNodeTexture>(vsnode.ptr()); VisualShaderNodeTexture3D *texture3d = Object::cast_to<VisualShaderNodeTexture3D>(vsnode.ptr()); - if (texture2d || texture3d || curve) { + if (texture2d || texture3d || curve || curve3) { undo_redo->add_do_method(vsnode.ptr(), "set_texture", ResourceLoader::load(p_resource_path)); return; } @@ -3583,6 +3681,10 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE); saved_node_pos_dirty = true; _add_node(curve_node_option_idx, -1, arr[i], i); + } else if (type == "Curve3Texture") { + saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE); + saved_node_pos_dirty = true; + _add_node(curve3_node_option_idx, -1, arr[i], i); } else if (ClassDB::get_parent_class(type) == "Texture2D") { saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE); saved_node_pos_dirty = true; @@ -4304,6 +4406,8 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), -1, -1)); curve_node_option_idx = add_options.size(); add_options.push_back(AddOption("CurveTexture", "Textures", "Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), -1, -1)); + curve3_node_option_idx = add_options.size(); + add_options.push_back(AddOption("CurveTexture3", "Textures", "Functions", "VisualShaderNodeCurve3Texture", TTR("Perform the ternary curve texture lookup."), -1, -1)); texture2d_node_option_idx = add_options.size(); add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), -1, -1)); texture2d_array_node_option_idx = add_options.size(); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index d549a35306..2b354db7b3 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -75,7 +75,7 @@ private: LineEdit *uniform_name = nullptr; OptionButton *const_op = nullptr; CodeEdit *expression_edit = nullptr; - CurveEditor *curve_editor = nullptr; + CurveEditor *curve_editors[3] = { nullptr, nullptr, nullptr }; }; Ref<VisualShader> visual_shader; @@ -97,7 +97,7 @@ public: void register_default_input_button(int p_node_id, int p_port_id, Button *p_button); void register_constant_option_btn(int p_node_id, OptionButton *p_button); void register_expression_edit(int p_node_id, CodeEdit *p_expression_edit); - void register_curve_editor(int p_node_id, CurveEditor *p_curve_editor); + void register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor); void clear_links(); void set_shader_type(VisualShader::Type p_type); bool is_preview_visible(int p_id) const; @@ -117,6 +117,7 @@ public: void update_uniform_refs(); void set_uniform_name(VisualShader::Type p_type, int p_node_id, const String &p_name); void update_curve(int p_node_id); + void update_curve3(int p_node_id); void update_constant(VisualShader::Type p_type, int p_node_id); void set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression); int get_constant_index(float p_constant) const; @@ -289,6 +290,7 @@ class VisualShaderEditor : public VBoxContainer { int texture3d_node_option_idx; int custom_node_option_idx; int curve_node_option_idx; + int curve3_node_option_idx; List<String> keyword_list; List<VisualShaderNodeUniformRef> uniform_refs; diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp index d30cc7ad17..162379a49d 100644 --- a/editor/plugins/voxel_gi_editor_plugin.cpp +++ b/editor/plugins/voxel_gi_editor_plugin.cpp @@ -69,10 +69,7 @@ void VoxelGIEditorPlugin::_notification(int p_what) { const Vector3i size = voxel_gi->get_estimated_cell_size(); String text = vformat(String::utf8("%d × %d × %d"), size.x, size.y, size.z); - int data_size = 4; - if (GLOBAL_GET("rendering/quality/voxel_gi/anisotropic")) { - data_size += 4; - } + const int data_size = 4; const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0); text += " - " + vformat(TTR("VRAM Size: %s MB"), String::num(size_mb, 2)); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 75736a0723..ad88e1b45b 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -64,6 +64,7 @@ void ProjectExportDialog::_notification(int p_what) { duplicate_preset->set_icon(presets->get_theme_icon("Duplicate", "EditorIcons")); delete_preset->set_icon(presets->get_theme_icon("Remove", "EditorIcons")); connect("confirmed", callable_mp(this, &ProjectExportDialog::_export_pck_zip)); + _update_export_all(); } break; } } @@ -182,10 +183,12 @@ void ProjectExportDialog::_update_export_all() { } } + export_all_button->set_disabled(!can_export); + if (can_export) { - export_all_button->set_disabled(false); + export_all_button->set_tooltip(TTR("Export the project for all the presets defined.")); } else { - export_all_button->set_disabled(true); + export_all_button->set_tooltip(TTR("All presets must have an export path defined for Export All to work.")); } } @@ -433,6 +436,7 @@ void ProjectExportDialog::_export_path_changed(const StringName &p_property, con current->set_export_path(p_value); _update_presets(); + _update_export_all(); } void ProjectExportDialog::_enc_filters_changed(const String &p_filters) { @@ -589,6 +593,10 @@ void ProjectExportDialog::_delete_preset_confirm() { get_ok_button()->set_disabled(true); EditorExport::get_singleton()->remove_export_preset(idx); _update_presets(); + + // The Export All button might become enabled (if all other presets have an export path defined), + // or it could be disabled (if there are no presets anymore). + _update_export_all(); } Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) { @@ -1199,8 +1207,8 @@ ProjectExportDialog::ProjectExportDialog() { updating = false; get_cancel_button()->set_text(TTR("Close")); - get_ok_button()->set_text(TTR("Export PCK/Zip")); - export_button = add_button(TTR("Export Project"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export"); + get_ok_button()->set_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 export_button->set_disabled(true); @@ -1209,19 +1217,19 @@ ProjectExportDialog::ProjectExportDialog() { export_all_dialog = memnew(ConfirmationDialog); add_child(export_all_dialog); export_all_dialog->set_title("Export All"); - export_all_dialog->set_text(TTR("Export mode?")); + export_all_dialog->set_text(TTR("Choose an export mode:")); export_all_dialog->get_ok_button()->hide(); export_all_dialog->add_button(TTR("Debug"), true, "debug"); export_all_dialog->add_button(TTR("Release"), true, "release"); export_all_dialog->connect("custom_action", callable_mp(this, &ProjectExportDialog::_export_all_dialog_action)); - export_all_button = add_button(TTR("Export All"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export"); + export_all_button = add_button(TTR("Export All..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export"); export_all_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_all_dialog)); 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 Game Pack")); + 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); @@ -1282,8 +1290,6 @@ ProjectExportDialog::ProjectExportDialog() { default_filename = "UnnamedProject"; } } - - _update_export_all(); } ProjectExportDialog::~ProjectExportDialog() { diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 262861cb11..a9dcbc9f09 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -359,7 +359,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; } - if (reset_create_dialog) { + if (reset_create_dialog && !p_confirm_override) { create_dialog->set_base_type("Node"); reset_create_dialog = false; } @@ -1134,12 +1134,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } } - editor_data->get_undo_redo().create_action(TTR("New Scene Root")); - editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", new_node); - editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree"); - editor_data->get_undo_redo().add_do_reference(new_node); - editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)nullptr); - editor_data->get_undo_redo().commit_action(); + add_root_node(new_node); editor->edit_node(new_node); editor_selection->clear(); @@ -1162,6 +1157,15 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } } +void SceneTreeDock::add_root_node(Node *p_node) { + editor_data->get_undo_redo().create_action(TTR("New Scene Root")); + editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", p_node); + editor_data->get_undo_redo().add_do_method(scene_tree, "update_tree"); + editor_data->get_undo_redo().add_do_reference(p_node); + editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)nullptr); + editor_data->get_undo_redo().commit_action(); +} + void SceneTreeDock::_node_collapsed(Object *p_obj) { TreeItem *ti = Object::cast_to<TreeItem>(p_obj); if (!ti) { @@ -1202,9 +1206,6 @@ void SceneTreeDock::_notification(int p_what) { filter->set_right_icon(get_theme_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); - EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed)); - scene_tree->get_scene_tree()->connect("item_collapsed", callable_mp(this, &SceneTreeDock::_node_collapsed)); - // create_root_dialog HBoxContainer *top_row = memnew(HBoxContainer); top_row->set_name("NodeShortcutsTopRow"); @@ -3212,6 +3213,9 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel scene_tree->connect("nodes_dragged", callable_mp(this, &SceneTreeDock::_nodes_drag_begin)); scene_tree->get_scene_tree()->connect("item_double_clicked", callable_mp(this, &SceneTreeDock::_focus_node)); + scene_tree->get_scene_tree()->connect("item_collapsed", callable_mp(this, &SceneTreeDock::_node_collapsed)); + + editor_selection->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed)); scene_tree->set_undo_redo(&editor_data->get_undo_redo()); scene_tree->set_editor_selection(editor_selection); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 88c4a85f4c..08d992d465 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -261,6 +261,7 @@ public: void _focus_node(); void import_subscene(); + void add_root_node(Node *p_node); void set_edited_scene(Node *p_scene); void instantiate(const String &p_file); void instantiate_scenes(const Vector<String> &p_files, Node *p_parent = nullptr); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 3aa04e4dc3..ee66f28045 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -659,7 +659,14 @@ void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_ } else { editor_selection->remove_node(n); } - emit_signal("node_changed"); + + // Selection changed to be single node, so emit "selected" (for single node) rather than "changed" (for multiple nodes) + if (editor_selection->get_selected_nodes().size() == 1) { + selected = editor_selection->get_selected_node_list()[0]; + emit_signal("node_selected"); + } else { + emit_signal("node_changed"); + } } void SceneTreeEditor::_notification(int p_what) { diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 50f05345da..b5028096e0 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -40,38 +40,35 @@ #include "editor/editor_scale.h" #include "editor_file_system.h" -void ScriptCreateDialog::_theme_changed() { - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - String lang = ScriptServer::get_language(i)->get_type(); - Ref<Texture2D> lang_icon = gc->get_theme_icon(lang, "EditorIcons"); - if (lang_icon.is_valid()) { - language_menu->set_item_icon(i, lang_icon); - } - } - - String last_lang = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", ""); - if (!last_lang.is_empty()) { - for (int i = 0; i < language_menu->get_item_count(); i++) { - if (language_menu->get_item_text(i) == last_lang) { - language_menu->select(i); - current_language = i; - break; +void ScriptCreateDialog::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + String lang = ScriptServer::get_language(i)->get_type(); + Ref<Texture2D> lang_icon = get_theme_icon(lang, "EditorIcons"); + if (lang_icon.is_valid()) { + language_menu->set_item_icon(i, lang_icon); + } } - } - } else { - language_menu->select(default_language); - } - path_button->set_icon(gc->get_theme_icon("Folder", "EditorIcons")); - parent_browse_button->set_icon(gc->get_theme_icon("Folder", "EditorIcons")); - parent_search_button->set_icon(gc->get_theme_icon("ClassList", "EditorIcons")); - status_panel->add_theme_style_override("panel", gc->get_theme_stylebox("bg", "Tree")); -} + String last_lang = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", ""); + if (!last_lang.is_empty()) { + for (int i = 0; i < language_menu->get_item_count(); i++) { + if (language_menu->get_item_text(i) == last_lang) { + language_menu->select(i); + current_language = i; + break; + } + } + } else { + language_menu->select(default_language); + } -void ScriptCreateDialog::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - _theme_changed(); + path_button->set_icon(get_theme_icon("Folder", "EditorIcons")); + parent_browse_button->set_icon(get_theme_icon("Folder", "EditorIcons")); + parent_search_button->set_icon(get_theme_icon("ClassList", "EditorIcons")); + status_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); } break; } } @@ -451,7 +448,7 @@ void ScriptCreateDialog::_lang_changed(int l) { override_info += ", "; } } - template_menu->set_item_icon(extended.id, gc->get_theme_icon("Override", "EditorIcons")); + template_menu->set_item_icon(extended.id, get_theme_icon("Override", "EditorIcons")); template_menu->get_popup()->set_item_tooltip(extended.id, override_info.as_string()); } // Reselect last selected template @@ -609,18 +606,18 @@ void ScriptCreateDialog::_path_submitted(const String &p_path) { void ScriptCreateDialog::_msg_script_valid(bool valid, const String &p_msg) { error_label->set_text("- " + p_msg); if (valid) { - error_label->add_theme_color_override("font_color", gc->get_theme_color("success_color", "Editor")); + error_label->add_theme_color_override("font_color", get_theme_color("success_color", "Editor")); } else { - error_label->add_theme_color_override("font_color", gc->get_theme_color("error_color", "Editor")); + error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); } } void ScriptCreateDialog::_msg_path_valid(bool valid, const String &p_msg) { path_error_label->set_text("- " + p_msg); if (valid) { - path_error_label->add_theme_color_override("font_color", gc->get_theme_color("success_color", "Editor")); + path_error_label->add_theme_color_override("font_color", get_theme_color("success_color", "Editor")); } else { - path_error_label->add_theme_color_override("font_color", gc->get_theme_color("error_color", "Editor")); + path_error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); } } @@ -748,15 +745,11 @@ void ScriptCreateDialog::_bind_methods() { } ScriptCreateDialog::ScriptCreateDialog() { - /* DIALOG */ - /* Main Controls */ - gc = memnew(GridContainer); + GridContainer *gc = memnew(GridContainer); gc->set_columns(2); - gc->connect("theme_changed", callable_mp(this, &ScriptCreateDialog::_theme_changed)); - /* Error Messages Field */ VBoxContainer *vb = memnew(VBoxContainer); @@ -832,7 +825,6 @@ ScriptCreateDialog::ScriptCreateDialog() { parent_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(parent_name); parent_search_button = memnew(Button); - parent_search_button->set_flat(true); parent_search_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_class_in_tree)); hb->add_child(parent_search_button); parent_browse_button = memnew(Button); diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h index a020be0478..7c2ef1e150 100644 --- a/editor/script_create_dialog.h +++ b/editor/script_create_dialog.h @@ -45,7 +45,6 @@ class CreateDialog; class ScriptCreateDialog : public ConfirmationDialog { GDCLASS(ScriptCreateDialog, ConfirmationDialog); - GridContainer *gc; LineEdit *class_name; Label *error_label; Label *path_error_label; @@ -127,7 +126,6 @@ class ScriptCreateDialog : public ConfirmationDialog { void _update_dialog(); protected: - void _theme_changed(); void _notification(int p_what); static void _bind_methods(); |
