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"]
|
[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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
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