summaryrefslogtreecommitdiffstats
path: root/scene
diff options
context:
space:
mode:
authorMalcolm Nixon <Malcolm.nixon@gmail.com>2024-04-13 17:26:46 -0400
committerMalcolm Nixon <Malcolm.nixon@gmail.com>2024-04-18 20:04:01 -0400
commit823ae7b3fa25832d1cd9d7613c650bfc712d1f49 (patch)
tree36a0c75dd36faf7c15cf81a78267f71c62b3009e /scene
parent3b1806182a3564736ad64793b203c2c13c251f56 (diff)
downloadredot-engine-823ae7b3fa25832d1cd9d7613c650bfc712d1f49.tar.gz
Rework XR Trackers to have a common ancestor. Allow creation of XRNode3D to drive node positions and visibility.
Diffstat (limited to 'scene')
-rw-r--r--scene/3d/xr_body_modifier_3d.cpp45
-rw-r--r--scene/3d/xr_body_modifier_3d.h6
-rw-r--r--scene/3d/xr_face_modifier_3d.cpp8
-rw-r--r--scene/3d/xr_face_modifier_3d.h2
-rw-r--r--scene/3d/xr_hand_modifier_3d.cpp109
-rw-r--r--scene/3d/xr_hand_modifier_3d.h4
-rw-r--r--scene/3d/xr_nodes.cpp37
-rw-r--r--scene/3d/xr_nodes.h4
-rw-r--r--scene/register_scene_types.cpp2
9 files changed, 103 insertions, 114 deletions
diff --git a/scene/3d/xr_body_modifier_3d.cpp b/scene/3d/xr_body_modifier_3d.cpp
index 0099784a05..8aec3e856e 100644
--- a/scene/3d/xr_body_modifier_3d.cpp
+++ b/scene/3d/xr_body_modifier_3d.cpp
@@ -44,13 +44,9 @@ void XRBodyModifier3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bone_update", "bone_update"), &XRBodyModifier3D::set_bone_update);
ClassDB::bind_method(D_METHOD("get_bone_update"), &XRBodyModifier3D::get_bone_update);
- ClassDB::bind_method(D_METHOD("set_show_when_tracked", "show"), &XRBodyModifier3D::set_show_when_tracked);
- ClassDB::bind_method(D_METHOD("get_show_when_tracked"), &XRBodyModifier3D::get_show_when_tracked);
-
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "body_tracker", PROPERTY_HINT_ENUM_SUGGESTION, "/user/body"), "set_body_tracker", "get_body_tracker");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "body_tracker", PROPERTY_HINT_ENUM_SUGGESTION, "/user/body_tracker"), "set_body_tracker", "get_body_tracker");
ADD_PROPERTY(PropertyInfo(Variant::INT, "body_update", PROPERTY_HINT_FLAGS, "Upper Body,Lower Body,Hands"), "set_body_update", "get_body_update");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_update", PROPERTY_HINT_ENUM, "Full,Rotation Only"), "set_bone_update", "get_bone_update");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_when_tracked"), "set_show_when_tracked", "get_show_when_tracked");
BIND_BITFIELD_FLAG(BODY_UPDATE_UPPER_BODY);
BIND_BITFIELD_FLAG(BODY_UPDATE_LOWER_BODY);
@@ -86,14 +82,6 @@ XRBodyModifier3D::BoneUpdate XRBodyModifier3D::get_bone_update() const {
return bone_update;
}
-void XRBodyModifier3D::set_show_when_tracked(bool p_show_when_tracked) {
- show_when_tracked = p_show_when_tracked;
-}
-
-bool XRBodyModifier3D::get_show_when_tracked() const {
- return show_when_tracked;
-}
-
void XRBodyModifier3D::_get_joint_data() {
// Table of Godot Humanoid bone names.
static const String bone_names[XRBodyTracker::JOINT_MAX] = {
@@ -189,7 +177,7 @@ void XRBodyModifier3D::_get_joint_data() {
joints[i].parent_joint = -1;
}
- Skeleton3D *skeleton = get_skeleton();
+ const Skeleton3D *skeleton = get_skeleton();
if (!skeleton) {
return;
}
@@ -257,27 +245,22 @@ void XRBodyModifier3D::_process_modification() {
return;
}
- XRServer *xr_server = XRServer::get_singleton();
+ const XRServer *xr_server = XRServer::get_singleton();
if (!xr_server) {
return;
}
- Ref<XRBodyTracker> tracker = xr_server->get_body_tracker(tracker_name);
- if (tracker.is_null()) {
+ const Ref<XRBodyTracker> tracker = xr_server->get_tracker(tracker_name);
+ if (!tracker.is_valid()) {
return;
}
- // Handle no tracking data.
+ // Skip if no tracking data.
if (!tracker->get_has_tracking_data()) {
- // If tracking-state determines visibility then hide the node.
- if (show_when_tracked) {
- set_visible(false);
- }
return;
}
// Get the world and skeleton scale.
- const float ws = xr_server->get_world_scale();
const float ss = skeleton->get_motion_scale();
// Read the relevant tracking data. This applies the skeleton motion scale to
@@ -296,12 +279,8 @@ void XRBodyModifier3D::_process_modification() {
}
}
- // Handle root joint not tracked.
+ // Skip if root joint not tracked.
if (!has_valid_data[XRBodyTracker::JOINT_ROOT]) {
- // If tracking-state determines visibility then hide the node.
- if (show_when_tracked) {
- set_visible(false);
- }
return;
}
@@ -331,16 +310,6 @@ void XRBodyModifier3D::_process_modification() {
// Always update the bone rotation.
skeleton->set_bone_pose_rotation(joints[joint].bone, Quaternion(relative_transform.basis));
}
-
- // Transform to the tracking data root pose. This also applies the XR world-scale to allow
- // scaling the avatars mesh and skeleton appropriately (if they are child nodes).
- set_transform(
- transforms[XRBodyTracker::JOINT_ROOT] * ws);
-
- // If tracking-state determines visibility then show the node.
- if (show_when_tracked) {
- set_visible(true);
- }
}
void XRBodyModifier3D::_tracker_changed(const StringName &p_tracker_name, const Ref<XRBodyTracker> &p_tracker) {
diff --git a/scene/3d/xr_body_modifier_3d.h b/scene/3d/xr_body_modifier_3d.h
index 03b1c07d53..9ff0cd7207 100644
--- a/scene/3d/xr_body_modifier_3d.h
+++ b/scene/3d/xr_body_modifier_3d.h
@@ -66,9 +66,6 @@ public:
void set_bone_update(BoneUpdate p_bone_update);
BoneUpdate get_bone_update() const;
- void set_show_when_tracked(bool p_show_when_tracked);
- bool get_show_when_tracked() const;
-
void _notification(int p_what);
protected:
@@ -83,10 +80,9 @@ private:
int parent_joint = -1;
};
- StringName tracker_name = "/user/body";
+ StringName tracker_name = "/user/body_tracker";
BitField<BodyUpdate> body_update = BODY_UPDATE_UPPER_BODY | BODY_UPDATE_LOWER_BODY | BODY_UPDATE_HANDS;
BoneUpdate bone_update = BONE_UPDATE_FULL;
- bool show_when_tracked = true;
JointData joints[XRBodyTracker::JOINT_MAX];
void _get_joint_data();
diff --git a/scene/3d/xr_face_modifier_3d.cpp b/scene/3d/xr_face_modifier_3d.cpp
index be92a587b0..43cef95fb9 100644
--- a/scene/3d/xr_face_modifier_3d.cpp
+++ b/scene/3d/xr_face_modifier_3d.cpp
@@ -495,7 +495,7 @@ static void remove_driven_unified_blend_shapes(RBMap<int, int> &p_blend_mapping)
void XRFaceModifier3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_face_tracker", "tracker_name"), &XRFaceModifier3D::set_face_tracker);
ClassDB::bind_method(D_METHOD("get_face_tracker"), &XRFaceModifier3D::get_face_tracker);
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "face_tracker", PROPERTY_HINT_ENUM_SUGGESTION, "/user/head"), "set_face_tracker", "get_face_tracker");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "face_tracker", PROPERTY_HINT_ENUM_SUGGESTION, "/user/face_tracker"), "set_face_tracker", "get_face_tracker");
ClassDB::bind_method(D_METHOD("set_target", "target"), &XRFaceModifier3D::set_target);
ClassDB::bind_method(D_METHOD("get_target"), &XRFaceModifier3D::get_target);
@@ -576,8 +576,8 @@ void XRFaceModifier3D::_update_face_blends() const {
}
// Get the face tracker.
- const Ref<XRFaceTracker> p = xr_server->get_face_tracker(tracker_name);
- if (!p.is_valid()) {
+ const Ref<XRFaceTracker> tracker = xr_server->get_tracker(tracker_name);
+ if (!tracker.is_valid()) {
return;
}
@@ -588,7 +588,7 @@ void XRFaceModifier3D::_update_face_blends() const {
}
// Get the blend weights.
- const PackedFloat32Array weights = p->get_blend_shapes();
+ const PackedFloat32Array weights = tracker->get_blend_shapes();
// Apply all the face blend weights to the mesh.
for (const KeyValue<int, int> &it : blend_mapping) {
diff --git a/scene/3d/xr_face_modifier_3d.h b/scene/3d/xr_face_modifier_3d.h
index 147c374e95..e5e59afe1d 100644
--- a/scene/3d/xr_face_modifier_3d.h
+++ b/scene/3d/xr_face_modifier_3d.h
@@ -47,7 +47,7 @@ class XRFaceModifier3D : public Node3D {
GDCLASS(XRFaceModifier3D, Node3D);
private:
- StringName tracker_name = "/user/head";
+ StringName tracker_name = "/user/face_tracker";
NodePath target;
// Map from XRFaceTracker blend shape index to mesh blend shape index.
diff --git a/scene/3d/xr_hand_modifier_3d.cpp b/scene/3d/xr_hand_modifier_3d.cpp
index 7fecb53008..1e78a4630f 100644
--- a/scene/3d/xr_hand_modifier_3d.cpp
+++ b/scene/3d/xr_hand_modifier_3d.cpp
@@ -40,7 +40,7 @@ void XRHandModifier3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bone_update", "bone_update"), &XRHandModifier3D::set_bone_update);
ClassDB::bind_method(D_METHOD("get_bone_update"), &XRHandModifier3D::get_bone_update);
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "hand_tracker", PROPERTY_HINT_ENUM_SUGGESTION, "/user/left,/user/right"), "set_hand_tracker", "get_hand_tracker");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "hand_tracker", PROPERTY_HINT_ENUM_SUGGESTION, "/user/hand_tracker/left,/user/hand_tracker/right"), "set_hand_tracker", "get_hand_tracker");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_update", PROPERTY_HINT_ENUM, "Full,Rotation Only"), "set_bone_update", "get_bone_update");
BIND_ENUM_CONSTANT(BONE_UPDATE_FULL);
@@ -111,22 +111,30 @@ void XRHandModifier3D::_get_joint_data() {
joints[i].parent_joint = -1;
}
- Skeleton3D *skeleton = get_skeleton();
+ const Skeleton3D *skeleton = get_skeleton();
if (!skeleton) {
return;
}
- XRServer *xr_server = XRServer::get_singleton();
+ const XRServer *xr_server = XRServer::get_singleton();
if (!xr_server) {
return;
}
- Ref<XRHandTracker> tracker = xr_server->get_hand_tracker(tracker_name);
+ const Ref<XRHandTracker> tracker = xr_server->get_tracker(tracker_name);
if (tracker.is_null()) {
return;
}
- XRHandTracker::Hand hand = tracker->get_hand();
+ // Verify we have a left or right hand tracker.
+ const XRPositionalTracker::TrackerHand tracker_hand = tracker->get_tracker_hand();
+ if (tracker_hand != XRPositionalTracker::TRACKER_HAND_LEFT &&
+ tracker_hand != XRPositionalTracker::TRACKER_HAND_RIGHT) {
+ return;
+ }
+
+ // Get the hand index (0 = left, 1 = right).
+ const int hand = tracker_hand == XRPositionalTracker::TRACKER_HAND_LEFT ? 0 : 1;
// Find the skeleton-bones associated with each joint.
int bones[XRHandTracker::HAND_JOINT_MAX];
@@ -176,18 +184,22 @@ void XRHandModifier3D::_process_modification() {
return;
}
- XRServer *xr_server = XRServer::get_singleton();
+ const XRServer *xr_server = XRServer::get_singleton();
if (!xr_server) {
return;
}
- Ref<XRHandTracker> tracker = xr_server->get_hand_tracker(tracker_name);
+ const Ref<XRHandTracker> tracker = xr_server->get_tracker(tracker_name);
if (tracker.is_null()) {
return;
}
+ // Skip if no tracking data
+ if (!tracker->get_has_tracking_data()) {
+ return;
+ }
+
// Get the world and skeleton scale.
- const float ws = xr_server->get_world_scale();
const float ss = skeleton->get_motion_scale();
// We cache our transforms so we can quickly calculate local transforms.
@@ -195,55 +207,44 @@ void XRHandModifier3D::_process_modification() {
Transform3D transforms[XRHandTracker::HAND_JOINT_MAX];
Transform3D inv_transforms[XRHandTracker::HAND_JOINT_MAX];
- if (tracker->get_has_tracking_data()) {
- for (int joint = 0; joint < XRHandTracker::HAND_JOINT_MAX; joint++) {
- BitField<XRHandTracker::HandJointFlags> flags = tracker->get_hand_joint_flags((XRHandTracker::HandJoint)joint);
- has_valid_data[joint] = flags.has_flag(XRHandTracker::HAND_JOINT_FLAG_ORIENTATION_VALID);
+ for (int joint = 0; joint < XRHandTracker::HAND_JOINT_MAX; joint++) {
+ BitField<XRHandTracker::HandJointFlags> flags = tracker->get_hand_joint_flags((XRHandTracker::HandJoint)joint);
+ has_valid_data[joint] = flags.has_flag(XRHandTracker::HAND_JOINT_FLAG_ORIENTATION_VALID);
- if (has_valid_data[joint]) {
- transforms[joint] = tracker->get_hand_joint_transform((XRHandTracker::HandJoint)joint);
- transforms[joint].origin *= ss;
- inv_transforms[joint] = transforms[joint].inverse();
- }
+ if (has_valid_data[joint]) {
+ transforms[joint] = tracker->get_hand_joint_transform((XRHandTracker::HandJoint)joint);
+ transforms[joint].origin *= ss;
+ inv_transforms[joint] = transforms[joint].inverse();
}
+ }
- if (has_valid_data[XRHandTracker::HAND_JOINT_PALM]) {
- for (int joint = 0; joint < XRHandTracker::HAND_JOINT_MAX; joint++) {
- // Get the skeleton bone (skip if none).
- const int bone = joints[joint].bone;
- if (bone == -1) {
- continue;
- }
-
- // Calculate the relative relationship to the parent bone joint.
- const int parent_joint = joints[joint].parent_joint;
- const Transform3D relative_transform = inv_transforms[parent_joint] * transforms[joint];
-
- // Update the bone position if enabled by update mode.
- if (bone_update == BONE_UPDATE_FULL) {
- skeleton->set_bone_pose_position(joints[joint].bone, relative_transform.origin);
- }
-
- // Always update the bone rotation.
- skeleton->set_bone_pose_rotation(joints[joint].bone, Quaternion(relative_transform.basis));
- }
+ // Skip if palm has no tracking data
+ if (!has_valid_data[XRHandTracker::HAND_JOINT_PALM]) {
+ return;
+ }
+
+ for (int joint = 0; joint < XRHandTracker::HAND_JOINT_MAX; joint++) {
+ // Get the skeleton bone (skip if none).
+ const int bone = joints[joint].bone;
+ if (bone == -1) {
+ continue;
+ }
- // Transform to the skeleton pose. This uses the HAND_JOINT_PALM position without skeleton-scaling, as it
- // must be positioned to match the physical hand location. It is scaled with the world space to match
- // the scaling done to the camera and eyes.
- set_transform(
- tracker->get_hand_joint_transform(XRHandTracker::HAND_JOINT_PALM) * ws);
+ // Calculate the relative relationship to the parent bone joint.
+ const int parent_joint = joints[joint].parent_joint;
+ const Transform3D relative_transform = inv_transforms[parent_joint] * transforms[joint];
- set_visible(true);
- } else {
- set_visible(false);
+ // Update the bone position if enabled by update mode.
+ if (bone_update == BONE_UPDATE_FULL) {
+ skeleton->set_bone_pose_position(joints[joint].bone, relative_transform.origin);
}
- } else {
- set_visible(false);
+
+ // Always update the bone rotation.
+ skeleton->set_bone_pose_rotation(joints[joint].bone, Quaternion(relative_transform.basis));
}
}
-void XRHandModifier3D::_tracker_changed(StringName p_tracker_name, const Ref<XRHandTracker> &p_tracker) {
+void XRHandModifier3D::_tracker_changed(StringName p_tracker_name, XRServer::TrackerType p_tracker_type) {
if (tracker_name == p_tracker_name) {
_get_joint_data();
}
@@ -258,9 +259,9 @@ void XRHandModifier3D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
XRServer *xr_server = XRServer::get_singleton();
if (xr_server) {
- xr_server->connect("hand_tracker_added", callable_mp(this, &XRHandModifier3D::_tracker_changed));
- xr_server->connect("hand_tracker_updated", callable_mp(this, &XRHandModifier3D::_tracker_changed));
- xr_server->connect("hand_tracker_removed", callable_mp(this, &XRHandModifier3D::_tracker_changed).bind(Ref<XRHandTracker>()));
+ xr_server->connect("tracker_added", callable_mp(this, &XRHandModifier3D::_tracker_changed));
+ xr_server->connect("tracker_updated", callable_mp(this, &XRHandModifier3D::_tracker_changed));
+ xr_server->connect("tracker_removed", callable_mp(this, &XRHandModifier3D::_tracker_changed));
}
_get_joint_data();
@@ -268,9 +269,9 @@ void XRHandModifier3D::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
XRServer *xr_server = XRServer::get_singleton();
if (xr_server) {
- xr_server->disconnect("hand_tracker_added", callable_mp(this, &XRHandModifier3D::_tracker_changed));
- xr_server->disconnect("hand_tracker_updated", callable_mp(this, &XRHandModifier3D::_tracker_changed));
- xr_server->disconnect("hand_tracker_removed", callable_mp(this, &XRHandModifier3D::_tracker_changed).bind(Ref<XRHandTracker>()));
+ xr_server->disconnect("tracker_added", callable_mp(this, &XRHandModifier3D::_tracker_changed));
+ xr_server->disconnect("tracker_updated", callable_mp(this, &XRHandModifier3D::_tracker_changed));
+ xr_server->disconnect("tracker_removed", callable_mp(this, &XRHandModifier3D::_tracker_changed));
}
for (int i = 0; i < XRHandTracker::HAND_JOINT_MAX; i++) {
diff --git a/scene/3d/xr_hand_modifier_3d.h b/scene/3d/xr_hand_modifier_3d.h
index 9f7ce45c9d..67d1694d41 100644
--- a/scene/3d/xr_hand_modifier_3d.h
+++ b/scene/3d/xr_hand_modifier_3d.h
@@ -69,12 +69,12 @@ private:
int parent_joint = -1;
};
- StringName tracker_name = "/user/left";
+ StringName tracker_name = "/user/hand_tracker/left";
BoneUpdate bone_update = BONE_UPDATE_FULL;
JointData joints[XRHandTracker::HAND_JOINT_MAX];
void _get_joint_data();
- void _tracker_changed(StringName p_tracker_name, const Ref<XRHandTracker> &p_tracker);
+ void _tracker_changed(StringName p_tracker_name, XRServer::TrackerType p_tracker_type);
};
VARIANT_ENUM_CAST(XRHandModifier3D::BoneUpdate)
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index 12a9f50ed7..3f4b962641 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -80,10 +80,11 @@ PackedStringArray XRCamera3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
if (is_visible() && is_inside_tree()) {
- // must be child node of XROrigin3D!
- XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
- if (origin == nullptr) {
- warnings.push_back(RTR("XRCamera3D must have an XROrigin3D node as its parent."));
+ // Warn if the node has a parent which isn't an XROrigin3D!
+ Node *parent = get_parent();
+ XROrigin3D *origin = Object::cast_to<XROrigin3D>(parent);
+ if (parent && origin == nullptr) {
+ warnings.push_back(RTR("XRCamera3D may not function as expected without an XROrigin3D node as its parent."));
};
}
@@ -229,6 +230,10 @@ void XRNode3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_pose_name"), &XRNode3D::get_pose_name);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "pose", PROPERTY_HINT_ENUM_SUGGESTION), "set_pose_name", "get_pose_name");
+ ClassDB::bind_method(D_METHOD("set_show_when_tracked", "show"), &XRNode3D::set_show_when_tracked);
+ ClassDB::bind_method(D_METHOD("get_show_when_tracked"), &XRNode3D::get_show_when_tracked);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_when_tracked"), "set_show_when_tracked", "get_show_when_tracked");
+
ClassDB::bind_method(D_METHOD("get_is_active"), &XRNode3D::get_is_active);
ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRNode3D::get_has_tracking_data);
ClassDB::bind_method(D_METHOD("get_pose"), &XRNode3D::get_pose);
@@ -296,6 +301,14 @@ StringName XRNode3D::get_pose_name() const {
return pose_name;
}
+void XRNode3D::set_show_when_tracked(bool p_show) {
+ show_when_tracked = p_show;
+}
+
+bool XRNode3D::get_show_when_tracked() const {
+ return show_when_tracked;
+}
+
bool XRNode3D::get_is_active() const {
if (tracker.is_null()) {
return false;
@@ -402,6 +415,11 @@ 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);
+
+ // If configured, show or hide the node based on tracking data.
+ if (show_when_tracked) {
+ set_visible(has_tracking_data);
+ }
}
XRNode3D::XRNode3D() {
@@ -428,11 +446,12 @@ PackedStringArray XRNode3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
if (is_visible() && is_inside_tree()) {
- // must be child node of XROrigin!
- XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
- if (origin == nullptr) {
- warnings.push_back(RTR("XRController3D must have an XROrigin3D node as its parent."));
- }
+ // Warn if the node has a parent which isn't an XROrigin3D!
+ Node *parent = get_parent();
+ XROrigin3D *origin = Object::cast_to<XROrigin3D>(parent);
+ if (parent && origin == nullptr) {
+ warnings.push_back(RTR("XRNode3D may not function as expected without an XROrigin3D node as its parent."));
+ };
if (tracker_name == "") {
warnings.push_back(RTR("No tracker name is set."));
diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h
index bdcccd51ea..a42f6d470f 100644
--- a/scene/3d/xr_nodes.h
+++ b/scene/3d/xr_nodes.h
@@ -79,6 +79,7 @@ private:
StringName tracker_name;
StringName pose_name = "default";
bool has_tracking_data = false;
+ bool show_when_tracked = false;
protected:
Ref<XRPositionalTracker> tracker;
@@ -105,6 +106,9 @@ public:
bool get_is_active() const;
bool get_has_tracking_data() const;
+ void set_show_when_tracked(bool p_show);
+ bool get_show_when_tracked() const;
+
void trigger_haptic_pulse(const String &p_action_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec = 0);
Ref<XRPose> get_pose();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 1c8833494d..21682cca94 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -545,7 +545,7 @@ void register_scene_types() {
GDREGISTER_CLASS(Camera3D);
GDREGISTER_CLASS(AudioListener3D);
GDREGISTER_CLASS(XRCamera3D);
- GDREGISTER_ABSTRACT_CLASS(XRNode3D);
+ GDREGISTER_CLASS(XRNode3D);
GDREGISTER_CLASS(XRController3D);
GDREGISTER_CLASS(XRAnchor3D);
GDREGISTER_CLASS(XROrigin3D);