diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp index d9a66aa827d9..8fe027dee73d 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp @@ -225,6 +225,7 @@ void OpenXRHandTrackingExtension::on_process() { // not successful? then we do nothing. print_line("OpenXR: Failed to get tracking for hand", i, "[", OpenXRAPI::get_singleton()->get_error_string(result), "]"); godot_tracker->set_has_tracking_data(false); + godot_tracker->invalidate_pose("default"); continue; } @@ -235,8 +236,6 @@ void OpenXRHandTrackingExtension::on_process() { } if (hand_trackers[i].locations.isActive) { - godot_tracker->set_has_tracking_data(true); - // SKELETON_RIG_HUMANOID bone adjustment. This rotation performs: // OpenXR Z+ -> Godot Humanoid Y- (Back along the bone) // OpenXR Y+ -> Godot Humanoid Z- (Out the back of the hand) @@ -293,7 +292,8 @@ void OpenXRHandTrackingExtension::on_process() { } godot_tracker->set_hand_tracking_source(source); - if (location.locationFlags & XR_SPACE_LOCATION_POSITION_TRACKED_BIT) { + if (location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) { + godot_tracker->set_has_tracking_data(true); godot_tracker->set_pose("default", transform, linear_velocity, angular_velocity); } else { godot_tracker->set_has_tracking_data(false); diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index 3f4b9626417f..b71f9bc0c498 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -303,6 +303,8 @@ StringName XRNode3D::get_pose_name() const { void XRNode3D::set_show_when_tracked(bool p_show) { show_when_tracked = p_show; + + _update_visibility(); } bool XRNode3D::get_show_when_tracked() const { @@ -361,6 +363,9 @@ void XRNode3D::_bind_tracker() { if (pose.is_valid()) { set_transform(pose->get_adjusted_transform()); _set_has_tracking_data(pose->get_has_tracking_data()); + } else { + // Pose has been invalidated or was never set. + _set_has_tracking_data(false); } } } @@ -407,6 +412,10 @@ void XRNode3D::_pose_lost_tracking(const Ref &p_pose) { } void XRNode3D::_set_has_tracking_data(bool p_has_tracking_data) { + // Always update our visibility, we may have set our tracking data + // when conditions weren't right. + _update_visibility(); + // Ignore if the has_tracking_data state isn't changing. if (p_has_tracking_data == has_tracking_data) { return; @@ -415,10 +424,19 @@ void XRNode3D::_set_has_tracking_data(bool p_has_tracking_data) { // Handle change of has_tracking_data. has_tracking_data = p_has_tracking_data; emit_signal(SNAME("tracking_changed"), has_tracking_data); +} +void XRNode3D::_update_visibility() { // If configured, show or hide the node based on tracking data. if (show_when_tracked) { - set_visible(has_tracking_data); + // Only react to this if we have a primary interface. + XRServer *xr_server = XRServer::get_singleton(); + if (xr_server != nullptr) { + Ref xr_interface = xr_server->get_primary_interface(); + if (xr_interface.is_valid()) { + set_visible(has_tracking_data); + } + } } } diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h index a42f6d470ff0..94c3923433fe 100644 --- a/scene/3d/xr_nodes.h +++ b/scene/3d/xr_nodes.h @@ -95,6 +95,8 @@ class XRNode3D : public Node3D { void _pose_lost_tracking(const Ref &p_pose); void _set_has_tracking_data(bool p_has_tracking_data); + void _update_visibility(); + public: void _validate_property(PropertyInfo &p_property) const; void set_tracker(const StringName &p_tracker_name);