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")