From 2f1e7c28a48b8a36c0131cc0320e07859f9da8e8 Mon Sep 17 00:00:00 2001 From: Hendrik Brucker Date: Tue, 1 Feb 2022 00:19:01 +0100 Subject: Minor fixes/refactoring of project and editor setting dialogs --- editor/editor_node.cpp | 20 +- editor/editor_node.h | 6 +- editor/editor_properties.cpp | 11 +- editor/editor_settings_dialog.cpp | 720 +++++++++++++++++++++++++++++++++++++ editor/editor_settings_dialog.h | 131 +++++++ editor/project_settings_editor.cpp | 94 +++-- editor/project_settings_editor.h | 6 +- editor/settings_config_dialog.cpp | 720 ------------------------------------- editor/settings_config_dialog.h | 131 ------- main/main.cpp | 6 +- 10 files changed, 947 insertions(+), 898 deletions(-) create mode 100644 editor/editor_settings_dialog.cpp create mode 100644 editor/editor_settings_dialog.h delete mode 100644 editor/settings_config_dialog.cpp delete mode 100644 editor/settings_config_dialog.h diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index a1f259c864..ded6e0b309 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -93,6 +93,7 @@ #include "editor/editor_run_script.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_settings_dialog.h" #include "editor/editor_spin_slider.h" #include "editor/editor_themes.h" #include "editor/editor_toaster.h" @@ -190,7 +191,6 @@ #include "editor/project_settings_editor.h" #include "editor/quick_open.h" #include "editor/register_exporters.h" -#include "editor/settings_config_dialog.h" #include #include @@ -822,8 +822,8 @@ void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_nam if (p_activate_name.length()) { set_addon_plugin_enabled(p_activate_name, true); } - project_settings->update_plugins(); - project_settings->hide(); + project_settings_editor->update_plugins(); + project_settings_editor->hide(); push_item(script.operator->()); } @@ -2773,7 +2773,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_SETTINGS: { - project_settings->popup_project_settings(); + project_settings_editor->popup_project_settings(); } break; case FILE_INSTALL_ANDROID_SOURCE: { if (p_confirmed) { @@ -2846,7 +2846,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { _update_update_spinner(); } break; case SETTINGS_PREFERENCES: { - settings_config_dialog->popup_edit_settings(); + editor_settings_dialog->popup_edit_settings(); } break; case SETTINGS_EDITOR_DATA_FOLDER: { OS::get_singleton()->shell_open(String("file://") + EditorPaths::get_singleton()->get_data_dir()); @@ -3240,7 +3240,7 @@ void EditorNode::_update_addon_config() { ProjectSettings::get_singleton()->set("editor_plugins/enabled", enabled_addons); } - project_settings->queue_save(); + project_settings_editor->queue_save(); } void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed) { @@ -6325,11 +6325,11 @@ EditorNode::EditorNode() { dependency_fixer = memnew(DependencyEditor); gui_base->add_child(dependency_fixer); - settings_config_dialog = memnew(EditorSettingsDialog); - gui_base->add_child(settings_config_dialog); + editor_settings_dialog = memnew(EditorSettingsDialog); + gui_base->add_child(editor_settings_dialog); - project_settings = memnew(ProjectSettingsEditor(&editor_data)); - gui_base->add_child(project_settings); + project_settings_editor = memnew(ProjectSettingsEditor(&editor_data)); + gui_base->add_child(project_settings_editor); scene_import_settings = memnew(SceneImportSettings); gui_base->add_child(scene_import_settings); diff --git a/editor/editor_node.h b/editor/editor_node.h index f8489777bd..5c013a18d9 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -323,8 +323,8 @@ private: ConfirmationDialog *install_android_build_template; ConfirmationDialog *remove_android_build_template; - EditorSettingsDialog *settings_config_dialog; - ProjectSettingsEditor *project_settings; + EditorSettingsDialog *editor_settings_dialog; + ProjectSettingsEditor *project_settings_editor; bool settings_changed = true; // make it update settings on first frame void _update_from_settings(); @@ -713,7 +713,7 @@ public: EditorPluginList *get_editor_plugins_force_over() { return editor_plugins_force_over; } EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; } - ProjectSettingsEditor *get_project_settings() { return project_settings; } + ProjectSettingsEditor *get_project_settings() { return project_settings_editor; } static void add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); static void remove_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index bce553661c..36e42b8e9b 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1263,7 +1263,7 @@ void EditorPropertyInteger::_bind_methods() { void EditorPropertyInteger::setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_allow_greater, bool p_allow_lesser) { spin->set_min(p_min); spin->set_max(p_max); - spin->set_step(p_step); + spin->set_step((p_step == 0) ? 1 : p_step); spin->set_allow_greater(p_allow_greater); spin->set_allow_lesser(p_allow_lesser); } @@ -1353,7 +1353,7 @@ void EditorPropertyFloat::setup(double p_min, double p_max, double p_step, bool angle_in_radians = p_angle_in_radians; spin->set_min(p_min); spin->set_max(p_max); - spin->set_step(p_step); + spin->set_step((p_step == 0) ? 0.1 : p_step); spin->set_hide_slider(p_no_slider); spin->set_exp_ratio(p_exp_range); spin->set_allow_greater(p_greater); @@ -3435,7 +3435,9 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyInteger *editor = memnew(EditorPropertyInteger); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); - + if (hint.step == 0) { + WARN_PRINT(p_path + ": Range step size is 0."); + } editor->setup(hint.min, hint.max, hint.step, hint.greater, hint.lesser); return editor; @@ -3464,6 +3466,9 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyFloat *editor = memnew(EditorPropertyFloat); EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + if (hint.step == 0) { + WARN_PRINT(p_path + ": Range step size is 0."); + } editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.exp_range, hint.greater, hint.lesser, hint.suffix, hint.radians); return editor; diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp new file mode 100644 index 0000000000..2520d662c5 --- /dev/null +++ b/editor/editor_settings_dialog.cpp @@ -0,0 +1,720 @@ +/*************************************************************************/ +/* editor_settings_dialog.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "editor_settings_dialog.h" + +#include "core/config/project_settings.h" +#include "core/input/input_map.h" +#include "core/os/keyboard.h" +#include "editor/debugger/editor_debugger_node.h" +#include "editor_file_system.h" +#include "editor_log.h" +#include "editor_node.h" +#include "editor_scale.h" +#include "editor_settings.h" +#include "scene/gui/margin_container.h" + +void EditorSettingsDialog::ok_pressed() { + if (!EditorSettings::get_singleton()) { + return; + } + + _settings_save(); + timer->stop(); +} + +void EditorSettingsDialog::_settings_changed() { + timer->start(); +} + +void EditorSettingsDialog::_settings_property_edited(const String &p_name) { + String full_name = inspector->get_full_item_path(p_name); + + if (full_name == "interface/theme/accent_color" || full_name == "interface/theme/base_color" || full_name == "interface/theme/contrast") { + EditorSettings::get_singleton()->set_manually("interface/theme/preset", "Custom"); // set preset to Custom + } else if (full_name.begins_with("text_editor/theme/highlighting")) { + EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom"); + } +} + +void EditorSettingsDialog::_settings_save() { + EditorSettings::get_singleton()->notify_changes(); + EditorSettings::get_singleton()->save(); +} + +void EditorSettingsDialog::cancel_pressed() { + if (!EditorSettings::get_singleton()) { + return; + } + + EditorSettings::get_singleton()->notify_changes(); +} + +void EditorSettingsDialog::popup_edit_settings() { + if (!EditorSettings::get_singleton()) { + return; + } + + EditorSettings::get_singleton()->list_text_editor_themes(); // make sure we have an up to date list of themes + + inspector->edit(EditorSettings::get_singleton()); + inspector->get_inspector()->update_tree(); + + search_box->select_all(); + search_box->grab_focus(); + + _update_shortcuts(); + set_process_unhandled_input(true); + + // Restore valid window bounds or pop up at default size. + Rect2 saved_size = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "editor_settings", Rect2()); + if (saved_size != Rect2()) { + popup(saved_size); + } else { + popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); + } + + _focus_current_search_box(); +} + +void EditorSettingsDialog::_filter_shortcuts(const String &p_filter) { + shortcut_filter = p_filter; + _update_shortcuts(); +} + +void EditorSettingsDialog::_undo_redo_callback(void *p_self, const String &p_name) { + EditorNode::get_log()->add_message(p_name, EditorLog::MSG_TYPE_EDITOR); +} + +void EditorSettingsDialog::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "editor_settings", Rect2(get_position(), get_size())); + set_process_unhandled_input(false); + } + } break; + case NOTIFICATION_READY: { + undo_redo->set_method_notify_callback(EditorDebuggerNode::_method_changeds, nullptr); + undo_redo->set_property_notify_callback(EditorDebuggerNode::_property_changeds, nullptr); + undo_redo->set_commit_notify_callback(_undo_redo_callback, this); + } break; + case NOTIFICATION_ENTER_TREE: { + _update_icons(); + } break; + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + _update_icons(); + // Update theme colors. + inspector->update_category_list(); + _update_shortcuts(); + } break; + } +} + +void EditorSettingsDialog::unhandled_input(const Ref &p_event) { + ERR_FAIL_COND(p_event.is_null()); + + const Ref k = p_event; + + if (k.is_valid() && k->is_pressed()) { + bool handled = false; + + if (ED_IS_SHORTCUT("ui_undo", p_event)) { + String action = undo_redo->get_current_action_name(); + if (!action.is_empty()) { + EditorNode::get_log()->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR); + } + undo_redo->undo(); + handled = true; + } + + if (ED_IS_SHORTCUT("ui_redo", p_event)) { + undo_redo->redo(); + String action = undo_redo->get_current_action_name(); + if (!action.is_empty()) { + EditorNode::get_log()->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR); + } + handled = true; + } + + if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F)) { + _focus_current_search_box(); + handled = true; + } + + if (handled) { + set_input_as_handled(); + } + } +} + +void EditorSettingsDialog::_update_icons() { + search_box->set_right_icon(shortcuts->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + search_box->set_clear_button_enabled(true); + shortcut_search_box->set_right_icon(shortcuts->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + shortcut_search_box->set_clear_button_enabled(true); + + restart_close_button->set_icon(shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); + restart_container->add_theme_style_override("panel", shortcuts->get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + restart_icon->set_texture(shortcuts->get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); + restart_label->add_theme_color_override("font_color", shortcuts->get_theme_color(SNAME("warning_color"), SNAME("Editor"))); +} + +void EditorSettingsDialog::_event_config_confirmed() { + Ref k = shortcut_editor->get_event(); + if (k.is_null()) { + return; + } + + if (current_event_index == -1) { + // Add new event + current_events.push_back(k); + } else { + // Edit existing event + current_events[current_event_index] = k; + } + + if (is_editing_action) { + _update_builtin_action(current_edited_identifier, current_events); + } else { + _update_shortcut_events(current_edited_identifier, current_events); + } +} + +void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Array &p_events) { + Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(p_name); + + undo_redo->create_action(TTR("Edit Built-in Action") + " '" + p_name + "'"); + undo_redo->add_do_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, p_events); + undo_redo->add_undo_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, old_input_array); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); + + _update_shortcuts(); +} + +void EditorSettingsDialog::_update_shortcut_events(const String &p_path, const Array &p_events) { + Ref current_sc = EditorSettings::get_singleton()->get_shortcut(p_path); + + undo_redo->create_action(TTR("Edit Shortcut") + " '" + p_path + "'"); + undo_redo->add_do_method(current_sc.ptr(), "set_events", p_events); + undo_redo->add_undo_method(current_sc.ptr(), "set_events", current_sc->get_events()); + undo_redo->add_do_method(this, "_update_shortcuts"); + undo_redo->add_undo_method(this, "_update_shortcuts"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); +} + +Array EditorSettingsDialog::_event_list_to_array_helper(List> &p_events) { + Array events; + + // Convert the list to an array, and only keep key events as this is for the editor. + for (List>::Element *E = p_events.front(); E; E = E->next()) { + Ref k = E->get(); + if (k.is_valid()) { + events.append(E->get()); + } + } + + return events; +} + +void EditorSettingsDialog::_create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_action, bool p_is_collapsed) { + TreeItem *shortcut_item = shortcuts->create_item(p_parent); + shortcut_item->set_collapsed(p_is_collapsed); + shortcut_item->set_text(0, p_display); + + Ref primary = p_events.size() > 0 ? Ref(p_events[0]) : Ref(); + Ref secondary = p_events.size() > 1 ? Ref(p_events[1]) : Ref(); + + String sc_text = "None"; + if (primary.is_valid()) { + sc_text = primary->as_text(); + + if (secondary.is_valid()) { + sc_text += ", " + secondary->as_text(); + + if (p_events.size() > 2) { + sc_text += " (+" + itos(p_events.size() - 2) + ")"; + } + } + } + + shortcut_item->set_text(1, sc_text); + if (sc_text == "None") { + // Fade out unassigned shortcut labels for easier visual grepping. + shortcut_item->set_custom_color(1, shortcuts->get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.5)); + } + + if (p_allow_revert) { + shortcut_item->add_button(1, shortcuts->get_theme_icon("Reload", "EditorIcons"), SHORTCUT_REVERT); + } + + shortcut_item->add_button(1, shortcuts->get_theme_icon("Add", "EditorIcons"), SHORTCUT_ADD); + shortcut_item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), SHORTCUT_ERASE); + + shortcut_item->set_meta("is_action", p_is_action); + shortcut_item->set_meta("type", "shortcut"); + shortcut_item->set_meta("shortcut_identifier", p_shortcut_identifier); + shortcut_item->set_meta("events", p_events); + + // Shortcut Input Events + for (int i = 0; i < p_events.size(); i++) { + Ref ie = p_events[i]; + if (ie.is_null()) { + continue; + } + + TreeItem *event_item = shortcuts->create_item(shortcut_item); + + event_item->set_text(0, shortcut_item->get_child_count() == 1 ? "Primary" : ""); + event_item->set_text(1, ie->as_text()); + + event_item->add_button(1, shortcuts->get_theme_icon("Edit", "EditorIcons"), SHORTCUT_EDIT); + event_item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), SHORTCUT_ERASE); + + event_item->set_custom_bg_color(0, shortcuts->get_theme_color("dark_color_3", "Editor")); + event_item->set_custom_bg_color(1, shortcuts->get_theme_color("dark_color_3", "Editor")); + + event_item->set_meta("is_action", p_is_action); + event_item->set_meta("type", "event"); + event_item->set_meta("event_index", i); + } +} + +void EditorSettingsDialog::_update_shortcuts() { + // Before clearing the tree, take note of which categories are collapsed so that this state can be maintained when the tree is repopulated. + Map collapsed; + + if (shortcuts->get_root() && shortcuts->get_root()->get_first_child()) { + TreeItem *ti = shortcuts->get_root()->get_first_child(); + while (ti) { + // Not all items have valid or unique text in the first column - so if it has an identifier, use that, as it should be unique. + if (ti->get_first_child() && ti->has_meta("shortcut_identifier")) { + collapsed[ti->get_meta("shortcut_identifier")] = ti->is_collapsed(); + } else { + collapsed[ti->get_text(0)] = ti->is_collapsed(); + } + + // Try go down tree + TreeItem *ti_next = ti->get_first_child(); + // Try go across tree + if (!ti_next) { + ti_next = ti->get_next(); + } + // Try go up tree, to next node + if (!ti_next) { + ti_next = ti->get_parent()->get_next(); + } + + ti = ti_next; + } + } + + shortcuts->clear(); + + TreeItem *root = shortcuts->create_item(); + Map sections; + + // Set up section for Common/Built-in actions + TreeItem *common_section = shortcuts->create_item(root); + sections["Common"] = common_section; + common_section->set_text(0, TTR("Common")); + common_section->set_selectable(0, false); + common_section->set_selectable(1, false); + if (collapsed.has("Common")) { + common_section->set_collapsed(collapsed["Common"]); + } + common_section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); + common_section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); + + // Get the action map for the editor, and add each item to the "Common" section. + OrderedHashMap action_map = InputMap::get_singleton()->get_action_map(); + for (OrderedHashMap::Element E = action_map.front(); E; E = E.next()) { + String action_name = E.key(); + InputMap::Action action = E.get(); + + Array events; // Need to get the list of events into an array so it can be set as metadata on the item. + Vector event_strings; + + List> all_default_events = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(action_name).value(); + List> key_default_events; + // Remove all non-key events from the defaults. Only check keys, since we are in the editor. + for (List>::Element *I = all_default_events.front(); I; I = I->next()) { + Ref k = I->get(); + if (k.is_valid()) { + key_default_events.push_back(k); + } + } + + // Join the text of the events with a delimiter so they can all be displayed in one cell. + String events_display_string = event_strings.is_empty() ? "None" : String("; ").join(event_strings); + + if (!shortcut_filter.is_subsequence_ofn(action_name) && (events_display_string == "None" || !shortcut_filter.is_subsequence_ofn(events_display_string))) { + continue; + } + + Array action_events = _event_list_to_array_helper(action.inputs); + Array default_events = _event_list_to_array_helper(all_default_events); + bool same_as_defaults = Shortcut::is_event_array_equal(default_events, action_events); + bool collapse = !collapsed.has(action_name) || (collapsed.has(action_name) && collapsed[action_name]); + + _create_shortcut_treeitem(common_section, action_name, action_name, action_events, !same_as_defaults, true, collapse); + } + + // Editor Shortcuts + + List slist; + EditorSettings::get_singleton()->get_shortcut_list(&slist); + + for (const String &E : slist) { + Ref sc = EditorSettings::get_singleton()->get_shortcut(E); + if (!sc->has_meta("original")) { + continue; + } + + // Shortcut Section + + TreeItem *section; + String section_name = E.get_slice("/", 0); + + if (sections.has(section_name)) { + section = sections[section_name]; + } else { + section = shortcuts->create_item(root); + + String item_name = section_name.capitalize(); + section->set_text(0, item_name); + section->set_selectable(0, false); + section->set_selectable(1, false); + section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); + section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); + + if (collapsed.has(item_name)) { + section->set_collapsed(collapsed[item_name]); + } + + sections[section_name] = section; + } + + // Shortcut Item + + if (!shortcut_filter.is_subsequence_ofn(sc->get_name())) { + continue; + } + + Array original = sc->get_meta("original"); + Array shortcuts_array = sc->get_events().duplicate(true); + bool same_as_defaults = Shortcut::is_event_array_equal(original, shortcuts_array); + bool collapse = !collapsed.has(E) || (collapsed.has(E) && collapsed[E]); + + _create_shortcut_treeitem(section, E, sc->get_name(), shortcuts_array, !same_as_defaults, false, collapse); + } + + // remove sections with no shortcuts + for (KeyValue &E : sections) { + TreeItem *section = E.value; + if (section->get_first_child() == nullptr) { + root->remove_child(section); + } + } +} + +void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column, int p_idx) { + TreeItem *ti = Object::cast_to(p_item); + ERR_FAIL_COND_MSG(!ti, "Object passed is not a TreeItem"); + + ShortcutButton button_idx = (ShortcutButton)p_idx; + + is_editing_action = ti->get_meta("is_action"); + + String type = ti->get_meta("type"); + + if (type == "event") { + current_edited_identifier = ti->get_parent()->get_meta("shortcut_identifier"); + current_events = ti->get_parent()->get_meta("events"); + current_event_index = ti->get_meta("event_index"); + } else { // Type is "shortcut" + current_edited_identifier = ti->get_meta("shortcut_identifier"); + current_events = ti->get_meta("events"); + current_event_index = -1; + } + + switch (button_idx) { + case EditorSettingsDialog::SHORTCUT_ADD: { + // Only for "shortcut" types + shortcut_editor->popup_and_configure(); + } break; + case EditorSettingsDialog::SHORTCUT_EDIT: { + // Only for "event" types + shortcut_editor->popup_and_configure(current_events[current_event_index]); + } break; + case EditorSettingsDialog::SHORTCUT_ERASE: { + if (type == "shortcut") { + if (is_editing_action) { + _update_builtin_action(current_edited_identifier, Array()); + } else { + _update_shortcut_events(current_edited_identifier, Array()); + } + } else if (type == "event") { + current_events.remove_at(current_event_index); + + if (is_editing_action) { + _update_builtin_action(current_edited_identifier, current_events); + } else { + _update_shortcut_events(current_edited_identifier, current_events); + } + } + } break; + case EditorSettingsDialog::SHORTCUT_REVERT: { + // Only for "shortcut" types + if (is_editing_action) { + List> defaults = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied()[current_edited_identifier]; + Array events = _event_list_to_array_helper(defaults); + + _update_builtin_action(current_edited_identifier, events); + } else { + Ref sc = EditorSettings::get_singleton()->get_shortcut(current_edited_identifier); + Array original = sc->get_meta("original"); + _update_shortcut_events(current_edited_identifier, original); + } + } break; + default: + break; + } +} + +Variant EditorSettingsDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + TreeItem *selected = shortcuts->get_selected(); + + // Only allow drag for events + if (!selected || !selected->has_meta("type") || selected->get_meta("type") != "event") { + return Variant(); + } + + String label_text = "Event " + itos(selected->get_meta("event_index")); + Label *label = memnew(Label(label_text)); + label->set_modulate(Color(1, 1, 1, 1.0f)); + shortcuts->set_drag_preview(label); + + shortcuts->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); + + return Dictionary(); // No data required +} + +bool EditorSettingsDialog::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + TreeItem *selected = shortcuts->get_selected(); + TreeItem *item = shortcuts->get_item_at_position(p_point); + if (!selected || !item || item == selected || !item->has_meta("type") || item->get_meta("type") != "event") { + return false; + } + + // Don't allow moving an events in-between shortcuts. + if (selected->get_parent()->get_meta("shortcut_identifier") != item->get_parent()->get_meta("shortcut_identifier")) { + return false; + } + + return true; +} + +void EditorSettingsDialog::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + if (!can_drop_data_fw(p_point, p_data, p_from)) { + return; + } + + TreeItem *selected = shortcuts->get_selected(); + TreeItem *target = shortcuts->get_item_at_position(p_point); + + if (!target) { + return; + } + + int target_event_index = target->get_meta("event_index"); + int index_moving_from = selected->get_meta("event_index"); + + Array events = selected->get_parent()->get_meta("events"); + + Variant event_moved = events[index_moving_from]; + events.remove_at(index_moving_from); + events.insert(target_event_index, event_moved); + + String ident = selected->get_parent()->get_meta("shortcut_identifier"); + if (selected->get_meta("is_action")) { + _update_builtin_action(ident, events); + } else { + _update_shortcut_events(ident, events); + } +} + +void EditorSettingsDialog::_tabs_tab_changed(int p_tab) { + _focus_current_search_box(); +} + +void EditorSettingsDialog::_focus_current_search_box() { + Control *tab = tabs->get_current_tab_control(); + LineEdit *current_search_box = nullptr; + if (tab == tab_general) { + current_search_box = search_box; + } else if (tab == tab_shortcuts) { + current_search_box = shortcut_search_box; + } + + if (current_search_box) { + current_search_box->grab_focus(); + current_search_box->select_all(); + } +} + +void EditorSettingsDialog::_editor_restart() { + EditorNode::get_singleton()->save_all_scenes(); + EditorNode::get_singleton()->restart_editor(); +} + +void EditorSettingsDialog::_editor_restart_request() { + restart_container->show(); +} + +void EditorSettingsDialog::_editor_restart_close() { + restart_container->hide(); +} + +void EditorSettingsDialog::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_shortcuts"), &EditorSettingsDialog::_update_shortcuts); + ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed); + + ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &EditorSettingsDialog::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &EditorSettingsDialog::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("_drop_data_fw"), &EditorSettingsDialog::drop_data_fw); +} + +EditorSettingsDialog::EditorSettingsDialog() { + set_title(TTR("Editor Settings")); + + undo_redo = memnew(UndoRedo); + + tabs = memnew(TabContainer); + tabs->set_tab_alignment(TabContainer::ALIGNMENT_LEFT); + tabs->connect("tab_changed", callable_mp(this, &EditorSettingsDialog::_tabs_tab_changed)); + add_child(tabs); + + // General Tab + + tab_general = memnew(VBoxContainer); + tabs->add_child(tab_general); + tab_general->set_name(TTR("General")); + + HBoxContainer *hbc = memnew(HBoxContainer); + hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tab_general->add_child(hbc); + + search_box = memnew(LineEdit); + search_box->set_placeholder(TTR("Search")); + search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + hbc->add_child(search_box); + + inspector = memnew(SectionedInspector); + inspector->get_inspector()->set_use_filter(true); + inspector->register_search_box(search_box); + inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); + inspector->get_inspector()->set_undo_redo(undo_redo); + tab_general->add_child(inspector); + inspector->get_inspector()->connect("property_edited", callable_mp(this, &EditorSettingsDialog::_settings_property_edited)); + inspector->get_inspector()->connect("restart_requested", callable_mp(this, &EditorSettingsDialog::_editor_restart_request)); + + restart_container = memnew(PanelContainer); + tab_general->add_child(restart_container); + HBoxContainer *restart_hb = memnew(HBoxContainer); + restart_container->add_child(restart_hb); + restart_icon = memnew(TextureRect); + restart_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + restart_hb->add_child(restart_icon); + restart_label = memnew(Label); + restart_label->set_text(TTR("The editor must be restarted for changes to take effect.")); + restart_hb->add_child(restart_label); + restart_hb->add_spacer(); + Button *restart_button = memnew(Button); + restart_button->connect("pressed", callable_mp(this, &EditorSettingsDialog::_editor_restart)); + restart_hb->add_child(restart_button); + restart_button->set_text(TTR("Save & Restart")); + restart_close_button = memnew(Button); + restart_close_button->set_flat(true); + restart_close_button->connect("pressed", callable_mp(this, &EditorSettingsDialog::_editor_restart_close)); + restart_hb->add_child(restart_close_button); + restart_container->hide(); + + // Shortcuts Tab + + tab_shortcuts = memnew(VBoxContainer); + + tabs->add_child(tab_shortcuts); + tab_shortcuts->set_name(TTR("Shortcuts")); + + shortcut_search_box = memnew(LineEdit); + shortcut_search_box->set_placeholder(TTR("Search")); + shortcut_search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tab_shortcuts->add_child(shortcut_search_box); + shortcut_search_box->connect("text_changed", callable_mp(this, &EditorSettingsDialog::_filter_shortcuts)); + + shortcuts = memnew(Tree); + shortcuts->set_v_size_flags(Control::SIZE_EXPAND_FILL); + shortcuts->set_columns(2); + shortcuts->set_hide_root(true); + shortcuts->set_column_titles_visible(true); + shortcuts->set_column_title(0, TTR("Name")); + shortcuts->set_column_title(1, TTR("Binding")); + shortcuts->connect("button_pressed", callable_mp(this, &EditorSettingsDialog::_shortcut_button_pressed)); + tab_shortcuts->add_child(shortcuts); + + shortcuts->set_drag_forwarding(this); + + // Adding event dialog + shortcut_editor = memnew(InputEventConfigurationDialog); + shortcut_editor->connect("confirmed", callable_mp(this, &EditorSettingsDialog::_event_config_confirmed)); + shortcut_editor->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_KEY); + add_child(shortcut_editor); + + set_hide_on_ok(true); + + timer = memnew(Timer); + timer->set_wait_time(1.5); + timer->connect("timeout", callable_mp(this, &EditorSettingsDialog::_settings_save)); + 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")); + + updating = false; +} + +EditorSettingsDialog::~EditorSettingsDialog() { + memdelete(undo_redo); +} diff --git a/editor/editor_settings_dialog.h b/editor/editor_settings_dialog.h new file mode 100644 index 0000000000..f1c4ea7770 --- /dev/null +++ b/editor/editor_settings_dialog.h @@ -0,0 +1,131 @@ +/*************************************************************************/ +/* editor_settings_dialog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 EDITOR_SETTINGS_DIALOG_H +#define EDITOR_SETTINGS_DIALOG_H + +#include "editor/action_map_editor.h" +#include "editor/editor_sectioned_inspector.h" +#include "editor_inspector.h" +#include "scene/gui/dialogs.h" +#include "scene/gui/panel_container.h" +#include "scene/gui/rich_text_label.h" +#include "scene/gui/tab_container.h" +#include "scene/gui/texture_rect.h" + +class EditorSettingsDialog : public AcceptDialog { + GDCLASS(EditorSettingsDialog, AcceptDialog); + + bool updating; + + TabContainer *tabs; + Control *tab_general; + Control *tab_shortcuts; + + LineEdit *search_box; + LineEdit *shortcut_search_box; + SectionedInspector *inspector; + + // Shortcuts + enum ShortcutButton { + SHORTCUT_ADD, + SHORTCUT_EDIT, + SHORTCUT_ERASE, + SHORTCUT_REVERT + }; + + Tree *shortcuts; + String shortcut_filter; + + InputEventConfigurationDialog *shortcut_editor; + + bool is_editing_action = false; + String current_edited_identifier; + Array current_events; + int current_event_index = -1; + + Timer *timer; + + UndoRedo *undo_redo; + + virtual void cancel_pressed() override; + virtual void ok_pressed() override; + + void _settings_changed(); + void _settings_property_edited(const String &p_name); + void _settings_save(); + + virtual void unhandled_input(const Ref &p_event) override; + void _notification(int p_what); + void _update_icons(); + + void _event_config_confirmed(); + + void _create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_common, bool p_is_collapsed); + Array _event_list_to_array_helper(List> &p_events); + void _update_builtin_action(const String &p_name, const Array &p_events); + void _update_shortcut_events(const String &p_path, const Array &p_events); + + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + + void _tabs_tab_changed(int p_tab); + void _focus_current_search_box(); + + void _filter_shortcuts(const String &p_filter); + + void _update_shortcuts(); + void _shortcut_button_pressed(Object *p_item, int p_column, int p_idx); + + void _builtin_action_popup_index_pressed(int p_index); + + static void _undo_redo_callback(void *p_self, const String &p_name); + + Label *restart_label; + TextureRect *restart_icon; + PanelContainer *restart_container; + Button *restart_close_button; + + void _editor_restart_request(); + void _editor_restart(); + void _editor_restart_close(); + +protected: + static void _bind_methods(); + +public: + void popup_edit_settings(); + + EditorSettingsDialog(); + ~EditorSettingsDialog(); +}; + +#endif // EDITOR_SETTINGS_DIALOG_H diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index bcc597d595..bedae4f8a9 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "editor/editor_export.h" +#include "editor/editor_log.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" @@ -47,7 +48,8 @@ void ProjectSettingsEditor::popup_project_settings() { } _add_feature_overrides(); - inspector->update_category_list(); + general_settings_inspector->update_category_list(); + set_process_unhandled_input(true); localization_editor->update_translations(); autoload_settings->update_autoload(); @@ -74,7 +76,7 @@ void ProjectSettingsEditor::_setting_edited(const String &p_name) { void ProjectSettingsEditor::_advanced_toggled(bool p_button_pressed) { EditorSettings::get_singleton()->set_project_metadata("project_settings", "advanced_mode", p_button_pressed); - inspector->set_restrict_to_basic_settings(!p_button_pressed); + general_settings_inspector->set_restrict_to_basic_settings(!p_button_pressed); } void ProjectSettingsEditor::_setting_selected(const String &p_path) { @@ -82,7 +84,7 @@ void ProjectSettingsEditor::_setting_selected(const String &p_path) { return; } - property_box->set_text(inspector->get_current_section() + "/" + p_path); + property_box->set_text(general_settings_inspector->get_current_section() + "/" + p_path); _update_property_box(); // set_text doesn't trigger text_changed } @@ -99,13 +101,13 @@ void ProjectSettingsEditor::_add_setting() { undo_redo->add_do_property(ps, setting, value); undo_redo->add_undo_property(ps, setting, ps->has_setting(setting) ? ps->get(setting) : Variant()); - undo_redo->add_do_method(inspector, "update_category_list"); - undo_redo->add_undo_method(inspector, "update_category_list"); + undo_redo->add_do_method(general_settings_inspector, "update_category_list"); + undo_redo->add_undo_method(general_settings_inspector, "update_category_list"); undo_redo->add_do_method(this, "queue_save"); undo_redo->add_undo_method(this, "queue_save"); undo_redo->commit_action(); - inspector->set_current_section(setting.get_slice("/", 1)); + general_settings_inspector->set_current_section(setting.get_slice("/", 1)); add_button->release_focus(); } @@ -120,8 +122,8 @@ void ProjectSettingsEditor::_delete_setting() { undo_redo->add_undo_method(ps, "set", setting, value); undo_redo->add_undo_method(ps, "set_order", setting, order); - undo_redo->add_do_method(inspector, "update_category_list"); - undo_redo->add_undo_method(inspector, "update_category_list"); + undo_redo->add_do_method(general_settings_inspector, "update_category_list"); + undo_redo->add_undo_method(general_settings_inspector, "update_category_list"); undo_redo->add_do_method(this, "queue_save"); undo_redo->add_undo_method(this, "queue_save"); @@ -200,6 +202,44 @@ void ProjectSettingsEditor::_select_type(Variant::Type p_type) { type_box->select(type_box->get_item_index(p_type)); } +void ProjectSettingsEditor::unhandled_input(const Ref &p_event) { + ERR_FAIL_COND(p_event.is_null()); + + const Ref k = p_event; + + if (k.is_valid() && k->is_pressed()) { + bool handled = false; + + if (ED_IS_SHORTCUT("ui_undo", p_event)) { + String action = undo_redo->get_current_action_name(); + if (!action.is_empty()) { + EditorNode::get_log()->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR); + } + undo_redo->undo(); + handled = true; + } + + if (ED_IS_SHORTCUT("ui_redo", p_event)) { + undo_redo->redo(); + String action = undo_redo->get_current_action_name(); + if (!action.is_empty()) { + EditorNode::get_log()->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR); + } + handled = true; + } + + if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F)) { + search_box->grab_focus(); + search_box->select_all(); + handled = true; + } + + if (handled) { + set_input_as_handled(); + } + } +} + String ProjectSettingsEditor::_get_setting_name() const { String name = property_box->get_text().strip_edges(); if (name.find("/") == -1) { @@ -463,7 +503,7 @@ void ProjectSettingsEditor::_update_action_map_editor() { actions.push_back(action_info); } - action_map->update_action_list(actions); + action_map_editor->update_action_list(actions); } void ProjectSettingsEditor::_update_theme() { @@ -482,7 +522,7 @@ void ProjectSettingsEditor::_notification(int p_what) { } } break; case NOTIFICATION_ENTER_TREE: { - inspector->edit(ps); + general_settings_inspector->edit(ps); _update_action_map_editor(); _update_theme(); } break; @@ -569,14 +609,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { del_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_delete_setting)); header->add_child(del_button); - inspector = memnew(SectionedInspector); - inspector->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); - inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); - inspector->register_search_box(search_box); - inspector->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_setting_selected)); - inspector->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited)); - inspector->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request)); - general_editor->add_child(inspector); + general_settings_inspector = memnew(SectionedInspector); + general_settings_inspector->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); + general_settings_inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); + general_settings_inspector->register_search_box(search_box); + general_settings_inspector->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_setting_selected)); + general_settings_inspector->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited)); + general_settings_inspector->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request)); + general_editor->add_child(general_settings_inspector); restart_container = memnew(PanelContainer); general_editor->add_child(restart_container); @@ -604,14 +644,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { restart_close_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_editor_restart_close)); restart_hb->add_child(restart_close_button); - action_map = memnew(ActionMapEditor); - action_map->set_name(TTR("Input Map")); - action_map->connect("action_added", callable_mp(this, &ProjectSettingsEditor::_action_added)); - action_map->connect("action_edited", callable_mp(this, &ProjectSettingsEditor::_action_edited)); - action_map->connect("action_removed", callable_mp(this, &ProjectSettingsEditor::_action_removed)); - action_map->connect("action_renamed", callable_mp(this, &ProjectSettingsEditor::_action_renamed)); - action_map->connect("action_reordered", callable_mp(this, &ProjectSettingsEditor::_action_reordered)); - tab_container->add_child(action_map); + action_map_editor = memnew(ActionMapEditor); + action_map_editor->set_name(TTR("Input Map")); + action_map_editor->connect("action_added", callable_mp(this, &ProjectSettingsEditor::_action_added)); + action_map_editor->connect("action_edited", callable_mp(this, &ProjectSettingsEditor::_action_edited)); + action_map_editor->connect("action_removed", callable_mp(this, &ProjectSettingsEditor::_action_removed)); + action_map_editor->connect("action_renamed", callable_mp(this, &ProjectSettingsEditor::_action_renamed)); + action_map_editor->connect("action_reordered", callable_mp(this, &ProjectSettingsEditor::_action_reordered)); + tab_container->add_child(action_map_editor); localization_editor = memnew(LocalizationEditor); localization_editor->set_name(TTR("Localization")); @@ -647,7 +687,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { advanced->set_pressed(true); } - inspector->set_restrict_to_basic_settings(!use_advanced); + general_settings_inspector->set_restrict_to_basic_settings(!use_advanced); import_defaults_editor = memnew(ImportDefaultsEditor); import_defaults_editor->set_name(TTR("Import Defaults")); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index a8eed0093f..d48c2b76ca 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -50,8 +50,8 @@ class ProjectSettingsEditor : public AcceptDialog { Timer *timer; TabContainer *tab_container; - SectionedInspector *inspector; - ActionMapEditor *action_map; + SectionedInspector *general_settings_inspector; + ActionMapEditor *action_map_editor; LocalizationEditor *localization_editor; EditorAutoloadSettings *autoload_settings; ShaderGlobalsEditor *shaders_global_variables_editor; @@ -81,6 +81,8 @@ class ProjectSettingsEditor : public AcceptDialog { void _feature_selected(int p_index); void _select_type(Variant::Type p_type); + virtual void unhandled_input(const Ref &p_event) override; + String _get_setting_name() const; void _setting_edited(const String &p_name); void _setting_selected(const String &p_path); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp deleted file mode 100644 index c4d361bd49..0000000000 --- a/editor/settings_config_dialog.cpp +++ /dev/null @@ -1,720 +0,0 @@ -/*************************************************************************/ -/* settings_config_dialog.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 "settings_config_dialog.h" - -#include "core/config/project_settings.h" -#include "core/input/input_map.h" -#include "core/os/keyboard.h" -#include "editor/debugger/editor_debugger_node.h" -#include "editor_file_system.h" -#include "editor_log.h" -#include "editor_node.h" -#include "editor_scale.h" -#include "editor_settings.h" -#include "scene/gui/margin_container.h" - -void EditorSettingsDialog::ok_pressed() { - if (!EditorSettings::get_singleton()) { - return; - } - - _settings_save(); - timer->stop(); -} - -void EditorSettingsDialog::_settings_changed() { - timer->start(); -} - -void EditorSettingsDialog::_settings_property_edited(const String &p_name) { - String full_name = inspector->get_full_item_path(p_name); - - if (full_name == "interface/theme/accent_color" || full_name == "interface/theme/base_color" || full_name == "interface/theme/contrast") { - EditorSettings::get_singleton()->set_manually("interface/theme/preset", "Custom"); // set preset to Custom - } else if (full_name.begins_with("text_editor/theme/highlighting")) { - EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom"); - } -} - -void EditorSettingsDialog::_settings_save() { - EditorSettings::get_singleton()->notify_changes(); - EditorSettings::get_singleton()->save(); -} - -void EditorSettingsDialog::cancel_pressed() { - if (!EditorSettings::get_singleton()) { - return; - } - - EditorSettings::get_singleton()->notify_changes(); -} - -void EditorSettingsDialog::popup_edit_settings() { - if (!EditorSettings::get_singleton()) { - return; - } - - EditorSettings::get_singleton()->list_text_editor_themes(); // make sure we have an up to date list of themes - - inspector->edit(EditorSettings::get_singleton()); - inspector->get_inspector()->update_tree(); - - search_box->select_all(); - search_box->grab_focus(); - - _update_shortcuts(); - set_process_unhandled_input(true); - - // Restore valid window bounds or pop up at default size. - Rect2 saved_size = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "editor_settings", Rect2()); - if (saved_size != Rect2()) { - popup(saved_size); - } else { - popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); - } - - _focus_current_search_box(); -} - -void EditorSettingsDialog::_filter_shortcuts(const String &p_filter) { - shortcut_filter = p_filter; - _update_shortcuts(); -} - -void EditorSettingsDialog::_undo_redo_callback(void *p_self, const String &p_name) { - EditorNode::get_log()->add_message(p_name, EditorLog::MSG_TYPE_EDITOR); -} - -void EditorSettingsDialog::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible()) { - EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "editor_settings", Rect2(get_position(), get_size())); - set_process_unhandled_input(false); - } - } break; - case NOTIFICATION_READY: { - undo_redo->set_method_notify_callback(EditorDebuggerNode::_method_changeds, nullptr); - undo_redo->set_property_notify_callback(EditorDebuggerNode::_property_changeds, nullptr); - undo_redo->set_commit_notify_callback(_undo_redo_callback, this); - } break; - case NOTIFICATION_ENTER_TREE: { - _update_icons(); - } break; - case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - _update_icons(); - // Update theme colors. - inspector->update_category_list(); - _update_shortcuts(); - } break; - } -} - -void EditorSettingsDialog::unhandled_input(const Ref &p_event) { - ERR_FAIL_COND(p_event.is_null()); - - const Ref k = p_event; - - if (k.is_valid() && k->is_pressed()) { - bool handled = false; - - if (ED_IS_SHORTCUT("ui_undo", p_event)) { - String action = undo_redo->get_current_action_name(); - if (!action.is_empty()) { - EditorNode::get_log()->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR); - } - undo_redo->undo(); - handled = true; - } - - if (ED_IS_SHORTCUT("ui_redo", p_event)) { - undo_redo->redo(); - String action = undo_redo->get_current_action_name(); - if (!action.is_empty()) { - EditorNode::get_log()->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR); - } - handled = true; - } - - if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F)) { - _focus_current_search_box(); - handled = true; - } - - if (handled) { - set_input_as_handled(); - } - } -} - -void EditorSettingsDialog::_update_icons() { - search_box->set_right_icon(shortcuts->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - search_box->set_clear_button_enabled(true); - shortcut_search_box->set_right_icon(shortcuts->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - shortcut_search_box->set_clear_button_enabled(true); - - restart_close_button->set_icon(shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); - restart_container->add_theme_style_override("panel", shortcuts->get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); - restart_icon->set_texture(shortcuts->get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); - restart_label->add_theme_color_override("font_color", shortcuts->get_theme_color(SNAME("warning_color"), SNAME("Editor"))); -} - -void EditorSettingsDialog::_event_config_confirmed() { - Ref k = shortcut_editor->get_event(); - if (k.is_null()) { - return; - } - - if (current_event_index == -1) { - // Add new event - current_events.push_back(k); - } else { - // Edit existing event - current_events[current_event_index] = k; - } - - if (is_editing_action) { - _update_builtin_action(current_edited_identifier, current_events); - } else { - _update_shortcut_events(current_edited_identifier, current_events); - } -} - -void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Array &p_events) { - Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(p_name); - - undo_redo->create_action(TTR("Edit Built-in Action") + " '" + p_name + "'"); - undo_redo->add_do_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, p_events); - undo_redo->add_undo_method(EditorSettings::get_singleton(), "set_builtin_action_override", p_name, old_input_array); - undo_redo->add_do_method(this, "_settings_changed"); - undo_redo->add_undo_method(this, "_settings_changed"); - undo_redo->commit_action(); - - _update_shortcuts(); -} - -void EditorSettingsDialog::_update_shortcut_events(const String &p_path, const Array &p_events) { - Ref current_sc = EditorSettings::get_singleton()->get_shortcut(p_path); - - undo_redo->create_action(TTR("Edit Shortcut") + " '" + p_path + "'"); - undo_redo->add_do_method(current_sc.ptr(), "set_events", p_events); - undo_redo->add_undo_method(current_sc.ptr(), "set_events", current_sc->get_events()); - undo_redo->add_do_method(this, "_update_shortcuts"); - undo_redo->add_undo_method(this, "_update_shortcuts"); - undo_redo->add_do_method(this, "_settings_changed"); - undo_redo->add_undo_method(this, "_settings_changed"); - undo_redo->commit_action(); -} - -Array EditorSettingsDialog::_event_list_to_array_helper(List> &p_events) { - Array events; - - // Convert the list to an array, and only keep key events as this is for the editor. - for (List>::Element *E = p_events.front(); E; E = E->next()) { - Ref k = E->get(); - if (k.is_valid()) { - events.append(E->get()); - } - } - - return events; -} - -void EditorSettingsDialog::_create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_action, bool p_is_collapsed) { - TreeItem *shortcut_item = shortcuts->create_item(p_parent); - shortcut_item->set_collapsed(p_is_collapsed); - shortcut_item->set_text(0, p_display); - - Ref primary = p_events.size() > 0 ? Ref(p_events[0]) : Ref(); - Ref secondary = p_events.size() > 1 ? Ref(p_events[1]) : Ref(); - - String sc_text = "None"; - if (primary.is_valid()) { - sc_text = primary->as_text(); - - if (secondary.is_valid()) { - sc_text += ", " + secondary->as_text(); - - if (p_events.size() > 2) { - sc_text += " (+" + itos(p_events.size() - 2) + ")"; - } - } - } - - shortcut_item->set_text(1, sc_text); - if (sc_text == "None") { - // Fade out unassigned shortcut labels for easier visual grepping. - shortcut_item->set_custom_color(1, shortcuts->get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.5)); - } - - if (p_allow_revert) { - shortcut_item->add_button(1, shortcuts->get_theme_icon("Reload", "EditorIcons"), SHORTCUT_REVERT); - } - - shortcut_item->add_button(1, shortcuts->get_theme_icon("Add", "EditorIcons"), SHORTCUT_ADD); - shortcut_item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), SHORTCUT_ERASE); - - shortcut_item->set_meta("is_action", p_is_action); - shortcut_item->set_meta("type", "shortcut"); - shortcut_item->set_meta("shortcut_identifier", p_shortcut_identifier); - shortcut_item->set_meta("events", p_events); - - // Shortcut Input Events - for (int i = 0; i < p_events.size(); i++) { - Ref ie = p_events[i]; - if (ie.is_null()) { - continue; - } - - TreeItem *event_item = shortcuts->create_item(shortcut_item); - - event_item->set_text(0, shortcut_item->get_child_count() == 1 ? "Primary" : ""); - event_item->set_text(1, ie->as_text()); - - event_item->add_button(1, shortcuts->get_theme_icon("Edit", "EditorIcons"), SHORTCUT_EDIT); - event_item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), SHORTCUT_ERASE); - - event_item->set_custom_bg_color(0, shortcuts->get_theme_color("dark_color_3", "Editor")); - event_item->set_custom_bg_color(1, shortcuts->get_theme_color("dark_color_3", "Editor")); - - event_item->set_meta("is_action", p_is_action); - event_item->set_meta("type", "event"); - event_item->set_meta("event_index", i); - } -} - -void EditorSettingsDialog::_update_shortcuts() { - // Before clearing the tree, take note of which categories are collapsed so that this state can be maintained when the tree is repopulated. - Map collapsed; - - if (shortcuts->get_root() && shortcuts->get_root()->get_first_child()) { - TreeItem *ti = shortcuts->get_root()->get_first_child(); - while (ti) { - // Not all items have valid or unique text in the first column - so if it has an identifier, use that, as it should be unique. - if (ti->get_first_child() && ti->has_meta("shortcut_identifier")) { - collapsed[ti->get_meta("shortcut_identifier")] = ti->is_collapsed(); - } else { - collapsed[ti->get_text(0)] = ti->is_collapsed(); - } - - // Try go down tree - TreeItem *ti_next = ti->get_first_child(); - // Try go across tree - if (!ti_next) { - ti_next = ti->get_next(); - } - // Try go up tree, to next node - if (!ti_next) { - ti_next = ti->get_parent()->get_next(); - } - - ti = ti_next; - } - } - - shortcuts->clear(); - - TreeItem *root = shortcuts->create_item(); - Map sections; - - // Set up section for Common/Built-in actions - TreeItem *common_section = shortcuts->create_item(root); - sections["Common"] = common_section; - common_section->set_text(0, TTR("Common")); - common_section->set_selectable(0, false); - common_section->set_selectable(1, false); - if (collapsed.has("Common")) { - common_section->set_collapsed(collapsed["Common"]); - } - common_section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); - common_section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); - - // Get the action map for the editor, and add each item to the "Common" section. - OrderedHashMap action_map = InputMap::get_singleton()->get_action_map(); - for (OrderedHashMap::Element E = action_map.front(); E; E = E.next()) { - String action_name = E.key(); - InputMap::Action action = E.get(); - - Array events; // Need to get the list of events into an array so it can be set as metadata on the item. - Vector event_strings; - - List> all_default_events = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(action_name).value(); - List> key_default_events; - // Remove all non-key events from the defaults. Only check keys, since we are in the editor. - for (List>::Element *I = all_default_events.front(); I; I = I->next()) { - Ref k = I->get(); - if (k.is_valid()) { - key_default_events.push_back(k); - } - } - - // Join the text of the events with a delimiter so they can all be displayed in one cell. - String events_display_string = event_strings.is_empty() ? "None" : String("; ").join(event_strings); - - if (!shortcut_filter.is_subsequence_ofn(action_name) && (events_display_string == "None" || !shortcut_filter.is_subsequence_ofn(events_display_string))) { - continue; - } - - Array action_events = _event_list_to_array_helper(action.inputs); - Array default_events = _event_list_to_array_helper(all_default_events); - bool same_as_defaults = Shortcut::is_event_array_equal(default_events, action_events); - bool collapse = !collapsed.has(action_name) || (collapsed.has(action_name) && collapsed[action_name]); - - _create_shortcut_treeitem(common_section, action_name, action_name, action_events, !same_as_defaults, true, collapse); - } - - // Editor Shortcuts - - List slist; - EditorSettings::get_singleton()->get_shortcut_list(&slist); - - for (const String &E : slist) { - Ref sc = EditorSettings::get_singleton()->get_shortcut(E); - if (!sc->has_meta("original")) { - continue; - } - - // Shortcut Section - - TreeItem *section; - String section_name = E.get_slice("/", 0); - - if (sections.has(section_name)) { - section = sections[section_name]; - } else { - section = shortcuts->create_item(root); - - String item_name = section_name.capitalize(); - section->set_text(0, item_name); - section->set_selectable(0, false); - section->set_selectable(1, false); - section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); - section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor"))); - - if (collapsed.has(item_name)) { - section->set_collapsed(collapsed[item_name]); - } - - sections[section_name] = section; - } - - // Shortcut Item - - if (!shortcut_filter.is_subsequence_ofn(sc->get_name())) { - continue; - } - - Array original = sc->get_meta("original"); - Array shortcuts_array = sc->get_events().duplicate(true); - bool same_as_defaults = Shortcut::is_event_array_equal(original, shortcuts_array); - bool collapse = !collapsed.has(E) || (collapsed.has(E) && collapsed[E]); - - _create_shortcut_treeitem(section, E, sc->get_name(), shortcuts_array, !same_as_defaults, false, collapse); - } - - // remove sections with no shortcuts - for (KeyValue &E : sections) { - TreeItem *section = E.value; - if (section->get_first_child() == nullptr) { - root->remove_child(section); - } - } -} - -void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column, int p_idx) { - TreeItem *ti = Object::cast_to(p_item); - ERR_FAIL_COND_MSG(!ti, "Object passed is not a TreeItem"); - - ShortcutButton button_idx = (ShortcutButton)p_idx; - - is_editing_action = ti->get_meta("is_action"); - - String type = ti->get_meta("type"); - - if (type == "event") { - current_edited_identifier = ti->get_parent()->get_meta("shortcut_identifier"); - current_events = ti->get_parent()->get_meta("events"); - current_event_index = ti->get_meta("event_index"); - } else { // Type is "shortcut" - current_edited_identifier = ti->get_meta("shortcut_identifier"); - current_events = ti->get_meta("events"); - current_event_index = -1; - } - - switch (button_idx) { - case EditorSettingsDialog::SHORTCUT_ADD: { - // Only for "shortcut" types - shortcut_editor->popup_and_configure(); - } break; - case EditorSettingsDialog::SHORTCUT_EDIT: { - // Only for "event" types - shortcut_editor->popup_and_configure(current_events[current_event_index]); - } break; - case EditorSettingsDialog::SHORTCUT_ERASE: { - if (type == "shortcut") { - if (is_editing_action) { - _update_builtin_action(current_edited_identifier, Array()); - } else { - _update_shortcut_events(current_edited_identifier, Array()); - } - } else if (type == "event") { - current_events.remove_at(current_event_index); - - if (is_editing_action) { - _update_builtin_action(current_edited_identifier, current_events); - } else { - _update_shortcut_events(current_edited_identifier, current_events); - } - } - } break; - case EditorSettingsDialog::SHORTCUT_REVERT: { - // Only for "shortcut" types - if (is_editing_action) { - List> defaults = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied()[current_edited_identifier]; - Array events = _event_list_to_array_helper(defaults); - - _update_builtin_action(current_edited_identifier, events); - } else { - Ref sc = EditorSettings::get_singleton()->get_shortcut(current_edited_identifier); - Array original = sc->get_meta("original"); - _update_shortcut_events(current_edited_identifier, original); - } - } break; - default: - break; - } -} - -Variant EditorSettingsDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) { - TreeItem *selected = shortcuts->get_selected(); - - // Only allow drag for events - if (!selected || !selected->has_meta("type") || selected->get_meta("type") != "event") { - return Variant(); - } - - String label_text = "Event " + itos(selected->get_meta("event_index")); - Label *label = memnew(Label(label_text)); - label->set_modulate(Color(1, 1, 1, 1.0f)); - shortcuts->set_drag_preview(label); - - shortcuts->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); - - return Dictionary(); // No data required -} - -bool EditorSettingsDialog::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { - TreeItem *selected = shortcuts->get_selected(); - TreeItem *item = shortcuts->get_item_at_position(p_point); - if (!selected || !item || item == selected || !item->has_meta("type") || item->get_meta("type") != "event") { - return false; - } - - // Don't allow moving an events in-between shortcuts. - if (selected->get_parent()->get_meta("shortcut_identifier") != item->get_parent()->get_meta("shortcut_identifier")) { - return false; - } - - return true; -} - -void EditorSettingsDialog::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { - if (!can_drop_data_fw(p_point, p_data, p_from)) { - return; - } - - TreeItem *selected = shortcuts->get_selected(); - TreeItem *target = shortcuts->get_item_at_position(p_point); - - if (!target) { - return; - } - - int target_event_index = target->get_meta("event_index"); - int index_moving_from = selected->get_meta("event_index"); - - Array events = selected->get_parent()->get_meta("events"); - - Variant event_moved = events[index_moving_from]; - events.remove_at(index_moving_from); - events.insert(target_event_index, event_moved); - - String ident = selected->get_parent()->get_meta("shortcut_identifier"); - if (selected->get_meta("is_action")) { - _update_builtin_action(ident, events); - } else { - _update_shortcut_events(ident, events); - } -} - -void EditorSettingsDialog::_tabs_tab_changed(int p_tab) { - _focus_current_search_box(); -} - -void EditorSettingsDialog::_focus_current_search_box() { - Control *tab = tabs->get_current_tab_control(); - LineEdit *current_search_box = nullptr; - if (tab == tab_general) { - current_search_box = search_box; - } else if (tab == tab_shortcuts) { - current_search_box = shortcut_search_box; - } - - if (current_search_box) { - current_search_box->grab_focus(); - current_search_box->select_all(); - } -} - -void EditorSettingsDialog::_editor_restart() { - EditorNode::get_singleton()->save_all_scenes(); - EditorNode::get_singleton()->restart_editor(); -} - -void EditorSettingsDialog::_editor_restart_request() { - restart_container->show(); -} - -void EditorSettingsDialog::_editor_restart_close() { - restart_container->hide(); -} - -void EditorSettingsDialog::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_shortcuts"), &EditorSettingsDialog::_update_shortcuts); - ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed); - - ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &EditorSettingsDialog::get_drag_data_fw); - ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &EditorSettingsDialog::can_drop_data_fw); - ClassDB::bind_method(D_METHOD("_drop_data_fw"), &EditorSettingsDialog::drop_data_fw); -} - -EditorSettingsDialog::EditorSettingsDialog() { - set_title(TTR("Editor Settings")); - - undo_redo = memnew(UndoRedo); - - tabs = memnew(TabContainer); - tabs->set_tab_alignment(TabContainer::ALIGNMENT_LEFT); - tabs->connect("tab_changed", callable_mp(this, &EditorSettingsDialog::_tabs_tab_changed)); - add_child(tabs); - - // General Tab - - tab_general = memnew(VBoxContainer); - tabs->add_child(tab_general); - tab_general->set_name(TTR("General")); - - HBoxContainer *hbc = memnew(HBoxContainer); - hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); - tab_general->add_child(hbc); - - search_box = memnew(LineEdit); - search_box->set_placeholder(TTR("Search")); - search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); - hbc->add_child(search_box); - - inspector = memnew(SectionedInspector); - inspector->get_inspector()->set_use_filter(true); - inspector->register_search_box(search_box); - inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); - inspector->get_inspector()->set_undo_redo(undo_redo); - tab_general->add_child(inspector); - inspector->get_inspector()->connect("property_edited", callable_mp(this, &EditorSettingsDialog::_settings_property_edited)); - inspector->get_inspector()->connect("restart_requested", callable_mp(this, &EditorSettingsDialog::_editor_restart_request)); - - restart_container = memnew(PanelContainer); - tab_general->add_child(restart_container); - HBoxContainer *restart_hb = memnew(HBoxContainer); - restart_container->add_child(restart_hb); - restart_icon = memnew(TextureRect); - restart_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - restart_hb->add_child(restart_icon); - restart_label = memnew(Label); - restart_label->set_text(TTR("The editor must be restarted for changes to take effect.")); - restart_hb->add_child(restart_label); - restart_hb->add_spacer(); - Button *restart_button = memnew(Button); - restart_button->connect("pressed", callable_mp(this, &EditorSettingsDialog::_editor_restart)); - restart_hb->add_child(restart_button); - restart_button->set_text(TTR("Save & Restart")); - restart_close_button = memnew(Button); - restart_close_button->set_flat(true); - restart_close_button->connect("pressed", callable_mp(this, &EditorSettingsDialog::_editor_restart_close)); - restart_hb->add_child(restart_close_button); - restart_container->hide(); - - // Shortcuts Tab - - tab_shortcuts = memnew(VBoxContainer); - - tabs->add_child(tab_shortcuts); - tab_shortcuts->set_name(TTR("Shortcuts")); - - shortcut_search_box = memnew(LineEdit); - shortcut_search_box->set_placeholder(TTR("Search")); - shortcut_search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); - tab_shortcuts->add_child(shortcut_search_box); - shortcut_search_box->connect("text_changed", callable_mp(this, &EditorSettingsDialog::_filter_shortcuts)); - - shortcuts = memnew(Tree); - shortcuts->set_v_size_flags(Control::SIZE_EXPAND_FILL); - shortcuts->set_columns(2); - shortcuts->set_hide_root(true); - shortcuts->set_column_titles_visible(true); - shortcuts->set_column_title(0, TTR("Name")); - shortcuts->set_column_title(1, TTR("Binding")); - shortcuts->connect("button_pressed", callable_mp(this, &EditorSettingsDialog::_shortcut_button_pressed)); - tab_shortcuts->add_child(shortcuts); - - shortcuts->set_drag_forwarding(this); - - // Adding event dialog - shortcut_editor = memnew(InputEventConfigurationDialog); - shortcut_editor->connect("confirmed", callable_mp(this, &EditorSettingsDialog::_event_config_confirmed)); - shortcut_editor->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_KEY); - add_child(shortcut_editor); - - set_hide_on_ok(true); - - timer = memnew(Timer); - timer->set_wait_time(1.5); - timer->connect("timeout", callable_mp(this, &EditorSettingsDialog::_settings_save)); - 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")); - - updating = false; -} - -EditorSettingsDialog::~EditorSettingsDialog() { - memdelete(undo_redo); -} diff --git a/editor/settings_config_dialog.h b/editor/settings_config_dialog.h deleted file mode 100644 index c3dfd736d5..0000000000 --- a/editor/settings_config_dialog.h +++ /dev/null @@ -1,131 +0,0 @@ -/*************************************************************************/ -/* settings_config_dialog.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 SETTINGS_CONFIG_DIALOG_H -#define SETTINGS_CONFIG_DIALOG_H - -#include "editor/action_map_editor.h" -#include "editor/editor_sectioned_inspector.h" -#include "editor_inspector.h" -#include "scene/gui/dialogs.h" -#include "scene/gui/panel_container.h" -#include "scene/gui/rich_text_label.h" -#include "scene/gui/tab_container.h" -#include "scene/gui/texture_rect.h" - -class EditorSettingsDialog : public AcceptDialog { - GDCLASS(EditorSettingsDialog, AcceptDialog); - - bool updating; - - TabContainer *tabs; - Control *tab_general; - Control *tab_shortcuts; - - LineEdit *search_box; - LineEdit *shortcut_search_box; - SectionedInspector *inspector; - - // Shortcuts - enum ShortcutButton { - SHORTCUT_ADD, - SHORTCUT_EDIT, - SHORTCUT_ERASE, - SHORTCUT_REVERT - }; - - Tree *shortcuts; - String shortcut_filter; - - InputEventConfigurationDialog *shortcut_editor; - - bool is_editing_action = false; - String current_edited_identifier; - Array current_events; - int current_event_index = -1; - - Timer *timer; - - UndoRedo *undo_redo; - - virtual void cancel_pressed() override; - virtual void ok_pressed() override; - - void _settings_changed(); - void _settings_property_edited(const String &p_name); - void _settings_save(); - - virtual void unhandled_input(const Ref &p_event) override; - void _notification(int p_what); - void _update_icons(); - - void _event_config_confirmed(); - - void _create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_common, bool p_is_collapsed); - Array _event_list_to_array_helper(List> &p_events); - void _update_builtin_action(const String &p_name, const Array &p_events); - void _update_shortcut_events(const String &p_path, const Array &p_events); - - Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); - bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; - void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); - - void _tabs_tab_changed(int p_tab); - void _focus_current_search_box(); - - void _filter_shortcuts(const String &p_filter); - - void _update_shortcuts(); - void _shortcut_button_pressed(Object *p_item, int p_column, int p_idx); - - void _builtin_action_popup_index_pressed(int p_index); - - static void _undo_redo_callback(void *p_self, const String &p_name); - - Label *restart_label; - TextureRect *restart_icon; - PanelContainer *restart_container; - Button *restart_close_button; - - void _editor_restart_request(); - void _editor_restart(); - void _editor_restart_close(); - -protected: - static void _bind_methods(); - -public: - void popup_edit_settings(); - - EditorSettingsDialog(); - ~EditorSettingsDialog(); -}; - -#endif // SETTINGS_CONFIG_DIALOG_H diff --git a/main/main.cpp b/main/main.cpp index 8b58641461..5cc1d3f7da 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1311,11 +1311,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph PropertyInfo(Variant::INT, "display/window/size/viewport_width", PROPERTY_HINT_RANGE, "0,7680,or_greater")); // 8K resolution + GLOBAL_DEF_BASIC("display/window/size/viewport_height", 600); ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/viewport_height", PropertyInfo(Variant::INT, "display/window/size/viewport_height", PROPERTY_HINT_RANGE, - "0,4320,or_greater")); // 8K resolution + "0,4320,1,or_greater")); // 8K resolution + GLOBAL_DEF_BASIC("display/window/size/resizable", true); GLOBAL_DEF_BASIC("display/window/size/borderless", false); GLOBAL_DEF_BASIC("display/window/size/fullscreen", false); @@ -1325,7 +1327,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, - "0,7680,or_greater")); // 8K resolution + "0,7680,1,or_greater")); // 8K resolution GLOBAL_DEF("display/window/size/window_height_override", 0); ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/window_height_override", PropertyInfo(Variant::INT, -- cgit v1.2.3