274 lines
8.3 KiB
GDScript3
274 lines
8.3 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
const PlayerMenuScene = preload("res://ui/player_menu.tscn")
|
||
|
|
const UIReferencePresentationType = preload(
|
||
|
|
"res://ui/ui_reference_presentation.gd"
|
||
|
|
)
|
||
|
|
const EXPECTED_HOST_SIZE := Vector2(278.0, 484.0)
|
||
|
|
const EXPECTED_ART_SIZE := Vector2(306.28125, 580.8)
|
||
|
|
const EXPECTED_ART_POSITION := Vector2(-4.140625, -28.4)
|
||
|
|
const INVENTORY_PANEL_RECT := Rect2(54.0, 166.0, 882.0, 484.0)
|
||
|
|
const NOTEPAD_HOST_RECT := Rect2(952.0, 166.0, 278.0, 484.0)
|
||
|
|
const NOTEPAD_ART_RECT := Rect2(
|
||
|
|
NOTEPAD_HOST_RECT.position + EXPECTED_ART_POSITION,
|
||
|
|
EXPECTED_ART_SIZE,
|
||
|
|
)
|
||
|
|
const HOTBAR_BUBBLE_FIELD_RECT := Rect2(245.0, 608.0, 790.0, 104.0)
|
||
|
|
const TARGET_SIZES: Array[Vector2] = [
|
||
|
|
Vector2(1280.0, 720.0),
|
||
|
|
Vector2(1920.0, 1080.0),
|
||
|
|
Vector2(2560.0, 1440.0),
|
||
|
|
Vector2(3840.0, 2160.0),
|
||
|
|
Vector2(640.0, 480.0),
|
||
|
|
Vector2(1024.0, 768.0),
|
||
|
|
Vector2(1729.0, 973.0),
|
||
|
|
Vector2(2560.0, 1080.0),
|
||
|
|
Vector2(3440.0, 1440.0),
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
func _initialize() -> void:
|
||
|
|
call_deferred("_run")
|
||
|
|
|
||
|
|
|
||
|
|
func _run() -> void:
|
||
|
|
_print_runtime_parameters()
|
||
|
|
var presentation_stage := Control.new()
|
||
|
|
presentation_stage.name = "CanonicalUIStage"
|
||
|
|
_apply_stage_layout(presentation_stage, Vector2(root.size))
|
||
|
|
root.add_child(presentation_stage)
|
||
|
|
var player_menu := PlayerMenuScene.instantiate() as PlayerMenu
|
||
|
|
presentation_stage.add_child(player_menu)
|
||
|
|
await process_frame
|
||
|
|
var notepads: Array[Node] = player_menu.find_children(
|
||
|
|
"*", "InventoryNotepad", true, false
|
||
|
|
)
|
||
|
|
assert(notepads.size() == 3)
|
||
|
|
for node: Node in notepads:
|
||
|
|
var notepad := node as InventoryNotepad
|
||
|
|
assert(notepad != null)
|
||
|
|
assert(notepad.size.is_equal_approx(EXPECTED_HOST_SIZE))
|
||
|
|
assert(notepad.mouse_filter == Control.MOUSE_FILTER_PASS)
|
||
|
|
var art_rect: Rect2 = notepad.get_art_rect()
|
||
|
|
assert(art_rect.size.is_equal_approx(EXPECTED_ART_SIZE))
|
||
|
|
assert(art_rect.position.is_equal_approx(EXPECTED_ART_POSITION))
|
||
|
|
assert(art_rect.get_center().is_equal_approx(
|
||
|
|
EXPECTED_HOST_SIZE * 0.5
|
||
|
|
+ InventoryNotepad.NOTEPAD_ART_OFFSET
|
||
|
|
))
|
||
|
|
_validate_shared_inventory_geometry(player_menu)
|
||
|
|
_validate_inventory_layering(player_menu)
|
||
|
|
_validate_resolution_matrix()
|
||
|
|
await _capture_inventory_pages(player_menu)
|
||
|
|
print("Inventory notepad artwork validation: PASS")
|
||
|
|
presentation_stage.queue_free()
|
||
|
|
await process_frame
|
||
|
|
quit()
|
||
|
|
|
||
|
|
|
||
|
|
func _print_runtime_parameters() -> void:
|
||
|
|
var window: Window = root
|
||
|
|
var screen_index: int = window.current_screen
|
||
|
|
print(
|
||
|
|
(
|
||
|
|
"Runtime UI: window=%s screen=%s screen_scale=%.3f dpi=%d "
|
||
|
|
+ "content_size=%s content_mode=%d content_aspect=%d "
|
||
|
|
+ "content_factor=%.3f"
|
||
|
|
)
|
||
|
|
% [
|
||
|
|
window.size,
|
||
|
|
DisplayServer.screen_get_size(screen_index),
|
||
|
|
DisplayServer.screen_get_scale(screen_index),
|
||
|
|
DisplayServer.screen_get_dpi(screen_index),
|
||
|
|
window.content_scale_size,
|
||
|
|
window.content_scale_mode,
|
||
|
|
window.content_scale_aspect,
|
||
|
|
window.content_scale_factor,
|
||
|
|
]
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
func _apply_stage_layout(stage: Control, display_size: Vector2) -> void:
|
||
|
|
stage.set_anchors_preset(Control.PRESET_TOP_LEFT)
|
||
|
|
stage.position = UIReferencePresentationType.get_offset(display_size)
|
||
|
|
stage.size = UIReferencePresentationType.REFERENCE_SIZE
|
||
|
|
stage.scale = Vector2.ONE * UIReferencePresentationType.get_scale(
|
||
|
|
display_size
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
func _validate_shared_inventory_geometry(player_menu: PlayerMenu) -> void:
|
||
|
|
for node_name: StringName in [
|
||
|
|
&"DetailConstellation",
|
||
|
|
&"BagDetailConstellation",
|
||
|
|
&"TackleDetailPanel",
|
||
|
|
]:
|
||
|
|
var host := player_menu.get_node("%%%s" % node_name) as Control
|
||
|
|
assert(host != null)
|
||
|
|
assert(host.position.is_equal_approx(Vector2(952.0, 166.0)))
|
||
|
|
assert(host.size.is_equal_approx(EXPECTED_HOST_SIZE))
|
||
|
|
|
||
|
|
|
||
|
|
func _validate_inventory_layering(player_menu: PlayerMenu) -> void:
|
||
|
|
var bag_filters := player_menu.get_node("%BagFilterTabs") as Control
|
||
|
|
var bag_panel := player_menu.get_node("%BagOuterWall") as Control
|
||
|
|
var sale_confirmation := player_menu.get_node("%SaleConfirmation") as Control
|
||
|
|
var cooler_panel := player_menu.get_node("%CoolerOuterWall") as Control
|
||
|
|
var tackle_panel := player_menu.get_node("%TackleMainPanel") as Control
|
||
|
|
assert(bag_filters != null)
|
||
|
|
assert(bag_panel != null)
|
||
|
|
assert(sale_confirmation != null)
|
||
|
|
assert(cooler_panel != null)
|
||
|
|
assert(tackle_panel != null)
|
||
|
|
assert(bag_filters.z_index > bag_panel.z_index)
|
||
|
|
assert(sale_confirmation.z_index > cooler_panel.z_index)
|
||
|
|
assert(sale_confirmation.z_index > tackle_panel.z_index)
|
||
|
|
# The contextual Hotbar uses z=90 while the Player Menu is open.
|
||
|
|
assert(sale_confirmation.z_index > 90)
|
||
|
|
assert(sale_confirmation.position.is_equal_approx(Vector2(380.0, 265.0)))
|
||
|
|
assert(sale_confirmation.size.is_equal_approx(Vector2(520.0, 190.0)))
|
||
|
|
var confirmation_style := sale_confirmation.get_theme_stylebox(
|
||
|
|
"panel"
|
||
|
|
) as StyleBoxFlat
|
||
|
|
assert(confirmation_style != null)
|
||
|
|
assert(
|
||
|
|
confirmation_style.bg_color.is_equal_approx(
|
||
|
|
UtilityPageStyle.OCEAN_PANEL_DEEP
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
func _validate_resolution_matrix() -> void:
|
||
|
|
for target_size: Vector2 in TARGET_SIZES:
|
||
|
|
var stage_rect: Rect2 = UIReferencePresentationType.get_rect(
|
||
|
|
target_size
|
||
|
|
)
|
||
|
|
var stage_scale: float = UIReferencePresentationType.get_scale(
|
||
|
|
target_size
|
||
|
|
)
|
||
|
|
assert(is_equal_approx(
|
||
|
|
stage_rect.size.x / stage_rect.size.y,
|
||
|
|
1280.0 / 720.0,
|
||
|
|
))
|
||
|
|
assert(stage_rect.get_center().is_equal_approx(target_size * 0.5))
|
||
|
|
_validate_transformed_rect(
|
||
|
|
"Inventory panel", INVENTORY_PANEL_RECT, stage_rect, stage_scale
|
||
|
|
)
|
||
|
|
_validate_transformed_rect(
|
||
|
|
"Notepad host", NOTEPAD_HOST_RECT, stage_rect, stage_scale
|
||
|
|
)
|
||
|
|
_validate_transformed_rect(
|
||
|
|
"Notepad art", NOTEPAD_ART_RECT, stage_rect, stage_scale
|
||
|
|
)
|
||
|
|
_validate_transformed_rect(
|
||
|
|
"Hotbar", HOTBAR_BUBBLE_FIELD_RECT, stage_rect, stage_scale
|
||
|
|
)
|
||
|
|
var screen_host: Rect2 = _to_screen_rect(
|
||
|
|
NOTEPAD_HOST_RECT, stage_rect.position, stage_scale
|
||
|
|
)
|
||
|
|
var screen_art: Rect2 = _to_screen_rect(
|
||
|
|
NOTEPAD_ART_RECT, stage_rect.position, stage_scale
|
||
|
|
)
|
||
|
|
assert(is_equal_approx(
|
||
|
|
screen_art.size.y,
|
||
|
|
screen_host.size.y * InventoryNotepad.NOTEPAD_CANONICAL_OVERSCAN,
|
||
|
|
))
|
||
|
|
assert(screen_art.get_center().is_equal_approx(
|
||
|
|
screen_host.get_center()
|
||
|
|
+ InventoryNotepad.NOTEPAD_ART_OFFSET * stage_scale
|
||
|
|
))
|
||
|
|
print(
|
||
|
|
(
|
||
|
|
"UI geometry: window=%s stage=%s scale=%.6f "
|
||
|
|
+ "inventory=%s notepad=%s art=%s hotbar=%s"
|
||
|
|
)
|
||
|
|
% [
|
||
|
|
target_size,
|
||
|
|
stage_rect,
|
||
|
|
stage_scale,
|
||
|
|
_to_screen_rect(
|
||
|
|
INVENTORY_PANEL_RECT,
|
||
|
|
stage_rect.position,
|
||
|
|
stage_scale,
|
||
|
|
),
|
||
|
|
screen_host,
|
||
|
|
screen_art,
|
||
|
|
_to_screen_rect(
|
||
|
|
HOTBAR_BUBBLE_FIELD_RECT,
|
||
|
|
stage_rect.position,
|
||
|
|
stage_scale,
|
||
|
|
),
|
||
|
|
]
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
func _validate_transformed_rect(
|
||
|
|
label: String,
|
||
|
|
canonical_rect: Rect2,
|
||
|
|
stage_rect: Rect2,
|
||
|
|
stage_scale: float,
|
||
|
|
) -> void:
|
||
|
|
var screen_rect: Rect2 = _to_screen_rect(
|
||
|
|
canonical_rect, stage_rect.position, stage_scale
|
||
|
|
)
|
||
|
|
assert(
|
||
|
|
screen_rect.position.is_equal_approx(
|
||
|
|
stage_rect.position + canonical_rect.position * stage_scale
|
||
|
|
),
|
||
|
|
"%s position does not use the single stage transform" % label,
|
||
|
|
)
|
||
|
|
assert(
|
||
|
|
screen_rect.size.is_equal_approx(canonical_rect.size * stage_scale),
|
||
|
|
"%s size does not use the single stage transform" % label,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
func _to_screen_rect(
|
||
|
|
canonical_rect: Rect2,
|
||
|
|
stage_offset: Vector2,
|
||
|
|
stage_scale: float,
|
||
|
|
) -> Rect2:
|
||
|
|
return Rect2(
|
||
|
|
stage_offset + canonical_rect.position * stage_scale,
|
||
|
|
canonical_rect.size * stage_scale,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
func _capture_inventory_pages(player_menu: PlayerMenu) -> void:
|
||
|
|
if not OS.has_environment("NETFISHING_NOTEPAD_CAPTURE"):
|
||
|
|
return
|
||
|
|
player_menu.visible = true
|
||
|
|
var sections: Array[PlayerMenu.Section] = [
|
||
|
|
PlayerMenu.Section.COOLER,
|
||
|
|
PlayerMenu.Section.TACKLE_BOX,
|
||
|
|
PlayerMenu.Section.BAG,
|
||
|
|
]
|
||
|
|
var suffixes: Array[String] = ["cooler", "tackle", "equipment"]
|
||
|
|
for index: int in sections.size():
|
||
|
|
player_menu.call("_show_section_immediate", sections[index])
|
||
|
|
await process_frame
|
||
|
|
await process_frame
|
||
|
|
await _save_capture(suffixes[index])
|
||
|
|
player_menu.call("_show_section_immediate", PlayerMenu.Section.COOLER)
|
||
|
|
var sale_confirmation := player_menu.get_node("%SaleConfirmation") as Control
|
||
|
|
var confirmation_message := player_menu.get_node(
|
||
|
|
"%ConfirmationMessage"
|
||
|
|
) as Label
|
||
|
|
assert(sale_confirmation != null)
|
||
|
|
assert(confirmation_message != null)
|
||
|
|
confirmation_message.text = "sell selected fish?"
|
||
|
|
sale_confirmation.visible = true
|
||
|
|
await process_frame
|
||
|
|
await process_frame
|
||
|
|
await _save_capture("sale-confirmation")
|
||
|
|
sale_confirmation.visible = false
|
||
|
|
|
||
|
|
|
||
|
|
func _save_capture(suffix: String) -> void:
|
||
|
|
var image: Image = root.get_texture().get_image()
|
||
|
|
var path: String = "%s-%s.png" % [
|
||
|
|
OS.get_environment("NETFISHING_NOTEPAD_CAPTURE"),
|
||
|
|
suffix,
|
||
|
|
]
|
||
|
|
assert(image.save_png(path) == OK)
|