Fix crash when pressing up on an empty PopupMenu

This commit is contained in:
Michael Alexsander 2022-08-27 18:13:27 -03:00
parent d3db8bbebd
commit 06df59887b

View file

@ -278,102 +278,104 @@ void PopupMenu::_submenu_timeout() {
void PopupMenu::gui_input(const Ref<InputEvent> &p_event) { void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null()); ERR_FAIL_COND(p_event.is_null());
if (p_event->is_action("ui_down") && p_event->is_pressed()) { if (!items.is_empty()) {
int search_from = mouse_over + 1; if (p_event->is_action("ui_down") && p_event->is_pressed()) {
if (search_from >= items.size()) { int search_from = mouse_over + 1;
search_from = 0; if (search_from >= items.size()) {
} search_from = 0;
bool match_found = false;
for (int i = search_from; i < items.size(); i++) {
if (!items[i].separator && !items[i].disabled) {
mouse_over = i;
emit_signal(SNAME("id_focused"), i);
scroll_to_item(i);
control->update();
set_input_as_handled();
match_found = true;
break;
} }
}
if (!match_found) { bool match_found = false;
// If the last item is not selectable, try re-searching from the start. for (int i = search_from; i < items.size(); i++) {
for (int i = 0; i < search_from; i++) {
if (!items[i].separator && !items[i].disabled) { if (!items[i].separator && !items[i].disabled) {
mouse_over = i; mouse_over = i;
emit_signal(SNAME("id_focused"), i); emit_signal(SNAME("id_focused"), i);
scroll_to_item(i); scroll_to_item(i);
control->update(); control->update();
set_input_as_handled(); set_input_as_handled();
match_found = true;
break; break;
} }
} }
}
} else if (p_event->is_action("ui_up") && p_event->is_pressed()) {
int search_from = mouse_over - 1;
if (search_from < 0) {
search_from = items.size() - 1;
}
bool match_found = false; if (!match_found) {
for (int i = search_from; i >= 0; i--) { // If the last item is not selectable, try re-searching from the start.
if (!items[i].separator && !items[i].disabled) { for (int i = 0; i < search_from; i++) {
mouse_over = i; if (!items[i].separator && !items[i].disabled) {
emit_signal(SNAME("id_focused"), i); mouse_over = i;
scroll_to_item(i); emit_signal(SNAME("id_focused"), i);
control->update(); scroll_to_item(i);
set_input_as_handled(); control->update();
match_found = true; set_input_as_handled();
break; break;
}
}
}
} else if (p_event->is_action("ui_up") && p_event->is_pressed()) {
int search_from = mouse_over - 1;
if (search_from < 0) {
search_from = items.size() - 1;
} }
}
if (!match_found) { bool match_found = false;
// If the first item is not selectable, try re-searching from the end. for (int i = search_from; i >= 0; i--) {
for (int i = items.size() - 1; i >= search_from; i--) {
if (!items[i].separator && !items[i].disabled) { if (!items[i].separator && !items[i].disabled) {
mouse_over = i; mouse_over = i;
emit_signal(SNAME("id_focused"), i); emit_signal(SNAME("id_focused"), i);
scroll_to_item(i); scroll_to_item(i);
control->update(); control->update();
set_input_as_handled(); set_input_as_handled();
match_found = true;
break; break;
} }
} }
}
} else if (p_event->is_action("ui_left") && p_event->is_pressed()) { if (!match_found) {
Node *n = get_parent(); // If the first item is not selectable, try re-searching from the end.
if (n) { for (int i = items.size() - 1; i >= search_from; i--) {
if (Object::cast_to<PopupMenu>(n)) { if (!items[i].separator && !items[i].disabled) {
hide(); mouse_over = i;
set_input_as_handled(); emit_signal(SNAME("id_focused"), i);
} else if (Object::cast_to<MenuBar>(n)) { scroll_to_item(i);
Object::cast_to<MenuBar>(n)->gui_input(p_event); control->update();
set_input_as_handled(); set_input_as_handled();
return; break;
}
}
} }
} } else if (p_event->is_action("ui_left") && p_event->is_pressed()) {
} 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.is_empty() && submenu_over != mouse_over) {
_activate_submenu(mouse_over, true);
set_input_as_handled();
} else {
Node *n = get_parent(); Node *n = get_parent();
if (n && Object::cast_to<MenuBar>(n)) { if (n) {
Object::cast_to<MenuBar>(n)->gui_input(p_event); if (Object::cast_to<PopupMenu>(n)) {
set_input_as_handled(); hide();
return; set_input_as_handled();
} else if (Object::cast_to<MenuBar>(n)) {
Object::cast_to<MenuBar>(n)->gui_input(p_event);
set_input_as_handled();
return;
}
} }
} } else if (p_event->is_action("ui_right") && p_event->is_pressed()) {
} else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && !items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {
if (!items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
_activate_submenu(mouse_over, true); _activate_submenu(mouse_over, true);
set_input_as_handled();
} else { } else {
activate_item(mouse_over); Node *n = get_parent();
if (n && Object::cast_to<MenuBar>(n)) {
Object::cast_to<MenuBar>(n)->gui_input(p_event);
set_input_as_handled();
return;
}
}
} 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.is_empty() && submenu_over != mouse_over) {
_activate_submenu(mouse_over, true);
} else {
activate_item(mouse_over);
}
set_input_as_handled();
} }
set_input_as_handled();
} }
} }