OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_view_commands.gd

108 lines · gd ref:
extends Node
## GATE — keymap step 6, Blender's view commands (docs/keymap-blender-279.md §6a):
##   Home view all · Shift+C view all + 3D cursor to the origin · Alt+Home centre on the
##   3D cursor · Alt+F centre on the point under the pointer · Home yields to UV fit
##   while faces are selected.
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_view_commands.tscn

var fails := 0
var checks := 0


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)
	var map: Node3D = (load("res://scenes/maps/map_test.tscn") as PackedScene).instantiate()
	add_child(map)
	var cam := Camera3D.new()                  # no player here: the editor view drives this one
	add_child(cam)
	cam.current = true
	cam.global_position = Vector3(0, 10, 30)
	for i in 8:
		await get_tree().process_frame
	await _run(map)
	get_tree().root.get_node("/root/GameMode").set_mode("play")
	if checks < 7:
		print("  **FAIL** only %d checks ran -- setup died before the assertions" % checks)
		fails += 1
	print("\nGATE view_commands: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
	get_tree().quit(0 if fails == 0 else 1)


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


func _send(view: Node, e: InputEventKey) -> void:
	view._unhandled_input(e)
	await get_tree().process_frame


## Is world point p in front of the camera and inside the screen?
func _on_screen(cam: Camera3D, p: Vector3) -> bool:
	if cam.is_position_behind(p):
		return false
	return get_viewport().get_visible_rect().has_point(cam.unproject_position(p))


func _run(map: Node3D) -> void:
	var view: Node = map.get("_view")
	var cur: Node3D = map.get("_cursor3d")
	var level: Node = map.get("level")
	var persist: Node = map.get("_persist")
	_ok("setup: the editor view and the 3D cursor exist", view != null and cur != null)
	if view == null or cur == null:
		return
	# Two boxes far apart, so "all" is a real framing problem.
	for x: float in [0.0, 80.0]:
		persist.record("brush.create", {"planes": [1, 0, 0, x + 2, -1, 0, 0, -x, 0, 1, 0, 2, 0, -1, 0, 0,
			0, 0, 1, 2, 0, 0, -1, 0], "proj": [], "material_id": 2, "level_id": 0, "sky": false, "group": ""})
	persist.refold()
	var cam: Camera3D = view.camera()
	_ok("there is an editor camera", cam != null)
	if cam == null:
		return

	print("-- Home: view all --")
	await _send(view, _key(KEY_HOME))
	_ok("both far-apart boxes are on screen", _on_screen(cam, Vector3(1, 1, 1)) and _on_screen(cam, Vector3(81, 1, 1)))

	print("-- Shift+C: view all + cursor to origin --")
	cur.global_position = Vector3(10, 5, 10)
	await _send(view, _key(KEY_C, true))
	_ok("the 3D cursor is at the origin", cur.global_position.length() < 0.001, cur.global_position)

	print("-- Alt+Home: centre on the 3D cursor --")
	cur.global_position = Vector3(40, 1, 30)
	var fwd0: Vector3 = view.forward()
	await _send(view, _key(KEY_HOME, false, true))
	var to_c := (cur.global_position - cam.global_position).normalized()
	_ok("the cursor is at the centre of the view", view.forward().dot(to_c) > 0.999, view.forward().dot(to_c))
	_ok("... and the view kept its angle", view.forward().dot(fwd0) > 0.999)

	print("-- Home yields to UV fit while faces are selected --")
	var before := cam.global_position
	Keymap.push_context("face_sel")
	await _send(view, _key(KEY_HOME))
	_ok("with faces selected Home does not move the view", cam.global_position.distance_to(before) < 0.001)
	Keymap.pop_context("face_sel")