2026-01-16 15:38:26 +00:00
|
|
|
extends Draggable
|
2023-10-12 16:25:21 +00:00
|
|
|
class_name StickyNote
|
2025-04-07 15:26:06 +00:00
|
|
|
|
|
|
|
|
var sticky_id
|
2026-01-21 22:32:55 +00:00
|
|
|
var parent_id : StringName
|
2025-04-07 15:26:06 +00:00
|
|
|
|
2025-01-31 02:22:07 +00:00
|
|
|
var sibling: StickyNote
|
|
|
|
|
var shift_tween: Tween
|
|
|
|
|
var modulate_tween: Tween
|
2026-01-16 23:31:01 +00:00
|
|
|
|
2026-01-16 16:08:48 +00:00
|
|
|
# cannot be explicitly typed, as this can be both handled by picker and physics-board
|
2025-03-05 18:41:22 +00:00
|
|
|
var current_handle: Node
|
2023-04-19 16:53:24 +00:00
|
|
|
|
2025-03-28 17:20:21 +00:00
|
|
|
var position_locked: bool = false
|
|
|
|
|
|
2026-01-17 11:11:21 +00:00
|
|
|
## Computed property: Is this currently attached to a card
|
2026-01-18 09:48:03 +00:00
|
|
|
var is_attached : bool:
|
2026-01-17 11:11:21 +00:00
|
|
|
get: return get_parent() is Card
|
|
|
|
|
|
2026-01-16 23:31:01 +00:00
|
|
|
## Replaces the need for tracking attached_to as state
|
2026-01-17 11:11:21 +00:00
|
|
|
var attached_to: Card:
|
|
|
|
|
get: return get_parent() as Card if is_attached else null
|
|
|
|
|
|
2026-01-16 23:31:01 +00:00
|
|
|
|
2026-01-11 21:09:19 +00:00
|
|
|
@onready var background_sprite: AnimatedSprite2D = %BackgroundSprite
|
|
|
|
|
|
2023-04-19 16:53:24 +00:00
|
|
|
@export var text: String = "" :
|
2024-09-15 09:30:31 +00:00
|
|
|
set (value):
|
2025-04-13 17:07:31 +00:00
|
|
|
if is_node_ready():
|
2026-01-11 20:42:06 +00:00
|
|
|
_on_text_updated.call_deferred()
|
2024-09-15 09:30:31 +00:00
|
|
|
text = value
|
2025-04-13 17:07:31 +00:00
|
|
|
var content: Node2D
|
|
|
|
|
var label: Label
|
2023-06-28 13:27:05 +00:00
|
|
|
|
|
|
|
|
@export var shift_by: Vector2 = Vector2(-32, 0)
|
|
|
|
|
@export_color_no_alpha var highlight_color: Color = Color(1.5, 1.5, 1.5)
|
2024-09-15 09:30:31 +00:00
|
|
|
|
2026-01-17 11:11:21 +00:00
|
|
|
|
2026-01-16 21:40:28 +00:00
|
|
|
## Override set_highlight to add visual feedback for sticky notes
|
|
|
|
|
func set_highlight(value: bool) -> void:
|
|
|
|
|
if value != _highlighted:
|
|
|
|
|
_highlighted = value
|
|
|
|
|
|
2026-01-18 09:48:03 +00:00
|
|
|
if modulate_tween: modulate_tween.kill()
|
|
|
|
|
if shift_tween: shift_tween.kill()
|
|
|
|
|
|
|
|
|
|
if _highlighted:
|
|
|
|
|
modulate_tween = create_tween()
|
|
|
|
|
modulate_tween.tween_property(self, "modulate", highlight_color, 0.1)
|
|
|
|
|
shift_tween = create_tween()
|
|
|
|
|
shift_tween.tween_property(content, "position", shift_by, 0.2)
|
2026-01-16 21:40:28 +00:00
|
|
|
else:
|
2026-01-18 09:48:03 +00:00
|
|
|
modulate_tween = create_tween()
|
|
|
|
|
modulate_tween.tween_property(self, "modulate", Color(1, 1, 1), 0.3)
|
|
|
|
|
shift_tween = create_tween()
|
|
|
|
|
shift_tween.tween_property(content, "position", Vector2.ZERO, 0.5)
|
2023-06-28 13:27:05 +00:00
|
|
|
|
2023-04-19 16:53:24 +00:00
|
|
|
@export var voice_line: AudioStream = null
|
2026-01-21 20:38:31 +00:00
|
|
|
@export var is_draggable: bool = false
|
2023-07-14 19:36:20 +00:00
|
|
|
|
2026-01-16 16:08:48 +00:00
|
|
|
var mouse_offset: Vector2
|
2023-04-19 16:53:24 +00:00
|
|
|
|
2026-01-11 21:09:19 +00:00
|
|
|
@onready var diameter := 312.0
|
2023-07-18 13:54:34 +00:00
|
|
|
@export_range(1.0, 10.0) var bounce_speed: float = 8
|
2026-01-16 23:31:01 +00:00
|
|
|
|
2025-02-24 15:14:08 +00:00
|
|
|
|
2026-01-11 21:47:56 +00:00
|
|
|
func init(sticky_name: String = "sticky_note", card_id: StringName = "-1") -> void:
|
2025-05-16 21:50:19 +00:00
|
|
|
name = sticky_name
|
2025-04-07 15:26:06 +00:00
|
|
|
text = sticky_name
|
2025-05-30 14:10:44 +00:00
|
|
|
parent_id = StringName(card_id.rsplit(".", false, 1)[0])
|
|
|
|
|
sticky_id = card_id
|
2025-04-07 15:26:06 +00:00
|
|
|
|
2023-04-19 16:53:24 +00:00
|
|
|
func _ready() -> void:
|
2026-01-18 09:48:03 +00:00
|
|
|
super._ready()
|
2026-01-11 21:09:19 +00:00
|
|
|
label = $Content/Label
|
|
|
|
|
background_sprite = $Content/BackgroundSprite
|
|
|
|
|
content = $Content
|
2026-01-16 15:30:58 +00:00
|
|
|
|
2026-01-11 20:42:06 +00:00
|
|
|
_on_text_updated.call_deferred()
|
2026-01-16 15:30:58 +00:00
|
|
|
|
2025-04-13 17:07:31 +00:00
|
|
|
|
|
|
|
|
func _on_text_updated():
|
|
|
|
|
label.text = text
|
|
|
|
|
background_sprite.frame = text.hash() % background_sprite.sprite_frames.get_frame_count(background_sprite.animation)
|
2023-04-19 16:53:24 +00:00
|
|
|
|
2023-05-28 13:21:19 +00:00
|
|
|
|
2026-01-21 20:38:31 +00:00
|
|
|
func _process(_delta: float) -> void:
|
2024-09-15 09:30:31 +00:00
|
|
|
if is_dragged:
|
2026-01-16 19:46:16 +00:00
|
|
|
update_drag_position(get_viewport().get_mouse_position())
|
2023-11-01 22:19:47 +00:00
|
|
|
|
2026-01-16 19:46:16 +00:00
|
|
|
|
|
|
|
|
# === DRAG LIFECYCLE OVERRIDES ===
|
|
|
|
|
|
2026-01-21 20:40:30 +00:00
|
|
|
## End drag operation and return the node we were dropped on
|
2026-01-18 09:48:03 +00:00
|
|
|
func end_drag() -> Node:
|
|
|
|
|
super.end_drag()
|
|
|
|
|
return _find_drop_target()
|
2026-01-17 11:11:21 +00:00
|
|
|
|
2026-01-16 19:46:16 +00:00
|
|
|
|
|
|
|
|
## Find best drop target: Card > Panel > Board (in priority order)
|
2026-01-18 09:48:03 +00:00
|
|
|
func _find_drop_target() -> Node:
|
2026-01-16 19:46:16 +00:00
|
|
|
# Priority 1: Check for overlapping cards in dropzone
|
2026-01-18 09:48:03 +00:00
|
|
|
var closest : Card = null
|
2026-01-16 19:46:16 +00:00
|
|
|
for area in get_overlapping_areas():
|
2026-01-18 09:48:03 +00:00
|
|
|
if area is StickyNote and not area.is_attached: continue # Can only drop on attached stickies
|
|
|
|
|
|
|
|
|
|
if area is Card:
|
2026-01-18 16:32:31 +00:00
|
|
|
if (not closest) or ((area.position - position).length() < (closest.position - position).length()):
|
2026-01-18 09:48:03 +00:00
|
|
|
closest = area
|
|
|
|
|
|
2026-01-18 16:52:04 +00:00
|
|
|
return closest
|
2026-01-16 19:46:16 +00:00
|
|
|
|
2026-01-17 11:11:21 +00:00
|
|
|
|
2026-01-21 20:40:30 +00:00
|
|
|
## Sticky notes are exempt from confinement if stuck to a card
|
2026-01-17 11:11:21 +00:00
|
|
|
func confine_to_screen() -> void:
|
|
|
|
|
if attached_to is not Card: super.confine_to_screen()
|