diff options
author | Markus Sauermann <6299227+Sauermann@users.noreply.github.com> | 2023-07-23 15:47:37 +0200 |
---|---|---|
committer | Spartan322 <Megacake1234@gmail.com> | 2024-10-17 10:45:04 -0400 |
commit | d14035edccae40020226f3dced26969647e73a15 (patch) | |
tree | 769898d1a2b095832db80020c456ddc02e6bd0b2 | |
parent | fe04f5ff9bf3775a15e448794024b4aa44c2c2dc (diff) | |
download | redot-engine-d14035edccae40020226f3dced26969647e73a15.tar.gz |
Add an additional input stage after physics picking
Allow handling events, that were not used during physics picking.
(cherry picked from commit godotengine/godot@fbd5d2ba8bbd3c548a67dc3c462e0e0666510228)
-rw-r--r-- | doc/classes/Node.xml | 24 | ||||
-rw-r--r-- | scene/main/node.cpp | 42 | ||||
-rw-r--r-- | scene/main/node.h | 7 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 3 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 1 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 6 | ||||
-rw-r--r-- | scene/main/viewport.h | 1 | ||||
-rw-r--r-- | tests/scene/test_node.h | 12 |
8 files changed, 96 insertions, 0 deletions
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 0949bcf940..b8e71591e5 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -130,6 +130,17 @@ [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> </method> + <method name="_unhandled_picking_input" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="event" type="InputEvent" /> + <description> + Called when an [InputEventKey] hasn't been consumed by physics picking. The input event propagates up through the node tree in the current [Viewport] until a node consumes it. + It is only called if unhandled picking input processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_unhandled_picking_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 mouse and touch events that were not set to handled during physics picking. + [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> + </method> <method name="add_child"> <return type="void" /> <param index="0" name="node" type="Node" /> @@ -688,6 +699,12 @@ Returns [code]true[/code] if the node is processing unhandled key input (see [method set_process_unhandled_key_input]). </description> </method> + <method name="is_processing_unhandled_picking_input" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if the node is processing unhandled physics input (see [method set_process_unhandled_picking_input]). + </description> + </method> <method name="move_child"> <return type="void" /> <param index="0" name="child_node" type="Node" /> @@ -952,6 +969,13 @@ [b]Note:[/b] If [method _unhandled_key_input] is overridden, this will be automatically enabled before [method _ready] is called. </description> </method> + <method name="set_process_unhandled_picking_input"> + <return type="void" /> + <param index="0" name="enable" type="bool" /> + <description> + Enables unhandled picking input processing. Enabled automatically if [method _unhandled_picking_input] is overridden. Any calls to this before [method _ready] will be ignored. + </description> + </method> <method name="set_scene_instance_load_placeholder"> <return type="void" /> <param index="0" name="load_placeholder" type="bool" /> diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 67f78f1645..08281f67a7 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -209,6 +209,10 @@ void Node::_notification(int p_notification) { set_process_unhandled_key_input(true); } + if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_picking_input)) { + set_process_unhandled_picking_input(true); + } + if (GDVIRTUAL_IS_OVERRIDDEN(_process)) { set_process(true); } @@ -1255,6 +1259,27 @@ bool Node::is_processing_unhandled_key_input() const { return data.unhandled_key_input; } +void Node::set_process_unhandled_picking_input(bool p_enable) { + ERR_THREAD_GUARD + if (p_enable == data.unhandled_picking_input) { + return; + } + data.unhandled_picking_input = p_enable; + if (!is_inside_tree()) { + return; + } + + if (p_enable) { + add_to_group("_vp_unhandled_picking_input" + itos(get_viewport()->get_instance_id())); + } else { + remove_from_group("_vp_unhandled_picking_input" + itos(get_viewport()->get_instance_id())); + } +} + +bool Node::is_processing_unhandled_picking_input() const { + return data.unhandled_picking_input; +} + void Node::set_auto_translate_mode(AutoTranslateMode p_mode) { ERR_THREAD_GUARD if (data.auto_translate_mode == p_mode) { @@ -3387,6 +3412,16 @@ void Node::_call_unhandled_key_input(const Ref<InputEvent> &p_event) { unhandled_key_input(p_event); } +void Node::_call_unhandled_picking_input(const Ref<InputEvent> &p_event) { + if (p_event->get_device() != InputEvent::DEVICE_ID_INTERNAL) { + GDVIRTUAL_CALL(_unhandled_picking_input, p_event); + } + if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) { + return; + } + unhandled_key_input(p_event); +} + void Node::_validate_property(PropertyInfo &p_property) const { if ((p_property.name == "process_thread_group_order" || p_property.name == "process_thread_messages") && data.process_thread_group == PROCESS_THREAD_GROUP_INHERIT) { p_property.usage = 0; @@ -3405,6 +3440,9 @@ void Node::unhandled_input(const Ref<InputEvent> &p_event) { void Node::unhandled_key_input(const Ref<InputEvent> &p_key_event) { } +void Node::unhandled_picking_input(const Ref<InputEvent> &p_picking_event) { +} + Variant Node::_call_deferred_thread_group_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; @@ -3558,6 +3596,8 @@ void Node::_bind_methods() { 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); ClassDB::bind_method(D_METHOD("is_processing_unhandled_key_input"), &Node::is_processing_unhandled_key_input); + ClassDB::bind_method(D_METHOD("set_process_unhandled_picking_input", "enable"), &Node::set_process_unhandled_picking_input); + ClassDB::bind_method(D_METHOD("is_processing_unhandled_picking_input"), &Node::is_processing_unhandled_picking_input); ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Node::set_process_mode); ClassDB::bind_method(D_METHOD("get_process_mode"), &Node::get_process_mode); ClassDB::bind_method(D_METHOD("can_process"), &Node::can_process); @@ -3795,6 +3835,7 @@ void Node::_bind_methods() { GDVIRTUAL_BIND(_shortcut_input, "event"); GDVIRTUAL_BIND(_unhandled_input, "event"); GDVIRTUAL_BIND(_unhandled_key_input, "event"); + GDVIRTUAL_BIND(_unhandled_picking_input, "event"); } String Node::_get_name_num_separator() { @@ -3829,6 +3870,7 @@ Node::Node() { data.shortcut_input = false; data.unhandled_input = false; data.unhandled_key_input = false; + data.unhandled_picking_input = false; data.physics_interpolated = true; diff --git a/scene/main/node.h b/scene/main/node.h index f61961e6be..87cd1f677e 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -221,6 +221,7 @@ private: bool shortcut_input : 1; bool unhandled_input : 1; bool unhandled_key_input : 1; + bool unhandled_picking_input : 1; // Physics interpolation can be turned on and off on a per node basis. // This only takes effect when the SceneTree (or project setting) physics interpolation @@ -341,6 +342,7 @@ protected: void _call_shortcut_input(const Ref<InputEvent> &p_event); void _call_unhandled_input(const Ref<InputEvent> &p_event); void _call_unhandled_key_input(const Ref<InputEvent> &p_event); + void _call_unhandled_picking_input(const Ref<InputEvent> &p_event); void _validate_property(PropertyInfo &p_property) const; @@ -349,6 +351,7 @@ protected: virtual void shortcut_input(const Ref<InputEvent> &p_key_event); virtual void unhandled_input(const Ref<InputEvent> &p_event); virtual void unhandled_key_input(const Ref<InputEvent> &p_key_event); + virtual void unhandled_picking_input(const Ref<InputEvent> &p_picking_event); GDVIRTUAL1(_process, double) GDVIRTUAL1(_physics_process, double) @@ -361,6 +364,7 @@ protected: GDVIRTUAL1(_shortcut_input, Ref<InputEvent>) GDVIRTUAL1(_unhandled_input, Ref<InputEvent>) GDVIRTUAL1(_unhandled_key_input, Ref<InputEvent>) + GDVIRTUAL1(_unhandled_picking_input, Ref<InputEvent>) public: enum { @@ -578,6 +582,9 @@ public: void set_process_unhandled_key_input(bool p_enable); bool is_processing_unhandled_key_input() const; + void set_process_unhandled_picking_input(bool p_enable); + bool is_processing_unhandled_picking_input() const; + _FORCE_INLINE_ bool _is_any_processing() const { return data.process || data.process_internal || data.physics_process || data.physics_process_internal; } diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index a28650c9ad..12c708e2e2 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1232,6 +1232,9 @@ void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_cal case CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT: n->_call_unhandled_key_input(p_input); break; + case CALL_INPUT_TYPE_UNHANDLED_PICKING_INPUT: + n->_call_unhandled_picking_input(p_input); + break; } } diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 1915471712..f10c4ea882 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -257,6 +257,7 @@ private: CALL_INPUT_TYPE_SHORTCUT_INPUT, CALL_INPUT_TYPE_UNHANDLED_INPUT, CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, + CALL_INPUT_TYPE_UNHANDLED_PICKING_INPUT, }; //used by viewport diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index d6ffe35e78..59bbd2a3ee 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -961,6 +961,11 @@ void Viewport::_process_picking() { } } #endif // _3D_DISABLED + + if (!local_input_handled) { + ERR_FAIL_COND(!is_inside_tree()); + get_tree()->_call_input_pause(unhandled_picking_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_PICKING_INPUT, ev, this); + } } } @@ -5015,6 +5020,7 @@ Viewport::Viewport() { unhandled_input_group = "_vp_unhandled_input" + id; shortcut_input_group = "_vp_shortcut_input" + id; unhandled_key_input_group = "_vp_unhandled_key_input" + id; + unhandled_picking_input_group = "_vp_unhandled_picking_input" + id; // Window tooltip. gui.tooltip_delay = GLOBAL_GET("gui/timers/tooltip_delay_sec"); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 966b5d393b..45b4c4c913 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -278,6 +278,7 @@ private: StringName shortcut_input_group; StringName unhandled_input_group; StringName unhandled_key_input_group; + StringName unhandled_picking_input_group; void _update_audio_listener_2d(); diff --git a/tests/scene/test_node.h b/tests/scene/test_node.h index 25bea103b5..cc2c8cdcec 100644 --- a/tests/scene/test_node.h +++ b/tests/scene/test_node.h @@ -673,6 +673,18 @@ TEST_CASE("[Node] Processing checks") { CHECK_FALSE(node->is_processing_unhandled_key_input()); } + SUBCASE("Unhandled picking input processing") { + CHECK_FALSE(node->is_processing_unhandled_picking_input()); + + node->set_process_unhandled_picking_input(true); + + CHECK(node->is_processing_unhandled_picking_input()); + + node->set_process_unhandled_picking_input(false); + + CHECK_FALSE(node->is_processing_unhandled_picking_input()); + } + SUBCASE("Shortcut input processing") { CHECK_FALSE(node->is_processing_shortcut_input()); |