OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_move_proxy.gd

129 lines · gd ref:
extends SceneTree
## Gate: MOVE shows the actual brush moving (proxy mesh), not just its outline
## (docs/editor-texturing-selection-move.md §4; user 2026-10-03).
##
## Activation hides the brush (one rebuild) and puts its own mesh, with the LEVEL
## material, under the level; the drag moves that proxy (and, with texture lock, shifts
## its texture projection by the same delta); confirm unhides + translates; cancel
## unhides and leaves the brush where it was. Measured motivation: _probe_move_cost.
##
## Run: HYPERTPS_DAEMON_TCP=127.0.0.1:1 "$HYPER_TPS_GODOT" --headless --path . --script res://scenes/test/gate_move_proxy.gd

var ok := true
var checks := 0
var _frame := 0
var _map: Node


func _p(c: bool, m: String, got: Variant = "") -> void:
	checks += 1
	print(("ok   " if c else "FAIL: ") + m + ("" if str(got) == "" else "  (" + str(got) + ")"))
	if not c:
		ok = false


func _process(_d: float) -> bool:
	_frame += 1
	if _frame == 1:
		_map = (load("res://scenes/maps/map_flat.tscn") as PackedScene).instantiate()
		root.add_child(_map)
		return false
	if _frame < 30:
		return false
	_run()
	if checks < 12:
		_p(false, "only %d checks ran" % checks)
	print("GATE move_proxy: %s (%d checks)" % ["PASS" if ok else "FAIL", checks])
	quit(0 if ok else 1)
	return true


func _box(lo: Vector3, hi: Vector3) -> Array:
	return [1, 0, 0, hi.x, -1, 0, 0, -lo.x, 0, 1, 0, hi.y, 0, -1, 0, -lo.y, 0, 0, 1, hi.z, 0, 0, -1, -lo.z]


func _proxies(level: Node) -> Array:
	var out: Array = []
	for c in level.get_children():
		if String(c.name).begins_with("MoveProxy_") and not c.is_queued_for_deletion():
			out.append(c)
	return out


func _run() -> void:
	var level: Node = _map.get_node("DCLevel")
	var persist: Node = _map.get("_persist")
	var keet: Node = root.get_node_or_null("/root/KeetService")
	if keet != null:
		keet.current_member_id = "gate-author"
	var gs: Node = root.get_node_or_null("/root/GameState")
	if gs != null:
		gs.route("world:level:*", 1, "peer")
	var ft: Array = []
	for i in 6:
		ft.append({"tex": "kenney-prototype/dark_01", "mode": 1})
	var dot: String = persist.record("brush.create", {"planes": _box(Vector3(0, 0, 0), Vector3(1, 1, 1)),
		"proj": [], "material_id": 1, "level_id": 0, "sky": false, "face_tex": ft})
	persist.refold()
	var b: int = level.brush_by_key(dot)
	var lo0: Vector3 = level.get_brush(b)["aabb_min"]
	_p(level.has_method("get_brush_mesh"), "DCLevel exposes get_brush_mesh (rebuilt extension)")
	if not level.has_method("get_brush_mesh"):
		return
	var bm: Mesh = level.get_brush_mesh(b)
	_p(bm != null and bm.get_surface_count() == 1 and (bm.surface_get_arrays(0)[Mesh.ARRAY_VERTEX] as PackedVector3Array).size() == 36,
		"brush mesh: one surface, 12 triangles for a box")

	var stack: Node = _map.call("_ensure_ops")

	print("-- activate: the brush is hidden, its proxy stands in --")
	_map.select_brushes(PackedInt32Array([b]))
	var op := MoveOperator.new()
	op.map = _map
	op.level = level
	_map.add_child(op)
	stack.activate(op)
	var px := _proxies(level)
	_p(px.size() == 1, "one MoveProxy under the level", px.size())
	_p(level.is_brush_hidden(b), "the real brush is hidden while moving")
	var lm: MeshInstance3D = level.get_node("LevelMesh")
	_p(px.size() == 1 and (px[0] as MeshInstance3D).material_override == lm.material_override,
		"proxy uses the LEVEL material (same look)")

	print("-- drag 3 steps on x --")
	op.set("_steps", 3)
	op.update_preview()
	var d: Vector3 = op.call("_delta")
	_p(d.length() > 0.0, "a non-zero drag", d)
	if px.size() == 1:
		var mi: MeshInstance3D = px[0]
		_p(mi.position.is_equal_approx(d), "the proxy moved by the drag", mi.position)
		var sh: Variant = mi.get_instance_shader_parameter("tex_lock_shift")
		_p(sh is Vector3 and (sh as Vector3).is_equal_approx(d), "texture lock: projection shifted with it", sh)

	var ol: Node3D = _map.get("_outline")
	_p(ol != null and ol.position.is_equal_approx(d), "the selection outline travels with the proxy",
		ol.position if ol != null else "no outline")

	print("-- confirm: unhidden, translated, proxy gone --")
	stack.confirm()
	_p(ol == null or ol.position.is_equal_approx(Vector3.ZERO), "outline back at the origin after the drop")
	var lo1: Vector3 = level.get_brush(b)["aabb_min"]
	_p(not level.is_brush_hidden(b), "brush visible again")
	_p(lo1.is_equal_approx(lo0 + d), "brush translated by the drag", "%s -> %s" % [lo0, lo1])
	_p(_proxies(level).is_empty(), "proxy freed")

	print("-- cancel: back where it was --")
	_map.select_brushes(PackedInt32Array([b]))
	var op2 := MoveOperator.new()
	op2.map = _map
	op2.level = level
	_map.add_child(op2)
	stack.activate(op2)
	op2.set("_steps", 2)
	op2.update_preview()
	stack.cancel()
	_p(not level.is_brush_hidden(b), "cancel: brush visible again")
	_p((level.get_brush(b)["aabb_min"] as Vector3).is_equal_approx(lo1), "cancel: not moved")
	_p(_proxies(level).is_empty(), "cancel: proxy freed")