浏览代码

Merge pull request #56992 from YeldhamDev/smarter_popmenu_focus

Rémi Verschelde 3 年之前
父节点
当前提交
5e39a8eded
共有 4 个文件被更改,包括 49 次插入19 次删除
  1. 7 0
      doc/classes/PopupMenu.xml
  2. 7 1
      scene/gui/menu_button.cpp
  3. 8 1
      scene/gui/option_button.cpp
  4. 27 17
      scene/gui/popup_menu.cpp

+ 7 - 0
doc/classes/PopupMenu.xml

@@ -331,6 +331,13 @@
 				[b]Note:[/b] The indices of items after the removed item will be shifted by one.
 				[b]Note:[/b] The indices of items after the removed item will be shifted by one.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="set_current_index">
+			<return type="void" />
+			<argument index="0" name="index" type="int" />
+			<description>
+				Sets the currently focused item as the given [code]index[/code].
+			</description>
+		</method>
 		<method name="set_item_accelerator">
 		<method name="set_item_accelerator">
 			<return type="void" />
 			<return type="void" />
 			<argument index="0" name="index" type="int" />
 			<argument index="0" name="index" type="int" />

+ 7 - 1
scene/gui/menu_button.cpp

@@ -98,7 +98,13 @@ void MenuButton::pressed() {
 	popup->set_position(gp);
 	popup->set_position(gp);
 	popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), size));
 	popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), size));
 
 
-	popup->take_mouse_focus();
+	// 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")))) {
+		popup->set_current_index(0);
+	}
+
 	popup->popup();
 	popup->popup();
 }
 }
 
 

+ 8 - 1
scene/gui/option_button.cpp

@@ -181,7 +181,14 @@ void OptionButton::pressed() {
 	Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale();
 	Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale();
 	popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
 	popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
 	popup->set_size(Size2(size.width, 0));
 	popup->set_size(Size2(size.width, 0));
-	popup->set_current_index(current);
+
+	// If not triggered by the mouse, start the popup with the checked 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")))) {
+		popup->set_current_index(current > -1 ? current : 0);
+	}
+
 	popup->popup();
 	popup->popup();
 }
 }
 
 

+ 27 - 17
scene/gui/popup_menu.cpp

@@ -192,7 +192,7 @@ void PopupMenu::_activate_submenu(int p_over) {
 	Popup *submenu_popup = Object::cast_to<Popup>(n);
 	Popup *submenu_popup = Object::cast_to<Popup>(n);
 	ERR_FAIL_COND_MSG(!submenu_popup, "Item subnode is not a Popup: " + items[p_over].submenu + ".");
 	ERR_FAIL_COND_MSG(!submenu_popup, "Item subnode is not a Popup: " + items[p_over].submenu + ".");
 	if (submenu_popup->is_visible()) {
 	if (submenu_popup->is_visible()) {
-		return; //already visible!
+		return; // Already visible.
 	}
 	}
 
 
 	Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
 	Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
@@ -223,24 +223,33 @@ void PopupMenu::_activate_submenu(int p_over) {
 	submenu_popup->set_close_on_parent_focus(false);
 	submenu_popup->set_close_on_parent_focus(false);
 	submenu_popup->set_position(submenu_pos);
 	submenu_popup->set_position(submenu_pos);
 	submenu_popup->set_as_minsize(); // Shrink the popup size to its contents.
 	submenu_popup->set_as_minsize(); // Shrink the popup size to its contents.
-	submenu_popup->popup();
 
 
-	// Set autohide areas
 	PopupMenu *submenu_pum = Object::cast_to<PopupMenu>(submenu_popup);
 	PopupMenu *submenu_pum = Object::cast_to<PopupMenu>(submenu_popup);
-	if (submenu_pum) {
-		submenu_pum->take_mouse_focus();
-		// Make the position of the parent popup relative to submenu popup
-		this_rect.position = this_rect.position - submenu_pum->get_position();
-
-		// Autohide area above the submenu item
-		submenu_pum->clear_autohide_areas();
-		submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2));
-
-		// If there is an area below the submenu item, add an autohide area there.
-		if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) {
-			int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + vsep / 2 + style->get_offset().height;
-			submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from));
-		}
+	if (!submenu_pum) {
+		submenu_popup->popup();
+		return;
+	}
+
+	// If not triggered by the mouse, start the popup with its first item selected.
+	if (submenu_pum->get_item_count() > 0 && Input::get_singleton()->is_action_just_pressed("ui_accept")) {
+		submenu_pum->set_current_index(0);
+	}
+
+	submenu_pum->popup();
+
+	// Set autohide areas.
+
+	// Make the position of the parent popup relative to submenu popup.
+	this_rect.position = this_rect.position - submenu_pum->get_position();
+
+	// Autohide area above the submenu item.
+	submenu_pum->clear_autohide_areas();
+	submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2));
+
+	// If there is an area below the submenu item, add an autohide area there.
+	if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) {
+		int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + vsep / 2 + style->get_offset().height;
+		submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from));
 	}
 	}
 }
 }
 
 
@@ -1747,6 +1756,7 @@ void PopupMenu::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_item_tooltip", "index"), &PopupMenu::get_item_tooltip);
 	ClassDB::bind_method(D_METHOD("get_item_tooltip", "index"), &PopupMenu::get_item_tooltip);
 	ClassDB::bind_method(D_METHOD("get_item_shortcut", "index"), &PopupMenu::get_item_shortcut);
 	ClassDB::bind_method(D_METHOD("get_item_shortcut", "index"), &PopupMenu::get_item_shortcut);
 
 
+	ClassDB::bind_method(D_METHOD("set_current_index", "index"), &PopupMenu::set_current_index);
 	ClassDB::bind_method(D_METHOD("get_current_index"), &PopupMenu::get_current_index);
 	ClassDB::bind_method(D_METHOD("get_current_index"), &PopupMenu::get_current_index);
 	ClassDB::bind_method(D_METHOD("set_item_count", "count"), &PopupMenu::set_item_count);
 	ClassDB::bind_method(D_METHOD("set_item_count", "count"), &PopupMenu::set_item_count);
 	ClassDB::bind_method(D_METHOD("get_item_count"), &PopupMenu::get_item_count);
 	ClassDB::bind_method(D_METHOD("get_item_count"), &PopupMenu::get_item_count);