126 lines
4.1 KiB
GDScript
126 lines
4.1 KiB
GDScript
class_name StickyNotePanel
|
|
extends Panel
|
|
|
|
var minimum_size:Vector2 = Vector2(400, 100):
|
|
set(size):
|
|
minimum_size = size
|
|
custom_minimum_size = size
|
|
var attached_sticky_note: StickyNote
|
|
var ancor_position: Vector2
|
|
|
|
func _init(cstm_minimum_size: Vector2 = minimum_size, note_position: Vector2 = Vector2(105, 57)) -> void:
|
|
minimum_size = cstm_minimum_size
|
|
ancor_position = note_position
|
|
mouse_filter = MOUSE_FILTER_PASS
|
|
self_modulate = Color(1, 1, 1, 0)
|
|
|
|
func _ready():
|
|
custom_minimum_size = Vector2(custom_minimum_size.x, 0)
|
|
|
|
var is_attatching: bool = false
|
|
func attatch_sticky_note(attatchment: StickyNote, custom_owner: Node, animate:bool = true):
|
|
is_attatching = true
|
|
attached_sticky_note = attatchment
|
|
attatchment.current_handle = custom_owner
|
|
attatchment.owner = custom_owner
|
|
|
|
# Expand panel height
|
|
if animate:
|
|
var height_tween: Tween = create_tween()
|
|
height_tween.tween_property(self, "custom_minimum_size", minimum_size, 0.1)
|
|
else:
|
|
custom_minimum_size = minimum_size
|
|
|
|
# Position sticky
|
|
if animate:
|
|
await get_tree().process_frame
|
|
attatchment.on_board = false
|
|
attatchment.z_index = 125 # On top during animation
|
|
|
|
# Reparent while keeping world position for smooth animation
|
|
attatchment.reparent(self, true)
|
|
attatchment.attached_to = self
|
|
|
|
# Tween to anchor position in panel's coordinate space
|
|
var tween := create_tween().set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_BACK)
|
|
tween.tween_property(attatchment, "position", ancor_position, 0.7)
|
|
tween.tween_property(attatchment, "rotation", 0.0, 0.7)
|
|
tween.parallel().tween_property(attatchment, "scale", Vector2.ONE, 0.7)
|
|
await tween.finished
|
|
|
|
attatchment.z_index = 0
|
|
else:
|
|
# Immediate placement (for initial board setup)
|
|
if attatchment.get_parent():
|
|
attatchment.reparent(self)
|
|
else:
|
|
add_child(attatchment)
|
|
attatchment.on_board = false
|
|
attatchment.attached_to = self
|
|
attatchment.position = ancor_position
|
|
attatchment.rotation = 0.0
|
|
attatchment.scale = Vector2.ONE
|
|
|
|
is_attatching = false
|
|
|
|
|
|
var is_gapped: bool = false
|
|
func create_gap():
|
|
var self_id := get_parent().get_children().find(self)
|
|
var next_id = min(self_id + 1, get_parent().get_child_count() - 1)
|
|
var previous_id = max(self_id - 1, 0)
|
|
|
|
if not (is_gapped or get_parent().get_child(next_id).attached_sticky_note.is_dragged or get_parent().get_child(previous_id).attached_sticky_note.is_dragged) and owner.current_context == CardBoard.DRAG:
|
|
is_gapped = true
|
|
var height_tween: Tween = create_tween()
|
|
height_tween.tween_property(self, "custom_minimum_size", minimum_size*Vector2(1.0, 1.8), 0.1)
|
|
|
|
get_parent().get_child(next_id).collapse_gap()
|
|
if not get_parent().get_children().find(self) == 0: get_parent().get_child(previous_id).collapse_gap()
|
|
|
|
func collapse_gap():
|
|
if is_gapped:
|
|
is_gapped = false
|
|
var height_tween: Tween = create_tween()
|
|
height_tween.tween_property(self, "custom_minimum_size", minimum_size, 0.1)
|
|
|
|
var invalid: bool = false
|
|
func clear_if_empty():
|
|
if !is_empty(): return
|
|
invalid = true
|
|
if attached_sticky_note.attached_to == self: attached_sticky_note.attached_to = null
|
|
var height_tween: Tween = create_tween()
|
|
height_tween.tween_property(self, "custom_minimum_size", Vector2.ZERO, 0.3)
|
|
await height_tween.finished
|
|
owner.on_sticky_panel_cleared(get_parent().get_children().find(self))
|
|
self.queue_free()
|
|
|
|
func replace_sticky_note_with(new_sticky_note: StickyNote):
|
|
if is_empty():
|
|
attached_sticky_note = new_sticky_note
|
|
|
|
func is_empty() -> bool:
|
|
return get_child_count() == 0 and not is_attatching
|
|
|
|
|
|
# === DROP TARGET PATTERN IMPLEMENTATION ===
|
|
|
|
## Checks if this panel can accept the given draggable
|
|
func can_accept_drop(draggable: Draggable) -> bool:
|
|
return draggable is StickyNote and is_empty()
|
|
|
|
## Handles dropping a sticky note onto this panel
|
|
func handle_drop(draggable: StickyNote) -> int:
|
|
if not can_accept_drop(draggable):
|
|
return Draggable.DropResult.REJECTED
|
|
|
|
# Attach sticky to this panel with animation
|
|
attatch_sticky_note(draggable, owner, true)
|
|
|
|
# Clean up other empty panels
|
|
for panel in get_parent().get_children():
|
|
if panel is StickyNotePanel and panel != self:
|
|
panel.clear_if_empty()
|
|
|
|
return Draggable.DropResult.ACCEPTED
|