immersive-home/app/addons/godot-xr-tools/objects/grab_points/grab.gd
2024-03-16 01:16:08 +01:00

172 lines
3.8 KiB
GDScript

class_name Grab
extends Grabber
## Grab Class
##
## This class encodes information about an active grab. Additionally it applies
## hand poses and collision exceptions as appropriate.
## Priority for grip poses
const GRIP_POSE_PRIORITY := 100
## Priority for grip targeting
const GRIP_TARGET_PRIORITY := 100
## Grab target
var what : XRToolsPickable
## Grab point information
var point : XRToolsGrabPoint
## Hand grab point information
var hand_point : XRToolsGrabPointHand
## Grab transform
var transform : Transform3D
## Position drive strength
var drive_position : float = 1.0
## Angle drive strength
var drive_angle : float = 1.0
## Aim drive strength
var drive_aim : float = 0.0
## Has target arrived at grab point
var _arrived : bool = false
## Initialize the grab
func _init(
p_grabber : Grabber,
p_what : XRToolsPickable,
p_point : XRToolsGrabPoint,
p_precise : bool) -> void:
# Copy the grabber information
by = p_grabber.by
pickup = p_grabber.pickup
controller = p_grabber.controller
hand = p_grabber.hand
collision_hand = p_grabber.collision_hand
# Set the point
what = p_what
point = p_point
hand_point = p_point as XRToolsGrabPointHand
# Calculate the grab transform
if p_point:
transform = p_point.transform
elif p_precise:
transform = p_what.global_transform.inverse() * by.global_transform
else:
transform = Transform3D.IDENTITY
# Set the drive parameters
if hand_point:
drive_position = hand_point.drive_position
drive_angle = hand_point.drive_angle
drive_aim = hand_point.drive_aim
# Apply collision exceptions
if collision_hand:
what.add_collision_exception_with(collision_hand)
collision_hand.add_collision_exception_with(what)
## Set the target as arrived at the grab-point
func set_arrived() -> void:
# Ignore if already arrived
if _arrived:
return
# Set arrived and apply any hand pose
print_verbose("%s> arrived at %s" % [what.name, point])
_arrived = true
_set_hand_pose()
# Report the grab
print_verbose("%s> grabbed by %s", [what.name, by.name])
what.grabbed.emit(what, by)
## Set the grab point
func set_grab_point(p_point : XRToolsGrabPoint) -> void:
# Skip if no change
if p_point == point:
return
# Remove any current pose override
_clear_hand_pose()
# Update the grab point
point = p_point
hand_point = point as XRToolsGrabPointHand
# Update the transform
if point:
transform = point.transform
# Apply the new hand grab-point settings
if hand_point:
drive_position = hand_point.drive_position
drive_angle = hand_point.drive_angle
drive_aim = hand_point.drive_aim
# Apply any pose overrides
if _arrived:
_set_hand_pose()
# Report switch
print_verbose("%s> switched grab point to %s", [what.name, point.name])
what.released.emit(what, by)
what.grabbed.emit(what, by)
## Release the grip
func release() -> void:
# Clear any hand pose
_clear_hand_pose()
# Remove collision exceptions
if is_instance_valid(collision_hand):
what.remove_collision_exception_with(collision_hand)
collision_hand.remove_collision_exception_with(what)
# Report the release
print_verbose("%s> released by %s", [what.name, by.name])
what.released.emit(what, by)
# Set hand-pose overrides
func _set_hand_pose() -> void:
# Skip if not hand
if not is_instance_valid(hand) or not is_instance_valid(hand_point):
return
# Apply the hand-pose
if hand_point.hand_pose:
hand.add_pose_override(hand_point, GRIP_POSE_PRIORITY, hand_point.hand_pose)
# Apply hand snapping
if hand_point.snap_hand:
hand.add_target_override(hand_point, GRIP_TARGET_PRIORITY)
# Clear any hand-pose overrides
func _clear_hand_pose() -> void:
# Skip if not hand
if not is_instance_valid(hand) or not is_instance_valid(hand_point):
return
# Remove hand-pose
hand.remove_pose_override(hand_point)
# Remove hand snapping
hand.remove_target_override(hand_point)