Files
DartGame/game/core/ui/modifier_tray.gd
T

100 lines
2.4 KiB
GDScript

extends Control
## Spawns draggable modifier pieces along the bottom of the screen.
##
## For now it spawns ALL modifiers in the registry, one of each, and they never
## run out. That's a debug affordance — the real economy (random draws, rounds,
## consumption) is a later phase. Right now we just want to prove drag-and-drop
## works.
@export var drop_catcher: Control
@export_group("Layout")
@export var piece_size := Vector2(90, 110)
@export var spacing := 24.0
@export var bottom_margin := 30.0
@export_group("Behaviour")
## If false, pieces stay in the tray after a successful drop. Useful while
## testing; set true when the real economy lands.
@export var consume_on_use := false
const SectorSwatch := preload("res://core/ui/sector_swatch.gd")
var _pieces: Array[Control] = []
func _ready() -> void:
# The tray itself must not eat mouse events — only its pieces should.
mouse_filter = Control.MOUSE_FILTER_IGNORE
if drop_catcher == null:
push_error("ModifierTray: `drop_catcher` export is not set.")
return
spawn_all()
## Spawn one piece per registered modifier.
func spawn_all() -> void:
_clear_pieces()
var mods: Array[Modifier] = ModRegistry.modifiers
if mods.is_empty():
push_warning("ModifierTray: registry has no modifiers. Nothing to spawn.")
return
for mod in mods:
_spawn_piece(mod)
_layout()
func _spawn_piece(mod: Modifier) -> void:
var piece := Control.new()
piece.set_script(SectorSwatch)
piece.custom_minimum_size = piece_size
piece.size = piece_size
piece.modifier = mod
piece.paint_texture = mod.texture
piece.drop_catcher = drop_catcher
piece.tray = self
add_child(piece)
_pieces.append(piece)
func _layout() -> void:
var count := _pieces.size()
if count == 0:
return
var total_w := count * piece_size.x + (count - 1) * spacing
var screen := get_viewport_rect().size
var start_x := (screen.x - total_w) * 0.5
var y := screen.y - piece_size.y - bottom_margin
for i in count:
_pieces[i].position = Vector2(start_x + i * (piece_size.x + spacing), y)
## Called by a piece after a successful drop.
func on_piece_used(piece: Control) -> void:
if not consume_on_use:
return # piece snaps home; it's reusable
_pieces.erase(piece)
piece.queue_free()
_layout()
func _clear_pieces() -> void:
for p in _pieces:
if is_instance_valid(p):
p.queue_free()
_pieces.clear()
func _notification(what: int) -> void:
if what == NOTIFICATION_RESIZED:
_layout()