OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_editor_highlights.gd

115 lines · gd ref:
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])