sprint A cleanup: accessibility, signals, race, debris
G: large_text scales global theme font (14→20 at 1.4×) via new GameState.get_font_scale + EventBus.settings_changed. reduce_motion gates ResumeToast fade (HintOverlay already gated). I: InspectTooltip long-press wired (500ms hold, 12px drift cancel, tap-to-clear pin). Stale Phase 19 TODO replaced with accurate doc. H: Pawn.arrived_at_destination now also emitted on EventBus.pawn_arrived_at_destination; DirtinessSystem subscribes and bumps indoor traffic dirt (BUMP_INDOOR_TRAFFIC = 0.2). Outdoor-tracked bump needs Pawn.prev_tile — flagged for Phase 20. P: CraftingProvider caches ingredient item ref on Job.ingredient_item; JobRunner._tick_pickup validates is_instance_valid + not being_carried before the tile scan, cancels cleanly if another pawn grabbed it. J: rest_provider.gd deleted. Removed @onready + register call from world.gd, ext_resource + node from world.tscn. Provider count comment updated to 9. M: DIRTY_THRESHOLD extracted — cleaning_provider and job_runner now reference DirtinessSystem.DIRT_DIRTY_THRESHOLD. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2f76ae1639
commit
fd6f958344
15 changed files with 157 additions and 62 deletions
|
|
@ -1,24 +1,34 @@
|
|||
extends CanvasLayer
|
||||
## InspectTooltip — hover (or long-press) on a world tile to see what's there.
|
||||
## InspectTooltip — hover (mouse) or long-press (touch) on a world tile to see
|
||||
## what's there.
|
||||
##
|
||||
## Samples the mouse position every frame, maps to a tile, looks for an entity
|
||||
## or zone at that tile, builds a short description, and renders a small panel
|
||||
## offset from the cursor. Empty tile or off-map → tooltip hides.
|
||||
## Mouse path: samples position every frame, maps to a tile, builds a short
|
||||
## description, renders a small panel offset from the cursor.
|
||||
## Empty tile or off-map → tooltip hides.
|
||||
##
|
||||
## Touch fallback: long-press on a tile triggers the same lookup and pins the
|
||||
## tooltip until the next click anywhere (Phase 17 long-press inspect from the
|
||||
## design doc). Desktop hovering is the primary path on PC; the long-press
|
||||
## path is wired via Selection's long-press detector (TODO Phase 19).
|
||||
## Touch path: finger held for LONG_PRESS_MS without drifting more than
|
||||
## LONG_PRESS_DRIFT_PX pins the tooltip at the held tile until the next tap
|
||||
## anywhere. Touch-down cancels a previous pin. This self-contained path does
|
||||
## not depend on Selection; it reads the same tile + description helpers.
|
||||
|
||||
const TILE_SIZE_PX: int = 16
|
||||
const CURSOR_OFFSET: Vector2 = Vector2(14, 14)
|
||||
const EDGE_MARGIN_PX: int = 8
|
||||
const LONG_PRESS_MS: int = 500 # ms finger must be held to trigger inspect
|
||||
const LONG_PRESS_DRIFT_PX: float = 12.0 # cancel long-press if finger moves more than this
|
||||
|
||||
var _panel: PanelContainer = null
|
||||
var _label: RichTextLabel = null
|
||||
var _last_tile: Vector2i = Vector2i(-9999, -9999)
|
||||
var _last_text: String = ""
|
||||
|
||||
# Touch long-press state.
|
||||
var _touch_pressing: bool = false
|
||||
var _touch_screen_pos: Vector2 = Vector2.ZERO
|
||||
var _touch_start_ms: int = 0
|
||||
var _touch_pinned: bool = false # true while a long-press pin is held open
|
||||
var _touch_pin_tile: Vector2i = Vector2i(-9999, -9999)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
layer = 50 # below modals (which are 100+), above world
|
||||
|
|
@ -58,10 +68,65 @@ func _ready() -> void:
|
|||
_panel.add_child(_label)
|
||||
|
||||
|
||||
## Touch-input handler for long-press inspect.
|
||||
## InputEventScreenTouch press starts the long-press clock; release or excess
|
||||
## drift cancels it. A subsequent tap anywhere while pinned dismisses the panel.
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventScreenTouch:
|
||||
if event.pressed:
|
||||
if _touch_pinned:
|
||||
# A new tap clears the pin.
|
||||
_touch_pinned = false
|
||||
_panel.visible = false
|
||||
_last_text = ""
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
_touch_pressing = true
|
||||
_touch_screen_pos = event.position
|
||||
_touch_start_ms = Time.get_ticks_msec()
|
||||
else:
|
||||
# Finger lifted — cancel the pending long-press (pin only fires from _process).
|
||||
_touch_pressing = false
|
||||
elif event is InputEventScreenDrag and _touch_pressing:
|
||||
var drift: float = event.position.distance_to(_touch_screen_pos)
|
||||
if drift > LONG_PRESS_DRIFT_PX:
|
||||
_touch_pressing = false
|
||||
|
||||
|
||||
func _process(_dt: float) -> void:
|
||||
var vp := get_viewport()
|
||||
if vp == null:
|
||||
return
|
||||
|
||||
# ── Touch long-press poll ─────────────────────────────────────────────────
|
||||
if _touch_pressing and not _touch_pinned:
|
||||
var held_ms: int = Time.get_ticks_msec() - _touch_start_ms
|
||||
if held_ms >= LONG_PRESS_MS:
|
||||
_touch_pressing = false
|
||||
_touch_pinned = true
|
||||
# Describe tile under held finger.
|
||||
var world_touch: Vector2 = vp.get_canvas_transform().affine_inverse() * _touch_screen_pos
|
||||
_touch_pin_tile = Vector2i(
|
||||
floori(world_touch.x / float(TILE_SIZE_PX)),
|
||||
floori(world_touch.y / float(TILE_SIZE_PX)),
|
||||
)
|
||||
if _tile_in_map(_touch_pin_tile):
|
||||
var pin_text: String = _describe_tile(_touch_pin_tile)
|
||||
if pin_text != "":
|
||||
_label.text = pin_text
|
||||
_last_text = pin_text
|
||||
_panel.reset_size()
|
||||
_panel.visible = true
|
||||
_position_near(_touch_screen_pos)
|
||||
return
|
||||
# Nothing to show — cancel pin.
|
||||
_touch_pinned = false
|
||||
|
||||
# Pinned: keep the panel up; skip the mouse-hover update.
|
||||
if _touch_pinned:
|
||||
return
|
||||
|
||||
# ── Mouse hover path ──────────────────────────────────────────────────────
|
||||
var mouse_screen: Vector2 = vp.get_mouse_position()
|
||||
# Convert screen → world via canvas transform (selection.gd does the same).
|
||||
var world_pos: Vector2 = vp.get_canvas_transform().affine_inverse() * mouse_screen
|
||||
|
|
|
|||
|
|
@ -97,6 +97,11 @@ func _on_load_finished(_slot: StringName, ok: bool, real_seconds_away: int) -> v
|
|||
|
||||
|
||||
func _start_fade() -> void:
|
||||
if bool(GameState.settings.get("accessibility_reduce_motion", false)):
|
||||
# Snap to hidden immediately — no fade animation.
|
||||
_root.visible = false
|
||||
_root.modulate = Color.WHITE
|
||||
return
|
||||
_fading = true
|
||||
_fade_time = FADE_DURATION_SEC
|
||||
|
||||
|
|
|
|||
|
|
@ -302,6 +302,7 @@ func _unhandled_input(event: InputEvent) -> void:
|
|||
|
||||
func _on_save_pressed() -> void:
|
||||
GameState.apply_settings(_collect_to_dict())
|
||||
EventBus.settings_changed.emit()
|
||||
Audit.log("settings_menu", "settings saved")
|
||||
_set_visible(false)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue