2
0
Эх сурвалжийг харах

Fix some corner cases in the `Menu/OptionButton` item auto-highlight

(cherry picked from commit 1e80b17a8d2391f0743b33b79d6ceb232591b30d)
Michael Alexsander 3 жил өмнө
parent
commit
a65247a405

+ 1 - 0
doc/classes/PopupMenu.xml

@@ -317,6 +317,7 @@
 			<argument index="0" name="index" type="int" />
 			<description>
 				Sets the currently focused item as the given [code]index[/code].
+				Passing [code]-1[/code] as the index makes so that no item is focused.
 			</description>
 		</method>
 		<method name="set_hide_on_window_lose_focus">

+ 2 - 1
scene/gui/base_button.cpp

@@ -65,8 +65,9 @@ void BaseButton::_gui_input(Ref<InputEvent> 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);
+		was_mouse_pressed = false;
+
 		return;
 	}
 

+ 8 - 3
scene/gui/menu_button.cpp

@@ -62,9 +62,14 @@ void MenuButton::pressed() {
 	popup->set_scale(get_global_transform().get_scale());
 	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 && !_was_pressed_by_mouse()) {
-		popup->set_current_index(0);
+	// If not triggered by the mouse, start the popup with its first enabled item focused.
+	if (!_was_pressed_by_mouse()) {
+		for (int i = 0; i < popup->get_item_count(); i++) {
+			if (!popup->is_item_disabled(i)) {
+				popup->set_current_index(i);
+				break;
+			}
+		}
 	}
 
 	popup->popup();

+ 12 - 3
scene/gui/option_button.cpp

@@ -112,9 +112,18 @@ void OptionButton::pressed() {
 	popup->set_size(Size2(size.width, 0));
 	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 && !_was_pressed_by_mouse()) {
-		popup->set_current_index(0);
+	// If not triggered by the mouse, start the popup with the checked item (or the first enabled one) focused.
+	if (!_was_pressed_by_mouse()) {
+		if (current > -1 && !popup->is_item_disabled(current)) {
+			popup->set_current_index(current);
+		} else {
+			for (int i = 0; i < popup->get_item_count(); i++) {
+				if (!popup->is_item_disabled(i)) {
+					popup->set_current_index(i);
+					break;
+				}
+			}
+		}
 	}
 
 	popup->popup();

+ 16 - 4
scene/gui/popup_menu.cpp

@@ -171,9 +171,14 @@ void PopupMenu::_activate_submenu(int over, bool p_by_keyboard) {
 
 	PopupMenu *pum = Object::cast_to<PopupMenu>(pm);
 	if (pum) {
-		// If not triggered by the mouse, start the popup with its first item selected.
-		if (pum->get_item_count() > 0 && p_by_keyboard) {
-			pum->set_current_index(0);
+		// If not triggered by the mouse, start the popup with its first enabled item focused.
+		if (p_by_keyboard) {
+			for (int i = 0; i < pum->get_item_count(); i++) {
+				if (!pum->is_item_disabled(i)) {
+					pum->set_current_index(i);
+					break;
+				}
+			}
 		}
 
 		// Setting autohide areas *must* be done after `popup()` which can move the popup (to fit it into the viewport).
@@ -1051,7 +1056,14 @@ bool PopupMenu::is_item_shortcut_disabled(int p_idx) const {
 }
 
 void PopupMenu::set_current_index(int p_idx) {
-	ERR_FAIL_INDEX(p_idx, items.size());
+	if (p_idx != -1) {
+		ERR_FAIL_INDEX(p_idx, items.size());
+	}
+
+	if (mouse_over == p_idx) {
+		return;
+	}
+
 	mouse_over = p_idx;
 	update();
 }

+ 2 - 0
scene/main/viewport.cpp

@@ -2174,6 +2174,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
 					popup_menu->hide();
 
 					menu_button->pressed();
+					// As the popup wasn't triggered by a mouse click, the item focus needs to be removed manually.
+					menu_button->get_popup()->set_current_index(-1);
 				} else {
 					over = nullptr; //nothing can be found outside the modal stack
 				}