## SnapReceiver — scans for nearby SnapPoints when the parent Character is released. ## Attach as child of Character. Connects automatically to DragDropComponent signals. class_name SnapReceiver extends Node const SCAN_RADIUS: float = 80.0 var _current_snap: SnapPoint = null var _character: Character func _ready() -> void: _character = get_parent() as Character var drag: DragDropComponent = _character.get_node_or_null("DragDropComponent") as DragDropComponent if drag != null: drag.drag_picked_up.connect(_on_drag_picked_up) drag.drag_released.connect(_on_drag_released) func _on_drag_picked_up(_pos: Vector2) -> void: if _current_snap != null: _current_snap.unsnap() _current_snap = null _character.set_animation_state("held") func _on_drag_released(_pos: Vector2) -> void: var nearest: SnapPoint = _find_nearest_accepting_snap() if nearest != null: _current_snap = nearest nearest.snap(_character) _character.global_position = nearest.global_position _character.set_animation_state(nearest.pose) else: _character.set_animation_state("idle") func _find_nearest_accepting_snap() -> SnapPoint: var best: SnapPoint = null var best_dist: float = SCAN_RADIUS for node: Node in get_tree().get_nodes_in_group("snap_points"): var snap_point: SnapPoint = node as SnapPoint if snap_point == null: continue if not snap_point.accepts(_character): continue var dist: float = _character.global_position.distance_to(snap_point.global_position) if dist < best_dist: best_dist = dist best = snap_point return best func get_current_snap() -> SnapPoint: return _current_snap func force_unsnap() -> void: if _current_snap == null: return _current_snap.unsnap() _current_snap = null _character.set_animation_state("idle")