204 lines
7.2 KiB
C#
204 lines
7.2 KiB
C#
using Godot;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Mr.BrickAdventures.Autoloads;
|
|
|
|
public partial class SettingsManager : Node
|
|
{
|
|
public static SettingsManager Instance { get; private set; }
|
|
|
|
public float GamepadDeadzone { get; set; } = 0.2f;
|
|
public float GamepadSensitivity { get; set; } = 1.0f;
|
|
public string WindowMode { get; set; } = "fullscreen";
|
|
public Vector2I Resolution { get; set; } = new Vector2I(1920, 1080);
|
|
|
|
private static readonly List<Vector2I> CuratedResolutions = new()
|
|
{
|
|
// 4:3
|
|
new Vector2I(640, 480),
|
|
new Vector2I(800, 600),
|
|
new Vector2I(1024, 768),
|
|
new Vector2I(1280, 960),
|
|
new Vector2I(1600, 1200),
|
|
// 16:9
|
|
new Vector2I(1280, 720),
|
|
new Vector2I(1366, 768),
|
|
new Vector2I(1600, 900),
|
|
new Vector2I(1920, 1080),
|
|
new Vector2I(2560, 1440),
|
|
new Vector2I(3840, 2160),
|
|
// 16:10
|
|
new Vector2I(1280, 800),
|
|
new Vector2I(1440, 900),
|
|
new Vector2I(1920, 1200),
|
|
new Vector2I(2560, 1600),
|
|
};
|
|
|
|
private readonly List<Vector2I> _customResolutions = new();
|
|
|
|
private static readonly string[] DeadzoneActions = { "left", "right", "up", "down" };
|
|
|
|
public override void _Ready()
|
|
{
|
|
Instance = this;
|
|
|
|
if (ConfigFileHandler.Instance == null)
|
|
{
|
|
GD.PushError("SettingsManager: ConfigFileHandler.Instance is null");
|
|
return;
|
|
}
|
|
|
|
var cfg = ConfigFileHandler.Instance.SettingsConfig;
|
|
|
|
// --- display_settings ---
|
|
WindowMode = cfg.GetValue("display_settings", "window_mode", Variant.From("fullscreen")).AsString();
|
|
var resStr = cfg.GetValue("display_settings", "resolution", Variant.From("1920x1080")).AsString();
|
|
Resolution = ParseResolution(resStr, new Vector2I(1920, 1080));
|
|
|
|
var customResStr = cfg.GetValue("display_settings", "custom_resolutions", Variant.From("")).AsString();
|
|
if (!string.IsNullOrWhiteSpace(customResStr))
|
|
{
|
|
foreach (var part in customResStr.Split(','))
|
|
{
|
|
var r = ParseResolution(part.Trim(), Vector2I.Zero);
|
|
if (r != Vector2I.Zero)
|
|
_customResolutions.Add(r);
|
|
}
|
|
}
|
|
|
|
ApplyDisplaySettings();
|
|
|
|
// --- gameplay_settings ---
|
|
GamepadDeadzone = (float)cfg.GetValue("gameplay_settings", "gamepad_deadzone", Variant.From(0.2)).AsDouble();
|
|
GamepadSensitivity = (float)cfg.GetValue("gameplay_settings", "gamepad_sensitivity", Variant.From(1.0)).AsDouble();
|
|
|
|
ApplyGamepadDeadzone();
|
|
|
|
// --- input_settings ---
|
|
ApplyInputBindings(cfg);
|
|
}
|
|
|
|
public override void _ExitTree()
|
|
{
|
|
if (Instance == this) Instance = null;
|
|
}
|
|
|
|
// ── public API ───────────────────────────────────────────────────────────
|
|
|
|
public List<Vector2I> GetAllResolutions()
|
|
{
|
|
var all = new List<Vector2I>(CuratedResolutions);
|
|
all.AddRange(_customResolutions);
|
|
return all;
|
|
}
|
|
|
|
public void SaveDisplaySettings()
|
|
{
|
|
var cfg = ConfigFileHandler.Instance.SettingsConfig;
|
|
cfg.SetValue("display_settings", "window_mode", WindowMode);
|
|
cfg.SetValue("display_settings", "resolution", $"{Resolution.X}x{Resolution.Y}");
|
|
cfg.SetValue("display_settings", "custom_resolutions", BuildCustomResolutionsString());
|
|
cfg.Save(ConfigFileHandler.SettingsPath);
|
|
}
|
|
|
|
public void SaveGameplaySettings()
|
|
{
|
|
var cfg = ConfigFileHandler.Instance.SettingsConfig;
|
|
cfg.SetValue("gameplay_settings", "gamepad_deadzone", (double)GamepadDeadzone);
|
|
cfg.SetValue("gameplay_settings", "gamepad_sensitivity", (double)GamepadSensitivity);
|
|
cfg.Save(ConfigFileHandler.SettingsPath);
|
|
}
|
|
|
|
public void SaveInputSettings()
|
|
{
|
|
var cfg = ConfigFileHandler.Instance.SettingsConfig;
|
|
foreach (var action in InputMap.GetActions())
|
|
{
|
|
if (action.ToString().StartsWith("ui_")) continue;
|
|
foreach (var ev in InputMap.ActionGetEvents(action))
|
|
{
|
|
if (ev is InputEventKey key)
|
|
{
|
|
cfg.SetValue("input_settings", action, (long)key.PhysicalKeycode);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
cfg.Save(ConfigFileHandler.SettingsPath);
|
|
}
|
|
|
|
// ── apply helpers ────────────────────────────────────────────────────────
|
|
|
|
private void ApplyDisplaySettings()
|
|
{
|
|
switch (WindowMode)
|
|
{
|
|
case "fullscreen":
|
|
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Fullscreen);
|
|
break;
|
|
case "borderless":
|
|
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Windowed);
|
|
DisplayServer.WindowSetFlag(DisplayServer.WindowFlags.Borderless, true);
|
|
DisplayServer.WindowSetSize(Resolution);
|
|
break;
|
|
default: // "windowed"
|
|
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Windowed);
|
|
DisplayServer.WindowSetFlag(DisplayServer.WindowFlags.Borderless, false);
|
|
DisplayServer.WindowSetSize(Resolution);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void ApplyGamepadDeadzone()
|
|
{
|
|
foreach (var action in DeadzoneActions)
|
|
{
|
|
if (InputMap.HasAction(action))
|
|
InputMap.ActionSetDeadzone(action, GamepadDeadzone);
|
|
}
|
|
}
|
|
|
|
private static void ApplyInputBindings(ConfigFile cfg)
|
|
{
|
|
if (!cfg.HasSection("input_settings")) return;
|
|
|
|
foreach (var actionName in cfg.GetSectionKeys("input_settings"))
|
|
{
|
|
if (actionName.StartsWith("ui_")) continue;
|
|
if (!InputMap.HasAction(actionName)) continue;
|
|
|
|
var scancode = (Key)(long)cfg.GetValue("input_settings", actionName);
|
|
|
|
// Remove existing keyboard events for this action
|
|
var events = InputMap.ActionGetEvents(actionName);
|
|
foreach (var ev in events)
|
|
{
|
|
if (ev is InputEventKey)
|
|
InputMap.ActionEraseEvent(actionName, ev);
|
|
}
|
|
|
|
// Add the saved key
|
|
var newKey = new InputEventKey { PhysicalKeycode = scancode };
|
|
InputMap.ActionAddEvent(actionName, newKey);
|
|
}
|
|
}
|
|
|
|
// ── util ─────────────────────────────────────────────────────────────────
|
|
|
|
private static Vector2I ParseResolution(string s, Vector2I fallback)
|
|
{
|
|
var parts = s.Split('x');
|
|
if (parts.Length == 2 && int.TryParse(parts[0], out var w) && int.TryParse(parts[1], out var h))
|
|
return new Vector2I(w, h);
|
|
return fallback;
|
|
}
|
|
|
|
private string BuildCustomResolutionsString()
|
|
{
|
|
var parts = new List<string>();
|
|
foreach (var r in _customResolutions)
|
|
parts.Add($"{r.X}x{r.Y}");
|
|
return string.Join(",", parts);
|
|
}
|
|
}
|