extends SceneTree
## GATE — editor redesign E1 (docs/editor-redesign.md §3): the four collapsible regions,
## the top bar (menus generated from the keymap, select modes, grid, texture lock), the
## toolbar and the generated status bar, on a REAL map_flat in build mode.
##
## Every surface runs actions through Keymap.run — the same path a key press takes — so
## the assertions click a control and then read the MAP's state, never the control's.
##
## Run: "$HYPER_TPS_GODOT" --headless --path . --script res://scenes/test/gate_editor_e1.gd
var ok := true
var checks := 0
var _frame := 0
var _map: Node
var _dock: Node
var _km: Node
var _hud: Node
var _top: Node
var _tools: Node
var _vis0 := false
var _saved_grid: Variant = 5
var _saved_snap: Variant = true
func _p(cond: bool, what: String, note: String = "") -> void:
checks += 1
if not cond:
ok = false
print(" %-62s %s %s" % [what, "OK" if cond else "**FAIL**", note])
func _process(_d: float) -> bool:
_frame += 1
match _frame:
1:
_map = (load("res://scenes/maps/map_flat.tscn") as PackedScene).instantiate()
root.add_child(_map)
30:
_dock = root.get_node("/root/BuildDock")
# Gates share the installed game's user:// — put the player's saved grid and
# snap back at the end (the grid steps below would otherwise persist).
_saved_grid = _dock.pref("grid", 5)
_saved_snap = _dock.pref("snap", true)
_km = root.get_node("/root/Keymap")
_hud = root.get_node("/root/BuildHud")
root.get_node("/root/GameMode").set_mode("build")
print("-- four regions, each collapsible --")
for side: String in ["top", "bottom", "left", "right"]:
_p(_dock.has_region(side), "region '%s' exists" % side)
_p(_dock.has_panel("topbar") and String(_dock._panels["topbar"]["side"]) == "top", "the top bar is in the TOP region")
_p(_dock.has_panel("tools") and String(_dock._panels["tools"]["side"]) == "left", "the toolbar is in the LEFT region")
for side: String in ["top", "bottom", "left", "right"]:
var t: Button = _dock.region_toggle(side)
_p(t != null and t.is_visible_in_tree(), "'%s' has a visible ▸/▾ toggle" % side)
var lt: Button = _dock.region_toggle("left")
lt.pressed.emit()
_p(_dock.is_region_collapsed("left") and not _dock.region_content("left").visible,
"clicking the left toggle collapses the left region")
_p(lt.is_visible_in_tree(), "and the toggle stays reachable")
_p(FileAccess.get_file_as_string(_dock.LAYOUT_PATH).contains("left"), "collapse state saved per player")
lt.pressed.emit()
_p(not _dock.is_region_collapsed("left") and _dock.region_content("left").visible, "clicking again restores it")
# NARROW WINDOWS: the bands must fit between the two columns of a 1280-px
# window, or the bottom one runs under the right column (it did: the status
# line and the strip's top row refused to shrink below ~1350 px).
var cols: float = _dock._column_width("left") + _dock._column_width("right") + 48.0
for side: String in ["top", "bottom"]:
var col: Control = _dock._sides[side]["column"]
var need: float = col.get_combined_minimum_size().x + 32.0 # + the toggle
_p(cols + need <= 1280.0, "the %s band fits a 1280-px window" % side,
"needs %d px between columns of %d" % [int(need), int(cols)])
var sb_need: float = (_dock._status_left as Control).get_combined_minimum_size().x
_p(cols + sb_need + 120.0 <= 1280.0, "and so does the status bar", "%d px" % int(sb_need))
print("\n-- the top bar's menus come from the keymap --")
_top = _map.get("_top_bar")
_p(_top != null, "the map keeps its top bar")
var items := 0
var bad: Array[String] = []
for pm: PopupMenu in _top.menus():
for i in pm.item_count:
if pm.is_item_separator(i):
continue
items += 1
var action: String = String(pm.get_item_metadata(i))
if _km.binding_of(action).is_empty():
bad.append(action)
elif pm.get_item_accelerator(i) != _top.accel_of(action):
bad.append(action + " (accel)")
_p(items >= 18 and bad.is_empty(), "every menu item names a bound action with its live key",
"%d items, bad %s" % [items, str(bad)])
# Since keymap step 6.5 V is the "Brush outlines" OVERLAY: its own switch, and the
# level-outline layer (the BrushView node itself is build mode).
_vis0 = bool(_map.overlay_on("outlines"))
_top.activate("builder.brush_view") # what clicking View > Brush outlines does
34:
var bv: Node = _map.get("_brush_view")
_p(bv != null and bool(_map.overlay_on("outlines")) != _vis0 and bool(bv.show_outlines) == bool(_map.overlay_shown("outlines")),
"View > Brush outlines toggled the outlines overlay")
_map.set_overlay("outlines", _vis0) # back as it was
print("\n-- select modes, grid, texture lock --")
_top.select_mode_button("brush").pressed.emit()
38:
_p(String(_map.get("_sel_mode")) == "brush", "the 'brush' select-mode button set the map's mode",
String(_map.get("_sel_mode")))
_top.grid_option().select(1)
_top.grid_option().item_selected.emit(1)
_p(int(_map.get("_grid_idx")) == 1, "choosing grid 2u set the map's grid", str(_map.get("_grid_idx")))
_km.run("builder.grid_coarser") # 2u -> 4u (index 1 -> 2)
42:
_p(int(_map.get("_grid_idx")) == 2 and _top.grid_option().selected == 2,
"the key changed the grid AND the dropdown follows", "%d / %d" % [int(_map.get("_grid_idx")), _top.grid_option().selected])
_top.tex_lock_button().button_pressed = false
_top.tex_lock_button().toggled.emit(false)
_p(not bool(_map.get("tex_lock")), "the Texture Lock toggle sets the map's tex_lock")
_top.tex_lock_button().button_pressed = true
_top.tex_lock_button().toggled.emit(true)
print("\n-- the toolbar --")
_tools = _map.get("_tool_bar")
_p(_tools != null and _tools.buttons().size() >= 8, "the toolbar has the tools", str(_tools.buttons().size() if _tools else 0))
var tip_bad := PackedStringArray()
for a: String in _tools.buttons():
var b: Button = _tools.buttons()[a]
var lbl := String(_km.binding_of(a).get("label", ""))
# key_text: the live key, or how a key-less tool is reached (keymap step 3).
if not (b.tooltip_text.contains(lbl) and b.tooltip_text.contains(String(_tools.key_text(a)))):
tip_bad.append("%s: %s" % [a, b.tooltip_text.left(60)])
_p(tip_bad.is_empty(), "every tool tooltip shows its label AND its live key", " | ".join(tip_bad))
_p(not (_tools.buttons().values()[0] as Button).tooltip_text.contains("Physical"), "no 'Physical' noise in tooltips")
print("\n-- the status bar is generated --")
var idle: String = _hud.status_text()
_p(idle.contains("F1") and idle.contains(String(_km.describe("builder.add_menu"))), "idle: hints include F1 and the add-menu key", idle.left(90))
_p(_hud.status_right().contains("%du" % int(_map.GRID_UNITS[int(_map.get("_grid_idx"))])), "right side shows the grid", _hud.status_right())
var stack: Node = _map.call("_ensure_ops")
var op := LevelOperator.new()
_map.add_child(op)
stack.activate(op)
_map.call("_update_op_hud")
46:
var busy: String = _hud.status_text()
_p(busy.contains("Esc") and busy.contains("RMB"), "a tool is up: Enter/Esc and 'hold RMB fly' are shown", busy.left(90))
if checks < 25:
_p(false, "only %d checks ran" % checks)
_dock.set_pref("grid", _saved_grid)
_dock.set_pref("snap", _saved_snap)
print("GATE editor_e1: %s (%d checks)" % ["PASS" if ok else "FAIL", checks])
quit(0 if ok else 1)
return true
return false