DISPLAY_RATIO_DEEP 1.0 -> 2.0, so a viewport-fit request at District/ Quarter/Block/Chunk asks for ~4x fewer gridunits (1920x1080: ~2.07M cells -> ~518K) and the server-side derive cost falls with it. Texel- exactness is preserved — the ratio stays a whole number of screen px per gridunit, so every source texel still lands on whole pixels; only the block size changes. Non-integer ratios are not an option here: they reintroduce exactly the sub-pixel blur D-255's texel-exactness exists to prevent. Judged live by Jeroen against the 1x1 build (pair session): the deep rungs read as crisp larger pixels rather than blur, and the speedup is substantial. Looks were the gate. Both transport tests that pinned the old literal now assert the RELATIONSHIP instead — deep rungs share the constant, viewport-fit divides by it — plus a new guard that the ratio stays whole, so the value remains tunable without editing tests that are not about it. Co-Authored-By: Claude <noreply@anthropic.com>
452 lines
20 KiB
GDScript
452 lines
20 KiB
GDScript
## T-1182 tests: step_canvas_transport.gd — the D-255(a) six-rung stepped
|
|
## transport state machine (rung ladder, cursor-anchored step math,
|
|
## viewport-fit extent, world<->canvas-local projection). All pure
|
|
## functions, no scene tree needed.
|
|
class_name TestStepCanvasTransport
|
|
extends GdUnitTestSuite
|
|
|
|
const StepCanvasTransport := preload("res://ui/implant/apps/atlas/step_canvas/step_canvas_transport.gd")
|
|
|
|
|
|
# =============================================================================
|
|
# Rung ladder — index <-> name, scroll clamping
|
|
# =============================================================================
|
|
|
|
|
|
func test_rung_at_index_zero_is_global() -> void:
|
|
assert_str(StepCanvasTransport.rung_at_index(0)).is_equal(StepCanvasTransport.RUNG_GLOBAL)
|
|
|
|
|
|
func test_rung_at_index_five_is_chunk_the_deepest() -> void:
|
|
assert_str(StepCanvasTransport.rung_at_index(5)).is_equal(StepCanvasTransport.RUNG_CHUNK)
|
|
|
|
|
|
func test_rung_at_index_clamps_out_of_range_indices() -> void:
|
|
assert_str(StepCanvasTransport.rung_at_index(-3)).is_equal(StepCanvasTransport.RUNG_GLOBAL)
|
|
assert_str(StepCanvasTransport.rung_at_index(99)).is_equal(StepCanvasTransport.RUNG_CHUNK)
|
|
|
|
|
|
func test_index_for_rung_round_trips_every_ladder_entry() -> void:
|
|
for i in range(StepCanvasTransport.RUNG_LADDER.size()):
|
|
var rung: String = StepCanvasTransport.rung_at_index(i)
|
|
assert_int(StepCanvasTransport.index_for_rung(rung)).is_equal(i)
|
|
|
|
|
|
func test_index_for_rung_unrecognized_returns_negative_one() -> void:
|
|
assert_int(StepCanvasTransport.index_for_rung("Sector")).is_equal(-1)
|
|
|
|
|
|
func test_scroll_step_descends_one_notch_at_a_time() -> void:
|
|
assert_int(StepCanvasTransport.scroll_step(0, 1)).is_equal(1)
|
|
assert_int(StepCanvasTransport.scroll_step(2, 1)).is_equal(3)
|
|
|
|
|
|
func test_scroll_step_ascends_one_notch_at_a_time() -> void:
|
|
assert_int(StepCanvasTransport.scroll_step(3, -1)).is_equal(2)
|
|
|
|
|
|
func test_scroll_step_clamps_at_the_deepest_rung() -> void:
|
|
assert_int(StepCanvasTransport.scroll_step(5, 1)).is_equal(5)
|
|
|
|
|
|
func test_scroll_step_clamps_at_the_global_opener() -> void:
|
|
assert_int(StepCanvasTransport.scroll_step(0, -1)).is_equal(0)
|
|
|
|
|
|
func test_scroll_step_zero_direction_is_a_no_op() -> void:
|
|
assert_int(StepCanvasTransport.scroll_step(2, 0)).is_equal(2)
|
|
|
|
|
|
# =============================================================================
|
|
# D-243 gridunit spacing — pinned against the same metre values scale.rs uses
|
|
# =============================================================================
|
|
|
|
|
|
func test_spacing_for_rung_matches_d243_metre_values() -> void:
|
|
assert_float(StepCanvasTransport.spacing_for_rung("Global")).is_equal_approx(204_800.0, 0.01)
|
|
assert_float(StepCanvasTransport.spacing_for_rung("Region")).is_equal_approx(204_800.0, 0.01)
|
|
assert_float(StepCanvasTransport.spacing_for_rung("District")).is_equal_approx(2_048.0, 0.01)
|
|
assert_float(StepCanvasTransport.spacing_for_rung("Quarter")).is_equal_approx(512.0, 0.01)
|
|
assert_float(StepCanvasTransport.spacing_for_rung("Block")).is_equal_approx(128.0, 0.01)
|
|
assert_float(StepCanvasTransport.spacing_for_rung("Chunk")).is_equal_approx(64.0, 0.01)
|
|
|
|
|
|
# =============================================================================
|
|
# Display ratio — deep/mid 1x1, shallow ~5x5, PRESENTATION only (D-255(a))
|
|
# =============================================================================
|
|
|
|
|
|
## The four deep rungs share ONE display ratio, whatever its current value —
|
|
## asserting the relationship rather than the literal, so tuning
|
|
## DISPLAY_RATIO_DEEP (pair session 2026-07-26: 1.0 -> 2.0, the cost/looks
|
|
## experiment) doesn't require editing a test that isn't about the number.
|
|
## The value itself is a presentation tunable (D-255(a)); what must hold is
|
|
## that the deep rungs agree with each other and stay a texel-exact integer.
|
|
func test_display_ratio_deep_rungs_all_share_the_deep_ratio() -> void:
|
|
var deep: float = StepCanvasTransport.DISPLAY_RATIO_DEEP
|
|
for rung in ["District", "Quarter", "Block", "Chunk"]:
|
|
assert_float(StepCanvasTransport.display_ratio_for_rung(rung)).is_equal_approx(deep, 0.001)
|
|
assert_float(deep).override_failure_message(
|
|
"the deep display ratio must be a whole number of screen px per gridunit —"
|
|
+ " a fractional ratio reintroduces the sub-pixel blur D-255 texel-exactness prevents"
|
|
).is_equal_approx(floorf(deep), 0.0001)
|
|
assert_float(deep).is_greater(0.0)
|
|
|
|
|
|
func test_display_ratio_shallow_rungs_use_the_five_x_five_fallback() -> void:
|
|
for rung in ["Global", "Region"]:
|
|
assert_float(StepCanvasTransport.display_ratio_for_rung(rung)).is_equal_approx(5.0, 0.001)
|
|
|
|
|
|
func test_is_orbital_rung_true_only_for_global_and_region() -> void:
|
|
assert_bool(StepCanvasTransport.is_orbital_rung("Global")).is_true()
|
|
assert_bool(StepCanvasTransport.is_orbital_rung("Region")).is_true()
|
|
assert_bool(StepCanvasTransport.is_orbital_rung("District")).is_false()
|
|
assert_bool(StepCanvasTransport.is_orbital_rung("Chunk")).is_false()
|
|
|
|
|
|
# =============================================================================
|
|
# Viewport-fit extent — the client half of "viewport-sized canvas"
|
|
# =============================================================================
|
|
|
|
|
|
## A deep-rung request asks for viewport_px / DISPLAY_RATIO_DEEP gridunits —
|
|
## derived from the constant, not the literal, so the ratio stays tunable
|
|
## (see the deep-ratio test above). This IS the cost lever: doubling the
|
|
## ratio quarters the requested cell count.
|
|
func test_viewport_fit_extent_at_deep_ratio_divides_by_the_deep_ratio() -> void:
|
|
var deep: float = StepCanvasTransport.DISPLAY_RATIO_DEEP
|
|
var viewport := Vector2(800.0, 600.0)
|
|
var extent: Vector2i = StepCanvasTransport.viewport_fit_extent(viewport, "Chunk")
|
|
var expected := Vector2i(int(ceil(viewport.x / deep)), int(ceil(viewport.y / deep)))
|
|
assert_that(extent).is_equal(expected)
|
|
|
|
|
|
func test_viewport_fit_extent_at_shallow_ratio_divides_by_the_display_ratio() -> void:
|
|
var extent: Vector2i = StepCanvasTransport.viewport_fit_extent(Vector2(1000.0, 500.0), "Region")
|
|
assert_that(extent).is_equal(Vector2i(200, 100))
|
|
|
|
|
|
func test_viewport_fit_extent_clamps_to_the_fixed_canvas_max_axis() -> void:
|
|
var extent: Vector2i = StepCanvasTransport.viewport_fit_extent(
|
|
Vector2(20_000.0, 20_000.0), "Chunk"
|
|
)
|
|
assert_int(extent.x).is_equal(StepCanvasTransport.FIXED_CANVAS_MAX_AXIS)
|
|
assert_int(extent.y).is_equal(StepCanvasTransport.FIXED_CANVAS_MAX_AXIS)
|
|
|
|
|
|
func test_viewport_fit_extent_never_produces_a_zero_axis() -> void:
|
|
var extent: Vector2i = StepCanvasTransport.viewport_fit_extent(Vector2(0.0, 0.0), "Chunk")
|
|
assert_int(extent.x).is_greater_equal(1)
|
|
assert_int(extent.y).is_greater_equal(1)
|
|
|
|
|
|
# =============================================================================
|
|
# Gridunit snapping — cache-key stability for repeated "same spot" requests
|
|
# =============================================================================
|
|
|
|
|
|
func test_snap_to_gridunit_snaps_to_the_rungs_own_spacing() -> void:
|
|
var snapped: Vector2i = StepCanvasTransport.snap_to_gridunit(Vector2(2100.0, -1000.0), "District")
|
|
# District spacing = 2048 m: 2100 rounds to 1*2048=2048, -1000 rounds to 0.
|
|
assert_int(snapped.x).is_equal(2048)
|
|
assert_int(snapped.y).is_equal(0)
|
|
|
|
|
|
func test_snap_to_gridunit_is_idempotent_once_already_on_grid() -> void:
|
|
var once: Vector2i = StepCanvasTransport.snap_to_gridunit(Vector2(4096.0, 6144.0), "District")
|
|
var world_again := Vector2(once.x, once.y)
|
|
var twice: Vector2i = StepCanvasTransport.snap_to_gridunit(world_again, "District")
|
|
assert_that(once).is_equal(twice)
|
|
|
|
|
|
# =============================================================================
|
|
# World <-> canvas-local projection — the shared transform both the terrain
|
|
# and annotation layers agree on by construction
|
|
# =============================================================================
|
|
|
|
|
|
func test_world_m_to_canvas_local_centers_the_world_center_on_the_canvas_center() -> void:
|
|
var extent := Vector2i(64, 64)
|
|
var rung := "District"
|
|
var world_center := Vector2(10_000.0, 20_000.0)
|
|
var local: Vector2 = StepCanvasTransport.world_m_to_canvas_local(
|
|
world_center, world_center, rung, extent
|
|
)
|
|
var expected_center: Vector2 = StepCanvasTransport.canvas_footprint_px(rung, extent) * 0.5
|
|
assert_that(local).is_equal_approx(expected_center, Vector2(0.01, 0.01))
|
|
|
|
|
|
## world_m_to_canvas_local() and canvas_local_to_world_m() must be exact
|
|
## inverses of one another — a round trip through both must recover the
|
|
## original world point (within float tolerance). This is the invariant the
|
|
## cursor-anchored scroll step depends on: whatever point the cursor reads
|
|
## as "under it" before a scroll must be the SAME point after re-deriving
|
|
## from the new step's own frame.
|
|
func test_world_to_local_and_back_round_trips() -> void:
|
|
var extent := Vector2i(128, 96)
|
|
var rung := "Quarter"
|
|
var world_center := Vector2(50_000.0, -30_000.0)
|
|
var original_world := Vector2(51_200.0, -29_500.0)
|
|
|
|
var local: Vector2 = StepCanvasTransport.world_m_to_canvas_local(
|
|
original_world, world_center, rung, extent
|
|
)
|
|
var recovered_world: Vector2 = StepCanvasTransport.canvas_local_to_world_m(
|
|
local, world_center, rung, extent
|
|
)
|
|
assert_that(recovered_world).is_equal_approx(original_world, Vector2(0.5, 0.5))
|
|
|
|
|
|
func test_canvas_footprint_px_is_extent_times_display_ratio() -> void:
|
|
var footprint: Vector2 = StepCanvasTransport.canvas_footprint_px("Region", Vector2i(100, 50))
|
|
assert_that(footprint).is_equal(Vector2(500.0, 250.0)) # 5x5 shallow ratio
|
|
|
|
|
|
func test_half_extent_m_is_half_the_cell_count_times_spacing() -> void:
|
|
var half: float = StepCanvasTransport.half_extent_m("District", 64)
|
|
assert_float(half).is_equal_approx(64.0 * 0.5 * 2048.0, 0.01)
|
|
|
|
|
|
# =============================================================================
|
|
# T-1189: extent cap to the body's own region grid — the sideways-repeat /
|
|
# pole-smear fix. The Global echo IS the cap (its canvas already equals the
|
|
# body's region grid, D-255(a): "the Global canvas IS the whole body at
|
|
# region spacing"), so no unit conversion is needed — Region shares Global's
|
|
# gridunit spacing exactly.
|
|
# =============================================================================
|
|
|
|
|
|
func test_cap_extent_to_body_clamps_region_to_the_global_echo() -> void:
|
|
# T-1183 eyeball: 384x216 requested at Region on GJ1c, whose Global echo
|
|
# is 177x88 — the requested extent overruns the body on both axes.
|
|
var capped: Vector2i = StepCanvasTransport.cap_extent_to_body(
|
|
Vector2i(384, 216), "Region", Vector2i(177, 88)
|
|
)
|
|
assert_that(capped).is_equal(Vector2i(177, 88))
|
|
|
|
|
|
func test_cap_extent_to_body_is_a_no_op_when_already_inside_the_grid() -> void:
|
|
var capped: Vector2i = StepCanvasTransport.cap_extent_to_body(
|
|
Vector2i(100, 40), "Region", Vector2i(177, 88)
|
|
)
|
|
assert_that(capped).is_equal(Vector2i(100, 40))
|
|
|
|
|
|
## Shape-generic per the ticket: the guard compares SPACING, not rung name,
|
|
## so it caps ANY rung sharing Global's spacing, not just a hardcoded
|
|
## "Region" check. District's spacing (2048 m) differs from Global's
|
|
## (204,800 m), so it must NEVER be capped by the body-grid cell count —
|
|
## capping cell counts across mismatched spacings would be a unit error.
|
|
func test_cap_extent_to_body_leaves_finer_rungs_uncapped() -> void:
|
|
var capped: Vector2i = StepCanvasTransport.cap_extent_to_body(
|
|
Vector2i(3000, 3000), "District", Vector2i(177, 88)
|
|
)
|
|
assert_that(capped).is_equal(Vector2i(3000, 3000))
|
|
|
|
|
|
## Cold-start fallback (T-1189, StepCanvasViewer's own documented choice):
|
|
## before any Global response has arrived, `_global_body_extent` is ZERO —
|
|
## cap_extent_to_body() must leave the request UNCAPPED on a non-positive
|
|
## axis (server clamps independently) rather than clamping to zero cells.
|
|
func test_cap_extent_to_body_uncapped_when_global_echo_not_yet_available() -> void:
|
|
var capped: Vector2i = StepCanvasTransport.cap_extent_to_body(
|
|
Vector2i(384, 216), "Region", Vector2i.ZERO
|
|
)
|
|
assert_that(capped).is_equal(Vector2i(384, 216))
|
|
|
|
|
|
## A mixed case: one axis of the Global echo has arrived-and-is-real, the
|
|
## other is still ZERO (shouldn't happen in practice since both arrive
|
|
## together, but the function must handle each axis independently rather
|
|
## than assuming both-or-neither).
|
|
func test_cap_extent_to_body_caps_only_the_positive_echo_axis() -> void:
|
|
var capped: Vector2i = StepCanvasTransport.cap_extent_to_body(
|
|
Vector2i(384, 216), "Region", Vector2i(177, 0)
|
|
)
|
|
assert_that(capped).is_equal(Vector2i(177, 216))
|
|
|
|
|
|
# =============================================================================
|
|
# T-1189/T-1192: shared letterbox/centering mechanism
|
|
# =============================================================================
|
|
|
|
|
|
func test_center_offset_centers_a_smaller_canvas_in_a_larger_viewport() -> void:
|
|
var offset: Vector2 = StepCanvasTransport.center_offset(
|
|
Vector2(800.0, 400.0), Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_that(offset).is_equal(Vector2((1920.0 - 800.0) * 0.5, (1080.0 - 400.0) * 0.5))
|
|
|
|
|
|
func test_center_offset_is_zero_when_canvas_exactly_fills_the_viewport() -> void:
|
|
var offset: Vector2 = StepCanvasTransport.center_offset(
|
|
Vector2(1920.0, 1080.0), Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_that(offset).is_equal(Vector2.ZERO)
|
|
|
|
|
|
func test_center_offset_goes_negative_when_the_canvas_overflows_the_viewport() -> void:
|
|
# A canvas bigger than the viewport on an axis crops rather than shrinks
|
|
# (matches every fixed rung's own "canvas can exceed the viewport"
|
|
# precedent) — a negative offset on that axis is the correct, honest
|
|
# result, not clamped to zero.
|
|
var offset: Vector2 = StepCanvasTransport.center_offset(
|
|
Vector2(2000.0, 400.0), Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_float(offset.x).is_less(0.0)
|
|
assert_float(offset.y).is_greater(0.0)
|
|
|
|
|
|
## D-255 texel-exactness: an integer-px/gridunit canvas (fit_scale_ratio())
|
|
## can still land on an ODD-vs-viewport remainder that halves to a .5px
|
|
## boundary — GJ1c's own 1593x792 footprint in a 1628x1080 available area
|
|
## ((1628-1593)*0.5 = 17.5) is the real case this guards. The offset must be
|
|
## FLOORED to a whole pixel, never left fractional (a fractional offset
|
|
## would blur the texel grid this whole mechanism exists to keep crisp).
|
|
func test_center_offset_floors_a_half_pixel_remainder_to_a_whole_pixel() -> void:
|
|
var offset: Vector2 = StepCanvasTransport.center_offset(
|
|
Vector2(1593.0, 792.0), Vector2(1628.0, 1080.0)
|
|
)
|
|
assert_float(offset.x).is_equal_approx(17.0, 0.001)
|
|
assert_float(offset.y).is_equal_approx(144.0, 0.001)
|
|
|
|
|
|
# =============================================================================
|
|
# T-1192: Global integer PIXELS-PER-GRIDUNIT fit — D-255 amendment
|
|
# 2026-07-25 (rung-0's display ratio is viewport-fitted per body to an
|
|
# INTEGER px/gridunit ratio; the fractional-fit branch a prior round of this
|
|
# ticket carried was a mis-citation of D-255 — the record's actual mandate
|
|
# is unqualified texel-exact — and independently a real bug (Hoshe): a
|
|
# canvas exceeding the viewport on one axis could fit_scale() down to
|
|
# sub-1x, violating the "never below native resolution" invariant. Fixed at
|
|
# the root by fitting the INTEGER ratio, not a fraction of the whole
|
|
# footprint — this lattice is fine-grained (per gridunit, not per 5px-base
|
|
# footprint step), so the coverage-threshold escape hatch this section used
|
|
# to need does not come up: the achievable ratios are close enough together
|
|
# that the largest one that fits is always a good use of the frame.
|
|
# =============================================================================
|
|
|
|
|
|
func test_fit_scale_ratio_picks_the_largest_px_per_gridunit_that_fits_both_axes() -> void:
|
|
# GJ1c reference case (T-1183 eyeball): 177x88 gridunits against a full
|
|
# 1920x1080 viewport (no legend reservation) — floor(1920/177)=10,
|
|
# floor(1080/88)=12, the tighter axis (x) wins.
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(
|
|
Vector2(177.0, 88.0), Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_int(ratio).is_equal(10)
|
|
|
|
|
|
## The GJ1c reference case AFTER the legend column is reserved (T-1192, the
|
|
## StepCanvasViewer end-to-end scenario): available area shrinks to
|
|
## 1628x1080 — floor(1628/177)=9, floor(1080/88)=12 — the lead's own cited
|
|
## reference number for this exact case.
|
|
func test_fit_scale_ratio_matches_the_gj1c_legend_reserved_reference_case() -> void:
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(
|
|
Vector2(177.0, 88.0), Vector2(1628.0, 1080.0)
|
|
)
|
|
assert_int(ratio).is_equal(9)
|
|
|
|
|
|
## GJ1c at 4K, legend column reserved (3840 - 292 = 3548 available) — the
|
|
## lead's own cited reference number for a large viewport.
|
|
func test_fit_scale_ratio_matches_the_gj1c_4k_reference_case() -> void:
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(
|
|
Vector2(177.0, 88.0), Vector2(3548.0, 2160.0)
|
|
)
|
|
assert_int(ratio).is_equal(20)
|
|
|
|
|
|
## Hoshe's repro, now a regression test: a canvas whose BASE footprint
|
|
## (885x440 px at the old 5x5-multiple framing) exceeds a narrow 348px-wide
|
|
## available viewport used to make fit_scale() return 0.39x — a sub-1x
|
|
## downscale violating "never below native resolution". The integer
|
|
## px/gridunit ratio floors at 1 instead: draws at native (1 px/gridunit)
|
|
## and crops/pans, exactly like every other fixed rung's own
|
|
## exceeds-the-viewport precedent.
|
|
func test_fit_scale_ratio_floors_at_one_when_gridunits_exceed_a_narrow_viewport() -> void:
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(
|
|
Vector2(177.0, 88.0), Vector2(348.0, 1080.0)
|
|
)
|
|
assert_int(ratio).is_equal(1)
|
|
|
|
|
|
## A small moon's Global canvas (few gridunits) in a large viewport still
|
|
## only wins as large an integer ratio as fits — no special-casing for a
|
|
## small canvas, same formula, much larger achievable ratio.
|
|
func test_fit_scale_ratio_a_tiny_moon_canvas_wins_a_large_integer_ratio() -> void:
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(
|
|
Vector2(20.0, 20.0), Vector2(1920.0, 1080.0)
|
|
)
|
|
assert_int(ratio).is_equal(54)
|
|
|
|
|
|
## Exact-fit boundary: the viewport is PRECISELY `extent * 3` on both axes —
|
|
## the ratio must land exactly on 3, not overshoot to 4 (floor(exact) must
|
|
## not round up) and not undershoot to 2 (an exact multiple is a legal fit,
|
|
## not treated as "just barely doesn't fit").
|
|
func test_fit_scale_ratio_exact_multiple_boundary_lands_on_the_multiple() -> void:
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(
|
|
Vector2(100.0, 50.0), Vector2(300.0, 150.0)
|
|
)
|
|
assert_int(ratio).is_equal(3)
|
|
|
|
|
|
## One pixel short of the exact multiple must drop to the NEXT integer down
|
|
## — confirms the boundary isn't fuzzy/off-by-one in the other direction.
|
|
func test_fit_scale_ratio_one_pixel_short_of_the_multiple_drops_a_step() -> void:
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(
|
|
Vector2(100.0, 50.0), Vector2(299.0, 150.0)
|
|
)
|
|
assert_int(ratio).is_equal(2)
|
|
|
|
|
|
func test_fit_scale_ratio_is_bounded_by_the_tighter_axis() -> void:
|
|
# Wide-but-short viewport: x could fit 10x, y only fits 1x — the smaller
|
|
# wins (never overflow either axis).
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(
|
|
Vector2(100.0, 100.0), Vector2(1000.0, 150.0)
|
|
)
|
|
assert_int(ratio).is_equal(1)
|
|
|
|
|
|
func test_fit_scale_ratio_handles_a_zero_extent_axis_without_dividing_by_zero() -> void:
|
|
var ratio: int = StepCanvasTransport.fit_scale_ratio(Vector2.ZERO, Vector2(800.0, 600.0))
|
|
assert_int(ratio).is_equal(1)
|
|
|
|
|
|
## fit_scale_from_ratio() converts the INTEGER px/gridunit ratio into the
|
|
## `_canvas.scale` multiplier applied on top of a texture already rendered
|
|
## at the rung's own base display ratio (5x5 for Global) — this multiplier
|
|
## itself may be a non-integer float (9/5 = 1.8), and that is CORRECT:
|
|
## texel-exactness is about the final ratio being a whole number, not the
|
|
## Node2D scale field.
|
|
func test_fit_scale_from_ratio_divides_by_the_base_display_ratio() -> void:
|
|
var scale: float = StepCanvasTransport.fit_scale_from_ratio(9, 5.0)
|
|
assert_float(scale).is_equal_approx(1.8, 0.001)
|
|
|
|
|
|
func test_fit_scale_from_ratio_at_the_gj1c_4k_reference_case() -> void:
|
|
var scale: float = StepCanvasTransport.fit_scale_from_ratio(20, 5.0)
|
|
assert_float(scale).is_equal_approx(4.0, 0.001)
|
|
|
|
|
|
func test_fit_scale_from_ratio_handles_a_zero_base_ratio_without_dividing_by_zero() -> void:
|
|
var scale: float = StepCanvasTransport.fit_scale_from_ratio(9, 0.0)
|
|
assert_float(scale).is_greater(0.0)
|
|
|
|
|
|
# =============================================================================
|
|
# T-1192: shared legend-column reservation constant
|
|
# =============================================================================
|
|
|
|
|
|
## StepCanvasTransport is the CANONICAL source for this width (T-1192
|
|
## review fix) — step_canvas_legend.gd's own RESERVED_COLUMN_PX is now a
|
|
## direct read of THIS constant, not an independently-typed literal, so
|
|
## there is no separate cross-pin test needed here; this just pins the
|
|
## canonical value itself (260 panel width + 16*2 margin = 292).
|
|
func test_legend_column_px_is_the_panel_width_plus_margin_on_both_sides() -> void:
|
|
assert_float(StepCanvasTransport.LEGEND_COLUMN_PX).is_equal_approx(292.0, 0.01)
|