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,77 @@
[gd_scene load_steps=3 format=3 uid="uid://display_settings_scene"]
[ext_resource type="Script" uid="uid://display_settings_script" path="res://scripts/UI/DisplaySettings.cs" id="1_dispset"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dispset"]
bg_color = Color(0, 0, 0, 1)
[node name="Display settings" type="Control" node_paths=PackedStringArray("WindowModeButton", "ResolutionButton", "DisplaySettingsControl")]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 6
size_flags_vertical = 6
script = ExtResource("1_dispset")
WindowModeButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Window Mode/WindowModeButton")
ResolutionButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Resolution/ResolutionButton")
DisplaySettingsControl = NodePath(".")
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_dispset")
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer"]
layout_mode = 2
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/MarginContainer"]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="Display" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "DISPLAY"
horizontal_alignment = 1
vertical_alignment = 1
uppercase = true
[node name="Spacer" type="Control" parent="PanelContainer/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
size_flags_vertical = 3
[node name="Window Mode" type="VBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 4
[node name="Label" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer/Window Mode"]
layout_mode = 2
text = "WINDOW_MODE"
horizontal_alignment = 1
[node name="WindowModeButton" type="OptionButton" parent="PanelContainer/MarginContainer/VBoxContainer/Window Mode"]
layout_mode = 2
[node name="Resolution" type="VBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 4
[node name="Label" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer/Resolution"]
layout_mode = 2
text = "RESOLUTION"
horizontal_alignment = 1
[node name="ResolutionButton" type="OptionButton" parent="PanelContainer/MarginContainer/VBoxContainer/Resolution"]
layout_mode = 2

View File

@@ -59,7 +59,6 @@ flat = true
[node name="Display Settings Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"] [node name="Display Settings Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2 layout_mode = 2
disabled = true
text = "DISPLAY_BUTTON" text = "DISPLAY_BUTTON"
flat = true flat = true

View File

@@ -1,10 +1,11 @@
[gd_scene load_steps=6 format=3 uid="uid://cl00e2ocomk3m"] [gd_scene load_steps=7 format=3 uid="uid://cl00e2ocomk3m"]
[ext_resource type="PackedScene" uid="uid://8b6ol5sssbgo" path="res://objects/ui/main_menu.tscn" id="1_ekxnf"] [ext_resource type="PackedScene" uid="uid://8b6ol5sssbgo" path="res://objects/ui/main_menu.tscn" id="1_ekxnf"]
[ext_resource type="PackedScene" uid="uid://y0ae6e7t70fj" path="res://objects/ui/settings_menu.tscn" id="2_bqqt6"] [ext_resource type="PackedScene" uid="uid://y0ae6e7t70fj" path="res://objects/ui/settings_menu.tscn" id="2_bqqt6"]
[ext_resource type="PackedScene" uid="uid://bwgmrcyj4mvu" path="res://objects/ui/credits.tscn" id="3_bqqt6"] [ext_resource type="PackedScene" uid="uid://bwgmrcyj4mvu" path="res://objects/ui/credits.tscn" id="3_bqqt6"]
[ext_resource type="PackedScene" uid="uid://b5fx1vdfky307" path="res://objects/ui/audio_settings.tscn" id="4_8ln24"] [ext_resource type="PackedScene" uid="uid://b5fx1vdfky307" path="res://objects/ui/audio_settings.tscn" id="4_8ln24"]
[ext_resource type="PackedScene" uid="uid://cvfsbiy5ggrpg" path="res://objects/ui/input_settings.tscn" id="5_rtw2f"] [ext_resource type="PackedScene" uid="uid://cvfsbiy5ggrpg" path="res://objects/ui/input_settings.tscn" id="5_rtw2f"]
[ext_resource type="PackedScene" uid="uid://display_settings_scene" path="res://objects/ui/display_settings.tscn" id="6_dispset"]
[node name="Main menu" type="CanvasLayer"] [node name="Main menu" type="CanvasLayer"]
@@ -34,8 +35,5 @@ anchors_preset = 0
offset_right = 40.0 offset_right = 40.0
offset_bottom = 40.0 offset_bottom = 40.0
[node name="Display Settings" type="Control" parent="."] [node name="Display Settings" parent="." instance=ExtResource("6_dispset")]
layout_mode = 3 visible = false
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0

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;
}
}