From dd7c42167a041b3ae73262e7fd8716d35803ed77 Mon Sep 17 00:00:00 2001 From: Vincent D <40196601+deakcor@users.noreply.github.com> Date: Fri, 12 Aug 2022 00:39:05 +0200 Subject: [PATCH] add allow_echo parameter for popup menu item shortcut --- doc/classes/PopupMenu.xml | 3 +++ scene/gui/menu_button.cpp | 4 ++-- scene/gui/popup_menu.cpp | 46 ++++++++++++++++++++++----------------- scene/gui/popup_menu.h | 9 ++++---- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 284c5a18704a..a2e84758354b 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -96,6 +96,7 @@ + Adds a new item and assigns the specified [Shortcut] and icon [code]texture[/code] to it. Sets the label of the checkbox to the [Shortcut]'s name. An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index. @@ -161,6 +162,7 @@ + Adds a [Shortcut]. An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index. @@ -442,6 +444,7 @@ + Sets a [Shortcut] for the item at the given [code]index[/code]. diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 069a31d9d2df..f0cc601dcad8 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -44,12 +44,12 @@ void MenuButton::shortcut_input(const Ref &p_event) { return; } - if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to(p_event.ptr()) || Object::cast_to(p_event.ptr()) || Object::cast_to(*p_event) || Object::cast_to(*p_event))) { + if (p_event->is_pressed() && (Object::cast_to(p_event.ptr()) || Object::cast_to(p_event.ptr()) || Object::cast_to(*p_event) || Object::cast_to(*p_event))) { if (!get_parent() || !is_visible_in_tree() || is_disabled()) { return; } - if (popup->activate_item_by_event(p_event, false)) { + if (popup->activate_item_by_event(p_event, false, p_event->is_echo())) { accept_event(); } } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index cd0d4370513c..bc8fa912c0c4 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -955,27 +955,28 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int child_controls_changed(); } -#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global) \ +#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo) \ ERR_FAIL_COND_MSG(p_shortcut.is_null(), "Cannot add item with invalid Shortcut."); \ _ref_shortcut(p_shortcut); \ item.text = p_shortcut->get_name(); \ item.xl_text = atr(item.text); \ item.id = p_id == -1 ? items.size() : p_id; \ item.shortcut = p_shortcut; \ - item.shortcut_is_global = p_global; + item.shortcut_is_global = p_global; \ + item.shortcut_allow_echo = p_allow_echo; -void PopupMenu::add_shortcut(const Ref &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_shortcut(const Ref &p_shortcut, int p_id, bool p_global, bool p_allow_echo) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo); items.push_back(item); _shape_item(items.size() - 1); control->update(); child_controls_changed(); } -void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global, bool p_allow_echo) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo); item.icon = p_icon; items.push_back(item); _shape_item(items.size() - 1); @@ -985,7 +986,7 @@ void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false); item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); _shape_item(items.size() - 1); @@ -995,7 +996,7 @@ void PopupMenu::add_check_shortcut(const Ref &p_shortcut, int p_id, bo void PopupMenu::add_icon_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false); item.icon = p_icon; item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); @@ -1006,7 +1007,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref &p_icon, const Ref< void PopupMenu::add_radio_check_shortcut(const Ref &p_shortcut, int p_id, bool p_global) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false); item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; items.push_back(item); _shape_item(items.size() - 1); @@ -1016,7 +1017,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref &p_shortcut, int p_ void PopupMenu::add_icon_radio_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false); item.icon = p_icon; item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; items.push_back(item); @@ -1298,7 +1299,7 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) { control->update(); } -void PopupMenu::set_item_shortcut(int p_idx, const Ref &p_shortcut, bool p_global) { +void PopupMenu::set_item_shortcut(int p_idx, const Ref &p_shortcut, bool p_global, bool p_allow_echo) { if (p_idx < 0) { p_idx += get_item_count(); } @@ -1308,6 +1309,7 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref &p_shortcut, bo } items.write[p_idx].shortcut = p_shortcut; items.write[p_idx].shortcut_is_global = p_global; + items.write[p_idx].shortcut_allow_echo = p_allow_echo; items.write[p_idx].dirty = true; if (items[p_idx].shortcut.is_valid()) { @@ -1419,7 +1421,7 @@ void PopupMenu::scroll_to_item(int p_item) { } } -bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_for_global_only) { +bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_for_global_only, bool p_is_echo) { Key code = Key::NONE; Ref k = p_event; @@ -1448,13 +1450,17 @@ bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_fo } if (items[i].shortcut.is_valid() && items[i].shortcut->matches_event(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) { - activate_item(i); - return true; + if (!p_is_echo || items[i].shortcut_allow_echo) { + activate_item(i); + return true; + } } if (code != Key::NONE && items[i].accel == code) { - activate_item(i); - return true; + if (!p_is_echo) { + activate_item(i); + return true; + } } if (!items[i].submenu.is_empty()) { @@ -1468,7 +1474,7 @@ bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_fo continue; } - if (pm->activate_item_by_event(p_event, p_for_global_only)) { + if (pm->activate_item_by_event(p_event, p_for_global_only, p_is_echo)) { return true; } } @@ -1815,8 +1821,8 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("add_multistate_item", "label", "max_states", "default_state", "id", "accel"), &PopupMenu::add_multistate_item, DEFVAL(0), DEFVAL(-1), DEFVAL(0)); - ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut", "id", "global"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut", "id", "global", "p_allow_echo"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global", "p_allow_echo"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_check_shortcut, DEFVAL(-1), DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_radio_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_radio_check_shortcut, DEFVAL(-1), DEFVAL(false)); @@ -1838,7 +1844,7 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("set_item_as_checkable", "index", "enable"), &PopupMenu::set_item_as_checkable); ClassDB::bind_method(D_METHOD("set_item_as_radio_checkable", "index", "enable"), &PopupMenu::set_item_as_radio_checkable); ClassDB::bind_method(D_METHOD("set_item_tooltip", "index", "tooltip"), &PopupMenu::set_item_tooltip); - ClassDB::bind_method(D_METHOD("set_item_shortcut", "index", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("set_item_shortcut", "index", "shortcut", "global", "allow_echo"), &PopupMenu::set_item_shortcut, DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_item_horizontal_offset", "index", "offset"), &PopupMenu::set_item_horizontal_offset); ClassDB::bind_method(D_METHOD("set_item_multistate", "index", "state"), &PopupMenu::set_item_multistate); ClassDB::bind_method(D_METHOD("set_item_shortcut_disabled", "index", "disabled"), &PopupMenu::set_item_shortcut_disabled); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index e203793c2e17..0bb930fc6724 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -72,6 +72,7 @@ class PopupMenu : public Popup { Ref shortcut; bool shortcut_is_global = false; bool shortcut_is_disabled = false; + bool shortcut_allow_echo = false; // Returns (0,0) if icon is null. Size2 get_icon_size() const { @@ -158,8 +159,8 @@ class PopupMenu : public Popup { void add_multistate_item(const String &p_label, int p_max_states, int p_default_state = 0, int p_id = -1, Key p_accel = Key::NONE); - void add_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false); - void add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false); + void add_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false, bool p_allow_echo = false); + void add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false, bool p_allow_echo = false); void add_check_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false); void add_icon_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false); void add_radio_check_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false); @@ -182,7 +183,7 @@ class PopupMenu : public Popup { void set_item_as_checkable(int p_idx, bool p_checkable); void set_item_as_radio_checkable(int p_idx, bool p_radio_checkable); void set_item_tooltip(int p_idx, const String &p_tooltip); - void set_item_shortcut(int p_idx, const Ref &p_shortcut, bool p_global = false); + void set_item_shortcut(int p_idx, const Ref &p_shortcut, bool p_global = false, bool p_allow_echo = false); void set_item_horizontal_offset(int p_idx, int p_offset); void set_item_multistate(int p_idx, int p_state); void toggle_item_multistate(int p_idx); @@ -219,7 +220,7 @@ class PopupMenu : public Popup { void scroll_to_item(int p_item); - bool activate_item_by_event(const Ref &p_event, bool p_for_global_only = false); + bool activate_item_by_event(const Ref &p_event, bool p_for_global_only = false, bool p_is_echo = false); void activate_item(int p_item); void remove_item(int p_idx);