123 lines
5.6 KiB
GDScript
123 lines
5.6 KiB
GDScript
extends Node
|
|
|
|
const GAME := preload("res://scenes/game/game.tscn")
|
|
|
|
func motion(point: Vector2, relative: Vector2 = Vector2.ZERO) -> void:
|
|
var event := InputEventMouseMotion.new()
|
|
event.position = point
|
|
event.global_position = point
|
|
event.relative = relative
|
|
event.button_mask = MOUSE_BUTTON_MASK_LEFT if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) else 0
|
|
get_viewport().push_input(event, true)
|
|
|
|
func mouse(point: Vector2, pressed: bool) -> void:
|
|
var event := InputEventMouseButton.new()
|
|
event.position = point
|
|
event.global_position = point
|
|
event.button_index = MOUSE_BUTTON_LEFT
|
|
event.pressed = pressed
|
|
event.button_mask = MOUSE_BUTTON_MASK_LEFT if pressed else 0
|
|
get_viewport().push_input(event, true)
|
|
|
|
func click(point: Vector2) -> void:
|
|
motion(point)
|
|
mouse(point, true)
|
|
mouse(point, false)
|
|
|
|
func drag(header: Control, displacement: Vector2) -> void:
|
|
var origin := header.get_global_rect().position + Vector2(15, header.get_global_rect().size.y * 0.5)
|
|
motion(origin)
|
|
mouse(origin, true)
|
|
motion(origin + displacement, displacement)
|
|
mouse(origin + displacement, false)
|
|
|
|
func _ready() -> void:
|
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
|
GameState.start_new_run()
|
|
var game := GAME.instantiate() as Node2D
|
|
add_child(game)
|
|
await get_tree().process_frame
|
|
await get_tree().process_frame
|
|
game.set_physics_process(false)
|
|
var ship := game.get_node("PlayerShip") as CharacterBody2D
|
|
ship.set_physics_process(false)
|
|
ship.get_node("WeaponController").set_physics_process(false)
|
|
for enemy in get_tree().get_nodes_in_group("enemies"):
|
|
enemy.set_physics_process(false)
|
|
var hud := game.get_node("HUD")
|
|
var manager := hud.get_node("HUDRoot/FloatingWindows")
|
|
var craft: PanelContainer = hud.get("_crafting_window")
|
|
var inventory: Control = hud.get("inventory_panel")
|
|
var drawer: Control = hud.get("_inventory_clip")
|
|
var sidebar: Control = hud.get("_sidebar")
|
|
hud.call("_toggle_inventory")
|
|
craft.show()
|
|
await get_tree().process_frame
|
|
await get_tree().process_frame
|
|
# Put inventory directly behind crafting. Its salvage button occupies the same pixel.
|
|
drawer.set_meta("floating_window_dragged", true)
|
|
var recipe: Button = craft.get_node("Contents/CraftingPanel").get("_recipe_buttons")["parts"]
|
|
var point := recipe.get_global_rect().get_center()
|
|
var first_slot := inventory.get_node("Contents/CargoGrid").get_child(0) as Control
|
|
drawer.global_position += point - first_slot.get_global_rect().get_center()
|
|
manager.call("focus_window", drawer)
|
|
manager.call("focus_window", craft)
|
|
var stock := ship.get_node("ShipInventory") as ShipInventory
|
|
var item := ItemInstance.new()
|
|
item.definition = preload("res://resources/items/plasma_cannon.tres")
|
|
assert(stock.add_item(item))
|
|
GameState.captain.minerals.merge({"iron": 2, "titanium": 2, "aluminium": 2}, true)
|
|
GameState.captain.emit_changed()
|
|
await get_tree().process_frame
|
|
assert(manager.call("window_at", point) == craft)
|
|
click(point)
|
|
assert(GameState.captain.parts == 1.0, "Top crafting button must receive the click")
|
|
assert(stock.cargo[0] == item, "Underlying inventory must not consume the click")
|
|
assert(craft.z_index > drawer.z_index)
|
|
assert(craft.get_index() > drawer.get_index())
|
|
# Dragging a title moves its window; content clicks do not start a window drag.
|
|
var before := craft.global_position
|
|
drag(craft.get_node("Contents/Header"), Vector2(-80, -60))
|
|
assert(craft.global_position.is_equal_approx(before + Vector2(-80, -60)))
|
|
await get_tree().process_frame
|
|
assert(craft.global_position.is_equal_approx(before + Vector2(-80, -60)))
|
|
# The exposed inventory header can activate and raise the lower window.
|
|
drawer.global_position = Vector2(70, 80)
|
|
manager.call("focus_window", craft)
|
|
var inv_header := inventory.get_node("Contents/Header") as Control
|
|
click(inv_header.get_global_rect().position + Vector2(10, 8))
|
|
assert(drawer.z_index > craft.z_index and drawer.get_index() > craft.get_index())
|
|
before = drawer.global_position
|
|
drag(inv_header, Vector2(100, 80))
|
|
assert(drawer.global_position.is_equal_approx(before + Vector2(100, 80)))
|
|
hud.call("_layout_inventory")
|
|
assert(drawer.global_position.is_equal_approx(before + Vector2(100, 80)))
|
|
# Close buttons do not turn into drag handles; reopening preserves the moved position.
|
|
click(inventory.get_node("Contents/Header/CloseButton").get_global_rect().get_center())
|
|
assert(not inventory.visible)
|
|
inventory.call("_set_drawer_open", true)
|
|
assert(drawer.global_position.is_equal_approx(before + Vector2(100, 80)))
|
|
# Sidebar dragging survives equipment relayout and viewport clamping.
|
|
manager.call("focus_window", sidebar)
|
|
before = sidebar.global_position
|
|
drag(sidebar.get_node("Scroll/Contents/ShipEquipmentPanel/Contents/Title"), Vector2(-100, -50))
|
|
hud.call("_layout_sidebar")
|
|
assert(sidebar.global_position.is_equal_approx(before + Vector2(-100, -50)))
|
|
# The captain modal remains draggable while paused and blocks windows below it.
|
|
var skills: CanvasLayer = hud.get("_captain_skills_ui")
|
|
skills.call("open_management")
|
|
await get_tree().process_frame
|
|
await get_tree().process_frame
|
|
assert(get_tree().paused)
|
|
var panel: Control = skills.get("_panel")
|
|
before = panel.global_position
|
|
drag((skills.get("_contents") as Control).get_node("Header"), Vector2(50, 30))
|
|
assert(panel.global_position.is_equal_approx(before + Vector2(50, 30)))
|
|
skills.call("_layout")
|
|
assert(panel.global_position.is_equal_approx(before + Vector2(50, 30)))
|
|
skills.call("_close")
|
|
assert(not get_tree().paused)
|
|
assert(not ship.get_node("WeaponController").get("_fire_buttons_down")[0])
|
|
print("FLOATING_WINDOWS_TEST: PASS (real GUI click routing over inventory, matching z/tree order, title drag, focus/raise, close/reopen, relayout persistence, paused captain modal, gameplay input blocked)")
|
|
get_tree().quit()
|