2026-08-02 00:45:07 -04:00
|
|
|
extends SceneTree
|
|
|
|
|
|
|
|
|
|
const MainScene: PackedScene = preload("res://main/main.tscn")
|
|
|
|
|
const TEST_PORT: int = 18136
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _initialize() -> void:
|
|
|
|
|
call_deferred("_run")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _run() -> void:
|
|
|
|
|
root.size = Vector2i(1280, 720)
|
|
|
|
|
var main: Node = MainScene.instantiate()
|
|
|
|
|
root.add_child(main)
|
|
|
|
|
for _frame: int in 4:
|
|
|
|
|
await process_frame
|
|
|
|
|
if not bool(main.get("_application_initialized")):
|
|
|
|
|
main.call("_activate_selected_data_path", "", true)
|
|
|
|
|
for _frame: int in 8:
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(bool(main.get("_application_initialized")))
|
|
|
|
|
assert(bool(main.call("_prepare_private_host")))
|
|
|
|
|
var save_manager := main.get("_save_manager") as PlayerSaveManager
|
|
|
|
|
assert(save_manager.initialize_new_game())
|
|
|
|
|
main.call("_enter_gameplay")
|
|
|
|
|
await physics_frame
|
|
|
|
|
await physics_frame
|
|
|
|
|
|
|
|
|
|
var player := main.get("_player") as Player
|
|
|
|
|
var service := main.get_node(
|
|
|
|
|
"%NetworkSurfaceDrawingService"
|
|
|
|
|
) as NetworkSurfaceDrawingService
|
|
|
|
|
var game_ui := main.get_node("%GameUI") as GameUI
|
|
|
|
|
var toolbar := game_ui.get_node(
|
|
|
|
|
"%SurfaceDrawingToolbar"
|
|
|
|
|
) as SurfaceDrawingToolbar
|
2026-08-02 09:20:44 -04:00
|
|
|
var chat_ui := game_ui.get_node("%ChatUI") as ChatUI
|
2026-08-02 00:45:07 -04:00
|
|
|
assert(player != null and service != null and toolbar != null)
|
2026-08-02 09:20:44 -04:00
|
|
|
assert(chat_ui != null)
|
2026-08-03 20:49:19 -04:00
|
|
|
assert(bool(game_ui.call("_can_start_virtual_mouse")))
|
|
|
|
|
game_ui.call("_begin_virtual_mouse", 0)
|
|
|
|
|
var virtual_cursor := game_ui.get_node(
|
|
|
|
|
"%ControllerVirtualCursor"
|
|
|
|
|
) as ControllerVirtualCursor
|
|
|
|
|
assert(virtual_cursor.visible)
|
|
|
|
|
assert(not player.is_camera_input_enabled())
|
|
|
|
|
game_ui.call("_end_virtual_mouse")
|
|
|
|
|
assert(not virtual_cursor.visible)
|
|
|
|
|
assert(player.is_camera_input_enabled())
|
2026-08-02 09:20:44 -04:00
|
|
|
var settings_panel := game_ui.get(
|
|
|
|
|
"_pause_settings_panel"
|
|
|
|
|
) as SettingsPanel
|
|
|
|
|
var chat_dock_button := settings_panel.get_node("%ChatDock") as BubbleButton
|
2026-08-03 20:49:19 -04:00
|
|
|
var chat_mode_button := settings_panel.get_node("%ChatMode") as BubbleButton
|
2026-08-02 09:20:44 -04:00
|
|
|
var paint_dock_button := settings_panel.get_node("%PaintDock") as BubbleButton
|
|
|
|
|
assert(chat_dock_button.neutral_size.x == chat_dock_button.neutral_size.y)
|
2026-08-03 20:49:19 -04:00
|
|
|
assert(chat_mode_button.neutral_size.x == chat_mode_button.neutral_size.y)
|
2026-08-02 09:20:44 -04:00
|
|
|
assert(paint_dock_button.neutral_size.x == paint_dock_button.neutral_size.y)
|
|
|
|
|
assert(
|
|
|
|
|
chat_dock_button.compact_minimum_size.x
|
|
|
|
|
== chat_dock_button.compact_minimum_size.y
|
|
|
|
|
)
|
2026-08-03 20:49:19 -04:00
|
|
|
assert(
|
|
|
|
|
chat_mode_button.compact_minimum_size.x
|
|
|
|
|
== chat_mode_button.compact_minimum_size.y
|
|
|
|
|
)
|
2026-08-02 09:20:44 -04:00
|
|
|
assert(
|
|
|
|
|
paint_dock_button.compact_minimum_size.x
|
|
|
|
|
== paint_dock_button.compact_minimum_size.y
|
|
|
|
|
)
|
|
|
|
|
assert(not chat_ui.is_docked_right())
|
|
|
|
|
assert(toolbar.is_docked_right())
|
|
|
|
|
var settings_manager := main.get_node(
|
|
|
|
|
"%PlayerSettingsManager"
|
|
|
|
|
) as PlayerSettingsManager
|
|
|
|
|
assert(settings_manager != null)
|
|
|
|
|
var changed_docks: PlayerSettings = settings_manager.current_settings.copy()
|
|
|
|
|
changed_docks.chat_dock_right = true
|
2026-08-03 20:49:19 -04:00
|
|
|
changed_docks.chat_mobile_mode = true
|
2026-08-02 09:20:44 -04:00
|
|
|
changed_docks.paint_dock_right = false
|
|
|
|
|
assert(settings_manager.apply_settings(changed_docks))
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(chat_ui.is_docked_right())
|
2026-08-03 20:49:19 -04:00
|
|
|
assert(chat_ui.is_mobile_mode())
|
2026-08-02 09:20:44 -04:00
|
|
|
assert(not toolbar.is_docked_right())
|
2026-08-03 20:49:19 -04:00
|
|
|
var chat_panel := chat_ui.get_node("ChatPanel") as PanelContainer
|
|
|
|
|
var chat_height_button := chat_ui.get_node("ChatHeightButton") as Button
|
|
|
|
|
assert(is_zero_approx(chat_panel.position.y))
|
|
|
|
|
assert(is_equal_approx(chat_panel.size.x, ChatUI.MOBILE_COMPACT_WIDTH))
|
|
|
|
|
assert(not chat_height_button.visible)
|
2026-08-02 09:20:44 -04:00
|
|
|
var reloaded_settings := PlayerSettingsManager.new()
|
|
|
|
|
root.add_child(reloaded_settings)
|
|
|
|
|
assert(reloaded_settings.load_settings())
|
|
|
|
|
assert(reloaded_settings.current_settings.chat_dock_right)
|
2026-08-03 20:49:19 -04:00
|
|
|
assert(reloaded_settings.current_settings.chat_mobile_mode)
|
2026-08-02 09:20:44 -04:00
|
|
|
assert(not reloaded_settings.current_settings.paint_dock_right)
|
|
|
|
|
reloaded_settings.queue_free()
|
|
|
|
|
var default_docks: PlayerSettings = settings_manager.current_settings.copy()
|
|
|
|
|
default_docks.chat_dock_right = false
|
2026-08-03 20:49:19 -04:00
|
|
|
default_docks.chat_mobile_mode = false
|
2026-08-02 09:20:44 -04:00
|
|
|
default_docks.paint_dock_right = true
|
|
|
|
|
assert(settings_manager.apply_settings(default_docks))
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(not chat_ui.is_docked_right())
|
2026-08-03 20:49:19 -04:00
|
|
|
assert(not chat_ui.is_mobile_mode())
|
2026-08-02 09:20:44 -04:00
|
|
|
assert(toolbar.is_docked_right())
|
2026-08-03 20:49:19 -04:00
|
|
|
assert(chat_height_button.visible)
|
|
|
|
|
var select_button := InputEventJoypadButton.new()
|
|
|
|
|
select_button.button_index = JOY_BUTTON_BACK
|
|
|
|
|
select_button.pressed = true
|
|
|
|
|
assert(bool(game_ui.call("_handle_controller_chat_controls", select_button)))
|
|
|
|
|
assert(chat_ui.is_open())
|
|
|
|
|
assert(chat_panel.mouse_filter == Control.MOUSE_FILTER_STOP)
|
|
|
|
|
var typed_chat_entry := chat_ui.find_child(
|
|
|
|
|
"ChatEntry", true, false
|
|
|
|
|
) as LineEdit
|
|
|
|
|
assert(typed_chat_entry != null)
|
|
|
|
|
assert(not typed_chat_entry.virtual_keyboard_enabled)
|
|
|
|
|
var accept_button := InputEventJoypadButton.new()
|
|
|
|
|
accept_button.button_index = JOY_BUTTON_A
|
|
|
|
|
accept_button.pressed = true
|
|
|
|
|
assert(bool(game_ui.call("_handle_controller_chat_controls", accept_button)))
|
|
|
|
|
assert(typed_chat_entry.virtual_keyboard_enabled)
|
|
|
|
|
var left_bumper := InputEventJoypadButton.new()
|
|
|
|
|
left_bumper.button_index = JOY_BUTTON_LEFT_SHOULDER
|
|
|
|
|
left_bumper.pressed = true
|
|
|
|
|
assert(bool(game_ui.call("_handle_controller_chat_controls", left_bumper)))
|
|
|
|
|
assert(not chat_ui.is_open())
|
|
|
|
|
assert(chat_panel.mouse_filter == Control.MOUSE_FILTER_IGNORE)
|
|
|
|
|
assert(not typed_chat_entry.virtual_keyboard_enabled)
|
|
|
|
|
assert(bool(game_ui.call("_handle_controller_chat_controls", left_bumper)))
|
|
|
|
|
assert(chat_ui.is_open())
|
|
|
|
|
assert(not typed_chat_entry.virtual_keyboard_enabled)
|
|
|
|
|
assert(bool(game_ui.call("_handle_controller_chat_controls", left_bumper)))
|
|
|
|
|
assert(not chat_ui.is_open())
|
|
|
|
|
assert(bool(game_ui.call("_handle_controller_chat_controls", select_button)))
|
|
|
|
|
assert(not chat_ui.is_open())
|
|
|
|
|
assert(chat_ui.is_collapsed())
|
|
|
|
|
assert(bool(game_ui.call("_handle_controller_chat_controls", select_button)))
|
|
|
|
|
assert(chat_ui.is_open())
|
|
|
|
|
chat_ui.refocus_gameplay()
|
|
|
|
|
var cancel_button := InputEventJoypadButton.new()
|
|
|
|
|
cancel_button.button_index = JOY_BUTTON_B
|
|
|
|
|
cancel_button.pressed = true
|
|
|
|
|
assert(not bool(main.call("_is_pause_open_request", cancel_button)))
|
|
|
|
|
var start_button := InputEventJoypadButton.new()
|
|
|
|
|
start_button.button_index = JOY_BUTTON_START
|
|
|
|
|
start_button.pressed = true
|
|
|
|
|
assert(bool(main.call("_is_pause_open_request", start_button)))
|
|
|
|
|
var player_menu := game_ui.get_node("%PlayerMenu") as PlayerMenu
|
|
|
|
|
player_menu.open_section(PlayerMenu.Section.PROFILE)
|
|
|
|
|
for _frame: int in 12:
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(root.gui_get_focus_owner() is not LineEdit)
|
|
|
|
|
player_menu.close_menu()
|
|
|
|
|
for _frame: int in 12:
|
|
|
|
|
await process_frame
|
2026-08-02 00:45:07 -04:00
|
|
|
assert(not service.can_activate())
|
|
|
|
|
assert(not service.is_active() and not toolbar.visible)
|
|
|
|
|
assert(player.bag.add_item(ArtShopStock.ART_KIT_ITEM_ID, 1))
|
|
|
|
|
assert(service.can_activate())
|
|
|
|
|
|
|
|
|
|
var paint_key := InputEventKey.new()
|
|
|
|
|
paint_key.physical_keycode = KEY_P
|
|
|
|
|
paint_key.pressed = true
|
|
|
|
|
assert(service.handle_input(paint_key, true))
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(service.is_active() and service.is_placement_mode())
|
|
|
|
|
assert(toolbar.visible)
|
2026-08-02 09:20:44 -04:00
|
|
|
var ui_root := game_ui.get_node("%UIRoot") as Control
|
|
|
|
|
assert(toolbar.get_parent() == ui_root)
|
|
|
|
|
assert(is_zero_approx(toolbar.position.y))
|
|
|
|
|
assert(
|
|
|
|
|
is_equal_approx(
|
|
|
|
|
toolbar.get_global_rect().end.x,
|
|
|
|
|
ui_root.get_global_rect().end.x,
|
|
|
|
|
)
|
|
|
|
|
)
|
2026-08-02 00:45:07 -04:00
|
|
|
assert(toolbar.get_global_rect().end.x <= 1280.0)
|
|
|
|
|
assert(toolbar.get_global_rect().end.y <= 720.0)
|
2026-08-02 09:20:44 -04:00
|
|
|
var top_panel := toolbar.get_node("%TopPanel") as PanelContainer
|
|
|
|
|
var color_panel := toolbar.get_node("%ColorPanel") as PanelContainer
|
|
|
|
|
assert(top_panel.position.is_equal_approx(Vector2.ZERO))
|
|
|
|
|
assert(color_panel.position.x > 0.0)
|
|
|
|
|
assert(is_equal_approx(color_panel.get_rect().end.x, top_panel.get_rect().end.x))
|
|
|
|
|
assert(color_panel.position.y < top_panel.get_rect().end.y)
|
|
|
|
|
assert(color_panel.get_rect().end.y > top_panel.get_rect().end.y)
|
|
|
|
|
var toolbar_origin: Vector2 = toolbar.get_global_rect().position
|
|
|
|
|
var top_pointer := InputEventMouseMotion.new()
|
|
|
|
|
top_pointer.position = toolbar_origin + Vector2(200.0, 24.0)
|
|
|
|
|
assert(toolbar.owns_pointer_event(top_pointer))
|
|
|
|
|
var rail_pointer := InputEventMouseMotion.new()
|
|
|
|
|
rail_pointer.position = color_panel.get_global_rect().get_center()
|
|
|
|
|
assert(toolbar.owns_pointer_event(rail_pointer))
|
|
|
|
|
var empty_pointer := InputEventMouseMotion.new()
|
|
|
|
|
empty_pointer.position = toolbar_origin + Vector2(200.0, 180.0)
|
|
|
|
|
assert(not toolbar.owns_pointer_event(empty_pointer))
|
2026-08-02 00:45:07 -04:00
|
|
|
|
|
|
|
|
var brush_option := toolbar.get_node("%BrushOption") as OptionButton
|
|
|
|
|
var grid_option := toolbar.get_node("%GridOption") as OptionButton
|
2026-08-02 09:20:44 -04:00
|
|
|
var mode_button := toolbar.get_node("%ModeButton") as Button
|
|
|
|
|
var eraser_button := toolbar.get_node("%EraserButton") as Button
|
|
|
|
|
var undo_button := toolbar.get_node("%UndoButton") as Button
|
|
|
|
|
var hide_button := toolbar.get_node("%HideGuideButton") as Button
|
|
|
|
|
var restore_button := toolbar.get_node("%RestoreGuideButton") as Button
|
|
|
|
|
var finalize_button := toolbar.get_node("%FinalizeGuideButton") as Button
|
|
|
|
|
var close_button := toolbar.get_node("%CloseButton") as Button
|
|
|
|
|
assert(
|
|
|
|
|
mode_button != null
|
|
|
|
|
and eraser_button != null
|
|
|
|
|
and undo_button != null
|
|
|
|
|
and hide_button != null
|
|
|
|
|
and restore_button != null
|
|
|
|
|
and finalize_button != null
|
|
|
|
|
and close_button != null
|
|
|
|
|
)
|
2026-08-02 00:45:07 -04:00
|
|
|
assert(brush_option.item_count == 4)
|
|
|
|
|
assert(grid_option.item_count == 4)
|
|
|
|
|
assert(not brush_option.get_popup().is_item_disabled(0))
|
|
|
|
|
assert(brush_option.get_popup().is_item_disabled(1))
|
|
|
|
|
assert(not grid_option.get_popup().is_item_disabled(0))
|
|
|
|
|
assert(grid_option.get_popup().is_item_disabled(1))
|
|
|
|
|
var color_buttons: Dictionary = toolbar.get("_color_buttons")
|
|
|
|
|
assert(color_buttons.size() == SurfaceDrawingPalette.COLORS.size())
|
|
|
|
|
assert(not (color_buttons[&"chalk_white"] as Button).disabled)
|
|
|
|
|
assert((color_buttons[&"ocean_teal"] as Button).disabled)
|
|
|
|
|
|
|
|
|
|
for product_id: StringName in [
|
|
|
|
|
&"marker_ocean_teal", &"brush_4x", &"grid_128x",
|
|
|
|
|
]:
|
|
|
|
|
assert(player.art_unlocks.unlock_product(product_id))
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(not (color_buttons[&"ocean_teal"] as Button).disabled)
|
|
|
|
|
assert(not brush_option.get_popup().is_item_disabled(3))
|
|
|
|
|
assert(not grid_option.get_popup().is_item_disabled(3))
|
|
|
|
|
assert(service.set_color_id(&"ocean_teal"))
|
|
|
|
|
assert(service.set_brush_size(4))
|
|
|
|
|
assert(service.set_grid_size(128))
|
|
|
|
|
assert(service.get_color_id() == &"ocean_teal")
|
|
|
|
|
assert(service.get_brush_size() == 4)
|
|
|
|
|
assert(service.get_grid_size() == 128)
|
|
|
|
|
|
2026-08-02 09:20:44 -04:00
|
|
|
mode_button.pressed.emit()
|
|
|
|
|
assert(not service.is_placement_mode())
|
|
|
|
|
eraser_button.pressed.emit()
|
|
|
|
|
assert(service.is_eraser_mode())
|
|
|
|
|
assert(eraser_button.button_pressed)
|
|
|
|
|
hide_button.pressed.emit()
|
|
|
|
|
assert(service.is_placement_mode())
|
|
|
|
|
assert(not service.is_eraser_mode())
|
|
|
|
|
assert(
|
|
|
|
|
service.get_armed_guide_action()
|
|
|
|
|
== NetworkSurfaceDrawingService.GuideAction.HIDE
|
|
|
|
|
)
|
|
|
|
|
var world_click := InputEventMouseButton.new()
|
|
|
|
|
world_click.button_index = MOUSE_BUTTON_LEFT
|
|
|
|
|
world_click.pressed = true
|
|
|
|
|
assert(service.handle_input(world_click, true))
|
|
|
|
|
assert(
|
|
|
|
|
service.get_armed_guide_action()
|
|
|
|
|
== NetworkSurfaceDrawingService.GuideAction.NONE
|
|
|
|
|
)
|
|
|
|
|
assert(not service.is_placement_mode())
|
|
|
|
|
assert(service.is_eraser_mode())
|
|
|
|
|
|
|
|
|
|
restore_button.pressed.emit()
|
|
|
|
|
assert(
|
|
|
|
|
service.get_armed_guide_action()
|
|
|
|
|
== NetworkSurfaceDrawingService.GuideAction.RESTORE
|
|
|
|
|
)
|
|
|
|
|
restore_button.pressed.emit()
|
|
|
|
|
assert(
|
|
|
|
|
service.get_armed_guide_action()
|
|
|
|
|
== NetworkSurfaceDrawingService.GuideAction.NONE
|
|
|
|
|
)
|
|
|
|
|
assert(not service.is_placement_mode() and service.is_eraser_mode())
|
|
|
|
|
finalize_button.pressed.emit()
|
|
|
|
|
assert(
|
|
|
|
|
service.get_armed_guide_action()
|
|
|
|
|
== NetworkSurfaceDrawingService.GuideAction.FINALIZE
|
|
|
|
|
)
|
|
|
|
|
assert(service.handle_input(world_click, true))
|
|
|
|
|
assert(not service.is_placement_mode() and service.is_eraser_mode())
|
|
|
|
|
(color_buttons[&"ocean_teal"] as Button).pressed.emit()
|
|
|
|
|
assert(not service.is_eraser_mode())
|
|
|
|
|
undo_button.pressed.emit()
|
|
|
|
|
assert(service.is_active())
|
|
|
|
|
close_button.pressed.emit()
|
|
|
|
|
assert(not service.is_active() and not toolbar.visible)
|
|
|
|
|
|
|
|
|
|
assert(service.handle_input(paint_key, true))
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(service.is_active() and toolbar.visible)
|
|
|
|
|
|
2026-08-02 00:45:07 -04:00
|
|
|
assert(service.handle_input(paint_key, true))
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(not service.is_active() and not toolbar.visible)
|
|
|
|
|
assert(player.hotbar.assign_item(0, ArtShopStock.ART_KIT_ITEM_ID))
|
2026-08-10 21:40:55 -04:00
|
|
|
player.hotbar.select_slot(0)
|
2026-08-02 00:45:07 -04:00
|
|
|
var fishing_spot := main.get_node("%FishingSpot") as FishingSpot
|
|
|
|
|
await process_frame
|
2026-08-10 21:40:55 -04:00
|
|
|
assert(not fishing_spot.has_signal(&"art_ui_toggle_requested"))
|
2026-08-02 00:45:07 -04:00
|
|
|
assert(service.is_active() and toolbar.visible)
|
|
|
|
|
assert(service.get_grid_size() == 128)
|
2026-08-10 21:40:55 -04:00
|
|
|
assert(service.handle_input(world_click, true))
|
|
|
|
|
assert(service.is_active() and toolbar.visible)
|
|
|
|
|
player.hotbar.select_slot(1)
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(not service.is_active() and not toolbar.visible)
|
|
|
|
|
assert(service.handle_input(paint_key, true))
|
|
|
|
|
await process_frame
|
|
|
|
|
assert(service.is_active() and toolbar.visible)
|
2026-08-02 00:45:07 -04:00
|
|
|
|
|
|
|
|
print("Art tools validation: PASS")
|
|
|
|
|
var session := main.get_node("%NetworkSession") as NetworkSession
|
|
|
|
|
session.disconnect_session("")
|
|
|
|
|
main.queue_free()
|
|
|
|
|
await process_frame
|
|
|
|
|
quit()
|