feat: display settings screen with window mode and resolution picker

This commit is contained in:
2026-03-19 03:32:40 +01:00
parent 0105698c33
commit 8cce1866b1
4 changed files with 225 additions and 7 deletions

View File

@@ -0,0 +1,144 @@
using Godot;
using Mr.BrickAdventures.Autoloads;
namespace Mr.BrickAdventures.scripts.UI;
public partial class DisplaySettings : Control
{
[Export] public OptionButton WindowModeButton { get; set; }
[Export] public OptionButton ResolutionButton { get; set; }
[Export] public Control DisplaySettingsControl { get; set; }
private UIManager UIManager => UIManager.Instance;
public override void _Ready()
{
PopulateWindowMode();
PopulateResolutions();
WindowModeButton.ItemSelected += OnWindowModeChanged;
ResolutionButton.ItemSelected += OnResolutionChanged;
LoadSettings();
if (InputDeviceManager.Instance != null)
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
DisplaySettingsControl.VisibilityChanged += OnVisibilityChanged;
}
public override void _ExitTree()
{
if (InputDeviceManager.Instance != null)
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
DisplaySettingsControl.VisibilityChanged -= OnVisibilityChanged;
SettingsManager.Instance?.SaveDisplaySettings();
}
public override void _UnhandledInput(InputEvent @event)
{
if (!@event.IsActionReleased("ui_cancel")) return;
if (!UIManager.IsScreenOnTop(DisplaySettingsControl)) return;
SettingsManager.Instance?.SaveDisplaySettings();
UIManager.PopScreen();
}
private void OnVisibilityChanged()
{
if (DisplaySettingsControl.IsVisibleInTree() && InputDeviceManager.Instance?.IsPointerless == true)
GrabFirstFocus();
}
private void OnDeviceChanged(int device)
{
var d = (InputDeviceManager.InputDevice)device;
if (d != InputDeviceManager.InputDevice.Mouse && DisplaySettingsControl.IsVisibleInTree())
GrabFirstFocus();
}
private void GrabFirstFocus() => WindowModeButton.GrabFocus();
private void PopulateWindowMode()
{
WindowModeButton.Clear();
WindowModeButton.AddItem("Fullscreen", 0);
WindowModeButton.AddItem("Borderless", 1);
WindowModeButton.AddItem("Windowed", 2);
}
private void PopulateResolutions()
{
ResolutionButton.Clear();
foreach (var res in SettingsManager.Instance.GetAllResolutions())
{
string label = $"{res.X}×{res.Y}";
ResolutionButton.AddItem(label);
}
}
private void OnWindowModeChanged(long idx)
{
string mode = idx switch
{
0 => "fullscreen",
1 => "borderless",
_ => "windowed"
};
ApplyWindowMode(mode);
SettingsManager.Instance.WindowMode = mode;
ResolutionButton.Disabled = mode == "fullscreen";
SettingsManager.Instance.SaveDisplaySettings();
}
private void OnResolutionChanged(long idx)
{
var resolutions = SettingsManager.Instance.GetAllResolutions();
if (idx < 0 || idx >= resolutions.Count) return;
var res = resolutions[(int)idx];
SettingsManager.Instance.Resolution = res;
var mode = SettingsManager.Instance.WindowMode;
if (mode != "fullscreen")
DisplayServer.WindowSetSize(res);
SettingsManager.Instance.SaveDisplaySettings();
}
private static void ApplyWindowMode(string mode)
{
switch (mode)
{
case "fullscreen":
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Fullscreen);
break;
case "borderless":
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Windowed);
DisplayServer.WindowSetFlag(DisplayServer.WindowFlags.Borderless, true);
break;
default:
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Windowed);
DisplayServer.WindowSetFlag(DisplayServer.WindowFlags.Borderless, false);
break;
}
}
private void LoadSettings()
{
var mode = SettingsManager.Instance.WindowMode;
WindowModeButton.Selected = mode switch
{
"fullscreen" => 0,
"borderless" => 1,
_ => 2
};
ResolutionButton.Disabled = mode == "fullscreen";
var resolution = SettingsManager.Instance.Resolution;
var resolutions = SettingsManager.Instance.GetAllResolutions();
int resIdx = resolutions.IndexOf(resolution);
if (resIdx >= 0)
ResolutionButton.Selected = resIdx;
}
}