OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_keymap_step3.gd

170 lines · gd ref:
extends Node
## GATE — keymap step 3's NEW commands (docs/keymap-blender-279.md §3a), each through its key.
##
##   A toggles select all / none · Ctrl+I inverts · B + a drag box-selects
##   Shift+A opens the add menu; its Stairs row starts the create tool on stairs
##   U opens the texture menu with every texture command (each with its key)
##   N collapses / restores the right column · Tab element <-> brush mode
##   Z toggles the wireframe · Shift+R repeats the last command (here: G -> move tool)
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_keymap_step3.tscn

var fails := 0
var checks := 0
var _cam: Camera3D = null


func _ok(what: String, cond: bool, note: Variant = "") -> void:
	checks += 1
	if not cond:
		fails += 1
	print("  %-64s %s  %s" % [what, "OK" if cond else "**FAIL**", str(note)])


func _ready() -> void:
	var gs: Node = get_tree().root.get_node_or_null("/root/GameState")
	gs.route("world:level:*", 1, "peer")
	var keet: Node = get_tree().root.get_node_or_null("/root/KeetService")
	if keet != null:
		keet.current_member_id = "gate-author"
	get_tree().root.get_node("/root/GameMode").set_mode("build")
	get_tree().root.size = Vector2i(1920, 1080)      # headless is 64x64 (see memory)
	var map: Node3D = (load("res://scenes/maps/map_test.tscn") as PackedScene).instantiate()
	add_child(map)
	_cam = Camera3D.new()
	add_child(_cam)
	_cam.current = true
	for i in 6:
		await get_tree().process_frame
	await _run(map)
	get_tree().root.get_node("/root/GameMode").set_mode("play")
	if checks < 16:
		print("  **FAIL** only %d checks ran -- setup died before the assertions" % checks)
		fails += 1
	print("\nGATE keymap_step3: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
	get_tree().quit(0 if fails == 0 else 1)


func _frames(n: int) -> void:
	for i in n:
		await get_tree().process_frame


func _key(code: Key, ctrl := false, shift := false, alt := false) -> InputEventKey:
	var e := InputEventKey.new()
	e.keycode = code
	e.physical_keycode = code
	e.pressed = true
	e.ctrl_pressed = ctrl
	e.shift_pressed = shift
	e.alt_pressed = alt
	return e


func _send(map: Node, e: InputEventKey) -> void:
	map._unhandled_key_input(e)
	await _frames(2)


func _run(map: Node3D) -> void:
	var level: Node = map.get("level")
	var persist: Node = map.get("_persist")
	var ol: Node = map.get("_outliner")
	if ol != null:
		ol.set("_save_key", "gate_keymap_step3")          # never the user's default.dat
	# Three boxes of our own, in front of the camera (map_test has one brush).
	for i in 3:
		var x := 60.0 + i * 3.0
		persist.record("brush.create", {"planes": [1, 0, 0, x + 1, -1, 0, 0, -x, 0, 1, 0, 1, 0, -1, 0, 0,
			0, 0, 1, 61, 0, 0, -1, -60], "proj": [], "material_id": 2, "level_id": 0, "sky": false, "group": ""})
	persist.refold()
	_cam.global_position = Vector3(63.5, 6, 70)
	_cam.look_at(Vector3(63.5, 0.5, 60.5), Vector3.UP)
	await _frames(2)
	var live: PackedInt32Array = level.get_live_brush_ids()
	_ok("setup: at least our three brushes", live.size() >= 3, live.size())

	print("-- select all / none / invert --")
	map.clear_selection()
	await _send(map, _key(KEY_A))
	_ok("A with nothing selected selects all", (map.get("_sel_brushes") as Array).size() == live.size(),
		(map.get("_sel_brushes") as Array).size())
	await _send(map, _key(KEY_A))
	_ok("A again selects none", (map.get("_sel_brushes") as Array).is_empty())
	map.select_brushes(PackedInt32Array([live[0]]))
	await _send(map, _key(KEY_I, true))
	var inv: Array = map.get("_sel_brushes")
	_ok("Ctrl+I inverts (all but the one)", inv.size() == live.size() - 1 and not inv.has(live[0]), inv.size())

	print("-- box select --")
	map.clear_selection()
	await _send(map, _key(KEY_B))
	_ok("B arms box select", bool(map.call("is_box_selecting")))
	var whole := Rect2(Vector2.ZERO, Vector2(get_viewport().get_visible_rect().size))
	var n: int = map.box_select(whole, false)
	map.set("_box_sel", false)
	_ok("a full-screen box selects what is in front of the camera", n > 0 and (map.get("_sel_brushes") as Array).size() == n, n)

	print("-- Shift+A add menu --")
	map.clear_selection()
	await _send(map, _key(KEY_A, false, true))
	var qm: Node = map.get("_q_menu")
	_ok("Shift+A opens the add menu with every shape", qm != null and bool(qm.is_open())
		and qm.has_action("builder.add_stairs") and qm.has_action("builder.add_sphere"))
	qm.pick("builder.add_stairs")
	await _frames(4)
	var op: Object = map.call("_ensure_ops").get("active")
	var bx: Object = map.get("_box")
	var si: int = (bx.shape_ids() as Array).find("param:stairs")
	_ok("its Stairs row sets the create tool to stairs", int(bx.get("_shape")) == si, [bx.get("_shape"), si])
	# Headless the POINTER sits at (0, 0), and the create tool aims where the pointer is, so
	# it cannot place here. What the row must do is dispatch the create tool's action —
	# which the map's builder handler records as the last repeatable command.
	_ok("... and dispatches the create tool", String(map.get("_last_repeatable")) == "builder.create_box",
		[map.get("_last_repeatable"), op])
	map.call("_ensure_ops").cancel()
	await _frames(2)

	print("-- U texture menu --")
	await _send(map, _key(KEY_U))
	_ok("U opens the texture menu", bool(qm.is_open()) and qm.has_action("builder.texture_apply")
		and qm.has_action("builder.texture_pick") and qm.has_action("builder.uv_hotspot") and qm.has_action("builder.uv_reroll"))
	_ok("... and its rows show their keys (apply = Ctrl+U)", String(qm.accel_text_of("builder.texture_apply")) == "Ctrl+U",
		qm.accel_text_of("builder.texture_apply"))
	(qm.get("_menu") as PopupMenu).hide()
	await _frames(2)

	print("-- N sidebar --")
	var was: bool = BuildDock.is_region_collapsed(BuildDock.SIDE_RIGHT)
	await _send(map, _key(KEY_N))
	_ok("N toggles the right column", BuildDock.is_region_collapsed(BuildDock.SIDE_RIGHT) != was)
	await _send(map, _key(KEY_N))
	_ok("N again restores it", BuildDock.is_region_collapsed(BuildDock.SIDE_RIGHT) == was)

	print("-- Tab element <-> brush --")
	map.call("set_select_mode", "face")
	await _send(map, _key(KEY_TAB))
	_ok("Tab from face mode -> brush mode", String(map.get("_sel_mode")) == "brush", map.get("_sel_mode"))
	await _send(map, _key(KEY_TAB))
	_ok("Tab again -> back to face mode", String(map.get("_sel_mode")) == "face", map.get("_sel_mode"))

	print("-- Z wireframe --")
	var vp := get_viewport()
	var dd0 := vp.debug_draw
	await _send(map, _key(KEY_Z))
	_ok("Z toggles the wireframe", vp.debug_draw != dd0, vp.debug_draw)
	await _send(map, _key(KEY_Z))
	_ok("Z again restores it", vp.debug_draw == dd0)

	print("-- Shift+R repeat last --")
	map.select_brushes(PackedInt32Array([live[0]]))
	await _send(map, _key(KEY_G))
	var stack: Node = map.call("_ensure_ops")
	_ok("G starts the move tool", stack.get("active") is MoveOperator, stack.get("active"))
	stack.cancel()
	await _frames(2)
	await _send(map, _key(KEY_R, false, true))
	await _frames(3)
	_ok("Shift+R repeats it: the move tool again", stack.get("active") is MoveOperator, stack.get("active"))
	stack.cancel()