Skip to content

Commit 181eec3

Browse files
Add back missing right controls in options
1 parent 63bf00b commit 181eec3

22 files changed

Lines changed: 526 additions & 26 deletions

Template.OptionsGen/OptionsGen/OptionsGen.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<NoWarn>NU5128</NoWarn>
1313

1414
<!-- Package Settings -->
15-
<Version>1.0.4</Version>
15+
<Version>1.0.5</Version>
1616
<PackageId>Template.OptionsGen</PackageId>
1717
<AssemblyName>Template.OptionsGen</AssemblyName>
1818
<Description>Strongly typed options settings source generator for CSharpGodotTools/Template</Description>
-11.9 KB
Binary file not shown.
11.9 KB
Binary file not shown.

Template/Framework/Scenes/Options/Core/OptionsManager.cs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using GodotUtils;
33
using System;
44
using System.Collections.Generic;
5+
using System.Linq;
56
using System.Threading.Tasks;
67
using VSyncMode = Godot.DisplayServer.VSyncMode;
78

@@ -27,16 +28,20 @@ public partial class OptionsManager : IDisposable, IOptionsService
2728
internal event Action<RegisteredDropdownOption> DropdownOptionRegistered = null!;
2829
internal event Action<RegisteredLineEditOption> LineEditOptionRegistered = null!;
2930
internal event Action<RegisteredToggleOption> ToggleOptionRegistered = null!;
31+
internal event Action<RegisteredRightControl> RightControlRegistered = null!;
3032

3133
// Fields
3234
private readonly OptionsSettingsStore _settingsStore = new();
3335
private readonly OptionsHotkeysService _hotkeysService = new();
3436
private readonly OptionsCustomRegistry _customRegistry;
3537
private readonly OptionsSettings _settings;
38+
private readonly Dictionary<string, int> _rightControlIds = new(StringComparer.OrdinalIgnoreCase);
39+
private readonly Dictionary<int, RegisteredRightControl> _rightControls = [];
3640

3741
private ResourceOptions _options;
3842
private string _currentOptionsTab = OptionsTabs.General;
3943
private AutoloadsFramework _autoloads = null!;
44+
private int _nextRightControlId;
4045

4146
public OptionsManager(AutoloadsFramework autoloads)
4247
{
@@ -184,9 +189,6 @@ private void SetFloatSetting(string key, float value)
184189
case OptionsSaveKeys.SfxVolume:
185190
SetSFXVolume(value);
186191
return;
187-
case OptionsSaveKeys.Resolution:
188-
SetResolution((int)value);
189-
return;
190192
case OptionsSaveKeys.MaxFps:
191193
SetMaxFPS((int)value);
192194
return;
@@ -264,11 +266,6 @@ private void SetWindowSize(int width, int height)
264266
ApplyWindowSize();
265267
}
266268

267-
private void SetResolution(int resolution)
268-
{
269-
WriteOptionInt(OptionsSaveKeys.Resolution, Math.Clamp(resolution, 1, 36));
270-
}
271-
272269
private void SetVSyncMode(VSyncMode vsyncMode)
273270
{
274271
VSyncMode clamped = CoerceVSyncMode((int)vsyncMode);
@@ -303,6 +300,11 @@ internal IEnumerable<RegisteredToggleOption> GetToggleOptions()
303300
return _customRegistry.GetToggleOptions();
304301
}
305302

303+
internal IEnumerable<RegisteredRightControl> GetRightControls()
304+
{
305+
return _rightControls.Values.OrderBy(control => control.Id);
306+
}
307+
306308
/// <summary>
307309
/// Registers a custom option class.
308310
/// </summary>
@@ -333,6 +335,31 @@ public void AddOption(OptionDefinition option)
333335
}
334336
}
335337

338+
public void AddRightControl(OptionRightControlDefinition definition)
339+
{
340+
ArgumentNullException.ThrowIfNull(definition);
341+
342+
OptionValidator.ValidateTab(definition.Tab);
343+
OptionValidator.ValidateLabel(definition.TargetLabel, "RightControl target");
344+
OptionValidator.ValidateLabel(definition.Name, "RightControl name");
345+
346+
string key = CreateRightControlKey(definition.Tab, definition.TargetLabel, definition.Name);
347+
if (!_rightControlIds.TryGetValue(key, out int id))
348+
{
349+
id = ++_nextRightControlId;
350+
_rightControlIds[key] = id;
351+
}
352+
353+
RegisteredRightControl registered = new(id, definition);
354+
_rightControls[id] = registered;
355+
RightControlRegistered?.Invoke(registered);
356+
}
357+
358+
private static string CreateRightControlKey(string tab, string targetLabel, string name)
359+
{
360+
return $"{tab.Trim()}::{targetLabel.Trim()}::{name.Trim()}";
361+
}
362+
336363
private void ToggleFullscreen()
337364
{
338365
if (DisplayServer.WindowGetMode() == DisplayServer.WindowMode.Windowed)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Godot;
2+
using System;
3+
4+
namespace __TEMPLATE__.Ui;
5+
6+
/// <summary>
7+
/// Disposable helper that owns a right-side control attached to an existing option row.
8+
/// </summary>
9+
internal sealed class RightControlBinding : IDisposable
10+
{
11+
private readonly Control _control;
12+
private readonly Control _anchorControl;
13+
private readonly Action<Control, Control>? _onDetaching;
14+
15+
private RightControlBinding(
16+
Control control,
17+
Control anchorControl,
18+
Action<Control, Control>? onDetaching)
19+
{
20+
_control = control;
21+
_anchorControl = anchorControl;
22+
_onDetaching = onDetaching;
23+
}
24+
25+
internal static RightControlBinding Create(
26+
HBoxContainer controlsContainer,
27+
Control anchorControl,
28+
RegisteredRightControl rightControl)
29+
{
30+
OptionRightControlDefinition definition = rightControl.Definition;
31+
32+
Control control = definition.CreateControl(anchorControl)
33+
?? throw new InvalidOperationException($"Right control '{definition.Name}' returned null.");
34+
35+
if (!string.IsNullOrWhiteSpace(definition.Name))
36+
control.Name = definition.Name;
37+
38+
controlsContainer.AddChild(control);
39+
definition.OnAttached?.Invoke(control, anchorControl);
40+
41+
return new RightControlBinding(control, anchorControl, definition.OnDetaching);
42+
}
43+
44+
public void Dispose()
45+
{
46+
_onDetaching?.Invoke(_control, _anchorControl);
47+
48+
if (GodotObject.IsInstanceValid(_control))
49+
_control.QueueFree();
50+
}
51+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
uid://c5datfuovvtvp

Template/Framework/Scenes/Options/Custom/Definitions/OptionDefinitions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using Godot;
34

45
namespace __TEMPLATE__.Ui;
56

@@ -8,6 +9,18 @@ namespace __TEMPLATE__.Ui;
89
/// </summary>
910
public static class OptionDefinitions
1011
{
12+
public static OptionRightControlDefinition RightControl(
13+
string tab,
14+
string targetLabel,
15+
string name,
16+
Func<Control, Control> createControl,
17+
Action<Control, Control>? onAttached = null,
18+
Action<Control, Control>? onDetaching = null)
19+
{
20+
ArgumentNullException.ThrowIfNull(createControl);
21+
return new OptionRightControlDefinition(tab, targetLabel, name, createControl, onAttached, onDetaching);
22+
}
23+
1124
public static SliderOptionDefinition Slider(
1225
string tab,
1326
string label,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Godot;
2+
using System;
3+
4+
namespace __TEMPLATE__.Ui;
5+
6+
/// <summary>
7+
/// Describes a UI control that should be attached to the right side of another option row.
8+
/// </summary>
9+
public sealed class OptionRightControlDefinition
10+
{
11+
private readonly string _tab;
12+
private readonly string _targetLabel;
13+
private readonly string _name;
14+
private readonly Func<Control, Control> _createControl;
15+
private readonly Action<Control, Control>? _onAttached;
16+
private readonly Action<Control, Control>? _onDetaching;
17+
18+
public OptionRightControlDefinition(
19+
string tab,
20+
string targetLabel,
21+
string name,
22+
Func<Control, Control> createControl,
23+
Action<Control, Control>? onAttached = null,
24+
Action<Control, Control>? onDetaching = null)
25+
{
26+
_tab = tab;
27+
_targetLabel = targetLabel;
28+
_name = name;
29+
_createControl = createControl;
30+
_onAttached = onAttached;
31+
_onDetaching = onDetaching;
32+
}
33+
34+
public string Tab => _tab;
35+
public string TargetLabel => _targetLabel;
36+
public string Name => _name;
37+
public Func<Control, Control> CreateControl => _createControl;
38+
public Action<Control, Control>? OnAttached => _onAttached;
39+
public Action<Control, Control>? OnDetaching => _onDetaching;
40+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
uid://bo8t7a03v20p5

Template/Framework/Scenes/Options/Custom/OptionsCustom.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ public sealed class OptionsCustom : IDisposable
1313
private readonly Action<RegisteredDropdownOption> _dropdownHandler;
1414
private readonly Action<RegisteredLineEditOption> _lineEditHandler;
1515
private readonly Action<RegisteredToggleOption> _toggleHandler;
16+
private readonly Action<RegisteredRightControl> _rightControlHandler;
1617

1718
// Properties
1819
internal OptionsNav Nav { get; }
1920
internal OptionsManager OptionsManager { get; }
2021
internal Dictionary<int, IDisposable> Bindings { get; } = [];
22+
internal Dictionary<int, IDisposable> RightControlBindings { get; } = [];
2123

2224
/// <summary>
2325
/// Constructs the custom options UI manager and subscribes to option registration events.
@@ -32,6 +34,7 @@ public OptionsCustom(OptionsNav nav, OptionsManager optionsManager)
3234
_dropdownHandler = d => CustomOptionSetup.OnDropdownRegistered(this, d);
3335
_lineEditHandler = l => CustomOptionSetup.OnLineEditRegistered(this, l);
3436
_toggleHandler = t => CustomOptionSetup.OnToggleRegistered(this, t);
37+
_rightControlHandler = r => CustomOptionSetup.OnRightControlRegistered(this, r);
3538

3639
// Build UI for options that were registered before this screen opened
3740
CustomOptionSetup.Setup(this);
@@ -41,6 +44,7 @@ public OptionsCustom(OptionsNav nav, OptionsManager optionsManager)
4144
OptionsManager.DropdownOptionRegistered += _dropdownHandler;
4245
OptionsManager.LineEditOptionRegistered += _lineEditHandler;
4346
OptionsManager.ToggleOptionRegistered += _toggleHandler;
47+
OptionsManager.RightControlRegistered += _rightControlHandler;
4448
}
4549

4650
/// <summary>
@@ -52,10 +56,15 @@ public void Dispose()
5256
OptionsManager.DropdownOptionRegistered -= _dropdownHandler;
5357
OptionsManager.LineEditOptionRegistered -= _lineEditHandler;
5458
OptionsManager.ToggleOptionRegistered -= _toggleHandler;
59+
OptionsManager.RightControlRegistered -= _rightControlHandler;
5560

5661
foreach (IDisposable binding in Bindings.Values)
5762
binding.Dispose();
5863

64+
foreach (IDisposable binding in RightControlBindings.Values)
65+
binding.Dispose();
66+
5967
Bindings.Clear();
68+
RightControlBindings.Clear();
6069
}
6170
}

0 commit comments

Comments
 (0)