Backported _shortcut_input() virtual from godot4.

This commit is contained in:
Relintai 2023-09-07 09:56:16 +02:00
parent 66e080d766
commit 9a2bf73280
47 changed files with 337 additions and 85 deletions

View File

@ -31,6 +31,7 @@
#include "input_event.h"
#include "core/input/input_map.h"
#include "core/input/shortcut.h"
#include "core/os/keyboard.h"
const int InputEvent::DEVICE_ID_TOUCH_MOUSE = -1;
@ -1067,8 +1068,9 @@ String InputEventScreenDrag::as_text() const {
bool InputEventScreenDrag::accumulate(const Ref<InputEvent> &p_event) {
Ref<InputEventScreenDrag> drag = p_event;
if (drag.is_null())
if (drag.is_null()) {
return false;
}
if (get_index() != drag->get_index()) {
return false;
@ -1378,3 +1380,39 @@ InputEventMIDI::InputEventMIDI() {
controller_number = 0;
controller_value = 0;
}
///////////////////////////////////
void InputEventShortCut::set_shortcut(Ref<ShortCut> p_shortcut) {
shortcut = p_shortcut;
emit_changed();
}
Ref<ShortCut> InputEventShortCut::get_shortcut() {
return shortcut;
}
void InputEventShortCut::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut"), &InputEventShortCut::set_shortcut);
ClassDB::bind_method(D_METHOD("get_shortcut"), &InputEventShortCut::get_shortcut);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "ShortCut"), "set_shortcut", "get_shortcut");
}
String InputEventShortCut::as_text() const {
ERR_FAIL_COND_V(shortcut.is_null(), "None");
return vformat(RTR("Input Event with ShortCut=%s"), shortcut->get_as_text());
}
String InputEventShortCut::to_string() {
ERR_FAIL_COND_V(shortcut.is_null(), "None");
return vformat("InputEventShortCut: shortcut=%s", shortcut->get_as_text());
}
InputEventShortCut::InputEventShortCut() {
}
InputEventShortCut::~InputEventShortCut() {
}

View File

@ -40,6 +40,8 @@
* The events are pretty obvious.
*/
class ShortCut;
enum ButtonList {
BUTTON_LEFT = 1,
BUTTON_RIGHT = 2,
@ -651,4 +653,23 @@ public:
InputEventMIDI();
};
class InputEventShortCut : public InputEvent {
GDCLASS(InputEventShortCut, InputEvent);
Ref<ShortCut> shortcut;
protected:
static void _bind_methods();
public:
void set_shortcut(Ref<ShortCut> p_shortcut);
Ref<ShortCut> get_shortcut();
virtual String as_text() const;
virtual String to_string();
InputEventShortCut();
~InputEventShortCut();
};
#endif

View File

@ -159,6 +159,7 @@ void register_core_types() {
ClassDB::register_class<InputEventMagnifyGesture>();
ClassDB::register_class<InputEventPanGesture>();
ClassDB::register_class<InputEventMIDI>();
ClassDB::register_class<InputEventShortCut>();
ClassDB::register_class<FuncRef>();
ClassDB::register_virtual_class<StreamPeer>();

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="InputEventShortCut" inherits="InputEvent" version="4.1">
<brief_description>
Represents a triggered keyboard [ShortCut].
</brief_description>
<description>
InputEventShortCut is a special event that can be received in [method Node._unhandled_key_input]. It is typically sent by the editor's Command Palette to trigger actions, but can also be sent manually using [method Viewport.push_input].
</description>
<tutorials>
</tutorials>
<members>
<member name="shortcut" type="ShortCut" setter="set_shortcut" getter="get_shortcut">
The [ShortCut] represented by this event. Its [method ShortCut.matches_event] method will always return [code]true[/code] for this event.
</member>
</members>
</class>

View File

@ -95,6 +95,17 @@
[b]Note:[/b] [method _ready] may be called only once for each node. After removing a node from the scene tree and adding it again, [code]_ready[/code] will not be called a second time. This can be bypassed by requesting another call with [method request_ready], which may be called anywhere before adding the node again.
</description>
</method>
<method name="_shortcut_input" qualifiers="virtual">
<return type="void" />
<argument index="0" name="event" type="InputEvent" />
<description>
Called when an [InputEventKey] or [InputEventShortcut] hasn't been consumed by [method _input] or any GUI [Control] item. The input event propagates up through the node tree until a node consumes it.
It is only called if shortcut processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_shortcut_input].
To consume the input event and stop it propagating further to other nodes, [method Viewport.set_input_as_handled] can be called.
This method can be used to handle shortcuts.
[b]Note:[/b] This method is only called if the node is present in the scene tree (i.e. if it's not orphan).
</description>
</method>
<method name="_unhandled_input" qualifiers="virtual">
<return type="void" />
<argument index="0" name="event" type="InputEvent" />
@ -113,6 +124,7 @@
Called when an [InputEventKey] hasn't been consumed by [method _input] or any GUI [Control] item. The input event propagates up through the node tree until a node consumes it.
It is only called if unhandled key input processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_unhandled_key_input].
To consume the input event and stop it propagating further to other nodes, [method SceneTree.set_input_as_handled] can be called.
This method can be used to handle Unicode character input with [kbd]Alt[/kbd], [kbd]Alt + Ctrl[/kbd], and [kbd]Alt + Shift[/kbd] modifiers, after shortcuts were handled.
For gameplay input, this and [method _unhandled_input] are usually a better fit than [method _input] as they allow the GUI to intercept the events first.
[b]Note:[/b] This method is only called if the node is present in the scene tree (i.e. if it's not an orphan).
</description>
@ -493,6 +505,12 @@
Returns [code]true[/code] if internal processing is enabled (see [method set_process_internal]).
</description>
</method>
<method name="is_processing_shortcut_input" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if the node is processing shortcuts (see [method set_process_shortcut_input]).
</description>
</method>
<method name="is_processing_unhandled_input" qualifiers="const">
<return type="bool" />
<description>
@ -798,6 +816,13 @@
[b]Warning:[/b] Built-in Nodes rely on the internal processing for their own logic, so changing this value from your code may lead to unexpected behavior. Script access to this internal logic is provided for specific advanced uses, but is unsafe and not supported.
</description>
</method>
<method name="set_process_shortcut_input">
<return type="void" />
<argument index="0" name="enable" type="bool" />
<description>
Enables shortcut processing. Enabled automatically if [method _shortcut_input] is overridden. Any calls to this before [method _ready] will be ignored.
</description>
</method>
<method name="set_process_unhandled_input">
<return type="void" />
<argument index="0" name="enable" type="bool" />

View File

@ -109,7 +109,7 @@ void EditorFileDialog::_notification(int p_what) {
}
}
} else if (p_what == NOTIFICATION_POPUP_HIDE) {
set_process_unhandled_input(false);
set_process_shortcut_input(false);
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
bool is_showing_hidden = EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files");
@ -146,7 +146,7 @@ void EditorFileDialog::_notification(int p_what) {
}
}
void EditorFileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
void EditorFileDialog::_shortcut_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid() && is_window_modal_on_top()) {
@ -345,7 +345,7 @@ void EditorFileDialog::_post_popup() {
_update_favorites();
}
set_process_unhandled_input(true);
set_process_shortcut_input(true);
}
void EditorFileDialog::_thumbnail_result(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) {
@ -1397,7 +1397,7 @@ EditorFileDialog::DisplayMode EditorFileDialog::get_display_mode() const {
}
void EditorFileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_input"), &EditorFileDialog::_unhandled_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &EditorFileDialog::_shortcut_input);
ClassDB::bind_method(D_METHOD("_item_selected"), &EditorFileDialog::_item_selected);
ClassDB::bind_method(D_METHOD("_multi_selected"), &EditorFileDialog::_multi_selected);

View File

@ -208,7 +208,7 @@ private:
void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata);
void _request_single_thumbnail(const String &p_path);
void _unhandled_input(const Ref<InputEvent> &p_event);
void _shortcut_input(const Ref<InputEvent> &p_event);
bool _is_open_should_be_disabled();

View File

@ -579,7 +579,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
}
}
void EditorProperty::_unhandled_key_input(const Ref<InputEvent> &p_event) {
void EditorProperty::_shortcut_input(const Ref<InputEvent> &p_event) {
if (!selected) {
return;
}
@ -755,7 +755,7 @@ void EditorProperty::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &EditorProperty::_gui_input);
ClassDB::bind_method(D_METHOD("_menu_option", "option"), &EditorProperty::_menu_option);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &EditorProperty::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &EditorProperty::_shortcut_input);
ClassDB::bind_method(D_METHOD("_focusable_focused"), &EditorProperty::_focusable_focused);
ClassDB::bind_method(D_METHOD("add_focusable", "control"), &EditorProperty::add_focusable);
@ -812,7 +812,7 @@ EditorProperty::EditorProperty() {
bottom_editor = nullptr;
menu = nullptr;
set_process_unhandled_key_input(true);
set_process_shortcut_input(true);
}
void EditorProperty::_update_popup() {

View File

@ -137,7 +137,7 @@ protected:
static void _bind_methods();
void _gui_input(const Ref<InputEvent> &p_event);
void _unhandled_key_input(const Ref<InputEvent> &p_event);
void _shortcut_input(const Ref<InputEvent> &p_event);
public:
void emit_changed(const StringName &p_property, const Variant &p_value, const StringName &p_field = StringName(), bool p_changing = false);

View File

@ -30,40 +30,38 @@
#include "animation_player_editor_plugin.h"
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/input/input.h"
#include "core/os/keyboard.h"
#include "core/config/project_settings.h"
#include "editor/animation_track_editor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
// For onion skinning.
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/spatial_editor_plugin.h"
#include "scene/main/viewport.h"
#include "servers/rendering_server.h"
#include "core/variant/array.h"
#include "core/object/class_db.h"
#include "core/math/color.h"
#include "core/containers/list.h"
#include "core/containers/rid_handle.h"
#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/input/input_event.h"
#include "core/io/image.h"
#include "core/containers/list.h"
#include "core/math/color.h"
#include "core/math/math_funcs.h"
#include "core/math/rect2.h"
#include "core/input/input_event.h"
#include "core/os/memory.h"
#include "core/object/class_db.h"
#include "core/object/resource.h"
#include "core/containers/rid_handle.h"
#include "core/object/undo_redo.h"
#include "core/os/memory.h"
#include "core/string/string_name.h"
#include "core/typedefs.h"
#include "core/object/undo_redo.h"
#include "core/variant/array.h"
#include "core/variant/variant.h"
#include "editor/editor_data.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/spatial_editor_plugin.h"
#include "editor/scene_tree_dock.h"
#include "editor/scene_tree_editor.h"
#include "scene/animation/animation_player.h"
@ -80,8 +78,10 @@
#include "scene/gui/tree.h"
#include "scene/main/node.h"
#include "scene/main/scene_tree.h"
#include "scene/main/viewport.h"
#include "scene/resources/animation.h"
#include "scene/resources/texture.h"
#include "servers/rendering_server.h"
void AnimationPlayerEditor::_node_removed(Node *p_node) {
if (player && player == p_node) {
@ -1296,7 +1296,7 @@ void AnimationPlayerEditor::_onion_skinning_menu(int p_option) {
}
}
void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
void AnimationPlayerEditor::_shortcut_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
Ref<InputEventKey> k = p_ev;
@ -1305,18 +1305,23 @@ void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
case KEY_A: {
if (!k->get_shift()) {
_play_bw_from_pressed();
accept_event();
} else {
_play_bw_pressed();
accept_event();
}
} break;
case KEY_S: {
_stop_pressed();
accept_event();
} break;
case KEY_D: {
if (!k->get_shift()) {
_play_from_pressed();
accept_event();
} else {
_play_pressed();
accept_event();
}
} break;
}
@ -1582,7 +1587,7 @@ void AnimationPlayerEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_animation_key_editor_anim_len_changed"), &AnimationPlayerEditor::_animation_key_editor_anim_len_changed);
ClassDB::bind_method(D_METHOD("_animation_duplicate"), &AnimationPlayerEditor::_animation_duplicate);
ClassDB::bind_method(D_METHOD("_blend_editor_next_changed"), &AnimationPlayerEditor::_blend_editor_next_changed);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &AnimationPlayerEditor::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &AnimationPlayerEditor::_shortcut_input);
ClassDB::bind_method(D_METHOD("_animation_tool_menu"), &AnimationPlayerEditor::_animation_tool_menu);
ClassDB::bind_method(D_METHOD("_onion_skinning_menu"), &AnimationPlayerEditor::_onion_skinning_menu);
@ -1789,7 +1794,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
last_active = false;
timeline_position = 0;
set_process_unhandled_key_input(true);
set_process_shortcut_input(true);
add_child(track_editor);
track_editor->set_v_size_flags(SIZE_EXPAND_FILL);

View File

@ -225,7 +225,7 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_key_editor_seek(float p_pos, bool p_drag);
void _animation_key_editor_anim_len_changed(float p_len);
void _unhandled_key_input(const Ref<InputEvent> &p_ev);
void _shortcut_input(const Ref<InputEvent> &p_ev);
void _animation_tool_menu(int p_option);
void _onion_skinning_menu(int p_option);

View File

@ -514,7 +514,7 @@ float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
return (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target;
}
void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
void CanvasItemEditor::_shortcut_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
Ref<InputEventKey> k = p_ev;
@ -532,6 +532,7 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
// Multiply the grid size
grid_step_multiplier = MIN(grid_step_multiplier + 1, 12);
viewport->update();
accept_event();
} else if ((grid_snap_active || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) {
// Divide the grid size
Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1);
@ -539,6 +540,7 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
grid_step_multiplier--;
}
viewport->update();
accept_event();
}
}
}
@ -5001,7 +5003,7 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data);
ClassDB::bind_method("_button_tool_select", &CanvasItemEditor::_button_tool_select);
ClassDB::bind_method("_keying_changed", &CanvasItemEditor::_keying_changed);
ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input);
ClassDB::bind_method("_shortcut_input", &CanvasItemEditor::_shortcut_input);
ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport);
ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport);
ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed);
@ -5772,7 +5774,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom to 800%"), KEY_4);
ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom to 1600%"), KEY_5);
set_process_unhandled_key_input(true);
set_process_shortcut_input(true);
// Update the menus' checkboxes
call_deferred("set_state", get_state());

View File

@ -488,7 +488,7 @@ private:
void _keying_changed();
void _unhandled_key_input(const Ref<InputEvent> &p_ev);
void _shortcut_input(const Ref<InputEvent> &p_ev);
void _draw_text_at_position(Point2 p_position, String p_string, Margin p_side);
void _draw_margin_at_position(int p_value, Point2 p_position, Margin p_side);

View File

@ -6703,7 +6703,7 @@ void SpatialEditor::snap_selected_nodes_to_floor() {
}
}
void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) {
void SpatialEditor::_shortcut_input(Ref<InputEvent> p_event) {
ERR_FAIL_COND(p_event.is_null());
if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack()) {
@ -6711,6 +6711,7 @@ void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) {
}
snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
// Don't accept event here
}
void SpatialEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
@ -7057,7 +7058,7 @@ void SpatialEditor::_register_all_gizmos() {
}
void SpatialEditor::_bind_methods() {
ClassDB::bind_method("_unhandled_key_input", &SpatialEditor::_unhandled_key_input);
ClassDB::bind_method("_shortcut_input", &SpatialEditor::_shortcut_input);
ClassDB::bind_method("_node_removed", &SpatialEditor::_node_removed);
ClassDB::bind_method("_menu_item_pressed", &SpatialEditor::_menu_item_pressed);
ClassDB::bind_method("_menu_gizmo_toggled", &SpatialEditor::_menu_gizmo_toggled);
@ -7483,7 +7484,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
selected = nullptr;
set_process_unhandled_key_input(true);
set_process_shortcut_input(true);
add_to_group("_spatial_editor_group");
EDITOR_DEF("editors/3d/manipulator_gizmo_size", 80);

View File

@ -739,7 +739,7 @@ private:
protected:
void _notification(int p_what);
//void _gui_input(InputEvent p_event);
void _unhandled_key_input(Ref<InputEvent> p_event);
void _shortcut_input(Ref<InputEvent> p_event);
static void _bind_methods();

View File

@ -1806,7 +1806,7 @@ void ProjectManager::_notification(int p_what) {
#endif
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
set_process_unhandled_input(is_visible_in_tree());
set_process_shortcut_input(is_visible_in_tree());
} break;
case NOTIFICATION_WM_QUIT_REQUEST: {
_dim_window();
@ -1848,7 +1848,7 @@ void ProjectManager::_update_project_buttons() {
erase_missing_btn->set_disabled(!_project_list->is_any_project_missing());
}
void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
void ProjectManager::_shortcut_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventKey> k = p_ev;
if (k.is_valid()) {
@ -2378,7 +2378,7 @@ void ProjectManager::_bind_methods() {
ClassDB::bind_method("_on_tab_changed", &ProjectManager::_on_tab_changed);
ClassDB::bind_method("_on_projects_updated", &ProjectManager::_on_projects_updated);
ClassDB::bind_method("_on_project_created", &ProjectManager::_on_project_created);
ClassDB::bind_method("_unhandled_input", &ProjectManager::_unhandled_input);
ClassDB::bind_method("_shortcut_input", &ProjectManager::_shortcut_input);
ClassDB::bind_method("_install_project", &ProjectManager::_install_project);
ClassDB::bind_method("_files_dropped", &ProjectManager::_files_dropped);
ClassDB::bind_method("_confirm_update_settings", &ProjectManager::_confirm_update_settings);

View File

@ -127,7 +127,7 @@ class ProjectManager : public Control {
void _install_project(const String &p_zip_path, const String &p_title);
void _dim_window();
void _unhandled_input(const Ref<InputEvent> &p_ev);
void _shortcut_input(const Ref<InputEvent> &p_ev);
void _files_dropped(PoolStringArray p_files, int p_screen);
void _scan_multiple_folders(PoolStringArray p_files);

View File

@ -122,7 +122,7 @@ static const char *_axis_names[JOY_AXIS_MAX * 2] = {
"", " (Right Trigger, Sony R2, Xbox RT)"
};
void ProjectSettingsEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
void ProjectSettingsEditor::_shortcut_input(const Ref<InputEvent> &p_event) {
const Ref<InputEventKey> k = p_event;
if (k.is_valid() && is_window_modal_on_top() && k->is_pressed()) {
@ -192,7 +192,7 @@ void ProjectSettingsEditor::_notification(int p_what) {
case NOTIFICATION_POPUP_HIDE: {
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "project_settings", get_rect());
set_process_unhandled_input(false);
set_process_shortcut_input(false);
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
search_button->set_icon(get_theme_icon("Search", "EditorIcons"));
@ -945,7 +945,7 @@ void ProjectSettingsEditor::popup_project_settings() {
autoload_settings->update_autoload();
plugin_settings->update_plugins();
import_defaults_editor->clear();
set_process_unhandled_input(true);
set_process_shortcut_input(true);
}
void ProjectSettingsEditor::update_plugins() {
@ -1822,7 +1822,7 @@ void ProjectSettingsEditor::_update_theme() {
}
void ProjectSettingsEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_input"), &ProjectSettingsEditor::_unhandled_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &ProjectSettingsEditor::_shortcut_input);
ClassDB::bind_method(D_METHOD("_item_selected"), &ProjectSettingsEditor::_item_selected);
ClassDB::bind_method(D_METHOD("_item_add"), &ProjectSettingsEditor::_item_add);
ClassDB::bind_method(D_METHOD("_item_adds"), &ProjectSettingsEditor::_item_adds);

View File

@ -206,7 +206,7 @@ class ProjectSettingsEditor : public AcceptDialog {
void _update_theme();
protected:
void _unhandled_input(const Ref<InputEvent> &p_event);
void _shortcut_input(const Ref<InputEvent> &p_event);
void _notification(int p_what);
static void _bind_methods();

View File

@ -127,7 +127,7 @@ void SceneTreeDock::_input(Ref<InputEvent> p_event) {
}
}
void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
void SceneTreeDock::_shortcut_input(Ref<InputEvent> p_event) {
ERR_FAIL_COND(p_event.is_null());
if (get_viewport()->get_modal_stack_top()) {
@ -186,7 +186,11 @@ void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
_tool_selected(TOOL_TOGGLE_SCENE_UNIQUE_NAME);
} else if (ED_IS_SHORTCUT("scene_tree/delete", p_event)) {
_tool_selected(TOOL_ERASE);
} else {
return;
}
accept_event();
}
void SceneTreeDock::instance(const String &p_file) {
@ -3355,7 +3359,7 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_script_creation_closed"), &SceneTreeDock::_script_creation_closed);
ClassDB::bind_method(D_METHOD("_load_request"), &SceneTreeDock::_load_request);
ClassDB::bind_method(D_METHOD("_script_open_request"), &SceneTreeDock::_script_open_request);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &SceneTreeDock::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &SceneTreeDock::_shortcut_input);
ClassDB::bind_method(D_METHOD("_input"), &SceneTreeDock::_input);
ClassDB::bind_method(D_METHOD("_nodes_drag_begin"), &SceneTreeDock::_nodes_drag_begin);
ClassDB::bind_method(D_METHOD("_delete_confirm"), &SceneTreeDock::_delete_confirm);
@ -3579,7 +3583,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
quick_open = memnew(EditorQuickOpen);
add_child(quick_open);
quick_open->connect("quick_open", this, "_quick_open");
set_process_unhandled_key_input(true);
set_process_shortcut_input(true);
delete_dialog = memnew(ConfirmationDialog);
add_child(delete_dialog);

View File

@ -240,7 +240,7 @@ class SceneTreeDock : public VBoxContainer {
void _nodes_drag_begin();
void _input(Ref<InputEvent> p_event);
void _unhandled_key_input(Ref<InputEvent> p_event);
void _shortcut_input(Ref<InputEvent> p_event);
void _import_subscene();

View File

@ -123,7 +123,7 @@ void EditorSettingsDialog::popup_edit_settings() {
search_box->grab_focus();
_update_shortcuts();
set_process_unhandled_input(true);
set_process_shortcut_input(true);
// Restore valid window bounds or pop up at default size.
Rect2 saved_size = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "editor_settings", Rect2());
@ -160,7 +160,7 @@ void EditorSettingsDialog::_notification(int p_what) {
} break;
case NOTIFICATION_POPUP_HIDE: {
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "editor_settings", get_rect());
set_process_unhandled_input(false);
set_process_shortcut_input(false);
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
_update_icons();
@ -171,7 +171,7 @@ void EditorSettingsDialog::_notification(int p_what) {
}
}
void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
void EditorSettingsDialog::_shortcut_input(const Ref<InputEvent> &p_event) {
const Ref<InputEventKey> k = p_event;
if (k.is_valid() && is_window_modal_on_top() && k->is_pressed()) {
@ -415,7 +415,7 @@ void EditorSettingsDialog::_editor_restart_close() {
}
void EditorSettingsDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_input"), &EditorSettingsDialog::_unhandled_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &EditorSettingsDialog::_shortcut_input);
ClassDB::bind_method(D_METHOD("_settings_save"), &EditorSettingsDialog::_settings_save);
ClassDB::bind_method(D_METHOD("_settings_changed"), &EditorSettingsDialog::_settings_changed);
ClassDB::bind_method(D_METHOD("_settings_property_edited"), &EditorSettingsDialog::_settings_property_edited);

View File

@ -81,7 +81,7 @@ class EditorSettingsDialog : public AcceptDialog {
void _settings_property_edited(const String &p_name);
void _settings_save();
void _unhandled_input(const Ref<InputEvent> &p_event);
void _shortcut_input(const Ref<InputEvent> &p_event);
void _notification(int p_what);
void _update_icons();

View File

@ -71,7 +71,7 @@
// This function should be used to handle shortcuts that could otherwise
// be handled too late if they weren't handled here.
void EditorCodeTextEditor::_input(const Ref<InputEvent> &event) {
void EditorCodeTextEditor::_shortcut_input(const Ref<InputEvent> &event) {
const Ref<InputEventKey> key_event = event;
if (!key_event.is_valid() || !key_event->is_pressed()) {
return;
@ -964,7 +964,7 @@ void EditorCodeTextEditor::_notification(int p_what) {
if (toggle_scripts_button->is_visible()) {
update_toggle_scripts_button();
}
set_process_input(is_visible_in_tree());
set_process_shortcut_input(is_visible_in_tree());
} break;
default:
break;
@ -1045,7 +1045,7 @@ void EditorCodeTextEditor::remove_all_bookmarks() {
}
void EditorCodeTextEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_input"), &EditorCodeTextEditor::_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &EditorCodeTextEditor::_shortcut_input);
ClassDB::bind_method("_text_editor_gui_input", &EditorCodeTextEditor::_text_editor_gui_input);
ClassDB::bind_method("_line_col_changed", &EditorCodeTextEditor::_line_col_changed);
ClassDB::bind_method("_text_changed", &EditorCodeTextEditor::_text_changed);

View File

@ -90,7 +90,7 @@ class EditorCodeTextEditor : public VBoxContainer {
void _font_resize_timeout();
bool _add_font_size(int p_delta);
void _input(const Ref<InputEvent> &event);
void _shortcut_input(const Ref<InputEvent> &event);
void _text_editor_gui_input(const Ref<InputEvent> &p_event);
void _zoom_in();
void _zoom_out();

View File

@ -2593,7 +2593,7 @@ void EditorScriptEditor::_input(const Ref<InputEvent> &p_event) {
}
}
void EditorScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
void EditorScriptEditor::_shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (!is_visible_in_tree() || !p_event->is_pressed() || p_event->is_echo()) {
@ -2606,6 +2606,7 @@ void EditorScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
_go_to_tab(script_list->get_item_metadata(next_tab));
_update_script_names();
}
accept_event();
}
if (ED_IS_SHORTCUT("script_editor/prev_script", p_event)) {
if (script_list->get_item_count() > 1) {
@ -2614,12 +2615,15 @@ void EditorScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
_go_to_tab(script_list->get_item_metadata(next_tab));
_update_script_names();
}
accept_event();
}
if (ED_IS_SHORTCUT("script_editor/window_move_up", p_event)) {
_menu_option(WINDOW_MOVE_UP);
accept_event();
}
if (ED_IS_SHORTCUT("script_editor/window_move_down", p_event)) {
_menu_option(WINDOW_MOVE_DOWN);
accept_event();
}
}
@ -3165,7 +3169,7 @@ void EditorScriptEditor::_bind_methods() {
ClassDB::bind_method("_history_back", &EditorScriptEditor::_history_back);
ClassDB::bind_method("_live_auto_reload_running_scripts", &EditorScriptEditor::_live_auto_reload_running_scripts);
ClassDB::bind_method("_input", &EditorScriptEditor::_input);
ClassDB::bind_method("_unhandled_input", &EditorScriptEditor::_unhandled_input);
ClassDB::bind_method("_shortcut_input", &EditorScriptEditor::_shortcut_input);
ClassDB::bind_method("_script_list_gui_input", &EditorScriptEditor::_script_list_gui_input);
ClassDB::bind_method("_toggle_members_overview_alpha_sort", &EditorScriptEditor::_toggle_members_overview_alpha_sort);
ClassDB::bind_method("_update_members_overview", &EditorScriptEditor::_update_members_overview);
@ -3301,7 +3305,7 @@ EditorScriptEditor::EditorScriptEditor(EditorNode *p_editor) {
ED_SHORTCUT("script_editor/next_script", TTR("Next Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_PERIOD);
ED_SHORTCUT("script_editor/prev_script", TTR("Previous Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_COMMA);
set_process_input(true);
set_process_unhandled_input(true);
set_process_shortcut_input(true);
file_menu = memnew(MenuButton);
menu_hb->add_child(file_menu);

View File

@ -328,7 +328,7 @@ class EditorScriptEditor : public PanelContainer {
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
void _input(const Ref<InputEvent> &p_event);
void _unhandled_input(const Ref<InputEvent> &p_event);
void _shortcut_input(const Ref<InputEvent> &p_event);
void _script_list_gui_input(const Ref<InputEvent> &ev);
void _make_script_list_context_menu();

View File

@ -98,13 +98,13 @@ void TouchButton::_gui_input(Ref<InputEvent> p_event) {
BaseButton::_gui_input(p_event);
}
void TouchButton::_unhandled_input(Ref<InputEvent> p_event) {
void TouchButton::_shortcut_input(Ref<InputEvent> p_event) {
if (p_event->get_device() == -1) {
//accept_event();
return;
}
Button::_unhandled_input(p_event);
Button::_shortcut_input(p_event);
}
void TouchButton::_bind_methods() {

View File

@ -39,7 +39,7 @@ public:
protected:
void _notification(int p_what);
virtual void _gui_input(Ref<InputEvent> p_event);
virtual void _unhandled_input(Ref<InputEvent> p_event);
virtual void _shortcut_input(Ref<InputEvent> p_event);
void _input(Ref<InputEvent> p_event);
static void _bind_methods();
};

View File

@ -342,14 +342,14 @@ bool BaseButton::is_keep_pressed_outside() const {
void BaseButton::set_shortcut(const Ref<ShortCut> &p_shortcut) {
shortcut = p_shortcut;
set_process_unhandled_input(shortcut.is_valid());
set_process_shortcut_input(shortcut.is_valid());
}
Ref<ShortCut> BaseButton::get_shortcut() const {
return shortcut;
}
void BaseButton::_unhandled_input(Ref<InputEvent> p_event) {
void BaseButton::_shortcut_input(Ref<InputEvent> p_event) {
ERR_FAIL_COND(p_event.is_null());
if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) {
@ -398,7 +398,7 @@ bool BaseButton::_was_pressed_by_mouse() const {
void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &BaseButton::_gui_input);
ClassDB::bind_method(D_METHOD("_unhandled_input"), &BaseButton::_unhandled_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &BaseButton::_shortcut_input);
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed);
ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed);
ClassDB::bind_method(D_METHOD("set_pressed_no_signal", "pressed"), &BaseButton::set_pressed_no_signal);

View File

@ -77,7 +77,7 @@ protected:
virtual void toggled(bool p_pressed);
static void _bind_methods();
virtual void _gui_input(Ref<InputEvent> p_event);
virtual void _unhandled_input(Ref<InputEvent> p_event);
virtual void _shortcut_input(Ref<InputEvent> p_event);
void _notification(int p_what);
bool _was_pressed_by_mouse() const;

View File

@ -82,11 +82,11 @@ void FileDialog::_notification(int p_what) {
show_hidden->add_theme_color_override("icon_color_pressed", font_color_pressed);
} else if (p_what == NOTIFICATION_POPUP_HIDE) {
set_process_unhandled_input(false);
set_process_shortcut_input(false);
}
}
void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
void FileDialog::_shortcut_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid() && is_window_modal_on_top()) {
if (k->is_pressed()) {
@ -181,7 +181,7 @@ void FileDialog::_post_popup() {
tree->grab_focus();
}
set_process_unhandled_input(true);
set_process_shortcut_input(true);
// For open dir mode, deselect all items on file dialog open.
if (mode == MODE_OPEN_DIR) {
@ -803,7 +803,7 @@ void FileDialog::_update_drives(bool p_select) {
bool FileDialog::default_show_hidden_files = false;
void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_input"), &FileDialog::_unhandled_input);
ClassDB::bind_method(D_METHOD("_shortcut_input"), &FileDialog::_shortcut_input);
ClassDB::bind_method(D_METHOD("_tree_multi_selected"), &FileDialog::_tree_multi_selected);
ClassDB::bind_method(D_METHOD("_tree_selected"), &FileDialog::_tree_selected);

View File

@ -125,7 +125,7 @@ private:
void _update_drives(bool p_select = true);
void _unhandled_input(const Ref<InputEvent> &p_event);
void _shortcut_input(const Ref<InputEvent> &p_event);
bool _is_open_should_be_disabled();

View File

@ -51,6 +51,27 @@ bool LineEdit::_is_text_char(CharType c) {
return !is_symbol(c);
}
void LineEdit::_unhandled_key_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
if (!k->is_pressed()) {
return;
}
// Handle Unicode (with modifiers active, process after shortcuts).
if (has_focus() && editable && (k->get_unicode() >= 32)) {
selection_delete();
char32_t ucodestr[2] = { (char32_t)k->get_unicode(), 0 };
int prev_len = text.length();
append_at_cursor(ucodestr);
if (text.length() != prev_len) {
_text_changed();
}
accept_event();
}
}
}
void LineEdit::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventMouseButton> b = p_event;
@ -1951,6 +1972,7 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_align"), &LineEdit::get_align);
ClassDB::bind_method(D_METHOD("_gui_input"), &LineEdit::_gui_input);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &LineEdit::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("clear"), &LineEdit::clear);
ClassDB::bind_method(D_METHOD("select", "from", "to"), &LineEdit::select, DEFVAL(0), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("select_all"), &LineEdit::select_all);
@ -2086,6 +2108,7 @@ LineEdit::LineEdit() {
set_focus_mode(FOCUS_ALL);
set_default_cursor_shape(CURSOR_IBEAM);
set_mouse_filter(MOUSE_FILTER_STOP);
set_process_unhandled_key_input(true);
draw_caret = true;
caret_blink_enabled = false;

View File

@ -175,6 +175,7 @@ private:
void _editor_settings_changed();
void _unhandled_key_input(const Ref<InputEvent> &p_event);
void _gui_input(Ref<InputEvent> p_event);
void _notification(int p_what);

View File

@ -35,13 +35,15 @@
#include "core/input/shortcut.h"
#include "scene/main/viewport.h"
void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) {
void MenuButton::_shortcut_input(Ref<InputEvent> p_event) {
ERR_FAIL_COND(p_event.is_null());
if (disable_shortcuts) {
return;
}
BaseButton::_shortcut_input(p_event);
if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to<InputEventKey>(p_event.ptr()) || Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventAction>(*p_event))) {
if (!get_parent() || !is_visible_in_tree() || is_disabled()) {
return;
@ -112,7 +114,6 @@ void MenuButton::_notification(int p_what) {
void MenuButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_popup"), &MenuButton::get_popup);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &MenuButton::_unhandled_key_input);
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);
@ -135,7 +136,7 @@ MenuButton::MenuButton() {
set_toggle_mode(true);
set_disable_shortcuts(false);
set_focus_mode(FOCUS_NONE);
set_process_unhandled_key_input(true);
set_process_shortcut_input(true);
set_action_mode(ACTION_MODE_BUTTON_PRESS);
popup = memnew(PopupMenu);

View File

@ -42,7 +42,7 @@ class MenuButton : public Button {
bool disable_shortcuts;
PopupMenu *popup;
void _unhandled_key_input(Ref<InputEvent> p_event);
void _shortcut_input(Ref<InputEvent> p_event);
Array _get_items() const;
void _set_items(const Array &p_items);

View File

@ -2300,6 +2300,45 @@ void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const
r_row = row;
}
void TextEdit::_unhandled_key_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
if (!k->is_pressed()) {
return;
}
// Handle Unicode (with modifiers active, process after shortcuts).
if (has_focus() && !readonly && (k->get_unicode() >= 32)) {
//handle_unicode_input(k->get_unicode());
_reset_caret_blink_timer();
const CharType chr[2] = { (CharType)k->get_unicode(), 0 };
if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
_consume_pair_symbol(chr[0]);
} else {
// Remove the old character if in insert mode.
if (insert_mode) {
begin_complex_operation();
// Make sure we don't try and remove empty space.
if (cursor.column < get_line(cursor.line).length()) {
_remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
}
}
_insert_text_at_cursor(chr);
if (insert_mode) {
end_complex_operation();
}
}
_update_completion_candidates();
accept_event();
}
}
}
void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
double prev_v_scroll = v_scroll->get_value();
double prev_h_scroll = h_scroll->get_value();
@ -7155,6 +7194,7 @@ int TextEdit::get_line_height() const {
void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &TextEdit::_gui_input);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &TextEdit::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("_scroll_moved"), &TextEdit::_scroll_moved);
ClassDB::bind_method(D_METHOD("_cursor_changed_emit"), &TextEdit::_cursor_changed_emit);
ClassDB::bind_method(D_METHOD("_text_changed_emit"), &TextEdit::_text_changed_emit);
@ -7401,6 +7441,7 @@ TextEdit::TextEdit() {
info_gutter_width = 0;
cache.info_gutter_width = 0;
set_default_cursor_shape(CURSOR_IBEAM);
set_process_unhandled_key_input(true);
drag_action = false;
drag_caret_force_displayed = false;

View File

@ -515,6 +515,7 @@ protected:
void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr);
void _remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
void _insert_text_at_cursor(const String &p_text);
void _unhandled_key_input(const Ref<InputEvent> &p_event);
void _gui_input(const Ref<InputEvent> &p_gui_input);
void _notification(int p_what);

View File

@ -131,6 +131,9 @@ void Node::_notification(int p_notification) {
if (data.input) {
add_to_group("_vp_input" + itos(get_viewport()->get_instance_id()));
}
if (data.shortcut_input) {
add_to_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id()));
}
if (data.unhandled_input) {
add_to_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id()));
}
@ -182,6 +185,9 @@ void Node::_notification(int p_notification) {
if (data.input) {
remove_from_group("_vp_input" + itos(get_viewport()->get_instance_id()));
}
if (data.shortcut_input) {
remove_from_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id()));
}
if (data.unhandled_input) {
remove_from_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id()));
}
@ -207,6 +213,10 @@ void Node::_notification(int p_notification) {
set_process_input(true);
}
if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_shortcut_input)) {
set_process_shortcut_input(true);
}
if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_unhandled_input)) {
set_process_unhandled_input(true);
}
@ -1402,6 +1412,27 @@ bool Node::is_processing_input() const {
return data.input;
}
void Node::set_process_shortcut_input(bool p_enable) {
if (p_enable == data.shortcut_input) {
return;
}
data.shortcut_input = p_enable;
if (!is_inside_tree()) {
return;
}
if (p_enable) {
add_to_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id()));
} else {
remove_from_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id()));
}
}
bool Node::is_processing_shortcut_input() const {
return data.shortcut_input;
}
void Node::set_process_unhandled_input(bool p_enable) {
if (p_enable == data.unhandled_input) {
return;
@ -3501,6 +3532,8 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_process_input", "enable"), &Node::set_process_input);
ClassDB::bind_method(D_METHOD("is_processing_input"), &Node::is_processing_input);
ClassDB::bind_method(D_METHOD("set_process_shortcut_input", "enable"), &Node::set_process_shortcut_input);
ClassDB::bind_method(D_METHOD("is_processing_shortcut_input"), &Node::is_processing_shortcut_input);
ClassDB::bind_method(D_METHOD("set_process_unhandled_input", "enable"), &Node::set_process_unhandled_input);
ClassDB::bind_method(D_METHOD("is_processing_unhandled_input"), &Node::is_processing_unhandled_input);
ClassDB::bind_method(D_METHOD("set_process_unhandled_key_input", "enable"), &Node::set_process_unhandled_key_input);
@ -3694,6 +3727,7 @@ void Node::_bind_methods() {
BIND_VMETHOD(MethodInfo("_exit_tree"));
BIND_VMETHOD(MethodInfo("_ready"));
BIND_VMETHOD(MethodInfo("_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo("_shortcut_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo("_unhandled_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEventKey")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_configuration_warning"));
@ -3738,6 +3772,7 @@ Node::Node() {
data.owner = nullptr;
data.OW = nullptr;
data.input = false;
data.shortcut_input = false;
data.unhandled_input = false;
data.unhandled_key_input = false;
data.pause_mode = PAUSE_MODE_INHERIT;

View File

@ -153,6 +153,7 @@ private:
bool idle_process_internal : 1;
bool input : 1;
bool shortcut_input : 1;
bool unhandled_input : 1;
bool unhandled_key_input : 1;
@ -484,6 +485,9 @@ public:
void set_process_input(bool p_enable);
bool is_processing_input() const;
void set_process_shortcut_input(bool p_enable);
bool is_processing_shortcut_input() const;
void set_process_unhandled_input(bool p_enable);
bool is_processing_unhandled_input() const;

View File

@ -1285,6 +1285,9 @@ void SceneTree::_call_input_pause(const StringName &p_group, const CallInputType
case CALL_INPUT_TYPE_INPUT:
method = SceneStringNames::get_singleton()->_input;
break;
case CALL_INPUT_TYPE_SHORTCUT_INPUT:
method = SceneStringNames::get_singleton()->_shortcut_input;
break;
case CALL_INPUT_TYPE_UNHANDLED_INPUT:
method = SceneStringNames::get_singleton()->_unhandled_input;
break;

View File

@ -224,6 +224,7 @@ private:
enum CallInputType {
CALL_INPUT_TYPE_INPUT,
CALL_INPUT_TYPE_SHORTCUT_INPUT,
CALL_INPUT_TYPE_UNHANDLED_INPUT,
CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT,
};

View File

@ -2827,14 +2827,34 @@ void Viewport::input(const Ref<InputEvent> &p_event) {
void Viewport::unhandled_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(!is_inside_tree());
get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, p_event);
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev);
if (!get_tree()->input_handled && Object::cast_to<InputEventKey>(*p_event) != nullptr) {
get_tree()->_call_input_pause(unhandled_key_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, p_event);
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev);
bool is_key_input = Object::cast_to<InputEventKey>(*p_event) != nullptr;
// Shortcut Input.
if (is_key_input || Object::cast_to<InputEventShortCut>(*p_event) != nullptr) {
get_tree()->_call_input_pause(shortcut_input_group, SceneTree::CALL_INPUT_TYPE_SHORTCUT_INPUT, p_event);
}
if (physics_object_picking && !get_tree()->input_handled) {
if (get_tree()->input_handled) {
return;
}
// Unhandled Input.
get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, p_event);
if (get_tree()->input_handled) {
return;
}
// Unhandled key Input - Used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, and to handle Unicode input with Alt / Ctrl modifiers after handling shortcuts.
if (is_key_input) {
get_tree()->_call_input_pause(unhandled_key_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, p_event);
if (get_tree()->input_handled) {
return;
}
}
if (physics_object_picking) {
if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED &&
(Object::cast_to<InputEventMouseButton>(*p_event) ||
Object::cast_to<InputEventMouseMotion>(*p_event) ||
@ -3393,6 +3413,7 @@ Viewport::Viewport() {
String id = itos(get_instance_id());
input_group = "_vp_input" + id;
gui_input_group = "_vp_gui_input" + id;
shortcut_input_group = "_vp_shortcut_input" + id;
unhandled_input_group = "_vp_unhandled_input" + id;
unhandled_key_input_group = "_vp_unhandled_key_input" + id;

View File

@ -416,6 +416,7 @@ private:
StringName input_group;
StringName gui_input_group;
StringName shortcut_input_group;
StringName unhandled_input_group;
StringName unhandled_key_input_group;

View File

@ -143,6 +143,8 @@ SceneStringNames::SceneStringNames() {
gui_input = StaticCString::create("gui_input");
_gui_input = StaticCString::create("_gui_input");
_shortcut_input = StaticCString::create("_shortcut_input");
_unhandled_input = StaticCString::create("_unhandled_input");
_unhandled_key_input = StaticCString::create("_unhandled_key_input");

View File

@ -126,8 +126,9 @@ public:
StringName _enter_tree;
StringName _exit_tree;
StringName _draw;
StringName _input;
StringName _ready;
StringName _input;
StringName _shortcut_input;
StringName _unhandled_input;
StringName _unhandled_key_input;