diff options
Diffstat (limited to 'scene/gui/menu_button.cpp')
-rw-r--r-- | scene/gui/menu_button.cpp | 116 |
1 files changed, 91 insertions, 25 deletions
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 737ba84617..069a31d9d2 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,10 +33,10 @@ #include "core/os/keyboard.h" #include "scene/main/window.h" -void MenuButton::unhandled_key_input(const Ref<InputEvent> &p_event) { +void MenuButton::shortcut_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); - if (!_is_focus_owner_in_shorcut_context()) { + if (!_is_focus_owner_in_shortcut_context()) { return; } @@ -87,16 +87,24 @@ void MenuButton::_popup_visibility_changed(bool p_visible) { void MenuButton::pressed() { emit_signal(SNAME("about_to_popup")); - Size2 size = get_size(); + Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); + popup->set_size(Size2(size.width, 0)); Point2 gp = get_screen_position(); - gp.y += get_size().y; - + gp.y += size.y; + if (is_layout_rtl()) { + gp.x += size.width - popup->get_size().width; + } popup->set_position(gp); + popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), 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")))) { + popup->set_current_index(0); + } - popup->set_size(Size2(size.width, 0)); - popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), get_size())); - popup->take_mouse_focus(); popup->popup(); } @@ -108,14 +116,6 @@ PopupMenu *MenuButton::get_popup() const { return popup; } -void MenuButton::_set_items(const Array &p_items) { - popup->set("items", p_items); -} - -Array MenuButton::_get_items() const { - return popup->get("items"); -} - void MenuButton::set_switch_on_hover(bool p_enabled) { switch_on_hover = p_enabled; } @@ -124,13 +124,28 @@ bool MenuButton::is_switch_on_hover() { return switch_on_hover; } +void MenuButton::set_item_count(int p_count) { + ERR_FAIL_COND(p_count < 0); + popup->set_item_count(p_count); + notify_property_list_changed(); +} + +int MenuButton::get_item_count() const { + return popup->get_item_count(); +} + void MenuButton::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { + popup->set_layout_direction((Window::LayoutDirection)get_layout_direction()); + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { if (!is_visible_in_tree()) { popup->hide(); } } break; + case NOTIFICATION_INTERNAL_PROCESS: { Vector2i mouse_pos = DisplayServer::get_singleton()->mouse_get_position() - mouse_pos_adjusted; MenuButton *menu_btn_other = Object::cast_to<MenuButton>(get_viewport()->gui_find_control(mouse_pos)); @@ -144,16 +159,66 @@ void MenuButton::_notification(int p_what) { } } +bool MenuButton::_set(const StringName &p_name, const Variant &p_value) { + Vector<String> components = String(p_name).split("/", true, 2); + if (components.size() >= 2 && components[0] == "popup") { + bool valid; + popup->set(String(p_name).trim_prefix("popup/"), p_value, &valid); + return valid; + } + return false; +} + +bool MenuButton::_get(const StringName &p_name, Variant &r_ret) const { + Vector<String> components = String(p_name).split("/", true, 2); + if (components.size() >= 2 && components[0] == "popup") { + bool valid; + r_ret = popup->get(String(p_name).trim_prefix("popup/"), &valid); + return valid; + } + return false; +} + +void MenuButton::_get_property_list(List<PropertyInfo> *p_list) const { + for (int i = 0; i < popup->get_item_count(); i++) { + p_list->push_back(PropertyInfo(Variant::STRING, vformat("popup/item_%d/text", i))); + + PropertyInfo pi = PropertyInfo(Variant::OBJECT, vformat("popup/item_%d/icon", i), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"); + pi.usage &= ~(popup->get_item_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/checkable", i), PROPERTY_HINT_ENUM, "No,As Checkbox,As Radio Button"); + pi.usage &= ~(!popup->is_item_checkable(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/checked", i)); + pi.usage &= ~(!popup->is_item_checked(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/id", i), PROPERTY_HINT_RANGE, "0,10,1,or_greater"); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/disabled", i)); + pi.usage &= ~(!popup->is_item_disabled(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/separator", i)); + pi.usage &= ~(!popup->is_item_separator(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + } +} + void MenuButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_popup"), &MenuButton::get_popup); - ClassDB::bind_method(D_METHOD("_set_items"), &MenuButton::_set_items); - ClassDB::bind_method(D_METHOD("_get_items"), &MenuButton::_get_items); ClassDB::bind_method(D_METHOD("set_switch_on_hover", "enable"), &MenuButton::set_switch_on_hover); ClassDB::bind_method(D_METHOD("is_switch_on_hover"), &MenuButton::is_switch_on_hover); ClassDB::bind_method(D_METHOD("set_disable_shortcuts", "disabled"), &MenuButton::set_disable_shortcuts); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); + ClassDB::bind_method(D_METHOD("set_item_count", "count"), &MenuButton::set_item_count); + ClassDB::bind_method(D_METHOD("get_item_count"), &MenuButton::get_item_count); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "switch_on_hover"), "set_switch_on_hover", "is_switch_on_hover"); + ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_"); ADD_SIGNAL(MethodInfo("about_to_popup")); } @@ -162,19 +227,20 @@ void MenuButton::set_disable_shortcuts(bool p_disabled) { disable_shortcuts = p_disabled; } -MenuButton::MenuButton() { +MenuButton::MenuButton(const String &p_text) : + Button(p_text) { set_flat(true); set_toggle_mode(true); set_disable_shortcuts(false); - set_process_unhandled_key_input(true); + set_process_shortcut_input(true); set_focus_mode(FOCUS_NONE); set_action_mode(ACTION_MODE_BUTTON_PRESS); popup = memnew(PopupMenu); popup->hide(); add_child(popup, false, INTERNAL_MODE_FRONT); - popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(true)); - popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(false)); + popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(true)); + popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed).bind(false)); } MenuButton::~MenuButton() { |