From 3dd881b4e423a28c5d6e8829a0b415fea80ac601 Mon Sep 17 00:00:00 2001 From: Tomasz Chabora Date: Sun, 23 Feb 2020 22:23:34 +0100 Subject: [PATCH] Add option to allow echo events in menu shortcuts --- doc/classes/PopupMenu.xml | 4 ++ editor/editor_node.cpp | 4 +- .../4.0-stable.expected | 8 ++++ scene/gui/menu_bar.cpp | 2 +- scene/gui/menu_button.cpp | 2 +- scene/gui/popup_menu.compat.inc | 46 +++++++++++++++++++ scene/gui/popup_menu.cpp | 28 +++++------ scene/gui/popup_menu.h | 11 ++++- 8 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 scene/gui/popup_menu.compat.inc diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index daf31638427..b72e65e63ab 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -96,9 +96,11 @@ + Adds a new item and assigns the specified [Shortcut] and icon [param texture] to it. Sets the label of the checkbox to the [Shortcut]'s name. An [param id] can optionally be provided. If no [param id] is provided, one will be created from the index. + If [param allow_echo] is [code]true[/code], the shortcut can be activated with echo events. @@ -161,9 +163,11 @@ + Adds a [Shortcut]. An [param id] can optionally be provided. If no [param id] is provided, one will be created from the index. + If [param allow_echo] is [code]true[/code], the shortcut can be activated with echo events. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index f207418f716..7f88225686a 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -7472,8 +7472,8 @@ EditorNode::EditorNode() { export_as_menu->connect("index_pressed", callable_mp(this, &EditorNode::_export_as_menu_option)); file_menu->add_separator(); - file_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO, true); - file_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO, true); + file_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO, true, true); + file_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO, true, true); file_menu->add_separator(); file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reload_saved_scene", TTR("Reload Saved Scene")), EDIT_RELOAD_SAVED_SCENE); diff --git a/misc/extension_api_validation/4.0-stable.expected b/misc/extension_api_validation/4.0-stable.expected index 823af03c8e8..5f982cbff6d 100644 --- a/misc/extension_api_validation/4.0-stable.expected +++ b/misc/extension_api_validation/4.0-stable.expected @@ -443,3 +443,11 @@ Validate extension JSON: API was removed: classes/SystemFont/properties/fallback The property was moved to their common base class Font. The setters and getters were already in Font, so this shouldn't affect compatibility. + + +GH-36493 +-------- +Validate extension JSON: Error: Field 'classes/PopupMenu/methods/add_icon_shortcut/arguments': size changed value in new API, from 4 to 5. +Validate extension JSON: Error: Field 'classes/PopupMenu/methods/add_shortcut/arguments': size changed value in new API, from 3 to 4. + +Added optional argument. Compatibility methods registered. diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp index 85068ac8625..0dd258d92c3 100644 --- a/scene/gui/menu_bar.cpp +++ b/scene/gui/menu_bar.cpp @@ -152,7 +152,7 @@ void MenuBar::shortcut_input(const Ref &p_event) { return; } - if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to(p_event.ptr()) || Object::cast_to(p_event.ptr()) || Object::cast_to(*p_event) || Object::cast_to(*p_event))) { + if (p_event->is_pressed() && (Object::cast_to(p_event.ptr()) || Object::cast_to(p_event.ptr()) || Object::cast_to(*p_event) || Object::cast_to(*p_event))) { if (!get_parent() || !is_visible_in_tree()) { return; } diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 4e80d7a2d6d..868383b1411 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -40,7 +40,7 @@ void MenuButton::shortcut_input(const Ref &p_event) { return; } - if (p_event->is_pressed() && !p_event->is_echo() && !is_disabled() && is_visible_in_tree() && popup->activate_item_by_event(p_event, false)) { + if (p_event->is_pressed() && !is_disabled() && is_visible_in_tree() && popup->activate_item_by_event(p_event, false)) { accept_event(); return; } diff --git a/scene/gui/popup_menu.compat.inc b/scene/gui/popup_menu.compat.inc new file mode 100644 index 00000000000..ef74a172289 --- /dev/null +++ b/scene/gui/popup_menu.compat.inc @@ -0,0 +1,46 @@ +/**************************************************************************/ +/* popup_menu.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +void PopupMenu::_add_shortcut_bind_compat_36493(const Ref &p_shortcut, int p_id, bool p_global) { + return add_shortcut(p_shortcut, p_id, p_global, false); +} + +void PopupMenu::_add_icon_shortcut_bind_compat_36493(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { + return add_icon_shortcut(p_icon, p_shortcut, p_id, p_global, false); +} + +void PopupMenu::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("add_shortcut", "shortcut", "id", "global"), &PopupMenu::_add_shortcut_bind_compat_36493, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_compatibility_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::_add_icon_shortcut_bind_compat_36493, DEFVAL(-1), DEFVAL(false)); +} + +#endif diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 40db8deaace..4bba33f18e4 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "popup_menu.h" +#include "popup_menu.compat.inc" #include "core/config/project_settings.h" #include "core/input/input.h" @@ -1164,18 +1165,19 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int _menu_changed(); } -#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global) \ +#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo) \ ERR_FAIL_COND_MSG(p_shortcut.is_null(), "Cannot add item with invalid Shortcut."); \ _ref_shortcut(p_shortcut); \ item.text = p_shortcut->get_name(); \ item.xl_text = atr(item.text); \ item.id = p_id == -1 ? items.size() : p_id; \ item.shortcut = p_shortcut; \ - item.shortcut_is_global = p_global; + item.shortcut_is_global = p_global; \ + item.allow_echo = p_allow_echo; -void PopupMenu::add_shortcut(const Ref &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_shortcut(const Ref &p_shortcut, int p_id, bool p_global, bool p_allow_echo) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo); items.push_back(item); _shape_item(items.size() - 1); @@ -1185,9 +1187,9 @@ void PopupMenu::add_shortcut(const Ref &p_shortcut, int p_id, bool p_g _menu_changed(); } -void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global, bool p_allow_echo) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo); item.icon = p_icon; items.push_back(item); @@ -1200,7 +1202,7 @@ void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false); // Echo for check shortcuts doesn't make sense. item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); @@ -1213,7 +1215,7 @@ void PopupMenu::add_check_shortcut(const Ref &p_shortcut, int p_id, bo void PopupMenu::add_icon_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false); item.icon = p_icon; item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); @@ -1227,7 +1229,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref &p_icon, const Ref< void PopupMenu::add_radio_check_shortcut(const Ref &p_shortcut, int p_id, bool p_global) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false); item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; items.push_back(item); @@ -1240,7 +1242,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref &p_shortcut, int p_ void PopupMenu::add_icon_radio_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id, bool p_global) { Item item; - ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); + ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, false); item.icon = p_icon; item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; items.push_back(item); @@ -1838,7 +1840,7 @@ bool PopupMenu::activate_item_by_event(const Ref &p_event, bool p_fo } for (int i = 0; i < items.size(); i++) { - if (is_item_disabled(i) || items[i].shortcut_is_disabled) { + if (is_item_disabled(i) || items[i].shortcut_is_disabled || (!items[i].allow_echo && p_event->is_echo())) { continue; } @@ -2213,8 +2215,8 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("add_multistate_item", "label", "max_states", "default_state", "id", "accel"), &PopupMenu::add_multistate_item, DEFVAL(0), DEFVAL(-1), DEFVAL(0)); - ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut", "id", "global"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_shortcut", "shortcut", "id", "global", "allow_echo"), &PopupMenu::add_shortcut, DEFVAL(-1), DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global", "allow_echo"), &PopupMenu::add_icon_shortcut, DEFVAL(-1), DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_check_shortcut, DEFVAL(-1), DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_icon_check_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::add_icon_check_shortcut, DEFVAL(-1), DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_radio_check_shortcut", "shortcut", "id", "global"), &PopupMenu::add_radio_check_shortcut, DEFVAL(-1), DEFVAL(false)); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 5ad9cd43030..ef754315f08 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -74,6 +74,7 @@ class PopupMenu : public Popup { Ref shortcut; bool shortcut_is_global = false; bool shortcut_is_disabled = false; + bool allow_echo = false; // Returns (0,0) if icon is null. Size2 get_icon_size() const { @@ -199,6 +200,12 @@ protected: void _get_property_list(List *p_list) const; static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + void _add_shortcut_bind_compat_36493(const Ref &p_shortcut, int p_id = -1, bool p_global = false); + void _add_icon_shortcut_bind_compat_36493(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false); + static void _bind_compatibility_methods(); +#endif + public: // ATTENTION: This is used by the POT generator's scene parser. If the number of properties returned by `_get_items()` ever changes, // this value should be updated to reflect the new size. @@ -215,8 +222,8 @@ public: void add_multistate_item(const String &p_label, int p_max_states, int p_default_state = 0, int p_id = -1, Key p_accel = Key::NONE); - void add_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false); - void add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false); + void add_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false, bool p_allow_echo = false); + void add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false, bool p_allow_echo = false); void add_check_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false); void add_icon_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_id = -1, bool p_global = false); void add_radio_check_shortcut(const Ref &p_shortcut, int p_id = -1, bool p_global = false);