using System;
using System.Collections.Generic;
using System.IO;
using Cthangover.BaseMenu;
using Cthangover.Core.Bootstrap;
using Cthangover.Core.Mods;
using Cthangover.Core.Settings;
using Cthangover.Core.Utils;
using Godot;
namespace Mods.DisplaySettingsTest
{
///
/// Display tab of the settings menu driven like a player, one step per tick
/// so the window settles: windowed mode with a picked size gives a window of
/// that size centred on the monitor; borderless fullscreen disables the size
/// list; the frame rate cap and V-Sync are applied; every change is in the
/// settings file at once; a "restart" (the file read anew and applied to a
/// window put in another state) restores it all; reset returns the game
/// defaults. The player's settings file is restored at the end. With a shots
/// directory the main menu and every settings tab are saved as PNG. Prints
/// [TEST_RESULT] name=display_settings.
///
public partial class DisplaySettingsTestDriverNode : Node
{
private const string Display = "Window/Column/Body/Pages/Display/";
private const float TimeoutSeconds = 60f;
private const string ResetButton = "Window/Column/Footer/Row/ResetButton";
private static readonly Vector2I WindowSize = new(1280, 720);
private readonly List failures = new();
private readonly string settingsPath = ProjectSettings.GlobalizePath("user://settings.json");
private readonly string backup;
private readonly string shotsDir;
private SettingsMenu menu;
private int passed;
private int step;
private int shotTab;
private double elapsed;
private double stepAt;
private bool done;
public DisplaySettingsTestDriverNode(string shotsDir)
{
this.shotsDir = shotsDir;
backup = File.Exists(settingsPath) ? File.ReadAllText(settingsPath) : null;
}
public override void _Process(double delta)
{
if (done)
return;
elapsed += delta;
if (elapsed > TimeoutSeconds)
{
failures.Add($"timeout at step {step}");
Finish();
return;
}
if (elapsed - stepAt < 0.5)
return;
stepAt = elapsed;
try
{
RunStep();
}
catch (Exception ex)
{
failures.Add($"step {step}: {ex.GetType().Name}: {ex.Message}");
Finish();
}
}
private void RunStep()
{
switch (step)
{
case 0:
if (!Boot.IsReady)
return;
if (GetTree().CurrentScene?.FindChild("LauncherPlay", true, false) is Button launcherPlay)
{
launcherPlay.EmitSignal(BaseButton.SignalName.Pressed);
return;
}
if (GetTree().CurrentScene is not MainMenu main)
return;
menu = main.GetNodeOrNull("SettingsPanel");
Check("settings panel exists", menu != null);
if (menu == null)
{
Finish();
return;
}
Shot("main_menu");
menu.Open();
shotTab = 0;
step = 100;
return;
case 100:
// One tick per settings tab for the screenshots, then the Display tab checks.
if (shotTab > 0)
Shot("settings_" + shotTab);
if (shotTab < 4 && !string.IsNullOrEmpty(shotsDir))
{
menu.ShowTab(shotTab++);
return;
}
menu.ShowTab(2);
Check("the Display tab shows its page and the display reset",
menu.GetNode("Window/Column/Body/Pages/Display").Visible && !menu.GetNode("Window/Column/Body/Pages/Audio").Visible
&& menu.GetNode