Files
godot-interaction-system/Scripts/Socket.gd
T

99 lines
2.8 KiB
GDScript

class_name Socket
extends Node3D
@export var snapPoint: Marker3D
@export var snapArea: Area3D
@export var snapDistance: float = 0.5
@export var lockOnSnap: bool = true
@export var hologramMaterial: Material
var hologramInstance: MeshInstance3D
var candidate: Pickupable = null
var attachedObject: Pickupable = null
func _ready() -> void:
if snapArea:
snapArea.body_entered.connect(onBodyEntered)
snapArea.body_exited.connect(onBodyExited)
hologramInstance = MeshInstance3D.new()
hologramInstance.top_level = true
hologramInstance.visible = false
if hologramMaterial:
hologramInstance.material_override = hologramMaterial
add_child(hologramInstance)
func canAttach(object: Pickupable) -> bool:
if attachedObject != null:
return false
if object == null or object.snapAnchor == null:
return false
var distance := object.snapAnchor.global_position.distance_to(snapPoint.global_position)
return distance <= snapDistance
func attachObject(object: Pickupable) -> bool:
if not canAttach(object):
return false
var targetTransform := getSnapTransform(object)
var body := object.body
body.linear_velocity = Vector3.ZERO
body.angular_velocity = Vector3.ZERO
body.global_transform = targetTransform
if lockOnSnap:
body.freeze = true
attachedObject = object
candidate = null
object.currentSocket = self
if hologramInstance:
hologramInstance.visible = false
return true
func detachObject() -> void:
if attachedObject == null:
return
var body := attachedObject.body
if lockOnSnap:
body.freeze = false
attachedObject.currentSocket = null
attachedObject = null
func getSnapTransform(object: Pickupable) -> Transform3D:
var objectTransform := object.body.global_transform
var anchorTransform := object.snapAnchor.global_transform
var anchorOffset := objectTransform.affine_inverse() * anchorTransform
return snapPoint.global_transform * anchorOffset.affine_inverse()
func onBodyEntered(body: Node3D):
if attachedObject != null: return
if body is RigidBody3D and body.get_parent() is Pickupable:
var pickup = body.get_parent() as Pickupable
pickup.currentSocket = self
candidate = pickup
if pickup.visualMeshNode and pickup.visualMeshNode.mesh:
hologramInstance.mesh = pickup.visualMeshNode.mesh
var targetBodyTransform = getSnapTransform(pickup)
var meshLocalTranform = pickup.body.global_transform.affine_inverse() * pickup.visualMeshNode.global_transform
hologramInstance.global_transform = targetBodyTransform * meshLocalTranform
hologramInstance.visible = true
func onBodyExited(body: Node3D):
if body is RigidBody3D and body.get_parent() is Pickupable:
var pickup = body.get_parent() as Pickupable
if pickup.currentSocket == self and attachedObject != pickup:
pickup.currentSocket = null
if candidate == pickup:
candidate = null
if hologramInstance:
hologramInstance.visible = false