From a557f22f1d5e88af75cd4b6e0a7a14c018f62d15 Mon Sep 17 00:00:00 2001 From: Michael Alexsander Date: Fri, 19 Aug 2022 15:19:34 -0300 Subject: [PATCH] Make `Menu/OptionButton` item auto-highlight behave better --- scene/gui/base_button.cpp | 7 +++++++ scene/gui/base_button.h | 3 +++ scene/gui/menu_button.cpp | 4 +--- scene/gui/option_button.cpp | 4 +--- scene/gui/popup_menu.cpp | 10 ++++++---- scene/gui/popup_menu.h | 4 +++- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 22db1ba88..fb0f3937b 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -65,6 +65,8 @@ void BaseButton::_gui_input(Ref p_event) { bool button_masked = mouse_button.is_valid() && ((1 << (mouse_button->get_button_index() - 1)) & button_mask) > 0; if (button_masked || ui_accept) { + was_mouse_pressed = button_masked; + on_action_event(p_event); return; } @@ -389,6 +391,10 @@ Ref BaseButton::get_button_group() const { return button_group; } +bool BaseButton::_was_pressed_by_mouse() const { + return was_mouse_pressed; +} + void BaseButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &BaseButton::_gui_input); ClassDB::bind_method(D_METHOD("_unhandled_input"), &BaseButton::_unhandled_input); @@ -450,6 +456,7 @@ BaseButton::BaseButton() { toggle_mode = false; shortcut_in_tooltip = true; keep_pressed_outside = false; + was_mouse_pressed = false; status.pressed = false; status.press_attempt = false; status.hovering = false; diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 2094f109d..7830ca84b 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -49,6 +49,7 @@ private: bool toggle_mode; bool shortcut_in_tooltip; bool keep_pressed_outside; + bool was_mouse_pressed; FocusMode enabled_focus_mode; Ref shortcut; @@ -79,6 +80,8 @@ protected: virtual void _unhandled_input(Ref p_event); void _notification(int p_what); + bool _was_pressed_by_mouse() const; + public: enum DrawMode { DRAW_NORMAL, diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index eb02bdded..00cd44d2c 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -66,9 +66,7 @@ void MenuButton::pressed() { popup->set_parent_rect(Rect2(Point2(gp - popup->get_global_position()), get_size())); // If not triggered by the mouse, start the popup with its first item selected. - if (popup->get_item_count() > 0 && - ((get_action_mode() == ActionMode::ACTION_MODE_BUTTON_PRESS && Input::get_singleton()->is_action_just_pressed("ui_accept")) || - (get_action_mode() == ActionMode::ACTION_MODE_BUTTON_RELEASE && Input::get_singleton()->is_action_just_released("ui_accept")))) { + if (popup->get_item_count() > 0 && !_was_pressed_by_mouse()) { popup->set_current_index(0); } diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index a1f4455df..dd7f7a515 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -116,9 +116,7 @@ void OptionButton::pressed() { popup->set_scale(get_global_transform().get_scale()); // If not triggered by the mouse, start the popup with its first item selected. - if (popup->get_item_count() > 0 && - ((get_action_mode() == ActionMode::ACTION_MODE_BUTTON_PRESS && Input::get_singleton()->is_action_just_pressed("ui_accept")) || - (get_action_mode() == ActionMode::ACTION_MODE_BUTTON_RELEASE && Input::get_singleton()->is_action_just_released("ui_accept")))) { + if (popup->get_item_count() > 0 && !_was_pressed_by_mouse()) { popup->set_current_index(0); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 8a9b07046..b24125582 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -165,7 +165,7 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const { return -1; } -void PopupMenu::_activate_submenu(int over) { +void PopupMenu::_activate_submenu(int over, bool p_by_keyboard) { Node *n = get_node(items[over].submenu); ERR_FAIL_COND_MSG(!n, "Item subnode does not exist: " + items[over].submenu + "."); Popup *pm = Object::cast_to(n); @@ -192,7 +192,7 @@ void PopupMenu::_activate_submenu(int over) { PopupMenu *pum = Object::cast_to(pm); if (pum) { // If not triggered by the mouse, start the popup with its first item selected. - if (pum->get_item_count() > 0 && Input::get_singleton()->is_action_just_pressed("ui_accept")) { + if (pum->get_item_count() > 0 && p_by_keyboard) { pum->set_current_index(0); } @@ -319,13 +319,13 @@ void PopupMenu::_gui_input(const Ref &p_event) { } } else if (p_event->is_action("ui_right") && p_event->is_pressed()) { if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) { - _activate_submenu(mouse_over); + _activate_submenu(mouse_over, true); accept_event(); } } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { if (items[mouse_over].submenu != "" && submenu_over != mouse_over) { - _activate_submenu(mouse_over); + _activate_submenu(mouse_over, true); } else { activate_item(mouse_over); } @@ -1496,6 +1496,8 @@ void PopupMenu::popup(const Rect2 &p_bounds) { } PopupMenu::PopupMenu() { + activated_by_keyboard = false; + mouse_over = -1; submenu_over = -1; initial_button_mask = 0; diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index ba7d4447f..f20ba63ec 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -66,6 +66,8 @@ class PopupMenu : public Popup { ~Item(); }; + bool activated_by_keyboard; + Timer *submenu_timer; List autohide_areas; Vector items; @@ -79,7 +81,7 @@ class PopupMenu : public Popup { virtual Size2 get_minimum_size() const; void _scroll(float p_factor, const Point2 &p_over); void _gui_input(const Ref &p_event); - void _activate_submenu(int over); + void _activate_submenu(int over, bool p_by_keyboard = false); void _submenu_timeout(); bool invalidated_click;