@tool # A draggable item in the game that can be picked up and displayed with an outline effect. class_name Draggable2D extends Area2D static var current_focusing_item = "" signal picked signal dropped # z +1 when picked (-1 when dropped) # @export var z_up_on_picked := true @export var item_name = "" @export var collision_shape: RectangleShape2D @export var sprite_offset := Vector2(0, 0): set(val): sprite_offset = val if is_node_ready(): sprite.offset = sprite_offset @export var freezing := false: set(val): freezing = val if freezing and holding: _drop() @export var texture: Texture2D: # The texture to display for the item set(val): texture = val if is_node_ready(): sprite.texture = texture @export var limit_rect := Rect2(Vector2.ZERO, Vector2(564, 316)) @onready var sprite = $Sprite2D as Sprite2D func _ready() -> void: sprite.texture = texture sprite.offset = sprite_offset $CollisionShape2D.shape = collision_shape if Engine.is_editor_hint(): queue_redraw() return mouse_entered.connect(_on_mouse_entered) mouse_exited.connect(_on_mouse_exited) # Whether the item is currently being held by the player var holding = false var touching = false func _on_mouse_entered() -> void: if freezing: return # 尝试获得 current_focusing_item if current_focusing_item != "": return current_focusing_item = item_name touching = true _toggle_outline(true) func _on_mouse_exited() -> void: if freezing: return if touching and not holding: current_focusing_item = "" touching = false _toggle_outline(false) func _input(event: InputEvent) -> void: if freezing or Engine.is_editor_hint(): return if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_LEFT and event.pressed: # Trigger the pick action if touching and not holding: _try_pick() elif holding: _drop() elif holding and event is InputEventMouseMotion: _update_pos_to_mouse() func _update_pos_to_mouse(): # update global position global_position = get_global_mouse_position() global_position.x = clamp(global_position.x, limit_rect.position.x, limit_rect.end.x) global_position.y = clamp(global_position.y, limit_rect.position.y, limit_rect.end.y) func _try_pick() -> void: if current_focusing_item != item_name: return # reset rotation rotation = 0 _toggle_outline(false) holding = true # z_index += 1 picked.emit() _update_pos_to_mouse() func _drop() -> void: if holding: holding = false # z_index -= 1 dropped.emit() if touching: _toggle_outline(true) else: # not touching but dropped, remove current_focusing_item if any current_focusing_item = "" func _toggle_outline(display = true): var tween = create_tween() if display: tween.tween_property(sprite.material, "shader_parameter/thickness", 1.0, 0.2) else: tween.tween_property(sprite.material, "shader_parameter/thickness", 0.0, 0.2)