vrp-gruppe-sechs/space-room/addons/godot-xr-tools/hands/hand_palm_offset.gd

101 lines
3.1 KiB
GDScript

@tool
class_name XRToolsHandPalmOffset
extends Node3D
## XRToolsHandPalmOffset will automatically adjust its position,
## to locate the palm of a hand (within limits).
## Hand offset to apply based on our controller pose
## You can use auto if you're using the default aim_pose or grip_pose poses.
@export_enum("auto", "aim", "grip", "palm", "disable") var hand_offset_mode : int = 0:
set(value):
hand_offset_mode = value
notify_property_list_changed()
if is_inside_tree():
_update_transform()
# Controller
var _controller : XRController3D
# Keep track of our tracker and pose
var _controller_tracker_and_pose : String = ""
# Which node are we applying our transform on?
var _apply_to : Node3D
# Additional transform to apply
var _base_transform : Transform3D = Transform3D()
## Add support for is_xr_class on XRTools classes
func is_xr_class(xr_name: String) -> bool:
return xr_name == "XRToolsHandAimOffset"
## Set the node we apply our transform to
## Must be set before _enter_tree is called for the first time.
func set_apply_to(node : Node3D) -> void:
_apply_to = node
## Set a base transform to apply
func set_base_transform(base_transform : Transform3D) -> void:
_base_transform = base_transform
if is_inside_tree():
_update_transform()
# Called when we're added to the tree
func _enter_tree():
if not _apply_to:
_apply_to = self
_controller = XRHelpers.get_xr_controller(self)
_update_transform()
# Called when we exit the tree
func _exit_tree():
if _controller:
_controller = null
# Check property config
func _validate_property(property):
if hand_offset_mode != 4 and (property.name == "position" or property.name == "rotation" or property.name == "scale" or property.name == "rotation_edit_mode" or property.name == "rotation_order"):
# We control these, don't let the user set them.
property.usage = PROPERTY_USAGE_NONE
# This method verifies the hand has a valid configuration.
func _get_configuration_warnings() -> PackedStringArray:
var warnings := PackedStringArray()
# Check for XR Controller
var controller = XRHelpers.get_xr_controller(self)
if not controller:
warnings.append("Hand should descent from an XRController3D node")
elif controller.pose == "aim":
# FIXME we don't get a refresh when the pose changes,
# so this doesn't clear until a scene is reloaded...
warnings.append("The aim pose is no longer suitable for hand position, consider using the grip pose instead")
return warnings
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
# If we have a controller, make sure our hand transform is updated when needed.
if _controller:
var tracker_and_pose = _controller.tracker + "." + _controller.pose
if _controller_tracker_and_pose != tracker_and_pose:
_controller_tracker_and_pose = tracker_and_pose
if hand_offset_mode == 0:
_update_transform()
# Update our transform so we are positioned on our palm
func _update_transform() -> void:
if _apply_to and hand_offset_mode != 4:
_apply_to.transform = XRTools.get_palm_offset(hand_offset_mode, _controller) * _base_transform