extends Node
## GATE — editor highlight housekeeping (2026-10-05: "a) make the auto highlight less
## bright and b) upon exiting editor mode no element highlight should remain").
##
## a. the AUTO highlight — the outline + corner handles that follow the crosshair
## (BrushView's aimed layers) — is dimmer than it was (0.75 / 0.95 alpha)
## b. leaving build mode leaves NO highlight on screen: selection outlines, the
## selected element, the face tint and the aimed outline are all hidden — and one
## made WHILE playing (a selection changed in play) is hidden too
## c. coming back to build mode shows the selection again (it was kept, not lost)
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_editor_highlights.tscn
var fails := 0
var checks := 0
func _ok(what: String, cond: bool, note: String = "") -> void:
checks += 1
if not cond:
fails += 1
print(" %-64s %s %s" % [what, "OK" if cond else "**FAIL**", note])
func _ready() -> void:
var gs: Node = get_tree().root.get_node_or_null("/root/GameState")
gs.route("world:level:*", 1, "peer")
var gm: Node = get_tree().root.get_node("/root/GameMode")
gm.set_mode("build")
var map: Node3D = (load("res://scenes/maps/map_test.tscn") as PackedScene).instantiate()
add_child(map)
for i in 6:
await get_tree().process_frame
_run(map, gm)
gm.set_mode("play")
if checks < 9:
print(" **FAIL** only %d checks ran -- setup died before the assertions" % checks)
fails += 1
print("\nGATE editor_highlights: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
get_tree().quit(0 if fails == 0 else 1)
## Every highlight node the map draws, that exists right now.
func _highlights(map: Node) -> Dictionary:
var out := {}
for name: String in ["_outline", "_sel_elem", "_hl"]:
var n: Variant = map.get(name)
if n is Node3D and is_instance_valid(n):
out[name] = n
var bv: Variant = map.get("_brush_view")
if bv is Node3D and is_instance_valid(bv):
out["aimed"] = (bv as Node).get("_aimed")
return out
func _shown(h: Dictionary) -> Array:
var on: Array = []
for k: String in h:
if (h[k] as Node3D).is_visible_in_tree():
on.append(k)
return on
func _run(map: Node3D, gm: Node) -> void:
var level: Node = map.get("level")
var bv: Node = map.call("_ensure_brush_view")
# ---- a ----
var aimed: MeshInstance3D = bv.get("_aimed")
var handles: MeshInstance3D = bv.get("_handles")
var a_aim: float = (aimed.material_override as StandardMaterial3D).albedo_color.a
var a_hdl: float = (handles.material_override as StandardMaterial3D).albedo_color.a
_ok("a. the auto (aimed) outline is dimmer than 0.75", a_aim <= 0.45, "%.2f" % a_aim)
_ok("a. its corner handles are dimmer than 0.95", a_hdl <= 0.6, "%.2f" % a_hdl)
# ---- b ----
var b1: int = level.brush_by_key("i:1:3")
var b2: int = level.brush_by_key("i:1:5")
map.select_brushes(PackedInt32Array([b1]))
bv.set_aimed(b2)
var h := _highlights(map)
_ok("setup: a selection and an aimed brush are drawn in build mode",
h.has("_outline") and h.has("aimed") and _shown(h).has("_outline") and _shown(h).has("aimed"), str(_shown(h)))
gm.set_mode("play")
h = _highlights(map)
_ok("b. leaving build mode hides every highlight", _shown(h).is_empty(), "still shown: %s" % str(_shown(h)))
map.select_brushes(PackedInt32Array([b2])) # a selection change while playing
map.call("_update_face_highlight")
h = _highlights(map)
_ok("b. a highlight made while playing stays hidden", _shown(h).is_empty(), "shown: %s" % str(_shown(h)))
var ol: Node = map.get("_outline")
_ok("b. the selection itself is kept", (map.get("_sel_brushes") as Array) == [b2], str(map.get("_sel_brushes")))
# ---- c ----
gm.set_mode("build")
h = _highlights(map)
_ok("c. back in build mode the selection outline shows again", _shown(h).has("_outline"), str(_shown(h)))
_ok("c. and the wireframe/aim layer is back", (bv as Node3D).is_visible_in_tree())
_ok("c. the outline still describes the selection", ol != null and is_instance_valid(ol))
# d. (same housekeeping pass) the Face panel's UV buttons name their KEY in the
# tooltip. It looked up /root/Keymap before the panel was in the tree: one engine
# error per button, and the tooltip silently lost its shortcut.
var fp: Node = map.get("_face_panel")
var with_key := 0
var bound := 0
if fp != null:
for b: Node in fp.find_children("*", "Button", true, false):
var t := String((b as Button).tooltip_text)
if (b as Button).text in ["◀", "▶", "▲", "▼", "−15°", "+15°"]:
bound += 1
if t.contains("(") and t.contains(")"):
with_key += 1
_ok("d. the Face panel's keyed UV buttons show their shortcut", bound == 6 and with_key == 6,
"%d/%d" % [with_key, bound])