1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

Improve Input Map and Shortcuts editor

- Fixes not being able to search by pressing ESC.
- Removes double translations.
- Cleans up `InputEventConfigurationDialog` for auto-translation.
- Adapts to editor theme change.
- Unifies search bar boilerplate code.
- Shortcuts: disable the "erase" button if there is no event to remove.
- Input Map: always include built-in actions when searching.
This commit is contained in:
Haoyu Qiu
2025-06-06 10:27:23 +08:00
parent 42c7f14422
commit 146599d3b2
11 changed files with 320 additions and 210 deletions

View File

@@ -33,6 +33,7 @@
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/editor_string_names.h" #include "editor/editor_string_names.h"
#include "editor/event_listener_line_edit.h" #include "editor/event_listener_line_edit.h"
#include "editor/gui/editor_event_search_bar.h"
#include "editor/input_event_configuration_dialog.h" #include "editor/input_event_configuration_dialog.h"
#include "editor/themes/editor_scale.h" #include "editor/themes/editor_scale.h"
#include "scene/gui/check_button.h" #include "scene/gui/check_button.h"
@@ -223,9 +224,8 @@ void ActionMapEditor::_tree_item_activated() {
_tree_button_pressed(item, 2, BUTTON_EDIT_EVENT, MouseButton::LEFT); _tree_button_pressed(item, 2, BUTTON_EDIT_EVENT, MouseButton::LEFT);
} }
void ActionMapEditor::set_show_builtin_actions(bool p_show) { void ActionMapEditor::_set_show_builtin_actions(bool p_show) {
show_builtin_actions = p_show; show_builtin_actions = p_show;
show_builtin_actions_checkbutton->set_pressed(p_show);
EditorSettings::get_singleton()->set_project_metadata("project_settings", "show_builtin_actions", show_builtin_actions); EditorSettings::get_singleton()->set_project_metadata("project_settings", "show_builtin_actions", show_builtin_actions);
// Prevent unnecessary updates of action list when cache is empty. // Prevent unnecessary updates of action list when cache is empty.
@@ -234,14 +234,17 @@ void ActionMapEditor::set_show_builtin_actions(bool p_show) {
} }
} }
void ActionMapEditor::_search_term_updated(const String &) { void ActionMapEditor::_on_search_bar_value_changed() {
update_action_list(); if (action_list_search_bar->is_searching()) {
} show_builtin_actions_checkbutton->set_pressed_no_signal(true);
show_builtin_actions_checkbutton->set_disabled(true);
void ActionMapEditor::_search_by_event(const Ref<InputEvent> &p_event) { show_builtin_actions_checkbutton->set_tooltip_text(TTRC("Built-in actions are always shown when searching."));
if (p_event.is_null() || (p_event->is_pressed() && !p_event->is_echo())) { } else {
update_action_list(); show_builtin_actions_checkbutton->set_pressed_no_signal(show_builtin_actions);
show_builtin_actions_checkbutton->set_disabled(false);
show_builtin_actions_checkbutton->set_tooltip_text(String());
} }
update_action_list();
} }
Variant ActionMapEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { Variant ActionMapEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
@@ -371,7 +374,6 @@ void ActionMapEditor::_notification(int p_what) {
} break; } break;
case NOTIFICATION_THEME_CHANGED: { case NOTIFICATION_THEME_CHANGED: {
action_list_search->set_right_icon(get_editor_theme_icon(SNAME("Search")));
add_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); add_button->set_button_icon(get_editor_theme_icon(SNAME("Add")));
if (!actions_cache.is_empty()) { if (!actions_cache.is_empty()) {
update_action_list(); update_action_list();
@@ -386,12 +388,10 @@ void ActionMapEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("action_removed", PropertyInfo(Variant::STRING, "name"))); ADD_SIGNAL(MethodInfo("action_removed", PropertyInfo(Variant::STRING, "name")));
ADD_SIGNAL(MethodInfo("action_renamed", PropertyInfo(Variant::STRING, "old_name"), PropertyInfo(Variant::STRING, "new_name"))); ADD_SIGNAL(MethodInfo("action_renamed", PropertyInfo(Variant::STRING, "old_name"), PropertyInfo(Variant::STRING, "new_name")));
ADD_SIGNAL(MethodInfo("action_reordered", PropertyInfo(Variant::STRING, "action_name"), PropertyInfo(Variant::STRING, "relative_to"), PropertyInfo(Variant::BOOL, "before"))); ADD_SIGNAL(MethodInfo("action_reordered", PropertyInfo(Variant::STRING, "action_name"), PropertyInfo(Variant::STRING, "relative_to"), PropertyInfo(Variant::BOOL, "before")));
ADD_SIGNAL(MethodInfo(SNAME("filter_focused")));
ADD_SIGNAL(MethodInfo(SNAME("filter_unfocused")));
} }
LineEdit *ActionMapEditor::get_search_box() const { LineEdit *ActionMapEditor::get_search_box() const {
return action_list_search; return action_list_search_bar->get_name_search_box();
} }
LineEdit *ActionMapEditor::get_path_box() const { LineEdit *ActionMapEditor::get_path_box() const {
@@ -403,7 +403,7 @@ InputEventConfigurationDialog *ActionMapEditor::get_configuration_dialog() {
} }
bool ActionMapEditor::_should_display_action(const String &p_name, const Array &p_events) const { bool ActionMapEditor::_should_display_action(const String &p_name, const Array &p_events) const {
const Ref<InputEvent> search_ev = action_list_search_by_event->get_event(); const Ref<InputEvent> search_ev = action_list_search_bar->get_event();
bool event_match = true; bool event_match = true;
if (search_ev.is_valid()) { if (search_ev.is_valid()) {
event_match = false; event_match = false;
@@ -415,7 +415,7 @@ bool ActionMapEditor::_should_display_action(const String &p_name, const Array &
} }
} }
return event_match && action_list_search->get_text().is_subsequence_ofn(p_name); return event_match && action_list_search_bar->get_name().is_subsequence_ofn(p_name);
} }
void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_infos) { void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_infos) {
@@ -426,15 +426,13 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
action_tree->clear(); action_tree->clear();
TreeItem *root = action_tree->create_item(); TreeItem *root = action_tree->create_item();
for (int i = 0; i < actions_cache.size(); i++) { for (const ActionInfo &action_info : actions_cache) {
ActionInfo action_info = actions_cache[i];
const Array events = action_info.action["events"]; const Array events = action_info.action["events"];
if (!_should_display_action(action_info.name, events)) { if (!_should_display_action(action_info.name, events)) {
continue; continue;
} }
if (!action_info.editable && !show_builtin_actions) { if (!action_info.editable && !action_list_search_bar->is_searching() && !show_builtin_actions) {
continue; continue;
} }
@@ -448,6 +446,7 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
action_item->set_meta("__name", action_info.name); action_item->set_meta("__name", action_info.name);
// First Column - Action Name // First Column - Action Name
action_item->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_DISABLED);
action_item->set_text(0, action_info.name); action_item->set_text(0, action_info.name);
action_item->set_editable(0, action_info.editable); action_item->set_editable(0, action_info.editable);
action_item->set_icon(0, action_info.icon); action_item->set_icon(0, action_info.icon);
@@ -464,13 +463,13 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
bool events_eq = Shortcut::is_event_array_equal(action_info.action_initial["events"], action_info.action["events"]); bool events_eq = Shortcut::is_event_array_equal(action_info.action_initial["events"], action_info.action["events"]);
bool action_eq = deadzone_eq && events_eq; bool action_eq = deadzone_eq && events_eq;
action_item->set_meta("__action_initial", action_info.action_initial); action_item->set_meta("__action_initial", action_info.action_initial);
action_item->add_button(2, action_tree->get_editor_theme_icon(SNAME("ReloadSmall")), BUTTON_REVERT_ACTION, action_eq, action_eq ? TTRC("Cannot Revert - Action is same as initial") : TTRC("Revert Action")); action_item->add_button(2, get_editor_theme_icon(SNAME("ReloadSmall")), BUTTON_REVERT_ACTION, action_eq, action_eq ? TTRC("Cannot Revert - Action is same as initial") : TTRC("Revert Action"));
} }
action_item->add_button(2, action_tree->get_editor_theme_icon(SNAME("Add")), BUTTON_ADD_EVENT, false, TTRC("Add Event")); action_item->add_button(2, get_editor_theme_icon(SNAME("Add")), BUTTON_ADD_EVENT, false, TTRC("Add Event"));
action_item->add_button(2, action_tree->get_editor_theme_icon(SNAME("Remove")), BUTTON_REMOVE_ACTION, !action_info.editable, action_info.editable ? TTRC("Remove Action") : TTRC("Cannot Remove Action")); action_item->add_button(2, get_editor_theme_icon(SNAME("Remove")), BUTTON_REMOVE_ACTION, !action_info.editable, action_info.editable ? TTRC("Remove Action") : TTRC("Cannot Remove Action"));
action_item->set_custom_bg_color(0, action_tree->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor))); action_item->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
action_item->set_custom_bg_color(1, action_tree->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor))); action_item->set_custom_bg_color(1, get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
for (int evnt_idx = 0; evnt_idx < events.size(); evnt_idx++) { for (int evnt_idx = 0; evnt_idx < events.size(); evnt_idx++) {
Ref<InputEvent> event = events[evnt_idx]; Ref<InputEvent> event = events[evnt_idx];
@@ -481,6 +480,7 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
TreeItem *event_item = action_tree->create_item(action_item); TreeItem *event_item = action_tree->create_item(action_item);
// First Column - Text // First Column - Text
event_item->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_DISABLED);
event_item->set_text(0, EventListenerLineEdit::get_event_text(event, true)); event_item->set_text(0, EventListenerLineEdit::get_event_text(event, true));
event_item->set_meta("__event", event); event_item->set_meta("__event", event);
event_item->set_meta("__index", evnt_idx); event_item->set_meta("__index", evnt_idx);
@@ -489,41 +489,38 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
Ref<InputEventKey> k = event; Ref<InputEventKey> k = event;
if (k.is_valid()) { if (k.is_valid()) {
if (k->get_physical_keycode() == Key::NONE && k->get_keycode() == Key::NONE && k->get_key_label() != Key::NONE) { if (k->get_physical_keycode() == Key::NONE && k->get_keycode() == Key::NONE && k->get_key_label() != Key::NONE) {
event_item->set_icon(0, action_tree->get_editor_theme_icon(SNAME("KeyboardLabel"))); event_item->set_icon(0, get_editor_theme_icon(SNAME("KeyboardLabel")));
} else if (k->get_keycode() != Key::NONE) { } else if (k->get_keycode() != Key::NONE) {
event_item->set_icon(0, action_tree->get_editor_theme_icon(SNAME("Keyboard"))); event_item->set_icon(0, get_editor_theme_icon(SNAME("Keyboard")));
} else if (k->get_physical_keycode() != Key::NONE) { } else if (k->get_physical_keycode() != Key::NONE) {
event_item->set_icon(0, action_tree->get_editor_theme_icon(SNAME("KeyboardPhysical"))); event_item->set_icon(0, get_editor_theme_icon(SNAME("KeyboardPhysical")));
} else { } else {
event_item->set_icon(0, action_tree->get_editor_theme_icon(SNAME("KeyboardError"))); event_item->set_icon(0, get_editor_theme_icon(SNAME("KeyboardError")));
} }
} }
Ref<InputEventMouseButton> mb = event; Ref<InputEventMouseButton> mb = event;
if (mb.is_valid()) { if (mb.is_valid()) {
event_item->set_icon(0, action_tree->get_editor_theme_icon(SNAME("Mouse"))); event_item->set_icon(0, get_editor_theme_icon(SNAME("Mouse")));
} }
Ref<InputEventJoypadButton> jb = event; Ref<InputEventJoypadButton> jb = event;
if (jb.is_valid()) { if (jb.is_valid()) {
event_item->set_icon(0, action_tree->get_editor_theme_icon(SNAME("JoyButton"))); event_item->set_icon(0, get_editor_theme_icon(SNAME("JoyButton")));
} }
Ref<InputEventJoypadMotion> jm = event; Ref<InputEventJoypadMotion> jm = event;
if (jm.is_valid()) { if (jm.is_valid()) {
event_item->set_icon(0, action_tree->get_editor_theme_icon(SNAME("JoyAxis"))); event_item->set_icon(0, get_editor_theme_icon(SNAME("JoyAxis")));
} }
// Third Column - Buttons // Third Column - Buttons
event_item->add_button(2, action_tree->get_editor_theme_icon(SNAME("Edit")), BUTTON_EDIT_EVENT, false, TTRC("Edit Event"), TTRC("Edit Event")); event_item->add_button(2, get_editor_theme_icon(SNAME("Edit")), BUTTON_EDIT_EVENT, false, TTRC("Edit Event"), TTRC("Edit Event"));
event_item->add_button(2, action_tree->get_editor_theme_icon(SNAME("Remove")), BUTTON_REMOVE_EVENT, false, TTRC("Remove Event"), TTRC("Remove Event")); event_item->add_button(2, get_editor_theme_icon(SNAME("Remove")), BUTTON_REMOVE_EVENT, false, TTRC("Remove Event"), TTRC("Remove Event"));
event_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); event_item->set_button_color(2, 0, Color(1, 1, 1, 0.75));
event_item->set_button_color(2, 1, Color(1, 1, 1, 0.75)); event_item->set_button_color(2, 1, Color(1, 1, 1, 0.75));
} }
} }
// Update UI.
clear_all_search->set_disabled(action_list_search->get_text().is_empty() && action_list_search_by_event->get_event().is_null());
} }
void ActionMapEditor::show_message(const String &p_message) { void ActionMapEditor::show_message(const String &p_message) {
@@ -531,52 +528,15 @@ void ActionMapEditor::show_message(const String &p_message) {
message->popup_centered(); message->popup_centered();
} }
void ActionMapEditor::use_external_search_box(LineEdit *p_searchbox) {
memdelete(action_list_search);
action_list_search = p_searchbox;
action_list_search->connect(SceneStringName(text_changed), callable_mp(this, &ActionMapEditor::_search_term_updated));
}
void ActionMapEditor::_on_filter_focused() {
emit_signal(SNAME("filter_focused"));
}
void ActionMapEditor::_on_filter_unfocused() {
emit_signal(SNAME("filter_unfocused"));
}
ActionMapEditor::ActionMapEditor() { ActionMapEditor::ActionMapEditor() {
// Main Vbox Container // Main Vbox Container
VBoxContainer *main_vbox = memnew(VBoxContainer); VBoxContainer *main_vbox = memnew(VBoxContainer);
main_vbox->set_anchors_and_offsets_preset(PRESET_FULL_RECT); main_vbox->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
add_child(main_vbox); add_child(main_vbox);
HBoxContainer *top_hbox = memnew(HBoxContainer); action_list_search_bar = memnew(EditorEventSearchBar);
main_vbox->add_child(top_hbox); action_list_search_bar->connect(SceneStringName(value_changed), callable_mp(this, &ActionMapEditor::_on_search_bar_value_changed));
main_vbox->add_child(action_list_search_bar);
action_list_search = memnew(LineEdit);
action_list_search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
action_list_search->set_placeholder(TTRC("Filter by Name"));
action_list_search->set_accessibility_name(TTRC("Filter by Name"));
action_list_search->set_clear_button_enabled(true);
action_list_search->connect(SceneStringName(text_changed), callable_mp(this, &ActionMapEditor::_search_term_updated));
top_hbox->add_child(action_list_search);
action_list_search_by_event = memnew(EventListenerLineEdit);
action_list_search_by_event->set_h_size_flags(Control::SIZE_EXPAND_FILL);
action_list_search_by_event->set_stretch_ratio(0.75);
action_list_search_by_event->set_accessibility_name(TTRC("Action Event"));
action_list_search_by_event->connect("event_changed", callable_mp(this, &ActionMapEditor::_search_by_event));
action_list_search_by_event->connect(SceneStringName(focus_entered), callable_mp(this, &ActionMapEditor::_on_filter_focused));
action_list_search_by_event->connect(SceneStringName(focus_exited), callable_mp(this, &ActionMapEditor::_on_filter_unfocused));
top_hbox->add_child(action_list_search_by_event);
clear_all_search = memnew(Button);
clear_all_search->set_text(TTRC("Clear All"));
clear_all_search->set_tooltip_text(TTRC("Clear all search filters."));
clear_all_search->connect(SceneStringName(pressed), callable_mp(action_list_search_by_event, &EventListenerLineEdit::clear_event));
clear_all_search->connect(SceneStringName(pressed), callable_mp(action_list_search, &LineEdit::clear));
top_hbox->add_child(clear_all_search);
// Adding Action line edit + button // Adding Action line edit + button
add_hbox = memnew(HBoxContainer); add_hbox = memnew(HBoxContainer);
@@ -603,7 +563,7 @@ ActionMapEditor::ActionMapEditor() {
show_builtin_actions_checkbutton = memnew(CheckButton); show_builtin_actions_checkbutton = memnew(CheckButton);
show_builtin_actions_checkbutton->set_text(TTRC("Show Built-in Actions")); show_builtin_actions_checkbutton->set_text(TTRC("Show Built-in Actions"));
show_builtin_actions_checkbutton->connect(SceneStringName(toggled), callable_mp(this, &ActionMapEditor::set_show_builtin_actions)); show_builtin_actions_checkbutton->connect(SceneStringName(toggled), callable_mp(this, &ActionMapEditor::_set_show_builtin_actions));
add_hbox->add_child(show_builtin_actions_checkbutton); add_hbox->add_child(show_builtin_actions_checkbutton);
show_builtin_actions = EditorSettings::get_singleton()->get_project_metadata("project_settings", "show_builtin_actions", false); show_builtin_actions = EditorSettings::get_singleton()->get_project_metadata("project_settings", "show_builtin_actions", false);

View File

@@ -32,13 +32,14 @@
#include "scene/gui/control.h" #include "scene/gui/control.h"
class Button;
class HBoxContainer;
class EventListenerLineEdit;
class LineEdit;
class CheckButton;
class AcceptDialog; class AcceptDialog;
class Button;
class CheckButton;
class EditorEventSearchBar;
class EventListenerLineEdit;
class HBoxContainer;
class InputEventConfigurationDialog; class InputEventConfigurationDialog;
class LineEdit;
class Tree; class Tree;
class ActionMapEditor : public Control { class ActionMapEditor : public Control {
@@ -82,9 +83,7 @@ private:
bool show_builtin_actions = false; bool show_builtin_actions = false;
CheckButton *show_builtin_actions_checkbutton = nullptr; CheckButton *show_builtin_actions_checkbutton = nullptr;
LineEdit *action_list_search = nullptr; EditorEventSearchBar *action_list_search_bar = nullptr;
EventListenerLineEdit *action_list_search_by_event = nullptr;
Button *clear_all_search = nullptr;
HBoxContainer *add_hbox = nullptr; HBoxContainer *add_hbox = nullptr;
LineEdit *add_edit = nullptr; LineEdit *add_edit = nullptr;
@@ -101,16 +100,14 @@ private:
void _tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button); void _tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button);
void _tree_item_activated(); void _tree_item_activated();
void _search_term_updated(const String &p_search_term); void _on_search_bar_value_changed();
void _search_by_event(const Ref<InputEvent> &p_event);
bool _should_display_action(const String &p_name, const Array &p_events) const; bool _should_display_action(const String &p_name, const Array &p_events) const;
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); 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; 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 drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
void _on_filter_focused(); void _set_show_builtin_actions(bool p_show);
void _on_filter_unfocused();
protected: protected:
void _notification(int p_what); void _notification(int p_what);
@@ -125,9 +122,5 @@ public:
void update_action_list(const Vector<ActionInfo> &p_action_infos = Vector<ActionInfo>()); void update_action_list(const Vector<ActionInfo> &p_action_infos = Vector<ActionInfo>());
void show_message(const String &p_message); void show_message(const String &p_message);
void set_show_builtin_actions(bool p_show);
void use_external_search_box(LineEdit *p_searchbox);
ActionMapEditor(); ActionMapEditor();
}; };

View File

@@ -43,9 +43,9 @@
#include "editor/editor_string_names.h" #include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/event_listener_line_edit.h" #include "editor/event_listener_line_edit.h"
#include "editor/gui/editor_event_search_bar.h"
#include "editor/input_event_configuration_dialog.h" #include "editor/input_event_configuration_dialog.h"
#include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/project_settings_editor.h"
#include "editor/themes/editor_scale.h" #include "editor/themes/editor_scale.h"
#include "editor/themes/editor_theme_manager.h" #include "editor/themes/editor_theme_manager.h"
#include "scene/gui/check_button.h" #include "scene/gui/check_button.h"
@@ -217,16 +217,6 @@ void EditorSettingsDialog::popup_edit_settings() {
_focus_current_search_box(); _focus_current_search_box();
} }
void EditorSettingsDialog::_filter_shortcuts(const String &) {
_update_shortcuts();
}
void EditorSettingsDialog::_filter_shortcuts_by_event(const Ref<InputEvent> &p_event) {
if (p_event.is_null() || (p_event->is_pressed() && !p_event->is_echo())) {
_update_shortcuts();
}
}
void EditorSettingsDialog::_undo_redo_callback(void *p_self, const String &p_name) { void EditorSettingsDialog::_undo_redo_callback(void *p_self, const String &p_name) {
EditorNode::get_log()->add_message(p_name, EditorLog::MSG_TYPE_EDITOR); EditorNode::get_log()->add_message(p_name, EditorLog::MSG_TYPE_EDITOR);
} }
@@ -253,6 +243,10 @@ void EditorSettingsDialog::_notification(int p_what) {
_update_icons(); _update_icons();
} break; } break;
case NOTIFICATION_THEME_CHANGED: {
_update_shortcuts();
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
if (EditorThemeManager::is_generated_theme_outdated()) { if (EditorThemeManager::is_generated_theme_outdated()) {
_update_icons(); _update_icons();
@@ -305,15 +299,13 @@ void EditorSettingsDialog::shortcut_input(const Ref<InputEvent> &p_event) {
} }
void EditorSettingsDialog::_update_icons() { void EditorSettingsDialog::_update_icons() {
search_box->set_right_icon(shortcuts->get_editor_theme_icon(SNAME("Search"))); search_box->set_right_icon(get_editor_theme_icon(SNAME("Search")));
search_box->set_clear_button_enabled(true); search_box->set_clear_button_enabled(true);
shortcut_search_box->set_right_icon(shortcuts->get_editor_theme_icon(SNAME("Search")));
shortcut_search_box->set_clear_button_enabled(true);
restart_close_button->set_button_icon(shortcuts->get_editor_theme_icon(SNAME("Close"))); restart_close_button->set_button_icon(get_editor_theme_icon(SNAME("Close")));
restart_container->add_theme_style_override(SceneStringName(panel), shortcuts->get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); restart_container->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));
restart_icon->set_texture(shortcuts->get_editor_theme_icon(SNAME("StatusWarning"))); restart_icon->set_texture(get_editor_theme_icon(SNAME("StatusWarning")));
restart_label->add_theme_color_override(SceneStringName(font_color), shortcuts->get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); restart_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor)));
} }
void EditorSettingsDialog::_event_config_confirmed() { void EditorSettingsDialog::_event_config_confirmed() {
@@ -422,15 +414,15 @@ TreeItem *EditorSettingsDialog::_create_shortcut_treeitem(TreeItem *p_parent, co
shortcut_item->set_text(1, sc_text); shortcut_item->set_text(1, sc_text);
if (sc_text == "None") { if (sc_text == "None") {
// Fade out unassigned shortcut labels for easier visual grepping. // Fade out unassigned shortcut labels for easier visual grepping.
shortcut_item->set_custom_color(1, shortcuts->get_theme_color(SceneStringName(font_color), SNAME("Label")) * Color(1, 1, 1, 0.5)); shortcut_item->set_custom_color(1, get_theme_color(SceneStringName(font_color), SNAME("Label")) * Color(1, 1, 1, 0.5));
} }
if (p_allow_revert) { if (p_allow_revert) {
shortcut_item->add_button(1, shortcuts->get_editor_theme_icon(SNAME("Reload")), SHORTCUT_REVERT); shortcut_item->add_button(1, get_editor_theme_icon(SNAME("Reload")), SHORTCUT_REVERT);
} }
shortcut_item->add_button(1, shortcuts->get_editor_theme_icon(SNAME("Add")), SHORTCUT_ADD); shortcut_item->add_button(1, get_editor_theme_icon(SNAME("Add")), SHORTCUT_ADD);
shortcut_item->add_button(1, shortcuts->get_editor_theme_icon(SNAME("Close")), SHORTCUT_ERASE); shortcut_item->add_button(1, get_editor_theme_icon(SNAME("Close")), SHORTCUT_ERASE, p_events.is_empty());
shortcut_item->set_meta("is_action", p_is_action); shortcut_item->set_meta("is_action", p_is_action);
shortcut_item->set_meta("type", "shortcut"); shortcut_item->set_meta("type", "shortcut");
@@ -451,11 +443,11 @@ TreeItem *EditorSettingsDialog::_create_shortcut_treeitem(TreeItem *p_parent, co
event_item->set_text(1, ie->as_text()); event_item->set_text(1, ie->as_text());
event_item->set_auto_translate_mode(1, AUTO_TRANSLATE_MODE_DISABLED); event_item->set_auto_translate_mode(1, AUTO_TRANSLATE_MODE_DISABLED);
event_item->add_button(1, shortcuts->get_editor_theme_icon(SNAME("Edit")), SHORTCUT_EDIT); event_item->add_button(1, get_editor_theme_icon(SNAME("Edit")), SHORTCUT_EDIT);
event_item->add_button(1, shortcuts->get_editor_theme_icon(SNAME("Close")), SHORTCUT_ERASE); event_item->add_button(1, get_editor_theme_icon(SNAME("Close")), SHORTCUT_ERASE);
event_item->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("dark_color_3"), EditorStringName(Editor))); event_item->set_custom_bg_color(0, get_theme_color(SNAME("dark_color_3"), EditorStringName(Editor)));
event_item->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("dark_color_3"), EditorStringName(Editor))); event_item->set_custom_bg_color(1, get_theme_color(SNAME("dark_color_3"), EditorStringName(Editor)));
event_item->set_meta("is_action", p_is_action); event_item->set_meta("is_action", p_is_action);
event_item->set_meta("type", "event"); event_item->set_meta("type", "event");
@@ -466,7 +458,7 @@ TreeItem *EditorSettingsDialog::_create_shortcut_treeitem(TreeItem *p_parent, co
} }
bool EditorSettingsDialog::_should_display_shortcut(const String &p_name, const Array &p_events, bool p_match_localized_name) const { bool EditorSettingsDialog::_should_display_shortcut(const String &p_name, const Array &p_events, bool p_match_localized_name) const {
const Ref<InputEvent> search_ev = shortcut_search_by_event->get_event(); const Ref<InputEvent> search_ev = shortcut_search_bar->get_event();
if (search_ev.is_valid()) { if (search_ev.is_valid()) {
bool event_match = false; bool event_match = false;
for (int i = 0; i < p_events.size(); ++i) { for (int i = 0; i < p_events.size(); ++i) {
@@ -481,7 +473,7 @@ bool EditorSettingsDialog::_should_display_shortcut(const String &p_name, const
} }
} }
const String &search_text = shortcut_search_box->get_text(); const String &search_text = shortcut_search_bar->get_name();
if (search_text.is_empty()) { if (search_text.is_empty()) {
return true; return true;
} }
@@ -540,8 +532,8 @@ void EditorSettingsDialog::_update_shortcuts() {
if (collapsed.has("Common")) { if (collapsed.has("Common")) {
common_section->set_collapsed(collapsed["Common"]); common_section->set_collapsed(collapsed["Common"]);
} }
common_section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor))); common_section->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
common_section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor))); common_section->set_custom_bg_color(1, get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
// Get the action map for the editor, and add each item to the "Common" section. // Get the action map for the editor, and add each item to the "Common" section.
for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) { for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) {
@@ -595,8 +587,8 @@ void EditorSettingsDialog::_update_shortcuts() {
section->set_tooltip_text(0, tooltip); section->set_tooltip_text(0, tooltip);
section->set_selectable(0, false); section->set_selectable(0, false);
section->set_selectable(1, false); section->set_selectable(1, false);
section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor))); section->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor))); section->set_custom_bg_color(1, get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
if (collapsed.has(item_name)) { if (collapsed.has(item_name)) {
section->set_collapsed(collapsed[item_name]); section->set_collapsed(collapsed[item_name]);
@@ -635,9 +627,6 @@ void EditorSettingsDialog::_update_shortcuts() {
memdelete(section); memdelete(section);
} }
} }
// Update UI.
clear_all_search->set_disabled(shortcut_search_box->get_text().is_empty() && shortcut_search_by_event->get_event().is_null());
} }
void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column, int p_idx, MouseButton p_button) { void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column, int p_idx, MouseButton p_button) {
@@ -853,7 +842,7 @@ void EditorSettingsDialog::_focus_current_search_box() {
if (tab == tab_general) { if (tab == tab_general) {
current_search_box = search_box; current_search_box = search_box;
} else if (tab == tab_shortcuts) { } else if (tab == tab_shortcuts) {
current_search_box = shortcut_search_box; current_search_box = shortcut_search_bar->get_name_search_box();
} }
if (current_search_box) { if (current_search_box) {
@@ -961,32 +950,9 @@ EditorSettingsDialog::EditorSettingsDialog() {
tabs->add_child(tab_shortcuts); tabs->add_child(tab_shortcuts);
tab_shortcuts->set_name(TTRC("Shortcuts")); tab_shortcuts->set_name(TTRC("Shortcuts"));
HBoxContainer *top_hbox = memnew(HBoxContainer); shortcut_search_bar = memnew(EditorEventSearchBar);
top_hbox->set_h_size_flags(Control::SIZE_EXPAND_FILL); shortcut_search_bar->connect(SceneStringName(value_changed), callable_mp(this, &EditorSettingsDialog::_update_shortcuts));
tab_shortcuts->add_child(top_hbox); tab_shortcuts->add_child(shortcut_search_bar);
shortcut_search_box = memnew(LineEdit);
shortcut_search_box->set_placeholder(TTRC("Filter by Name"));
shortcut_search_box->set_accessibility_name(TTRC("Filter by Name"));
shortcut_search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
top_hbox->add_child(shortcut_search_box);
shortcut_search_box->connect(SceneStringName(text_changed), callable_mp(this, &EditorSettingsDialog::_filter_shortcuts));
shortcut_search_by_event = memnew(EventListenerLineEdit);
shortcut_search_by_event->set_h_size_flags(Control::SIZE_EXPAND_FILL);
shortcut_search_by_event->set_stretch_ratio(0.75);
shortcut_search_by_event->set_allowed_input_types(INPUT_KEY);
shortcut_search_by_event->connect("event_changed", callable_mp(this, &EditorSettingsDialog::_filter_shortcuts_by_event));
shortcut_search_by_event->connect(SceneStringName(focus_entered), callable_mp((AcceptDialog *)this, &AcceptDialog::set_close_on_escape).bind(false));
shortcut_search_by_event->connect(SceneStringName(focus_exited), callable_mp((AcceptDialog *)this, &AcceptDialog::set_close_on_escape).bind(true));
top_hbox->add_child(shortcut_search_by_event);
clear_all_search = memnew(Button);
clear_all_search->set_text(TTRC("Clear All"));
clear_all_search->set_tooltip_text(TTRC("Clear all search filters."));
clear_all_search->connect(SceneStringName(pressed), callable_mp(shortcut_search_box, &LineEdit::clear));
clear_all_search->connect(SceneStringName(pressed), callable_mp(shortcut_search_by_event, &EventListenerLineEdit::clear_event));
top_hbox->add_child(clear_all_search);
shortcuts = memnew(Tree); shortcuts = memnew(Tree);
shortcuts->set_accessibility_name(TTRC("Shortcuts")); shortcuts->set_accessibility_name(TTRC("Shortcuts"));

View File

@@ -34,6 +34,7 @@
#include "scene/gui/dialogs.h" #include "scene/gui/dialogs.h"
class CheckButton; class CheckButton;
class EditorEventSearchBar;
class EventListenerLineEdit; class EventListenerLineEdit;
class InputEventConfigurationDialog; class InputEventConfigurationDialog;
class PanelContainer; class PanelContainer;
@@ -54,10 +55,8 @@ class EditorSettingsDialog : public AcceptDialog {
LineEdit *search_box = nullptr; LineEdit *search_box = nullptr;
CheckButton *advanced_switch = nullptr; CheckButton *advanced_switch = nullptr;
LineEdit *shortcut_search_box = nullptr;
EventListenerLineEdit *shortcut_search_by_event = nullptr;
SectionedInspector *inspector = nullptr; SectionedInspector *inspector = nullptr;
Button *clear_all_search = nullptr; EditorEventSearchBar *shortcut_search_bar = nullptr;
// Shortcuts // Shortcuts
enum ShortcutButton { enum ShortcutButton {
@@ -109,8 +108,6 @@ class EditorSettingsDialog : public AcceptDialog {
PropertyInfo _create_mouse_shortcut_property_info(const String &p_property_name, const String &p_shortcut_1_name, const String &p_shortcut_2_name); PropertyInfo _create_mouse_shortcut_property_info(const String &p_property_name, const String &p_shortcut_1_name, const String &p_shortcut_2_name);
String _get_shortcut_button_string(const String &p_shortcut_name); String _get_shortcut_button_string(const String &p_shortcut_name);
void _filter_shortcuts(const String &p_filter);
void _filter_shortcuts_by_event(const Ref<InputEvent> &p_event);
bool _should_display_shortcut(const String &p_name, const Array &p_events, bool p_match_localized_name) const; bool _should_display_shortcut(const String &p_name, const Array &p_events, bool p_match_localized_name) const;
void _update_shortcuts(); void _update_shortcuts();

View File

@@ -31,6 +31,7 @@
#include "editor/event_listener_line_edit.h" #include "editor/event_listener_line_edit.h"
#include "core/input/input_map.h" #include "core/input/input_map.h"
#include "scene/gui/dialogs.h"
// Maps to 2*axis if value is neg, or 2*axis+1 if value is pos. // Maps to 2*axis if value is neg, or 2*axis+1 if value is pos.
static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = { static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = {
@@ -162,9 +163,10 @@ void EventListenerLineEdit::gui_input(const Ref<InputEvent> &p_event) {
return; return;
} }
Ref<InputEvent> event_to_check = p_event;
// Allow releasing focus by holding "ui_cancel" action. // Allow releasing focus by holding "ui_cancel" action.
bool accept_release = false; const uint64_t hold_to_unfocus_timeout = 3000;
uint64_t hold_to_unfocus_timeout = 3000;
if (p_event->is_action_pressed(SNAME("ui_cancel"), true, true)) { if (p_event->is_action_pressed(SNAME("ui_cancel"), true, true)) {
if ((OS::get_singleton()->get_ticks_msec() - hold_next) < hold_to_unfocus_timeout) { if ((OS::get_singleton()->get_ticks_msec() - hold_next) < hold_to_unfocus_timeout) {
hold_next = 0; hold_next = 0;
@@ -172,20 +174,23 @@ void EventListenerLineEdit::gui_input(const Ref<InputEvent> &p_event) {
next->grab_focus(); next->grab_focus();
} else { } else {
hold_next = OS::get_singleton()->get_ticks_msec(); hold_next = OS::get_singleton()->get_ticks_msec();
hold_event = p_event;
} }
accept_event(); accept_event();
return; return;
} else if (p_event->is_action_released(SNAME("ui_cancel"), true)) {
accept_release = true;
} }
if (p_event->is_action_released(SNAME("ui_cancel"), true)) {
event_to_check = hold_event;
hold_next = 0; hold_next = 0;
hold_event = Ref<InputEvent>();
}
accept_event(); accept_event();
if (!(p_event->is_pressed() || accept_release) || p_event->is_echo() || p_event->is_match(event) || !_is_event_allowed(p_event)) { if (!event_to_check->is_pressed() || event_to_check->is_echo() || event_to_check->is_match(event) || !_is_event_allowed(event_to_check)) {
return; return;
} }
event = p_event; event = event_to_check;
set_text(get_event_text(event, false)); set_text(get_event_text(event, false));
emit_signal("event_changed", event); emit_signal("event_changed", event);
} }
@@ -196,15 +201,6 @@ void EventListenerLineEdit::_on_text_changed(const String &p_text) {
} }
} }
void EventListenerLineEdit::_on_focus() {
set_placeholder(TTRC("Listening for Input"));
}
void EventListenerLineEdit::_on_unfocus() {
ignore_next_event = true;
set_placeholder(TTRC("Filter by Event"));
}
Ref<InputEvent> EventListenerLineEdit::get_event() const { Ref<InputEvent> EventListenerLineEdit::get_event() const {
return event; return event;
} }
@@ -239,17 +235,39 @@ void EventListenerLineEdit::_notification(int p_what) {
DisplayServer::get_singleton()->accessibility_update_set_extra_info(ae, vformat(TTR("Listening for Input. Hold %s to release focus."), InputMap::get_singleton()->get_action_description("ui_cancel"))); DisplayServer::get_singleton()->accessibility_update_set_extra_info(ae, vformat(TTR("Listening for Input. Hold %s to release focus."), InputMap::get_singleton()->get_action_description("ui_cancel")));
} break; } break;
case NOTIFICATION_THEME_CHANGED: {
set_right_icon(get_editor_theme_icon(SNAME("Keyboard")));
} break;
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
connect(SceneStringName(text_changed), callable_mp(this, &EventListenerLineEdit::_on_text_changed)); connect(SceneStringName(text_changed), callable_mp(this, &EventListenerLineEdit::_on_text_changed));
connect(SceneStringName(focus_entered), callable_mp(this, &EventListenerLineEdit::_on_focus));
connect(SceneStringName(focus_exited), callable_mp(this, &EventListenerLineEdit::_on_unfocus));
set_right_icon(get_editor_theme_icon(SNAME("Keyboard")));
set_clear_button_enabled(true); set_clear_button_enabled(true);
} break; } break;
case NOTIFICATION_FOCUS_ENTER: {
AcceptDialog *dialog = Object::cast_to<AcceptDialog>(get_window());
if (dialog) {
dialog->set_close_on_escape(false);
}
set_placeholder(TTRC("Listening for Input"));
} break;
case NOTIFICATION_FOCUS_EXIT: {
AcceptDialog *dialog = Object::cast_to<AcceptDialog>(get_window());
if (dialog) {
dialog->set_close_on_escape(true);
}
ignore_next_event = true;
set_placeholder(TTRC("Filter by Event"));
} break;
} }
} }
void EventListenerLineEdit::_bind_methods() { void EventListenerLineEdit::_bind_methods() {
// `event` is either null or a valid InputEvent that is pressed and non-echo.
ADD_SIGNAL(MethodInfo("event_changed", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("event_changed", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
} }

View File

@@ -43,6 +43,7 @@ class EventListenerLineEdit : public LineEdit {
GDCLASS(EventListenerLineEdit, LineEdit) GDCLASS(EventListenerLineEdit, LineEdit)
uint64_t hold_next = 0; uint64_t hold_next = 0;
Ref<InputEvent> hold_event;
int allowed_input_types = INPUT_KEY | INPUT_MOUSE_BUTTON | INPUT_JOY_BUTTON | INPUT_JOY_MOTION; int allowed_input_types = INPUT_KEY | INPUT_MOUSE_BUTTON | INPUT_JOY_BUTTON | INPUT_JOY_MOTION;
bool ignore_next_event = true; bool ignore_next_event = true;
@@ -54,9 +55,6 @@ class EventListenerLineEdit : public LineEdit {
void gui_input(const Ref<InputEvent> &p_event) override; void gui_input(const Ref<InputEvent> &p_event) override;
void _on_text_changed(const String &p_text); void _on_text_changed(const String &p_text);
void _on_focus();
void _on_unfocus();
protected: protected:
void _notification(int p_what); void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();

View File

@@ -0,0 +1,109 @@
/**************************************************************************/
/* editor_event_search_bar.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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_event_search_bar.h"
#include "editor/event_listener_line_edit.h"
#include "scene/gui/button.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/line_edit.h"
void EditorEventSearchBar::_on_event_changed(const Ref<InputEvent> &p_event) {
if (p_event.is_valid() && (!p_event->is_pressed() || p_event->is_echo())) {
return;
}
_value_changed();
}
void EditorEventSearchBar::_on_clear_all() {
search_by_name->set_block_signals(true);
search_by_name->clear();
search_by_name->set_block_signals(false);
search_by_event->set_block_signals(true);
search_by_event->clear_event();
search_by_event->set_block_signals(false);
_value_changed();
}
void EditorEventSearchBar::_value_changed() {
clear_all->set_disabled(!is_searching());
emit_signal(SceneStringName(value_changed));
}
bool EditorEventSearchBar::is_searching() const {
return !get_name().is_empty() || get_event().is_valid();
}
String EditorEventSearchBar::get_name() const {
return search_by_name->get_text().strip_edges();
}
Ref<InputEvent> EditorEventSearchBar::get_event() const {
return search_by_event->get_event();
}
void EditorEventSearchBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
search_by_name->set_right_icon(get_editor_theme_icon(SNAME("Search")));
} break;
}
}
void EditorEventSearchBar::_bind_methods() {
ADD_SIGNAL(MethodInfo("value_changed"));
}
EditorEventSearchBar::EditorEventSearchBar() {
set_h_size_flags(Control::SIZE_EXPAND_FILL);
search_by_name = memnew(LineEdit);
search_by_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search_by_name->set_placeholder(TTRC("Filter by Name"));
search_by_name->set_accessibility_name(TTRC("Filter by Name"));
search_by_name->set_clear_button_enabled(true);
search_by_name->connect(SceneStringName(text_changed), callable_mp(this, &EditorEventSearchBar::_value_changed).unbind(1));
add_child(search_by_name);
search_by_event = memnew(EventListenerLineEdit);
search_by_event->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search_by_event->set_stretch_ratio(0.75);
search_by_event->set_accessibility_name(TTRC("Action Event"));
search_by_event->connect("event_changed", callable_mp(this, &EditorEventSearchBar::_on_event_changed));
add_child(search_by_event);
clear_all = memnew(Button(TTRC("Clear All")));
clear_all->set_tooltip_text(TTRC("Clear all search filters."));
clear_all->connect(SceneStringName(pressed), callable_mp(this, &EditorEventSearchBar::_on_clear_all));
clear_all->set_disabled(true);
add_child(clear_all);
}

View File

@@ -0,0 +1,64 @@
/**************************************************************************/
/* editor_event_search_bar.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#include "scene/gui/box_container.h"
class Button;
class EventListenerLineEdit;
class LineEdit;
class EditorEventSearchBar : public HBoxContainer {
GDCLASS(EditorEventSearchBar, HBoxContainer);
LineEdit *search_by_name = nullptr;
EventListenerLineEdit *search_by_event = nullptr;
Button *clear_all = nullptr;
void _on_event_changed(const Ref<InputEvent> &p_event);
void _on_clear_all();
void _value_changed();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
LineEdit *get_name_search_box() const { return search_by_name; }
bool is_searching() const;
String get_name() const;
Ref<InputEvent> get_event() const;
EditorEventSearchBar();
};

View File

@@ -94,7 +94,7 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, c
event = Ref<InputEvent>(); event = Ref<InputEvent>();
original_event = Ref<InputEvent>(); original_event = Ref<InputEvent>();
event_listener->clear_event(); event_listener->clear_event();
event_as_text->set_text(TTR("No Event Configured")); event_as_text->set_text(TTRC("No Event Configured"));
additional_options_container->hide(); additional_options_container->hide();
input_list_tree->deselect_all(); input_list_tree->deselect_all();
@@ -192,7 +192,7 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, c
event = Ref<InputEvent>(); event = Ref<InputEvent>();
original_event = Ref<InputEvent>(); original_event = Ref<InputEvent>();
event_listener->clear_event(); event_listener->clear_event();
event_as_text->set_text(TTR("No Event Configured")); event_as_text->set_text(TTRC("No Event Configured"));
additional_options_container->hide(); additional_options_container->hide();
input_list_tree->deselect_all(); input_list_tree->deselect_all();
@@ -587,6 +587,12 @@ void InputEventConfigurationDialog::_notification(int p_what) {
_update_input_list(); _update_input_list();
} break; } break;
case NOTIFICATION_TRANSLATION_CHANGED: {
key_location->set_item_text(key_location->get_item_index((int)KeyLocation::UNSPECIFIED), TTR("Unspecified", "Key Location"));
key_location->set_item_text(key_location->get_item_index((int)KeyLocation::LEFT), TTR("Left", "Key Location"));
key_location->set_item_text(key_location->get_item_index((int)KeyLocation::RIGHT), TTR("Right", "Key Location"));
} break;
} }
} }
@@ -654,21 +660,19 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
event_listener->set_h_size_flags(Control::SIZE_EXPAND_FILL); event_listener->set_h_size_flags(Control::SIZE_EXPAND_FILL);
event_listener->set_stretch_ratio(0.75); event_listener->set_stretch_ratio(0.75);
event_listener->connect("event_changed", callable_mp(this, &InputEventConfigurationDialog::_on_listen_input_changed)); event_listener->connect("event_changed", callable_mp(this, &InputEventConfigurationDialog::_on_listen_input_changed));
event_listener->connect(SceneStringName(focus_entered), callable_mp((AcceptDialog *)this, &AcceptDialog::set_close_on_escape).bind(false));
event_listener->connect(SceneStringName(focus_exited), callable_mp((AcceptDialog *)this, &AcceptDialog::set_close_on_escape).bind(true));
main_vbox->add_child(event_listener); main_vbox->add_child(event_listener);
main_vbox->add_child(memnew(HSeparator)); main_vbox->add_child(memnew(HSeparator));
// List of all input options to manually select from. // List of all input options to manually select from.
VBoxContainer *manual_vbox = memnew(VBoxContainer); VBoxContainer *manual_vbox = memnew(VBoxContainer);
manual_vbox->set_name(TTR("Manual Selection")); manual_vbox->set_name("Manual Selection");
manual_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); manual_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
main_vbox->add_child(manual_vbox); main_vbox->add_child(manual_vbox);
input_list_search = memnew(LineEdit); input_list_search = memnew(LineEdit);
input_list_search->set_h_size_flags(Control::SIZE_EXPAND_FILL); input_list_search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
input_list_search->set_placeholder(TTR("Filter Inputs")); input_list_search->set_placeholder(TTRC("Filter Inputs"));
input_list_search->set_accessibility_name(TTRC("Filter Inputs")); input_list_search->set_accessibility_name(TTRC("Filter Inputs"));
input_list_search->set_clear_button_enabled(true); input_list_search->set_clear_button_enabled(true);
input_list_search->connect(SceneStringName(text_changed), callable_mp(this, &InputEventConfigurationDialog::_search_term_updated)); input_list_search->connect(SceneStringName(text_changed), callable_mp(this, &InputEventConfigurationDialog::_search_term_updated));
@@ -690,18 +694,16 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
additional_options_container = memnew(VBoxContainer); additional_options_container = memnew(VBoxContainer);
additional_options_container->hide(); additional_options_container->hide();
Label *opts_label = memnew(Label); Label *opts_label = memnew(Label(TTRC("Additional Options")));
opts_label->set_theme_type_variation("HeaderSmall"); opts_label->set_theme_type_variation("HeaderSmall");
opts_label->set_text(TTR("Additional Options"));
additional_options_container->add_child(opts_label); additional_options_container->add_child(opts_label);
// Device Selection // Device Selection
device_container = memnew(HBoxContainer); device_container = memnew(HBoxContainer);
device_container->set_h_size_flags(Control::SIZE_EXPAND_FILL); device_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
Label *device_label = memnew(Label); Label *device_label = memnew(Label(TTRC("Device:")));
device_label->set_theme_type_variation("HeaderSmall"); device_label->set_theme_type_variation("HeaderSmall");
device_label->set_text(TTR("Device:"));
device_container->add_child(device_label); device_container->add_child(device_label);
device_id_option = memnew(OptionButton); device_id_option = memnew(OptionButton);
@@ -721,20 +723,20 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
mod_container = memnew(HBoxContainer); mod_container = memnew(HBoxContainer);
for (int i = 0; i < MOD_MAX; i++) { for (int i = 0; i < MOD_MAX; i++) {
String name = mods[i]; String name = mods[i];
mod_checkboxes[i] = memnew(CheckBox); mod_checkboxes[i] = memnew(CheckBox(name));
mod_checkboxes[i]->connect(SceneStringName(toggled), callable_mp(this, &InputEventConfigurationDialog::_mod_toggled).bind(i)); mod_checkboxes[i]->connect(SceneStringName(toggled), callable_mp(this, &InputEventConfigurationDialog::_mod_toggled).bind(i));
mod_checkboxes[i]->set_text(name); mod_checkboxes[i]->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
mod_checkboxes[i]->set_tooltip_text(TTR(mods_tip[i])); mod_checkboxes[i]->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_ALWAYS);
mod_checkboxes[i]->set_tooltip_text(mods_tip[i]);
mod_container->add_child(mod_checkboxes[i]); mod_container->add_child(mod_checkboxes[i]);
} }
mod_container->add_child(memnew(VSeparator)); mod_container->add_child(memnew(VSeparator));
autoremap_command_or_control_checkbox = memnew(CheckBox); autoremap_command_or_control_checkbox = memnew(CheckBox(TTRC("Command / Control (auto)")));
autoremap_command_or_control_checkbox->connect(SceneStringName(toggled), callable_mp(this, &InputEventConfigurationDialog::_autoremap_command_or_control_toggled)); autoremap_command_or_control_checkbox->connect(SceneStringName(toggled), callable_mp(this, &InputEventConfigurationDialog::_autoremap_command_or_control_toggled));
autoremap_command_or_control_checkbox->set_pressed(false); autoremap_command_or_control_checkbox->set_pressed(false);
autoremap_command_or_control_checkbox->set_text(TTR("Command / Control (auto)")); autoremap_command_or_control_checkbox->set_tooltip_text(TTRC("Automatically remaps between 'Meta' ('Command') and 'Control' depending on current platform."));
autoremap_command_or_control_checkbox->set_tooltip_text(TTR("Automatically remaps between 'Meta' ('Command') and 'Control' depending on current platform."));
mod_container->add_child(autoremap_command_or_control_checkbox); mod_container->add_child(autoremap_command_or_control_checkbox);
mod_container->hide(); mod_container->hide();
@@ -743,9 +745,9 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
// Key Mode Selection // Key Mode Selection
key_mode = memnew(OptionButton); key_mode = memnew(OptionButton);
key_mode->add_item(TTR("Keycode (Latin Equivalent)"), KEYMODE_KEYCODE); key_mode->add_item(TTRC("Keycode (Latin Equivalent)"), KEYMODE_KEYCODE);
key_mode->add_item(TTR("Physical Keycode (Position on US QWERTY Keyboard)"), KEYMODE_PHY_KEYCODE); key_mode->add_item(TTRC("Physical Keycode (Position on US QWERTY Keyboard)"), KEYMODE_PHY_KEYCODE);
key_mode->add_item(TTR("Key Label (Unicode, Case-Insensitive)"), KEYMODE_UNICODE); key_mode->add_item(TTRC("Key Label (Unicode, Case-Insensitive)"), KEYMODE_UNICODE);
key_mode->connect(SceneStringName(item_selected), callable_mp(this, &InputEventConfigurationDialog::_key_mode_selected)); key_mode->connect(SceneStringName(item_selected), callable_mp(this, &InputEventConfigurationDialog::_key_mode_selected));
key_mode->hide(); key_mode->hide();
additional_options_container->add_child(key_mode); additional_options_container->add_child(key_mode);
@@ -755,15 +757,15 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
location_container = memnew(HBoxContainer); location_container = memnew(HBoxContainer);
location_container->hide(); location_container->hide();
Label *location_label = memnew(Label); location_container->add_child(memnew(Label(TTRC("Physical location"))));
location_label->set_text(TTR("Physical location"));
location_container->add_child(location_label);
key_location = memnew(OptionButton); key_location = memnew(OptionButton);
key_location->set_h_size_flags(Control::SIZE_EXPAND_FILL); key_location->set_h_size_flags(Control::SIZE_EXPAND_FILL);
key_location->add_item(TTR("Any"), (int)KeyLocation::UNSPECIFIED); key_location->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
key_location->add_item(TTR("Left"), (int)KeyLocation::LEFT); // Item texts will be set in `NOTIFICATION_TRANSLATION_CHANGED`.
key_location->add_item(TTR("Right"), (int)KeyLocation::RIGHT); key_location->add_item(String(), (int)KeyLocation::UNSPECIFIED);
key_location->add_item(String(), (int)KeyLocation::LEFT);
key_location->add_item(String(), (int)KeyLocation::RIGHT);
key_location->connect(SceneStringName(item_selected), callable_mp(this, &InputEventConfigurationDialog::_key_location_selected)); key_location->connect(SceneStringName(item_selected), callable_mp(this, &InputEventConfigurationDialog::_key_location_selected));
key_location->set_accessibility_name(TTRC("Location")); key_location->set_accessibility_name(TTRC("Location"));

View File

@@ -85,7 +85,12 @@ private:
#else #else
String mods[MOD_MAX] = { "Alt", "Shift", "Ctrl", "Meta" }; String mods[MOD_MAX] = { "Alt", "Shift", "Ctrl", "Meta" };
#endif #endif
String mods_tip[MOD_MAX] = { "Alt or Option key", "Shift key", "Control key", "Meta/Windows or Command key" }; String mods_tip[MOD_MAX] = {
TTRC("Alt or Option key"),
TTRC("Shift key"),
TTRC("Control key"),
TTRC("Meta/Windows or Command key"),
};
CheckBox *mod_checkboxes[MOD_MAX]; CheckBox *mod_checkboxes[MOD_MAX];
CheckBox *autoremap_command_or_control_checkbox = nullptr; CheckBox *autoremap_command_or_control_checkbox = nullptr;

View File

@@ -804,8 +804,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
action_map_editor->connect("action_removed", callable_mp(this, &ProjectSettingsEditor::_action_removed)); 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_renamed", callable_mp(this, &ProjectSettingsEditor::_action_renamed));
action_map_editor->connect("action_reordered", callable_mp(this, &ProjectSettingsEditor::_action_reordered)); action_map_editor->connect("action_reordered", callable_mp(this, &ProjectSettingsEditor::_action_reordered));
action_map_editor->connect(SNAME("filter_focused"), callable_mp((AcceptDialog *)this, &AcceptDialog::set_close_on_escape).bind(false));
action_map_editor->connect(SNAME("filter_unfocused"), callable_mp((AcceptDialog *)this, &AcceptDialog::set_close_on_escape).bind(true));
tab_container->add_child(action_map_editor); tab_container->add_child(action_map_editor);
localization_editor = memnew(LocalizationEditor); localization_editor = memnew(LocalizationEditor);