Workbench bill editor — tap a workbench, see/edit bills
Tap-to-select chain extended to workbenches (pawn always wins on shared tile). Mutually exclusive with pawn selection via EventBus — selecting one clears the other. New WorkbenchPanel (scenes/ui/workbench_panel.gd, ~432 LOC, layer 18, right-anchored 360 px) mirrors PawnDetailPanel shape. Bill rows expose recipe name, mode (FOREVER / COUNT / UNTIL_N), target count, completed progress, pause, and remove. Add-bill popup filters RecipeCatalog.all() by accepted_skill so a Hearth only offers cooking recipes. Supporting plumbing: - EventBus.workbench_selected / workbench_deselected signals. - Workbench.remove_bill() — interrupts mid-craft cleanly via on_craft_interrupted() before erasing. - RecipeCatalog.all() static enumerator + Recipe.display_name() helper. - World.workbench_at_tile() lookup. - i18n keys ui.bill.* and ui.workbench.* in strings.gd. Closes the deferred Phase 17 "Bill UI for workbenches" item. Player- built workbenches are now functionally configurable; before this landed, only world.gd-hardcoded bills worked.
This commit is contained in:
parent
e5f3693ad9
commit
bdd435202d
9 changed files with 551 additions and 10 deletions
|
|
@ -14,6 +14,9 @@ const CLICK_MAX_DURATION_MS: int = 300
|
|||
|
||||
var _pathfinder: Pathfinder = null
|
||||
var _selected_pawn: Pawn = null
|
||||
## Currently selected workbench, or null. Mutually exclusive with _selected_pawn —
|
||||
## selecting one clears the other (see _select / _select_workbench).
|
||||
var _selected_workbench: Workbench = null
|
||||
var _camera = null # Camera2D (CameraRig) — set via bind_camera(); duck-typed to avoid circular preload
|
||||
|
||||
# When Designation paint mode is active this flag is raised by Designation so
|
||||
|
|
@ -62,23 +65,32 @@ func _unhandled_input(event: InputEvent) -> void:
|
|||
# ── Keyboard: Escape → deselect (lowest-priority; consumed last) ─────────────
|
||||
# Designation._input handles Escape first; panels handle it in _unhandled_input
|
||||
# before reaching here. If we still see it and have a selection, consume it.
|
||||
if event.is_action_pressed("cancel") and _selected_pawn != null:
|
||||
_deselect()
|
||||
get_viewport().set_input_as_handled()
|
||||
Audit.log("selection", "escape: deselected")
|
||||
return
|
||||
if event.is_action_pressed("cancel"):
|
||||
if _selected_pawn != null:
|
||||
_deselect()
|
||||
get_viewport().set_input_as_handled()
|
||||
Audit.log("selection", "escape: deselected pawn")
|
||||
return
|
||||
if _selected_workbench != null:
|
||||
_deselect_workbench()
|
||||
get_viewport().set_input_as_handled()
|
||||
Audit.log("selection", "escape: deselected workbench")
|
||||
return
|
||||
|
||||
# ── Mouse: only handle button events below ───────────────────────────────────
|
||||
if not (event is InputEventMouseButton):
|
||||
return
|
||||
|
||||
# ── Right-click: cancel designation (if active) or deselect pawn ─────────────
|
||||
# ── Right-click: cancel designation (if active) or deselect pawn / workbench ──
|
||||
if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
|
||||
# Designation cancellation is handled by Designation._input; if we see
|
||||
# this right-click, no designation was active. Deselect any selected pawn.
|
||||
# this right-click, no designation was active. Deselect whatever is selected.
|
||||
if _selected_pawn != null:
|
||||
_deselect()
|
||||
get_viewport().set_input_as_handled()
|
||||
elif _selected_workbench != null:
|
||||
_deselect_workbench()
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
|
||||
if event.button_index != MOUSE_BUTTON_LEFT:
|
||||
|
|
@ -114,14 +126,23 @@ func _handle_click(screen_pos: Vector2) -> void:
|
|||
floori(world_pos.y / float(Pawn.TILE_SIZE_PX)),
|
||||
)
|
||||
|
||||
# Click on a pawn → select.
|
||||
# Click on a pawn → select. Pawn wins over workbench when they share a tile
|
||||
# (a pawn working at a bench is selectable; tap empty bench tile to inspect bills).
|
||||
var hit_pawn: Pawn = World.pawn_at_tile(tile)
|
||||
if hit_pawn != null:
|
||||
_select(hit_pawn)
|
||||
return
|
||||
|
||||
# Empty tile with no current selection → no-op.
|
||||
# Click on a workbench → open the bill-editor panel.
|
||||
var hit_workbench = World.workbench_at_tile(tile)
|
||||
if hit_workbench != null:
|
||||
_select_workbench(hit_workbench)
|
||||
return
|
||||
|
||||
# Empty tile with no current pawn selection → also clear any workbench selection.
|
||||
if _selected_pawn == null:
|
||||
if _selected_workbench != null:
|
||||
_deselect_workbench()
|
||||
return
|
||||
|
||||
# Empty walkable tile with a selection → queue a forced job. Decision picks
|
||||
|
|
@ -140,6 +161,9 @@ func _handle_click(screen_pos: Vector2) -> void:
|
|||
func _select(pawn: Pawn) -> void:
|
||||
if _selected_pawn == pawn:
|
||||
return
|
||||
# Mutual exclusion with workbench selection: clear it before promoting pawn.
|
||||
if _selected_workbench != null:
|
||||
_deselect_workbench()
|
||||
if _selected_pawn != null:
|
||||
_selected_pawn.set_selected(false)
|
||||
EventBus.pawn_deselected.emit()
|
||||
|
|
@ -159,6 +183,28 @@ func _deselect() -> void:
|
|||
_selected_pawn = null
|
||||
|
||||
|
||||
## Select a workbench → opens the bill-editor panel via EventBus.
|
||||
## Mutually exclusive with pawn selection: clears _selected_pawn first.
|
||||
func _select_workbench(wb) -> void:
|
||||
if _selected_workbench == wb:
|
||||
return
|
||||
if _selected_pawn != null:
|
||||
_deselect()
|
||||
if _selected_workbench != null:
|
||||
EventBus.workbench_deselected.emit()
|
||||
_selected_workbench = wb
|
||||
EventBus.workbench_selected.emit(wb)
|
||||
Audit.log("selection", "selected workbench %s at %s" % [wb.label_text, wb.tile])
|
||||
|
||||
|
||||
func _deselect_workbench() -> void:
|
||||
if _selected_workbench == null:
|
||||
return
|
||||
Audit.log("selection", "deselected workbench %s" % _selected_workbench.label_text)
|
||||
_selected_workbench = null
|
||||
EventBus.workbench_deselected.emit()
|
||||
|
||||
|
||||
## Cycle the selection forward (dir=1) or backward (dir=-1) through World.pawns.
|
||||
## Wraps around. If no pawn currently selected, picks World.pawns[0].
|
||||
## Pans the camera to the newly selected pawn's tile.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue