Refactor multi-resource UI and transfers

This commit is contained in:
Loïc Wisniewski 2026-08-14 11:54:31 +02:00
commit 8231e165ff
20 changed files with 648 additions and 435 deletions

View file

@ -1,8 +1,7 @@
extends Node2D
# Preview, not a test. The resource readouts with the fleet carrying ore, so
# the #15 banked-vs-carried split can actually be looked at - headless draws
# no pixels and cannot say whether two numbers read as two different things.
# Preview, not a test. Both banked resources and both fleet-held resources
# are populated so the complete two-column HUD can be inspected.
#
# bash tests/screenshot.sh res://tests/_cargo_readout_preview.tscn /tmp/hud.png 20 720x1280
@ -11,5 +10,7 @@ func _ready() -> void:
GameState.buildings.clear()
GameState.extractors.clear()
GameState.rocks = 128
GameState.gas = 46
GameState.fleet_cargo = 34
GameState.fleet_gas_cargo = 17
add_child(load("res://Main.tscn").instantiate())

View file

@ -13,13 +13,16 @@ func _ready() -> void:
GameState.extractors.clear()
GameState.transporters.clear()
GameState.rocks = 180
GameState.gas = 36
GameState.fleet_cargo = 24
GameState.fleet_gas_cargo = 12
GameState.unlocked = ["shipyards", "logistics", "freight"]
var main: Node = load("res://Main.tscn").instantiate()
add_child(main)
main.get_node("BuildingField").place(GameState.BUILDING_SHIP_CRAFTER, Vector2(400.0, 0.0))
var crafter_id: int = int(GameState.buildings[-1].id)
GameState.deposit_to_building(crafter_id, 42)
GameState.find_building(crafter_id).gas_stock = 18
var bc: Node = main.get_node("BuildController")
bc.craft_building_id = crafter_id
# The shared header (#24) is the thing worth eyeballing here, so give it

View file

@ -0,0 +1,14 @@
extends Node2D
func _ready() -> void:
GameState.planet_name = "Violet Tempest"
GameState.planet_type = "gas_giant"
GameState.surviving_ship_count = 3
GameState.rocks = 128
GameState.gas = 46
GameState.fleet_cargo = 34
GameState.fleet_gas_cargo = 17
var surface: Node = load("res://PlanetSurface.tscn").instantiate()
surface.get_node("SurfaceController").fade_duration = 0.0
add_child(surface)

View file

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://tests/_gas_surface_preview.gd" id="1"]
[node name="GasSurfacePreview" type="Node2D"]
script = ExtResource("1")

View file

@ -13,7 +13,9 @@ func _ready() -> void:
GameState.extractors.clear()
GameState.transporters.clear()
GameState.rocks = 180
GameState.gas = 36
GameState.fleet_cargo = 24
GameState.fleet_gas_cargo = 12
GameState.unlocked = ["shipyards", "logistics", "freight"]
var main: Node = load("res://Main.tscn").instantiate()
add_child(main)

View file

@ -28,18 +28,15 @@ WAIT_FRAMES="${3:-60}"
RESOLUTION="${4:-1280x720}"
proot-distro login ubuntu -- bash -c "
# A killed run (or a session that ended mid-screenshot) leaves /tmp/.X99-lock
# behind, and Xvfb then refuses to claim :99 - which surfaces much later and
# far less obviously as Godot's 'X11 Display is not available'. Nothing else
# uses :99 here, so a lock with no live Xvfb behind it is always stale.
if ! pgrep -x Xvfb >/dev/null; then
rm -f /tmp/.X99-lock /tmp/.X11-unix/X99
fi
# Display :99 is dedicated to this helper. Clear both a live process left by
# an interrupted capture and its lock/socket before claiming it again.
pkill -x Xvfb >/dev/null 2>&1 || true
rm -f /tmp/.X99-lock /tmp/.X11-unix/X99
Xvfb :99 -screen 0 ${RESOLUTION}x24 &
XVFB_PID=\$!
trap 'kill \$XVFB_PID >/dev/null 2>&1 || true' EXIT
sleep 2
mkdir -p /tmp/xdgrt && chmod 700 /tmp/xdgrt
cd '$PROJECT_DIR'
DISPLAY=:99 XDG_RUNTIME_DIR=/tmp/xdgrt GALLIUM_DRIVER=softpipe '$GODOT_BIN' --rendering-driver opengl3 --rendering-method gl_compatibility --resolution '$RESOLUTION' -s res://tests/_screenshot_tool.gd -- '$SCENE_PATH' '$OUTPUT_PATH' '$WAIT_FRAMES'
kill \$XVFB_PID
DISPLAY=:99 XDG_RUNTIME_DIR=/tmp/xdgrt GALLIUM_DRIVER=softpipe '$GODOT_BIN' --audio-driver Dummy --rendering-driver opengl3 --rendering-method gl_compatibility --resolution '$RESOLUTION' -s res://tests/_screenshot_tool.gd -- '$SCENE_PATH' '$OUTPUT_PATH' '$WAIT_FRAMES'
"

View file

@ -96,7 +96,10 @@ func _process(delta: float) -> bool:
print("TEST_CRAFTER_FEEDBACK: FAIL (fleet parked on the crafter never registered)")
quit(1)
return true
# A crafter now has both Craft and Transfer, so the shared action
# button unfolds those choices before the craft action is selected.
_tap(controller.action_button)
_tap(controller.building_action_button)
if not controller.craft_menu.visible:
print("TEST_CRAFTER_FEEDBACK: FAIL (the action button did not open the crafter panel)")
quit(1)

View file

@ -162,8 +162,11 @@ func _process(delta: float) -> bool:
stage = 6
return false
6:
# Long enough for the build itself, which #23 made take time.
if elapsed < game_state.build_time(GameState.PRODUCT_SHIP) * 3.0:
# Long enough for both construction and the physical delivery trip
# from this remote crafter to the mothership hangar.
var delivery_time: float = CRAFTER_AT.distance_to(MOTHERSHIP_AT) \
/ GameState.VESSEL_DELIVERY_SPEED
if elapsed < game_state.build_time(GameState.PRODUCT_SHIP) * 3.0 + delivery_time + 0.5:
return false
# --- 5. the queued order completed off the fleet's own ore ---
if game_state.pending_orders(crafter_id) != 0:

View file

@ -180,7 +180,7 @@ func _process(delta: float) -> bool:
# The handler working while the BUTTON is inert is the exact bug
# class this project keeps hitting, so one press goes the long way.
var bank_at_tap: int = game_state.rocks
_tap(scene.get_node("UI/TransferMenu/ToFleetAllButton"))
_tap(scene.get_node("UI/TransferMenu/ResourceList/OreToFleetButton"))
_expect(game_state.fleet_cargo == bank_at_tap,
"a real tap did not load all banked ore")
_expect(game_state.rocks == 0,