From 22de1b31b527a617146e264e6901bb8356f5fffe Mon Sep 17 00:00:00 2001 From: Malcolm Nixon Date: Fri, 1 Sep 2023 19:13:54 -0400 Subject: [PATCH] Added XR tracking-state change signals Add "pose_lost_tracking" signal to XRPositionalTracker. Add "tracking_changed" signal to XRNode3D. --- doc/classes/XRNode3D.xml | 8 +++++++ doc/classes/XRPositionalTracker.xml | 6 +++++ scene/3d/xr_nodes.cpp | 33 ++++++++++++++++++++++------ scene/3d/xr_nodes.h | 4 +++- servers/xr/xr_positional_tracker.cpp | 6 ++++- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/doc/classes/XRNode3D.xml b/doc/classes/XRNode3D.xml index f9ea540e2e6e..3da1873ed817 100644 --- a/doc/classes/XRNode3D.xml +++ b/doc/classes/XRNode3D.xml @@ -51,4 +51,12 @@ Godot defines a number of standard trackers such as [code]left_hand[/code] and [code]right_hand[/code] but others may be configured within a given [XRInterface]. + + + + + Emitted when the [member tracker] starts or stops receiving updated tracking data for the [member pose] being tracked. The [param tracking] argument indicates whether the tracker is getting updated tracking data. + + + diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml index 958be92072c0..d43daa3028ce 100644 --- a/doc/classes/XRPositionalTracker.xml +++ b/doc/classes/XRPositionalTracker.xml @@ -112,6 +112,12 @@ Emitted when the state of a pose tracked by this tracker changes. + + + + Emitted when a pose tracked by this tracker stops getting updated tracking data. + + diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index ac0a47d1a1d6..c12e78eddcda 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -233,6 +233,8 @@ void XRNode3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRNode3D::get_has_tracking_data); ClassDB::bind_method(D_METHOD("get_pose"), &XRNode3D::get_pose); ClassDB::bind_method(D_METHOD("trigger_haptic_pulse", "action_name", "frequency", "amplitude", "duration_sec", "delay_sec"), &XRNode3D::trigger_haptic_pulse); + + ADD_SIGNAL(MethodInfo("tracking_changed", PropertyInfo(Variant::BOOL, "tracking"))); }; void XRNode3D::_validate_property(PropertyInfo &p_property) const { @@ -305,13 +307,7 @@ bool XRNode3D::get_is_active() const { } bool XRNode3D::get_has_tracking_data() const { - if (tracker.is_null()) { - return false; - } else if (!tracker->has_pose(pose_name)) { - return false; - } else { - return tracker->get_pose(pose_name)->get_has_tracking_data(); - } + return has_tracking_data; } void XRNode3D::trigger_haptic_pulse(const String &p_action_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) { @@ -346,10 +342,12 @@ void XRNode3D::_bind_tracker() { } tracker->connect("pose_changed", callable_mp(this, &XRNode3D::_pose_changed)); + tracker->connect("pose_lost_tracking", callable_mp(this, &XRNode3D::_pose_lost_tracking)); Ref pose = get_pose(); if (pose.is_valid()) { set_transform(pose->get_adjusted_transform()); + _set_has_tracking_data(pose->get_has_tracking_data()); } } } @@ -357,8 +355,11 @@ void XRNode3D::_bind_tracker() { void XRNode3D::_unbind_tracker() { if (tracker.is_valid()) { tracker->disconnect("pose_changed", callable_mp(this, &XRNode3D::_pose_changed)); + tracker->disconnect("pose_lost_tracking", callable_mp(this, &XRNode3D::_pose_lost_tracking)); tracker.unref(); + + _set_has_tracking_data(false); } } @@ -382,9 +383,27 @@ void XRNode3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_t void XRNode3D::_pose_changed(const Ref &p_pose) { if (p_pose.is_valid() && p_pose->get_name() == pose_name) { set_transform(p_pose->get_adjusted_transform()); + _set_has_tracking_data(p_pose->get_has_tracking_data()); } } +void XRNode3D::_pose_lost_tracking(const Ref &p_pose) { + if (p_pose.is_valid() && p_pose->get_name() == pose_name) { + _set_has_tracking_data(false); + } +} + +void XRNode3D::_set_has_tracking_data(bool p_has_tracking_data) { + // Ignore if the has_tracking_data state isn't changing. + if (p_has_tracking_data == has_tracking_data) { + return; + } + + // Handle change of has_tracking_data. + has_tracking_data = p_has_tracking_data; + emit_signal(SNAME("tracking_changed"), has_tracking_data); +} + XRNode3D::XRNode3D() { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h index 6e56aa28deaa..185a6361d39e 100644 --- a/scene/3d/xr_nodes.h +++ b/scene/3d/xr_nodes.h @@ -78,7 +78,7 @@ class XRNode3D : public Node3D { private: StringName tracker_name; StringName pose_name = "default"; - bool is_active = true; + bool has_tracking_data = false; protected: Ref tracker; @@ -91,6 +91,8 @@ class XRNode3D : public Node3D { void _removed_tracker(const StringName p_tracker_name, int p_tracker_type); void _pose_changed(const Ref &p_pose); + void _pose_lost_tracking(const Ref &p_pose); + void _set_has_tracking_data(bool p_has_tracking_data); public: void _validate_property(PropertyInfo &p_property) const; diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp index 2dacabe588e6..6c15e4c1b0f2 100644 --- a/servers/xr/xr_positional_tracker.cpp +++ b/servers/xr/xr_positional_tracker.cpp @@ -62,6 +62,7 @@ void XRPositionalTracker::_bind_methods() { ClassDB::bind_method(D_METHOD("invalidate_pose", "name"), &XRPositionalTracker::invalidate_pose); ClassDB::bind_method(D_METHOD("set_pose", "name", "transform", "linear_velocity", "angular_velocity", "tracking_confidence"), &XRPositionalTracker::set_pose); ADD_SIGNAL(MethodInfo("pose_changed", PropertyInfo(Variant::OBJECT, "pose", PROPERTY_HINT_RESOURCE_TYPE, "XRPose"))); + ADD_SIGNAL(MethodInfo("pose_lost_tracking", PropertyInfo(Variant::OBJECT, "pose", PROPERTY_HINT_RESOURCE_TYPE, "XRPose"))); ClassDB::bind_method(D_METHOD("get_input", "name"), &XRPositionalTracker::get_input); ClassDB::bind_method(D_METHOD("set_input", "name", "value"), &XRPositionalTracker::set_input); @@ -146,7 +147,10 @@ void XRPositionalTracker::invalidate_pose(const StringName &p_action_name) { // only update this if we were tracking this pose if (poses.has(p_action_name)) { // We just set tracking data as invalid, we leave our current transform and velocity data as is so controllers don't suddenly jump to origin. - poses[p_action_name]->set_has_tracking_data(false); + Ref pose = poses[p_action_name]; + pose->set_has_tracking_data(false); + + emit_signal(SNAME("pose_lost_tracking"), pose); } }