extends Node
## GATE — MODIFIER KEYS (#120 L1 §12.5; the menu + hotkey rule).
## K1 Shift+Ctrl+M on a shape opens Add modifier
## K2 ... its rows show their letters (M A G R C B D)
## K3 G picks Grid: the shape gains a grid modifier, the menu closes
## K4 Shift+Ctrl+M then D adds a Dice
##
## RUN AS A SCENE: CI=true "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_mod_keys.tscn
var fails := 0
var checks := 0
var map: Node3D
var persist: Node
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:
get_tree().root.size = Vector2i(1920, 1080)
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")
map = (load("res://scenes/maps/map_dev_test.tscn") as PackedScene).instantiate()
add_child(map)
for i in 6:
await get_tree().process_frame
await _run()
get_tree().root.get_node("/root/GameMode").set_mode("play")
if checks < 5:
print(" **FAIL** only %d checks ran -- setup died before the assertions" % checks)
fails += 1
print("\nGATE mod_keys: %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, ctrl := false) -> InputEventKey:
var e := InputEventKey.new()
e.keycode = code
e.physical_keycode = code
e.shift_pressed = shift
e.ctrl_pressed = ctrl
e.pressed = true
return e
func _kinds(shape: String) -> Array:
var out: Array = []
for m: Dictionary in (map.modifier_stack(shape) as Array):
out.append(String(m["kind"]))
return out
func _run() -> void:
persist = map.get("_persist")
var s: String = persist.record("shape.create", {"type": "box", "gv": 1, "params": {},
"frame": SceneObjects.xform_to(Transform3D(Basis.IDENTITY, Vector3(140, 0, 140))),
"size": [1, 1, 1], "material_id": 2, "level_id": 0})
persist.refold()
map.select_shape(s)
await get_tree().process_frame
var q: Node = map.get("_q_menu")
var menu: PopupMenu = q.get("_menu")
# ---- K1 / K2 ----
get_viewport().push_input(_key(KEY_M, true, true))
await get_tree().process_frame
_ok("K1 Shift+Ctrl+M opens Add modifier", q.is_open())
var shown: Array = []
for i in menu.item_count:
if menu.get_item_accelerator(i) != 0:
shown.append(OS.get_keycode_string(menu.get_item_accelerator(i)))
shown.sort()
_ok("K2 its rows show their letters", shown == ["A", "B", "C", "D", "G", "M", "R"], shown)
# ---- K3 ----
q.call("_on_window_input", _key(KEY_G))
for i in 3:
await get_tree().process_frame
_ok("K3 G adds a Grid", _kinds(s).has("grid"), _kinds(s))
_ok("K3 ... and the menu closed", not q.is_open())
# ---- K4 ----
get_viewport().push_input(_key(KEY_M, true, true))
await get_tree().process_frame
q.call("_on_window_input", _key(KEY_D))
for i in 3:
await get_tree().process_frame
_ok("K4 Shift+Ctrl+M, D adds a Dice", _kinds(s).has("dice"), _kinds(s))