Skip to content

Commit

Permalink
Add an additional input stage after physics picking
Browse files Browse the repository at this point in the history
Allow handling events, that were not used during physics picking.
  • Loading branch information
Sauermann committed Apr 11, 2024
1 parent a7b8602 commit fbd5d2b
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 0 deletions.
24 changes: 24 additions & 0 deletions doc/classes/Node.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down Expand Up @@ -682,6 +693,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" />
Expand Down Expand Up @@ -947,6 +964,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" />
Expand Down
42 changes: 42 additions & 0 deletions scene/main/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,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);
}
Expand Down Expand Up @@ -1250,6 +1254,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) {
Expand Down Expand Up @@ -3391,6 +3416,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;
Expand All @@ -3409,6 +3444,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;
Expand Down Expand Up @@ -3561,6 +3599,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);
Expand Down Expand Up @@ -3798,6 +3838,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() {
Expand Down Expand Up @@ -3832,6 +3873,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;

Expand Down
7 changes: 7 additions & 0 deletions scene/main/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ class Node : public Object {
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
Expand Down Expand Up @@ -343,6 +344,7 @@ class Node : public Object {
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;

Expand All @@ -351,6 +353,7 @@ class Node : public Object {
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)
Expand All @@ -363,6 +366,7 @@ class Node : public Object {
GDVIRTUAL1(_shortcut_input, Ref<InputEvent>)
GDVIRTUAL1(_unhandled_input, Ref<InputEvent>)
GDVIRTUAL1(_unhandled_key_input, Ref<InputEvent>)
GDVIRTUAL1(_unhandled_picking_input, Ref<InputEvent>)

public:
enum {
Expand Down Expand Up @@ -578,6 +582,9 @@ class Node : public Object {
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;
}
Expand Down
3 changes: 3 additions & 0 deletions scene/main/scene_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,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;
}
}

Expand Down
1 change: 1 addition & 0 deletions scene/main/scene_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class SceneTree : public MainLoop {
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
Expand Down
6 changes: 6 additions & 0 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,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);
}
}
}

Expand Down Expand Up @@ -4942,6 +4947,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_DEF(PropertyInfo(Variant::FLOAT, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5);
Expand Down
1 change: 1 addition & 0 deletions scene/main/viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ class Viewport : public Node {
StringName shortcut_input_group;
StringName unhandled_input_group;
StringName unhandled_key_input_group;
StringName unhandled_picking_input_group;

void _update_audio_listener_2d();

Expand Down
1 change: 1 addition & 0 deletions scene/scene_string_names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ SceneStringNames::SceneStringNames() {

_unhandled_input = StaticCString::create("_unhandled_input");
_unhandled_key_input = StaticCString::create("_unhandled_key_input");
_unhandled_picking_input = StaticCString::create("_unhandled_picking_input");

changed = StaticCString::create("changed");
_shader_changed = StaticCString::create("_shader_changed");
Expand Down
1 change: 1 addition & 0 deletions scene/scene_string_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class SceneStringNames {
StringName _ready;
StringName _unhandled_input;
StringName _unhandled_key_input;
StringName _unhandled_picking_input;

StringName _pressed;
StringName _toggled;
Expand Down
12 changes: 12 additions & 0 deletions tests/scene/test_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,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());

Expand Down

0 comments on commit fbd5d2b

Please sign in to comment.