Files

56 lines
1.7 KiB
GDScript

extends Interactable
class_name SliderInteractable
@export var body: RigidBody3D
@export var slider_joint: SliderJoint3D
@export var springStrength: float = 200.0
@export var springDamping: float = 15.0
@export var maxGrabDistance: float = 4.0
var dragging: bool = false
var grabLocal: Vector3
var handOffsetLocal: Vector3
func _ready() -> void:
if body:
body.mass = max(body.mass, 0.01)
await get_tree().physics_frame
if slider_joint:
var orig_a = slider_joint.node_a
var orig_b = slider_joint.node_b
slider_joint.node_a = NodePath("")
slider_joint.node_b = NodePath("")
slider_joint.node_a = orig_a
slider_joint.node_b = orig_b
func beginInteract(player, hitPosition: Vector3) -> void:
dragging = true
grabLocal = body.to_local(hitPosition)
var holdPoint = player.hand
handOffsetLocal = holdPoint.global_basis.inverse() * (hitPosition - holdPoint.global_position)
func updateInteract(player) -> void:
if !dragging:
return
body.sleeping = false
var worldGrab = body.to_global(grabLocal)
if player.global_position.distance_to(worldGrab) > maxGrabDistance:
player.stopInteraction()
return
var holdPoint = player.hand
var targetGrabGlobal = holdPoint.global_position + (holdPoint.global_basis * handOffsetLocal)
var errorVector = targetGrabGlobal - worldGrab
var slide_axis_global = slider_joint.global_basis.x.normalized()
var linear_error = errorVector.dot(slide_axis_global)
var linear_velocity = body.linear_velocity.dot(slide_axis_global)
var force_magnitude = (linear_error * springStrength) - (linear_velocity * springDamping)
body.apply_central_force(slide_axis_global * force_magnitude)
func endInteract(player) -> void:
dragging = false