summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Sauermann <6299227+Sauermann@users.noreply.github.com>2023-07-23 15:47:37 +0200
committerSpartan322 <Megacake1234@gmail.com>2024-10-17 10:45:04 -0400
commitd14035edccae40020226f3dced26969647e73a15 (patch)
tree769898d1a2b095832db80020c456ddc02e6bd0b2
parentfe04f5ff9bf3775a15e448794024b4aa44c2c2dc (diff)
downloadredot-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.xml24
-rw-r--r--scene/main/node.cpp42
-rw-r--r--scene/main/node.h7
-rw-r--r--scene/main/scene_tree.cpp3
-rw-r--r--scene/main/scene_tree.h1
-rw-r--r--scene/main/viewport.cpp6
-rw-r--r--scene/main/viewport.h1
-rw-r--r--tests/scene/test_node.h12
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());