OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_pivot.gd

105 lines · gd ref:
extends Node
## GATE — keymap step 6.2, THE PIVOT (Blender 2.79's , . keys; docs/keymap-blender-279.md §6a):
##   , bounding box · Ctrl+, median · . 3D cursor · Alt+. active — the keys set it, the
##   rotate tool turns about it, scale (base off) scales about it.
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_pivot.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")
	var map: Node3D = (load("res://scenes/maps/map_test.tscn") as PackedScene).instantiate()
	add_child(map)
	for i in 8:
		await get_tree().process_frame
	await _run(map)
	get_tree().root.get_node("/root/GameMode").set_mode("play")
	if checks < 10:
		print("  **FAIL** only %d checks ran -- setup died before the assertions" % checks)
		fails += 1
	print("\nGATE pivot: %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, ctrl := false, alt := false) -> InputEventKey:
	var e := InputEventKey.new()
	e.keycode = code
	e.physical_keycode = code
	e.pressed = true
	e.ctrl_pressed = ctrl
	e.alt_pressed = alt
	return e


func _near(a: Vector3, b: Vector3) -> bool:
	return a.distance_to(b) < 0.01


func _run(map: Node3D) -> void:
	var persist: Node = map.get("_persist")
	var level: Node = map.get("level")
	# Three unit boxes at x 0, 2 and 10: bbox centre x 5.5, median x 4.5 (centres 0.5, 2.5, 10.5).
	var ids: Array = []
	for x: float in [0.0, 2.0, 10.0]:
		var dot: String = 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, 1, 0, 0, -1, 0], "proj": [], "material_id": 2,
			"level_id": 0, "sky": false, "group": ""})
		persist.refold()
		ids.append(level.brush_by_key(dot))
	map.select_brushes(PackedInt32Array(ids))          # active = the last (x 10)

	print("-- the keys set the pivot --")
	for pair: Array in [[_key(KEY_COMMA), "bbox"], [_key(KEY_COMMA, true), "median"],
			[_key(KEY_PERIOD), "cursor"], [_key(KEY_PERIOD, false, true), "active"]]:
		map._unhandled_key_input(pair[0])
		_ok("%s -> %s" % [Keymap.describe("builder.pivot_%s" % pair[1]), pair[1]], String(map.pivot_mode) == pair[1],
			map.pivot_mode)

	print("-- the point each mode gives --")
	map.set_pivot_mode("bbox")
	_ok("bounding box: x 5.5", _near(map.pivot_point(ids), Vector3(5.5, 0.5, 0.5)), map.pivot_point(ids))
	map.set_pivot_mode("median")
	_ok("median: x 4.5", _near(map.pivot_point(ids), Vector3(4.5, 0.5, 0.5)), map.pivot_point(ids))
	var cur: Node3D = map.get("_cursor3d")
	cur.global_position = (level as Node3D).global_transform * Vector3(3, 7, -2)
	map.set_pivot_mode("cursor")
	_ok("3D cursor: where the cursor is (level space)", _near(map.pivot_point(ids), Vector3(3, 7, -2)), map.pivot_point(ids))
	map.set_pivot_mode("active")
	_ok("active: the last-selected brush (x 10.5)", _near(map.pivot_point(ids), Vector3(10.5, 0.5, 0.5)), map.pivot_point(ids))

	print("-- the tools use it --")
	map.set_pivot_mode("cursor")
	map._unhandled_key_input(_key(KEY_R))
	var stack: Node = map.call("_ensure_ops")
	var rot: Object = stack.get("active")
	_ok("R starts rotate", rot is RotateOperator, rot)
	if rot is RotateOperator:
		_ok("... about the 3D cursor", _near(rot.get("_pivot"), Vector3(3, 7, -2)), rot.get("_pivot"))
		stack.cancel()
	map.set_pivot_mode("median")
	map._unhandled_key_input(_key(KEY_S))
	var sc: Object = stack.get("active")
	if sc is ScaleOperator:
		sc.set_tool_setting("pivot", 1)                 # not the base
		_ok("scale with base off scales about the pivot (median)", _near(sc.pivot(), Vector3(4.5, 0.5, 0.5)), sc.pivot())
		sc.set_tool_setting("pivot", 0)
		stack.cancel()
	else:
		_ok("S starts scale", false, sc)
	map.set_pivot_mode("bbox")