208 lines
6.3 KiB
GDScript3
208 lines
6.3 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
const TitleScreenScene := preload("res://ui/title_screen.tscn")
|
||
|
|
const TitleCreditsPageType = preload("res://ui/title_credits_page.gd")
|
||
|
|
|
||
|
|
var _failures: Array[String] = []
|
||
|
|
|
||
|
|
|
||
|
|
func _initialize() -> void:
|
||
|
|
_run.call_deferred()
|
||
|
|
|
||
|
|
|
||
|
|
func _run() -> void:
|
||
|
|
var original_size: Vector2i = root.size
|
||
|
|
root.size = Vector2i(1280, 720)
|
||
|
|
var title_screen := TitleScreenScene.instantiate() as TitleScreen
|
||
|
|
root.add_child(title_screen)
|
||
|
|
await process_frame
|
||
|
|
await process_frame
|
||
|
|
|
||
|
|
var credits_button := title_screen.get_node(
|
||
|
|
"%CreditsButton"
|
||
|
|
) as BubbleButton
|
||
|
|
var credits_page := title_screen.get_node(
|
||
|
|
"%CreditsPage"
|
||
|
|
) as TitleCreditsPageType
|
||
|
|
var back_button: Button = credits_page.get_back_button()
|
||
|
|
var presentation := title_screen.get_node("%Center") as Control
|
||
|
|
var bubble_field := title_screen.get_node("%BubbleField") as Control
|
||
|
|
title_screen.call("_update_title_layout")
|
||
|
|
(title_screen.get_node("%ButtonCenter") as Control).show()
|
||
|
|
bubble_field.show()
|
||
|
|
title_screen.call("_set_title_bubbles_interactive", true)
|
||
|
|
await process_frame
|
||
|
|
|
||
|
|
_expect(credits_button != null, "title menu exposes a credits button")
|
||
|
|
_expect(credits_page != null, "title screen contains the credits page")
|
||
|
|
_expect(not credits_page.visible, "credits page starts closed")
|
||
|
|
_expect(
|
||
|
|
Rect2(Vector2.ZERO, bubble_field.size).encloses(
|
||
|
|
Rect2(credits_button.position, credits_button.size)
|
||
|
|
),
|
||
|
|
"credits bubble stays inside the authored title field",
|
||
|
|
)
|
||
|
|
_expect(
|
||
|
|
credits_button.mouse_filter == Control.MOUSE_FILTER_STOP,
|
||
|
|
"credits bubble accepts pointer input",
|
||
|
|
)
|
||
|
|
if OS.has_environment("NETFISHING_TITLE_MENU_CAPTURE"):
|
||
|
|
(title_screen.get_node("%StartPromptCenter") as Control).hide()
|
||
|
|
title_screen.set_process(true)
|
||
|
|
await create_timer(0.5).timeout
|
||
|
|
_expect(
|
||
|
|
_save_capture(
|
||
|
|
OS.get_environment("NETFISHING_TITLE_MENU_CAPTURE")
|
||
|
|
) == OK,
|
||
|
|
"title menu validation capture saves successfully",
|
||
|
|
)
|
||
|
|
title_screen.set_process(false)
|
||
|
|
|
||
|
|
title_screen.set("_navigation_focus_active", false)
|
||
|
|
credits_button.pressed.emit()
|
||
|
|
await process_frame
|
||
|
|
_expect(credits_page.visible, "pointer activation opens credits")
|
||
|
|
_expect(not presentation.visible, "credits replace the primary title menu")
|
||
|
|
_expect(
|
||
|
|
root.gui_get_focus_owner() != back_button,
|
||
|
|
"pointer activation does not pseudo-select back",
|
||
|
|
)
|
||
|
|
await create_timer(0.25).timeout
|
||
|
|
_expect(
|
||
|
|
credits_page.mouse_filter == Control.MOUSE_FILTER_PASS,
|
||
|
|
"credits page becomes pointer-interactive after entry motion",
|
||
|
|
)
|
||
|
|
_expect(
|
||
|
|
back_button.mouse_filter == Control.MOUSE_FILTER_STOP,
|
||
|
|
"credits back button accepts pointer clicks",
|
||
|
|
)
|
||
|
|
if OS.has_environment("NETFISHING_CREDITS_CAPTURE"):
|
||
|
|
await process_frame
|
||
|
|
_expect(
|
||
|
|
_save_capture(
|
||
|
|
OS.get_environment("NETFISHING_CREDITS_CAPTURE")
|
||
|
|
) == OK,
|
||
|
|
"credits validation capture saves successfully",
|
||
|
|
)
|
||
|
|
back_button.pressed.emit()
|
||
|
|
await process_frame
|
||
|
|
_expect(not credits_page.visible, "pointer back closes credits")
|
||
|
|
_expect(presentation.visible, "closing credits restores the title menu")
|
||
|
|
_expect(
|
||
|
|
root.gui_get_focus_owner() == null,
|
||
|
|
"pointer return leaves the title menu unfocused",
|
||
|
|
)
|
||
|
|
|
||
|
|
title_screen.set("_navigation_focus_active", true)
|
||
|
|
credits_button.grab_focus()
|
||
|
|
credits_button.pressed.emit()
|
||
|
|
await process_frame
|
||
|
|
await process_frame
|
||
|
|
_expect(
|
||
|
|
root.gui_get_focus_owner() == back_button,
|
||
|
|
"keyboard or controller activation focuses the credits back button",
|
||
|
|
)
|
||
|
|
|
||
|
|
var pointer_motion := InputEventMouseMotion.new()
|
||
|
|
pointer_motion.position = Vector2(640.0, 360.0)
|
||
|
|
title_screen._input(pointer_motion)
|
||
|
|
await process_frame
|
||
|
|
_expect(
|
||
|
|
root.gui_get_focus_owner() == null,
|
||
|
|
"pointer motion clears credits navigation focus",
|
||
|
|
)
|
||
|
|
|
||
|
|
var navigate := InputEventAction.new()
|
||
|
|
navigate.action = &"ui_down"
|
||
|
|
navigate.pressed = true
|
||
|
|
title_screen._input(navigate)
|
||
|
|
await process_frame
|
||
|
|
_expect(
|
||
|
|
root.gui_get_focus_owner() == back_button,
|
||
|
|
"navigation input restores credits focus",
|
||
|
|
)
|
||
|
|
|
||
|
|
var cancel := InputEventAction.new()
|
||
|
|
cancel.action = &"ui_cancel"
|
||
|
|
cancel.pressed = true
|
||
|
|
title_screen._input(cancel)
|
||
|
|
await process_frame
|
||
|
|
_expect(not credits_page.visible, "ui cancel closes credits")
|
||
|
|
_expect(
|
||
|
|
root.gui_get_focus_owner() == credits_button,
|
||
|
|
"navigation return restores focus to the credits bubble",
|
||
|
|
)
|
||
|
|
|
||
|
|
var chillnfill_name := credits_page.get_node(
|
||
|
|
"Paper/Margin/Layout/Columns/CreativeCredits/ChillnfillName"
|
||
|
|
) as Label
|
||
|
|
var voyager_name := credits_page.get_node(
|
||
|
|
"Paper/Margin/Layout/Columns/CreativeCredits/VoyagerName"
|
||
|
|
) as Label
|
||
|
|
var endeavour_name := credits_page.get_node(
|
||
|
|
"Paper/Margin/Layout/Columns/CreativeCredits/EndeavourName"
|
||
|
|
) as Label
|
||
|
|
var chillnfill_credit := credits_page.get_node(
|
||
|
|
"Paper/Margin/Layout/Columns/CreativeCredits/ChillnfillCredit"
|
||
|
|
) as Label
|
||
|
|
var tekgator_name := credits_page.get_node(
|
||
|
|
"Paper/Margin/Layout/Columns/CreativeCredits/TekgatorName"
|
||
|
|
) as Label
|
||
|
|
var tekgator_credit := credits_page.get_node(
|
||
|
|
"Paper/Margin/Layout/Columns/CreativeCredits/TekgatorCredit"
|
||
|
|
) as Label
|
||
|
|
var creative_credits := credits_page.get_node(
|
||
|
|
"Paper/Margin/Layout/Columns/CreativeCredits"
|
||
|
|
) as VBoxContainer
|
||
|
|
_expect(voyager_name.text == "Voyager", "in-game credits use Voyager")
|
||
|
|
_expect(
|
||
|
|
endeavour_name.text == "Endeavour",
|
||
|
|
"in-game credits use Endeavour",
|
||
|
|
)
|
||
|
|
_expect(
|
||
|
|
chillnfill_name.text == "chillnfill",
|
||
|
|
"in-game credits name chillnfill",
|
||
|
|
)
|
||
|
|
_expect(
|
||
|
|
"trees and bridges" in chillnfill_credit.text.to_lower(),
|
||
|
|
"in-game credits describe the supplied model families",
|
||
|
|
)
|
||
|
|
_expect(
|
||
|
|
tekgator_name.text == "Tekgator",
|
||
|
|
"in-game credits name Tekgator",
|
||
|
|
)
|
||
|
|
_expect(
|
||
|
|
"shop icon" in tekgator_credit.text.to_lower(),
|
||
|
|
"in-game credits describe Tekgator's shop icon artwork",
|
||
|
|
)
|
||
|
|
_expect(
|
||
|
|
Rect2(Vector2.ZERO, creative_credits.size).encloses(
|
||
|
|
Rect2(tekgator_credit.position, tekgator_credit.size)
|
||
|
|
),
|
||
|
|
"Tekgator's credit stays inside the authored credits column",
|
||
|
|
)
|
||
|
|
|
||
|
|
title_screen.queue_free()
|
||
|
|
root.size = original_size
|
||
|
|
await process_frame
|
||
|
|
await process_frame
|
||
|
|
if _failures.is_empty():
|
||
|
|
print("Title credits validation: PASS")
|
||
|
|
quit(0)
|
||
|
|
return
|
||
|
|
for failure: String in _failures:
|
||
|
|
push_error(failure)
|
||
|
|
quit(1)
|
||
|
|
|
||
|
|
|
||
|
|
func _expect(condition: bool, message: String) -> void:
|
||
|
|
if not condition:
|
||
|
|
_failures.append(message)
|
||
|
|
|
||
|
|
|
||
|
|
func _save_capture(path: String) -> Error:
|
||
|
|
var viewport_texture: Texture2D = root.get_texture()
|
||
|
|
if viewport_texture == null:
|
||
|
|
return ERR_UNAVAILABLE
|
||
|
|
return viewport_texture.get_image().save_png(path)
|