Godot interaction system init
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
extends Interactable
|
||||
class_name Pickupable
|
||||
|
||||
@export var springStrength: float = 150.0
|
||||
@export var springDamping: float = 50.0
|
||||
|
||||
@export var rotateStrength: float = 5.0
|
||||
@export var rotateDamping: float = 5.0
|
||||
|
||||
@export var throwForce: float = 10.0
|
||||
@export var maxDistance: float = 4.0
|
||||
@export var body: RigidBody3D
|
||||
@export var snapAnchor: Marker3D
|
||||
|
||||
@export_range(0.01, 1000.0, 0.01) var bodyMass: float = 1.0
|
||||
|
||||
var dragging: bool = false
|
||||
var rotating: bool = false
|
||||
var playerRef
|
||||
|
||||
var grabLocal: Vector3
|
||||
var holdDistance: float
|
||||
var rotationOffset: Basis
|
||||
|
||||
func _ready():
|
||||
if body:
|
||||
body.mass = bodyMass
|
||||
|
||||
func beginInteract(player, hitPosition: Vector3):
|
||||
playerRef = player
|
||||
dragging = true
|
||||
|
||||
grabLocal = body.to_local(hitPosition)
|
||||
var holdPoint = player.hand
|
||||
holdDistance = holdPoint.global_position.distance_to(hitPosition)
|
||||
rotationOffset = holdPoint.global_basis.inverse() * body.global_basis
|
||||
|
||||
func updateInteract(player):
|
||||
if !dragging:
|
||||
return
|
||||
|
||||
# Toggle rotation mode
|
||||
if Input.is_action_just_pressed("rotate"):
|
||||
rotating = true
|
||||
playerRef.setMouseFactors(0.0, 0.0)
|
||||
|
||||
if Input.is_action_just_released("rotate"):
|
||||
rotating = false
|
||||
playerRef.setMouseFactors(1.0, 1.0)
|
||||
|
||||
var holdPoint = player.hand
|
||||
|
||||
# Release if too far away
|
||||
if body.global_position.distance_to(player.global_position) > maxDistance:
|
||||
endInteract(player)
|
||||
return
|
||||
|
||||
# Target position
|
||||
var targetPosition = holdPoint.global_position + (-holdPoint.global_basis.z * holdDistance)
|
||||
var offset = targetPosition - body.global_position
|
||||
|
||||
# Linear spring
|
||||
body.apply_force(offset * springStrength - body.linear_velocity * springDamping, body.to_global(grabLocal) - body.global_position)
|
||||
|
||||
if rotating:
|
||||
var delta = player.interactionMouseDelta
|
||||
|
||||
rotationOffset = Basis(Vector3.UP, deg_to_rad(-delta.x * 0.35)) * rotationOffset
|
||||
rotationOffset = Basis(Vector3.RIGHT, deg_to_rad(delta.y * 0.35)) * rotationOffset
|
||||
|
||||
# Angular spring
|
||||
var targetBasis = holdPoint.global_basis * rotationOffset
|
||||
|
||||
var currentQuat = body.global_basis.get_rotation_quaternion()
|
||||
var targetQuat = targetBasis.get_rotation_quaternion()
|
||||
var diff = targetQuat * currentQuat.inverse()
|
||||
|
||||
if diff.dot(Quaternion.IDENTITY) < 0:
|
||||
diff = -diff
|
||||
|
||||
var angle = diff.get_angle()
|
||||
|
||||
if angle > 0.001:
|
||||
body.apply_torque(diff.get_axis() * angle * rotateStrength - body.angular_velocity * rotateDamping)
|
||||
|
||||
func endInteract(player):
|
||||
dragging = false
|
||||
rotating = false
|
||||
player.setMouseFactors(1.0, 1.0)
|
||||
playerRef = null
|
||||
|
||||
func throw():
|
||||
if !dragging:
|
||||
return
|
||||
|
||||
var direction = -playerRef.camera.global_basis.z
|
||||
body.apply_impulse(direction * throwForce)
|
||||
Reference in New Issue
Block a user