feat: display settings screen with window mode and resolution picker
This commit is contained in:
77
objects/ui/display_settings.tscn
Normal file
77
objects/ui/display_settings.tscn
Normal 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
|
||||
@@ -59,7 +59,6 @@ flat = true
|
||||
|
||||
[node name="Display Settings Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
disabled = true
|
||||
text = "DISPLAY_BUTTON"
|
||||
flat = true
|
||||
|
||||
|
||||
@@ -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://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://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://display_settings_scene" path="res://objects/ui/display_settings.tscn" id="6_dispset"]
|
||||
|
||||
[node name="Main menu" type="CanvasLayer"]
|
||||
|
||||
@@ -34,8 +35,5 @@ anchors_preset = 0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
|
||||
[node name="Display Settings" type="Control" parent="."]
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
offset_right = 40.0
|
||||
offset_bottom = 40.0
|
||||
[node name="Display Settings" parent="." instance=ExtResource("6_dispset")]
|
||||
visible = false
|
||||
|
||||
144
scripts/UI/DisplaySettings.cs
Normal file
144
scripts/UI/DisplaySettings.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user