Compare commits
17 Commits
53ebbbbac3
...
057cf7b368
| Author | SHA1 | Date | |
|---|---|---|---|
| 057cf7b368 | |||
| 829d081eab | |||
| 38c86f1a67 | |||
| e647cd7b29 | |||
| 9043cfa63c | |||
| dc46769c11 | |||
| 47600be867 | |||
| 3e74959bb9 | |||
| 8cce1866b1 | |||
| 0105698c33 | |||
| 3b18e328b2 | |||
| 2bc0b76050 | |||
| d83e3b4d82 | |||
| 42d7df27ae | |||
| fd54e16bf4 | |||
| 92a3c4f79a | |||
| 654a8b7ea7 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
# Godot 4+ specific ignores
|
# Godot 4+ specific ignores
|
||||||
.godot/
|
.godot/
|
||||||
/android/
|
/android/
|
||||||
builds/.worktrees/
|
builds/
|
||||||
|
.worktrees/
|
||||||
|
|||||||
54
Autoloads/InputDeviceManager.cs
Normal file
54
Autoloads/InputDeviceManager.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Mr.BrickAdventures.Autoloads;
|
||||||
|
|
||||||
|
public partial class InputDeviceManager : Node
|
||||||
|
{
|
||||||
|
public enum InputDevice { Mouse, Keyboard, Gamepad }
|
||||||
|
public static InputDeviceManager Instance { get; private set; }
|
||||||
|
|
||||||
|
public InputDevice CurrentDevice { get; private set; } = InputDevice.Mouse;
|
||||||
|
|
||||||
|
public bool IsPointerless => CurrentDevice is InputDevice.Keyboard or InputDevice.Gamepad;
|
||||||
|
|
||||||
|
[Signal] public delegate void DeviceChangedEventHandler(int device);
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
Input.MouseMode = Input.MouseModeEnum.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (Instance == this) Instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Input(InputEvent @event)
|
||||||
|
{
|
||||||
|
InputDevice detected;
|
||||||
|
|
||||||
|
if (@event is InputEventMouseMotion or InputEventMouseButton)
|
||||||
|
detected = InputDevice.Mouse;
|
||||||
|
else if (@event is InputEventKey)
|
||||||
|
detected = InputDevice.Keyboard;
|
||||||
|
else if (@event is InputEventJoypadButton)
|
||||||
|
detected = InputDevice.Gamepad;
|
||||||
|
else if (@event is InputEventJoypadMotion joyEvent)
|
||||||
|
{
|
||||||
|
if (Mathf.Abs(joyEvent.AxisValue) <= 0.15f) return;
|
||||||
|
detected = InputDevice.Gamepad;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (detected == CurrentDevice) return;
|
||||||
|
|
||||||
|
CurrentDevice = detected;
|
||||||
|
Input.MouseMode = CurrentDevice == InputDevice.Mouse
|
||||||
|
? Input.MouseModeEnum.Visible
|
||||||
|
: Input.MouseModeEnum.Hidden;
|
||||||
|
|
||||||
|
EmitSignal(SignalName.DeviceChanged, (int)CurrentDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Autoloads/InputDeviceManager.cs.uid
Normal file
1
Autoloads/InputDeviceManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b81610g8fd6p1
|
||||||
203
Autoloads/SettingsManager.cs
Normal file
203
Autoloads/SettingsManager.cs
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
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 ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
public 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Autoloads/SettingsManager.cs.uid
Normal file
1
Autoloads/SettingsManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://d4jyxtm4jgtka
|
||||||
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
|
||||||
97
objects/ui/gameplay_settings.tscn
Normal file
97
objects/ui/gameplay_settings.tscn
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://gameplay_settings_scene"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://gameplay_settings_script" path="res://scripts/UI/GameplaySettings.cs" id="1_gameplay"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gameplay"]
|
||||||
|
bg_color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
|
[node name="Gameplay Settings" type="Control" node_paths=PackedStringArray("DeadzoneSlider", "DeadzoneValueLabel", "SensitivitySlider", "SensitivityValueLabel", "GameplaySettingsControl")]
|
||||||
|
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_gameplay")
|
||||||
|
DeadzoneSlider = NodePath("PanelContainer/MarginContainer/VBoxContainer/Deadzone/HSlider")
|
||||||
|
DeadzoneValueLabel = NodePath("PanelContainer/MarginContainer/VBoxContainer/Deadzone/HBoxContainer/DeadzoneValueLabel")
|
||||||
|
SensitivitySlider = NodePath("PanelContainer/MarginContainer/VBoxContainer/Sensitivity/HSlider")
|
||||||
|
SensitivityValueLabel = NodePath("PanelContainer/MarginContainer/VBoxContainer/Sensitivity/HBoxContainer/SensitivityValueLabel")
|
||||||
|
GameplaySettingsControl = 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_gameplay")
|
||||||
|
|
||||||
|
[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="Gameplay" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "GAMEPLAY"
|
||||||
|
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="Deadzone" type="VBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 4
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer/Deadzone"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="DeadzoneLabel" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer/Deadzone/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "GAMEPAD_DEADZONE"
|
||||||
|
|
||||||
|
[node name="DeadzoneValueLabel" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer/Deadzone/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "0.20"
|
||||||
|
|
||||||
|
[node name="HSlider" type="HSlider" parent="PanelContainer/MarginContainer/VBoxContainer/Deadzone"]
|
||||||
|
custom_minimum_size = Vector2(64, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
value = 0.2
|
||||||
|
|
||||||
|
[node name="Sensitivity" type="VBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 4
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer/VBoxContainer/Sensitivity"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="SensitivityLabel" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer/Sensitivity/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "GAMEPAD_SENSITIVITY"
|
||||||
|
|
||||||
|
[node name="SensitivityValueLabel" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer/Sensitivity/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "1.00"
|
||||||
|
|
||||||
|
[node name="HSlider" type="HSlider" parent="PanelContainer/MarginContainer/VBoxContainer/Sensitivity"]
|
||||||
|
custom_minimum_size = Vector2(64, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
value = 1.0
|
||||||
@@ -1,17 +1,23 @@
|
|||||||
[gd_scene load_steps=3 format=3 uid="uid://cvfsbiy5ggrpg"]
|
[gd_scene load_steps=4 format=3 uid="uid://cvfsbiy5ggrpg"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://bxpr4m7lq7clh" path="res://objects/ui/input_button.tscn" id="1_h8s4o"]
|
[ext_resource type="PackedScene" uid="uid://bxpr4m7lq7clh" path="res://objects/ui/input_button.tscn" id="1_h8s4o"]
|
||||||
|
[ext_resource type="Script" uid="uid://input_settings_script" path="res://scripts/UI/InputSettings.cs" id="2_inputs"]
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_se25o"]
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_se25o"]
|
||||||
bg_color = Color(0, 0, 0, 1)
|
bg_color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
[node name="Input Settings" type="Control"]
|
[node name="Input Settings" type="Control" node_paths=PackedStringArray("ActionsContainer", "ResetButton", "InputSettingsControl")]
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
script = ExtResource("2_inputs")
|
||||||
|
ActionsContainer = NodePath("PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Actions")
|
||||||
|
ResetButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Reset to default Button")
|
||||||
|
InputSettingsControl = NodePath(".")
|
||||||
|
InputButtonScene = ExtResource("1_h8s4o")
|
||||||
|
|
||||||
[node name="PanelContainer" type="PanelContainer" parent="."]
|
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
@@ -48,24 +54,6 @@ layout_mode = 2
|
|||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
theme_override_constants/separation = 8
|
theme_override_constants/separation = 8
|
||||||
|
|
||||||
[node name="Input button" parent="PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Actions" instance=ExtResource("1_h8s4o")]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Input button2" parent="PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Actions" instance=ExtResource("1_h8s4o")]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Input button3" parent="PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Actions" instance=ExtResource("1_h8s4o")]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Input button4" parent="PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Actions" instance=ExtResource("1_h8s4o")]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Input button5" parent="PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Actions" instance=ExtResource("1_h8s4o")]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Input button6" parent="PanelContainer/MarginContainer/VBoxContainer/ScrollContainer/Actions" instance=ExtResource("1_h8s4o")]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="Reset to default Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
[node name="Reset to default Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "RESET_TO_DEFAULT_BUTTON"
|
text = "RESET_TO_DEFAULT_BUTTON"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
[ext_resource type="Script" uid="uid://vokgv56bjpf1" path="res://scripts/UI/MarketplaceButton.cs" id="2_vb2qn"]
|
[ext_resource type="Script" uid="uid://vokgv56bjpf1" path="res://scripts/UI/MarketplaceButton.cs" id="2_vb2qn"]
|
||||||
|
|
||||||
[node name="MarketplaceButton" type="Button" node_paths=PackedStringArray("SkillLevelContainer")]
|
[node name="MarketplaceButton" type="Button" node_paths=PackedStringArray("SkillLevelContainer")]
|
||||||
|
focus_mode = 2
|
||||||
offset_right = 8.0
|
offset_right = 8.0
|
||||||
offset_bottom = 8.0
|
offset_bottom = 8.0
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
|||||||
@@ -53,13 +53,11 @@ size_flags_vertical = 3
|
|||||||
|
|
||||||
[node name="Input Settings Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
[node name="Input Settings Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
disabled = true
|
|
||||||
text = "INPUT_BUTTON"
|
text = "INPUT_BUTTON"
|
||||||
flat = true
|
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
|
||||||
|
|
||||||
@@ -70,7 +68,6 @@ flat = true
|
|||||||
|
|
||||||
[node name="Gameplay Settings Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
[node name="Gameplay Settings Button" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
disabled = true
|
|
||||||
text = "GAMEPLAY_BUTTON"
|
text = "GAMEPLAY_BUTTON"
|
||||||
flat = true
|
flat = true
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
[ext_resource type="Script" uid="uid://bw8dlgq86jrtt" path="res://scripts/UI/SkillButton.cs" id="2_m2732"]
|
[ext_resource type="Script" uid="uid://bw8dlgq86jrtt" path="res://scripts/UI/SkillButton.cs" id="2_m2732"]
|
||||||
|
|
||||||
[node name="SkillButton" type="Button"]
|
[node name="SkillButton" type="Button"]
|
||||||
|
focus_mode = 2
|
||||||
offset_right = 8.0
|
offset_right = 8.0
|
||||||
offset_bottom = 8.0
|
offset_bottom = 8.0
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ PhantomCameraManager="*res://addons/phantom_camera/scripts/managers/phantom_came
|
|||||||
AudioController="*res://objects/audio_controller.tscn"
|
AudioController="*res://objects/audio_controller.tscn"
|
||||||
UIManager="*res://Autoloads/UIManager.cs"
|
UIManager="*res://Autoloads/UIManager.cs"
|
||||||
ConfigFileHandler="*res://Autoloads/ConfigFileHandler.cs"
|
ConfigFileHandler="*res://Autoloads/ConfigFileHandler.cs"
|
||||||
|
SettingsManager="*res://Autoloads/SettingsManager.cs"
|
||||||
|
InputDeviceManager="*res://Autoloads/InputDeviceManager.cs"
|
||||||
SaveSystem="*res://Autoloads/SaveSystem.cs"
|
SaveSystem="*res://Autoloads/SaveSystem.cs"
|
||||||
ConsoleManager="*res://Autoloads/ConsoleManager.cs"
|
ConsoleManager="*res://Autoloads/ConsoleManager.cs"
|
||||||
LimboConsole="*uid://dyxornv8vwibg"
|
LimboConsole="*uid://dyxornv8vwibg"
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
[gd_scene load_steps=6 format=3 uid="uid://cl00e2ocomk3m"]
|
[gd_scene load_steps=8 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"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://gameplay_settings_scene" path="res://objects/ui/gameplay_settings.tscn" id="7_gameplay"]
|
||||||
|
|
||||||
[node name="Main menu" type="CanvasLayer"]
|
[node name="Main menu" type="CanvasLayer"]
|
||||||
|
|
||||||
@@ -28,14 +30,8 @@ visible = false
|
|||||||
[node name="Input Settings" parent="." instance=ExtResource("5_rtw2f")]
|
[node name="Input Settings" parent="." instance=ExtResource("5_rtw2f")]
|
||||||
visible = false
|
visible = false
|
||||||
|
|
||||||
[node name="Gameplay Settings" type="Control" parent="."]
|
[node name="Gameplay Settings" parent="." instance=ExtResource("7_gameplay")]
|
||||||
layout_mode = 3
|
visible = false
|
||||||
anchors_preset = 0
|
|
||||||
offset_right = 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
|
|
||||||
|
|||||||
@@ -16,19 +16,45 @@ public partial class AudioSettings : Control
|
|||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
MasterVolumeSlider.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
MusicVolumeSlider.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
SfxVolumeSlider.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
MasterVolumeSlider.ValueChanged += OnMasterVolumeChanged;
|
MasterVolumeSlider.ValueChanged += OnMasterVolumeChanged;
|
||||||
MusicVolumeSlider.ValueChanged += OnMusicVolumeChanged;
|
MusicVolumeSlider.ValueChanged += OnMusicVolumeChanged;
|
||||||
SfxVolumeSlider.ValueChanged += OnSfxVolumeChanged;
|
SfxVolumeSlider.ValueChanged += OnSfxVolumeChanged;
|
||||||
|
|
||||||
LoadSettings();
|
LoadSettings();
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
|
||||||
|
AudioSettingsControl.VisibilityChanged += OnVisibilityChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ExitTree()
|
public override void _ExitTree()
|
||||||
{
|
{
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
|
||||||
|
AudioSettingsControl.VisibilityChanged -= OnVisibilityChanged;
|
||||||
SaveSettings();
|
SaveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnVisibilityChanged()
|
||||||
|
{
|
||||||
|
if (AudioSettingsControl.IsVisibleInTree() && InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDeviceChanged(int device)
|
||||||
|
{
|
||||||
|
var d = (InputDeviceManager.InputDevice)device;
|
||||||
|
if (d != InputDeviceManager.InputDevice.Mouse && AudioSettingsControl.IsVisibleInTree())
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GrabFirstFocus() => MasterVolumeSlider.GrabFocus();
|
||||||
|
|
||||||
public override void _UnhandledInput(InputEvent @event)
|
public override void _UnhandledInput(InputEvent @event)
|
||||||
{
|
{
|
||||||
if (!@event.IsActionReleased("ui_cancel")) return;
|
if (!@event.IsActionReleased("ui_cancel")) return;
|
||||||
|
|||||||
125
scripts/UI/DisplaySettings.cs
Normal file
125
scripts/UI/DisplaySettings.cs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
WindowModeButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
ResolutionButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
|
||||||
|
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"
|
||||||
|
};
|
||||||
|
|
||||||
|
SettingsManager.Instance.WindowMode = mode;
|
||||||
|
SettingsManager.Instance.ApplyDisplaySettings();
|
||||||
|
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;
|
||||||
|
SettingsManager.Instance.ApplyDisplaySettings();
|
||||||
|
SettingsManager.Instance.SaveDisplaySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
scripts/UI/DisplaySettings.cs.uid
Normal file
1
scripts/UI/DisplaySettings.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cplbdp0i08n0n
|
||||||
@@ -13,8 +13,27 @@ public partial class GameOverScreen : Control
|
|||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
RestartButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
MainMenuButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
|
||||||
RestartButton.Pressed += OnRestartClicked;
|
RestartButton.Pressed += OnRestartClicked;
|
||||||
MainMenuButton.Pressed += OnMainMenuClicked;
|
MainMenuButton.Pressed += OnMainMenuClicked;
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDeviceChanged(int device)
|
||||||
|
{
|
||||||
|
var d = (InputDeviceManager.InputDevice)device;
|
||||||
|
if (d != InputDeviceManager.InputDevice.Mouse && GameOverPanel.IsVisibleInTree())
|
||||||
|
RestartButton.GrabFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMainMenuClicked()
|
private void OnMainMenuClicked()
|
||||||
@@ -33,5 +52,7 @@ public partial class GameOverScreen : Control
|
|||||||
if (GameStateStore.Instance?.Player.Lives != 0) return;
|
if (GameStateStore.Instance?.Player.Lives != 0) return;
|
||||||
|
|
||||||
GameOverPanel.Show();
|
GameOverPanel.Show();
|
||||||
|
if (InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
RestartButton.GrabFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
97
scripts/UI/GameplaySettings.cs
Normal file
97
scripts/UI/GameplaySettings.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using Godot;
|
||||||
|
using Mr.BrickAdventures.Autoloads;
|
||||||
|
|
||||||
|
namespace Mr.BrickAdventures.scripts.UI;
|
||||||
|
|
||||||
|
public partial class GameplaySettings : Control
|
||||||
|
{
|
||||||
|
[Export] public HSlider DeadzoneSlider { get; set; }
|
||||||
|
[Export] public Label DeadzoneValueLabel { get; set; }
|
||||||
|
[Export] public HSlider SensitivitySlider { get; set; }
|
||||||
|
[Export] public Label SensitivityValueLabel { get; set; }
|
||||||
|
[Export] public Control GameplaySettingsControl { get; set; }
|
||||||
|
|
||||||
|
private UIManager UIManager => UIManager.Instance;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
DeadzoneSlider.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
SensitivitySlider.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
|
||||||
|
DeadzoneSlider.MinValue = 0.05;
|
||||||
|
DeadzoneSlider.MaxValue = 0.5;
|
||||||
|
DeadzoneSlider.Step = 0.05;
|
||||||
|
DeadzoneSlider.Value = 0.2;
|
||||||
|
|
||||||
|
SensitivitySlider.MinValue = 0.5;
|
||||||
|
SensitivitySlider.MaxValue = 2.0;
|
||||||
|
SensitivitySlider.Step = 0.1;
|
||||||
|
SensitivitySlider.Value = 1.0;
|
||||||
|
|
||||||
|
LoadSettings();
|
||||||
|
|
||||||
|
DeadzoneSlider.ValueChanged += OnDeadzoneChanged;
|
||||||
|
SensitivitySlider.ValueChanged += OnSensitivityChanged;
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
|
||||||
|
GameplaySettingsControl.VisibilityChanged += OnVisibilityChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
|
||||||
|
GameplaySettingsControl.VisibilityChanged -= OnVisibilityChanged;
|
||||||
|
SaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _UnhandledInput(InputEvent @event)
|
||||||
|
{
|
||||||
|
if (!@event.IsActionReleased("ui_cancel")) return;
|
||||||
|
if (!UIManager.IsScreenOnTop(GameplaySettingsControl)) return;
|
||||||
|
|
||||||
|
SaveSettings();
|
||||||
|
UIManager.PopScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVisibilityChanged()
|
||||||
|
{
|
||||||
|
if (GameplaySettingsControl.IsVisibleInTree() && InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDeviceChanged(int device)
|
||||||
|
{
|
||||||
|
var d = (InputDeviceManager.InputDevice)device;
|
||||||
|
if (d != InputDeviceManager.InputDevice.Mouse && GameplaySettingsControl.IsVisibleInTree())
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GrabFirstFocus() => DeadzoneSlider.GrabFocus();
|
||||||
|
|
||||||
|
private void OnDeadzoneChanged(double value)
|
||||||
|
{
|
||||||
|
SettingsManager.Instance.GamepadDeadzone = (float)value;
|
||||||
|
SettingsManager.Instance.ApplyGamepadDeadzone();
|
||||||
|
DeadzoneValueLabel.Text = $"{value:F2}";
|
||||||
|
SaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSensitivityChanged(double value)
|
||||||
|
{
|
||||||
|
SettingsManager.Instance.GamepadSensitivity = (float)value;
|
||||||
|
SensitivityValueLabel.Text = $"{value:F2}";
|
||||||
|
SaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadSettings()
|
||||||
|
{
|
||||||
|
DeadzoneSlider.Value = SettingsManager.Instance.GamepadDeadzone;
|
||||||
|
SensitivitySlider.Value = SettingsManager.Instance.GamepadSensitivity;
|
||||||
|
DeadzoneValueLabel.Text = $"{SettingsManager.Instance.GamepadDeadzone:F2}";
|
||||||
|
SensitivityValueLabel.Text = $"{SettingsManager.Instance.GamepadSensitivity:F2}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveSettings() => SettingsManager.Instance.SaveGameplaySettings();
|
||||||
|
}
|
||||||
1
scripts/UI/GameplaySettings.cs.uid
Normal file
1
scripts/UI/GameplaySettings.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://18e3imrmq1u6
|
||||||
201
scripts/UI/InputSettings.cs
Normal file
201
scripts/UI/InputSettings.cs
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
using Godot;
|
||||||
|
using Mr.BrickAdventures.Autoloads;
|
||||||
|
|
||||||
|
namespace Mr.BrickAdventures.scripts.UI;
|
||||||
|
|
||||||
|
public partial class InputSettings : Control
|
||||||
|
{
|
||||||
|
[Export] public VBoxContainer ActionsContainer { get; set; }
|
||||||
|
[Export] public Button ResetButton { get; set; }
|
||||||
|
[Export] public Control InputSettingsControl { get; set; }
|
||||||
|
[Export] public PackedScene InputButtonScene { get; set; }
|
||||||
|
|
||||||
|
// When adding new game actions, update this list to make them remappable in settings.
|
||||||
|
private static readonly string[] RemappableActions =
|
||||||
|
["left", "right", "jump", "attack", "pause", "show_marketplace"];
|
||||||
|
|
||||||
|
private UIManager UIManager => UIManager.Instance;
|
||||||
|
private ConfigFileHandler ConfigFileHandler => ConfigFileHandler.Instance;
|
||||||
|
|
||||||
|
private string _rebindingAction;
|
||||||
|
private Button _rebindingButton;
|
||||||
|
private Label _rebindingLabel;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
PopulateActions();
|
||||||
|
ResetButton.FocusMode = FocusModeEnum.All;
|
||||||
|
ResetButton.Pressed += OnResetPressed;
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
|
||||||
|
InputSettingsControl.VisibilityChanged += OnVisibilityChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
|
||||||
|
InputSettingsControl.VisibilityChanged -= OnVisibilityChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _UnhandledInput(InputEvent @event)
|
||||||
|
{
|
||||||
|
if (!IsVisibleInTree()) return;
|
||||||
|
|
||||||
|
if (_rebindingAction != null)
|
||||||
|
{
|
||||||
|
if (@event is InputEventKey keyEvent && keyEvent.Pressed && !keyEvent.Echo)
|
||||||
|
{
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
TryBind(_rebindingAction, _rebindingButton, _rebindingLabel, keyEvent);
|
||||||
|
}
|
||||||
|
else if (@event.IsActionReleased("ui_cancel"))
|
||||||
|
{
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
CancelRebind();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!@event.IsActionReleased("ui_cancel")) return;
|
||||||
|
if (!UIManager.IsScreenOnTop(InputSettingsControl)) return;
|
||||||
|
UIManager.PopScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PopulateActions()
|
||||||
|
{
|
||||||
|
foreach (Node child in ActionsContainer.GetChildren())
|
||||||
|
child.QueueFree();
|
||||||
|
|
||||||
|
foreach (var action in RemappableActions)
|
||||||
|
{
|
||||||
|
var row = InputButtonScene.Instantiate<Button>();
|
||||||
|
ActionsContainer.AddChild(row);
|
||||||
|
|
||||||
|
var labelAction = row.GetNode<Label>("MarginContainer/HBoxContainer/LabelAction");
|
||||||
|
var labelInput = row.GetNode<Label>("MarginContainer/HBoxContainer/LabelInput");
|
||||||
|
|
||||||
|
labelAction.Text = HumanizeAction(action);
|
||||||
|
labelInput.Text = GetKeyName(action);
|
||||||
|
|
||||||
|
row.FocusMode = FocusModeEnum.All;
|
||||||
|
|
||||||
|
var capturedAction = action;
|
||||||
|
var capturedLabel = labelInput;
|
||||||
|
var capturedRow = row;
|
||||||
|
row.Pressed += () => OnRowPressed(capturedAction, capturedRow, capturedLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRowPressed(string action, Button row, Label labelInput)
|
||||||
|
{
|
||||||
|
if (_rebindingAction != null)
|
||||||
|
CancelRebind();
|
||||||
|
|
||||||
|
_rebindingAction = action;
|
||||||
|
_rebindingButton = row;
|
||||||
|
_rebindingLabel = labelInput;
|
||||||
|
labelInput.Text = "Press a key...";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryBind(string action, Button row, Label labelInput, InputEventKey keyEvent)
|
||||||
|
{
|
||||||
|
var newKey = keyEvent.PhysicalKeycode;
|
||||||
|
|
||||||
|
// Conflict check
|
||||||
|
foreach (var other in RemappableActions)
|
||||||
|
{
|
||||||
|
if (other == action) continue;
|
||||||
|
var existing = GetCurrentKey(other);
|
||||||
|
if (existing == newKey)
|
||||||
|
{
|
||||||
|
labelInput.Text = $"Already used by {HumanizeAction(other)}!";
|
||||||
|
_rebindingAction = null;
|
||||||
|
_rebindingButton = null;
|
||||||
|
_rebindingLabel = null;
|
||||||
|
var capturedAction = action;
|
||||||
|
var capturedLabel = labelInput;
|
||||||
|
GetTree().CreateTimer(2.0).Timeout += () =>
|
||||||
|
{
|
||||||
|
if (IsInstanceValid(capturedLabel))
|
||||||
|
capturedLabel.Text = GetKeyName(capturedAction);
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply
|
||||||
|
foreach (var ev in InputMap.ActionGetEvents(action))
|
||||||
|
{
|
||||||
|
if (ev is InputEventKey)
|
||||||
|
InputMap.ActionEraseEvent(action, ev);
|
||||||
|
}
|
||||||
|
InputMap.ActionAddEvent(action, new InputEventKey { PhysicalKeycode = keyEvent.PhysicalKeycode });
|
||||||
|
|
||||||
|
// Persist
|
||||||
|
SettingsManager.Instance.SaveInputSettings();
|
||||||
|
|
||||||
|
labelInput.Text = OS.GetKeycodeString(newKey);
|
||||||
|
|
||||||
|
_rebindingAction = null;
|
||||||
|
_rebindingButton = null;
|
||||||
|
_rebindingLabel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelRebind()
|
||||||
|
{
|
||||||
|
if (_rebindingLabel != null)
|
||||||
|
_rebindingLabel.Text = GetKeyName(_rebindingAction);
|
||||||
|
_rebindingAction = null;
|
||||||
|
_rebindingButton = null;
|
||||||
|
_rebindingLabel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnResetPressed()
|
||||||
|
{
|
||||||
|
InputMap.LoadFromProjectSettings();
|
||||||
|
ConfigFileHandler.SettingsConfig.EraseSection("input_settings");
|
||||||
|
ConfigFileHandler.SettingsConfig.Save(ConfigFileHandler.SettingsPath);
|
||||||
|
PopulateActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVisibilityChanged()
|
||||||
|
{
|
||||||
|
if (InputSettingsControl.IsVisibleInTree() && InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDeviceChanged(int device)
|
||||||
|
{
|
||||||
|
var d = (InputDeviceManager.InputDevice)device;
|
||||||
|
if (d != InputDeviceManager.InputDevice.Mouse && InputSettingsControl.IsVisibleInTree())
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GrabFirstFocus()
|
||||||
|
{
|
||||||
|
var children = ActionsContainer.GetChildren();
|
||||||
|
if (children.Count > 0 && children[0] is Button btn)
|
||||||
|
btn.GrabFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Key GetCurrentKey(string action)
|
||||||
|
{
|
||||||
|
foreach (var ev in InputMap.ActionGetEvents(action))
|
||||||
|
{
|
||||||
|
if (ev is InputEventKey key)
|
||||||
|
return key.PhysicalKeycode;
|
||||||
|
}
|
||||||
|
return Key.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetKeyName(string action)
|
||||||
|
{
|
||||||
|
var key = GetCurrentKey(action);
|
||||||
|
return key == Key.None ? "---" : OS.GetKeycodeString(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string HumanizeAction(string action)
|
||||||
|
=> action.Replace("_", " ").ToUpper();
|
||||||
|
}
|
||||||
1
scripts/UI/InputSettings.cs.uid
Normal file
1
scripts/UI/InputSettings.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dqefxy5hke5a
|
||||||
@@ -21,6 +21,11 @@ public partial class MainMenu : Control
|
|||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
NewGameButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
ContinueButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
SettingsButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
CreditsButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
ExitButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
|
||||||
NewGameButton.Pressed += OnNewGamePressed;
|
NewGameButton.Pressed += OnNewGamePressed;
|
||||||
ContinueButton.Pressed += OnContinuePressed;
|
ContinueButton.Pressed += OnContinuePressed;
|
||||||
@@ -31,6 +36,36 @@ public partial class MainMenu : Control
|
|||||||
VersionLabel.Text = $"v. {ProjectSettings.GetSetting("application/config/version")}";
|
VersionLabel.Text = $"v. {ProjectSettings.GetSetting("application/config/version")}";
|
||||||
ContinueButton.Disabled = !SaveSystem.CheckSaveExists();
|
ContinueButton.Disabled = !SaveSystem.CheckSaveExists();
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
|
||||||
|
VisibilityChanged += OnVisibilityChanged;
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
|
||||||
|
VisibilityChanged -= OnVisibilityChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVisibilityChanged()
|
||||||
|
{
|
||||||
|
if (IsVisibleInTree() && InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDeviceChanged(int device)
|
||||||
|
{
|
||||||
|
var d = (InputDeviceManager.InputDevice)device;
|
||||||
|
if (d != InputDeviceManager.InputDevice.Mouse && IsVisibleInTree())
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GrabFirstFocus()
|
||||||
|
{
|
||||||
if (SaveSystem.CheckSaveExists())
|
if (SaveSystem.CheckSaveExists())
|
||||||
ContinueButton.GrabFocus();
|
ContinueButton.GrabFocus();
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ public partial class Marketplace : Control
|
|||||||
|
|
||||||
SkillUnlockerComponent.SkillUnlocked += OnSkillUnlocked;
|
SkillUnlockerComponent.SkillUnlocked += OnSkillUnlocked;
|
||||||
EventBus.Instance.SkillCollected += OnGlobalSkillCollected;
|
EventBus.Instance.SkillCollected += OnGlobalSkillCollected;
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ExitTree()
|
public override void _ExitTree()
|
||||||
@@ -47,10 +50,21 @@ public partial class Marketplace : Control
|
|||||||
{
|
{
|
||||||
EventBus.Instance.SkillCollected -= OnGlobalSkillCollected;
|
EventBus.Instance.SkillCollected -= OnGlobalSkillCollected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Input(InputEvent @event)
|
public override void _Input(InputEvent @event)
|
||||||
{
|
{
|
||||||
|
if (@event.IsActionReleased("ui_cancel") && IsVisible())
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
foreach (var c in ComponentsToDisable) c.ProcessMode = ProcessModeEnum.Inherit;
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!@event.IsActionPressed("show_marketplace")) return;
|
if (!@event.IsActionPressed("show_marketplace")) return;
|
||||||
|
|
||||||
if (IsVisible())
|
if (IsVisible())
|
||||||
@@ -62,6 +76,35 @@ public partial class Marketplace : Control
|
|||||||
{
|
{
|
||||||
Show();
|
Show();
|
||||||
foreach (var c in ComponentsToDisable) c.ProcessMode = ProcessModeEnum.Disabled;
|
foreach (var c in ComponentsToDisable) c.ProcessMode = ProcessModeEnum.Disabled;
|
||||||
|
if (InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDeviceChanged(int device)
|
||||||
|
{
|
||||||
|
var d = (InputDeviceManager.InputDevice)device;
|
||||||
|
if (d != InputDeviceManager.InputDevice.Mouse && IsVisible())
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GrabFirstFocus()
|
||||||
|
{
|
||||||
|
foreach (var btn in _unlockButtons)
|
||||||
|
{
|
||||||
|
if (btn.Visible && !btn.Disabled)
|
||||||
|
{
|
||||||
|
btn.GrabFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var btn in _skillButtons)
|
||||||
|
{
|
||||||
|
if (btn.Visible)
|
||||||
|
{
|
||||||
|
btn.GrabFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ public partial class PauseMenu : Control
|
|||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
ResumeButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
MainMenuButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
QuitButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
SettingsButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
|
||||||
ResumeButton.Pressed += OnResumePressed;
|
ResumeButton.Pressed += OnResumePressed;
|
||||||
MainMenuButton.Pressed += OnMainMenuPressed;
|
MainMenuButton.Pressed += OnMainMenuPressed;
|
||||||
@@ -25,8 +29,34 @@ public partial class PauseMenu : Control
|
|||||||
SettingsButton.Pressed += OnSettingsPressed;
|
SettingsButton.Pressed += OnSettingsPressed;
|
||||||
|
|
||||||
PauseMenuControl.Hide();
|
PauseMenuControl.Hide();
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
|
||||||
|
PauseMenuControl.VisibilityChanged += OnVisibilityChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
|
||||||
|
PauseMenuControl.VisibilityChanged -= OnVisibilityChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVisibilityChanged()
|
||||||
|
{
|
||||||
|
if (PauseMenuControl.IsVisibleInTree() && InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDeviceChanged(int device)
|
||||||
|
{
|
||||||
|
var d = (InputDeviceManager.InputDevice)device;
|
||||||
|
if (d != InputDeviceManager.InputDevice.Mouse && PauseMenuControl.IsVisibleInTree())
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GrabFirstFocus() => ResumeButton.GrabFocus();
|
||||||
|
|
||||||
public override void _UnhandledInput(InputEvent @event)
|
public override void _UnhandledInput(InputEvent @event)
|
||||||
{
|
{
|
||||||
if (!@event.IsActionPressed("pause")) return;
|
if (!@event.IsActionPressed("pause")) return;
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ public partial class SettingsMenu : Control
|
|||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
InputSettingsButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
AudioSettingsButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
DisplaySettingsButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
GameplaySettingsButton.FocusMode = Control.FocusModeEnum.All;
|
||||||
|
|
||||||
InputSettingsButton.Pressed += OnInputSettingsPressed;
|
InputSettingsButton.Pressed += OnInputSettingsPressed;
|
||||||
AudioSettingsButton.Pressed += OnAudioSettingsPressed;
|
AudioSettingsButton.Pressed += OnAudioSettingsPressed;
|
||||||
@@ -29,11 +33,37 @@ public partial class SettingsMenu : Control
|
|||||||
AudioSettingsControl?.Hide();
|
AudioSettingsControl?.Hide();
|
||||||
DisplaySettingsControl?.Hide();
|
DisplaySettingsControl?.Hide();
|
||||||
GameplaySettingsControl?.Hide();
|
GameplaySettingsControl?.Hide();
|
||||||
|
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
|
||||||
|
VisibilityChanged += OnVisibilityChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (InputDeviceManager.Instance != null)
|
||||||
|
InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
|
||||||
|
VisibilityChanged -= OnVisibilityChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVisibilityChanged()
|
||||||
|
{
|
||||||
|
if (IsVisibleInTree() && InputDeviceManager.Instance?.IsPointerless == true)
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDeviceChanged(int device)
|
||||||
|
{
|
||||||
|
var d = (InputDeviceManager.InputDevice)device;
|
||||||
|
if (d != InputDeviceManager.InputDevice.Mouse && IsVisibleInTree())
|
||||||
|
GrabFirstFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GrabFirstFocus() => InputSettingsButton.GrabFocus();
|
||||||
|
|
||||||
public override void _UnhandledInput(InputEvent @event)
|
public override void _UnhandledInput(InputEvent @event)
|
||||||
{
|
{
|
||||||
if (!@event.IsActionPressed("ui_cancel")) return;
|
if (!@event.IsActionReleased("ui_cancel")) return;
|
||||||
if (UIManager.IsScreenOnTop(SettingsMenuControl)) UIManager.PopScreen();
|
if (UIManager.IsScreenOnTop(SettingsMenuControl)) UIManager.PopScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
|
using Mr.BrickAdventures.Autoloads;
|
||||||
|
|
||||||
namespace Mr.BrickAdventures.scripts.components;
|
namespace Mr.BrickAdventures.scripts.components;
|
||||||
|
|
||||||
@@ -15,7 +16,11 @@ public partial class PlayerInputHandler : Node
|
|||||||
|
|
||||||
public override void _PhysicsProcess(double delta)
|
public override void _PhysicsProcess(double delta)
|
||||||
{
|
{
|
||||||
MoveDirection = Input.GetVector("left", "right", "up", "down");
|
var rawInput = Input.GetVector("left", "right", "up", "down");
|
||||||
|
var sensitivity = SettingsManager.Instance?.GamepadSensitivity ?? 1.0f;
|
||||||
|
MoveDirection = rawInput.Length() > 0
|
||||||
|
? rawInput.Normalized() * Mathf.Min(rawInput.Length() * sensitivity, 1.0f)
|
||||||
|
: Vector2.Zero;
|
||||||
|
|
||||||
JumpPressed = Input.IsActionJustPressed("jump");
|
JumpPressed = Input.IsActionJustPressed("jump");
|
||||||
JumpReleased = Input.IsActionJustReleased("jump");
|
JumpReleased = Input.IsActionJustReleased("jump");
|
||||||
|
|||||||
Reference in New Issue
Block a user