Skip to content

Commit b2a0f46

Browse files
authored
Refactor #154 to fix #192 (#194)
This fixes #192, and may or may not improve #154. It reverts 5676ce7 (which I didn't like, but couldn't fix at the time) and the commits that depend on it, and then re-implements ef55b5e in a way that doesn't require 5676ce7.
2 parents a459a39 + 6673241 commit b2a0f46

38 files changed

+154
-172
lines changed

Yafc.Model/Blueprints/Blueprint.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class BlueprintString(string blueprintName) {
1414
private static readonly byte[] header = { 0x78, 0xDA };
1515

1616
public string ToBpString() {
17-
if (Ui.ActiveInputSystem?.control ?? false) {
17+
if (InputSystem.Instance.control) {
1818
return ToJson();
1919
}
2020

Yafc.Model/Serialization/UndoSystem.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,8 @@ private static void MakeUndoBatch(object? state) {
5757
}
5858

5959
private void Schedule() {
60-
if (Ui.ActiveInputSystem != null) {
61-
Ui.ActiveInputSystem.DispatchOnGestureFinish(MakeUndoBatch, this);
62-
scheduled = true;
63-
}
60+
InputSystem.Instance.DispatchOnGestureFinish(MakeUndoBatch, this);
61+
scheduled = true;
6462
}
6563

6664
public void Suspend() {

Yafc.UI/Core/InputSystem.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ public interface IMouseFocus {
1717
}
1818

1919
public sealed class InputSystem {
20+
public static readonly InputSystem Instance = new InputSystem();
21+
22+
private InputSystem() { }
23+
2024
public Window? mouseOverWindow { get; private set; }
2125
private IPanel? hoveringPanel;
2226
private IPanel? mouseDownPanel;
@@ -62,7 +66,11 @@ public void SetMouseFocus(IMouseFocus? mouseFocus) {
6266
activeMouseFocus?.FocusChanged(true);
6367
}
6468

65-
public void SetDefaultKeyboardFocus(IKeyboardFocus? focus) => defaultKeyboardFocus = focus;
69+
public IKeyboardFocus? SetDefaultKeyboardFocus(IKeyboardFocus? focus) {
70+
IKeyboardFocus? previousFocus = defaultKeyboardFocus;
71+
defaultKeyboardFocus = focus;
72+
return previousFocus;
73+
}
6674

6775
public bool control => (keyMod & SDL.SDL_Keymod.KMOD_CTRL) != 0;
6876
public bool shift => (keyMod & SDL.SDL_Keymod.KMOD_SHIFT) != 0;

Yafc.UI/Core/Ui.cs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.ComponentModel;
43
using System.Diagnostics;
5-
using System.Linq;
64
using System.Runtime.InteropServices;
75
using System.Text;
86
using System.Threading;
@@ -36,15 +34,6 @@ public static void Start() {
3634
mainThreadId = Thread.CurrentThread.ManagedThreadId;
3735
}
3836

39-
/// <summary>
40-
/// The <see cref="InputSystem"/> belonging to the active window, if such a window exists. Failing that, it is the input system for the only window,
41-
/// if there is exactly one window. This is the *current* active input system, and may be about to change if a new (OS-level) window is being
42-
/// constructed or if the focus is changing. For this reason, try to get your InputSystem from a source that reflects the new value,
43-
/// rather than the current value.
44-
/// </summary>
45-
[EditorBrowsable(EditorBrowsableState.Never)]
46-
public static InputSystem? ActiveInputSystem => windows.Values.FirstOrDefault(w => w.active)?.InputSystem ?? (windows.Count == 1 ? windows.Values.First().InputSystem : null);
47-
4837
public static long time { get; private set; }
4938
private static readonly Stopwatch timeWatch = Stopwatch.StartNew();
5039

@@ -66,8 +55,7 @@ public static void MainLoop() {
6655

6756
public static void ProcessEvents() {
6857
try {
69-
InputSystem? inputSystem = ActiveInputSystem;
70-
if (inputSystem == null) { return; }
58+
var inputSystem = InputSystem.Instance;
7159
long minNextEvent = long.MaxValue - 1;
7260
foreach (var (_, window) in windows) {
7361
minNextEvent = Math.Min(minNextEvent, window.nextRepaintTime);
@@ -135,10 +123,10 @@ public static void ProcessEvents() {
135123

136124
switch (evt.window.windowEvent) {
137125
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_ENTER:
138-
window.InputSystem.MouseEnterWindow(window);
126+
inputSystem.MouseEnterWindow(window);
139127
break;
140128
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_LEAVE:
141-
window.InputSystem.MouseExitWindow(window);
129+
inputSystem.MouseExitWindow(window);
142130
break;
143131
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE:
144132
window.Close();
@@ -147,9 +135,11 @@ public static void ProcessEvents() {
147135
window.FocusLost();
148136
break;
149137
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED:
150-
window.FocusGained();
151138
window.Rebuild();
152139
break;
140+
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MINIMIZED:
141+
window.Minimized();
142+
break;
153143
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_MOVED:
154144
window.WindowMoved();
155145
break;

Yafc.UI/Core/Window.cs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics.CodeAnalysis;
23
using System.Numerics;
34
using SDL2;
45

@@ -13,7 +14,6 @@ public abstract class Window : IDisposable {
1314
internal bool repaintRequired = true;
1415
internal bool visible;
1516
internal bool closed;
16-
internal bool active;
1717
internal long nextRepaintTime = long.MaxValue;
1818
internal float pixelsPerUnit;
1919
public virtual SchemeColor backgroundColor => SchemeColor.Background;
@@ -28,13 +28,10 @@ public abstract class Window : IDisposable {
2828
public int displayIndex => SDL.SDL_GetWindowDisplayIndex(window);
2929
public int repaintCount { get; private set; }
3030

31-
public InputSystem InputSystem { get; } = new();
32-
3331
public Vector2 size => contentSize;
3432

3533
public virtual bool preventQuit => false;
36-
37-
internal Window(Padding padding) => rootGui = new ImGui(Build, padding, InputSystem);
34+
internal Window(Padding padding) => rootGui = new ImGui(Build, padding);
3835

3936
internal void Create() {
4037
if (surface is null) { throw new InvalidOperationException($"surface must be set by a derived class before calling {nameof(Create)}."); }
@@ -148,7 +145,6 @@ public void Repaint() {
148145

149146
protected internal virtual void Close() {
150147
visible = false;
151-
active = false;
152148
closed = true;
153149
surface?.Dispose();
154150
SDL.SDL_DestroyWindow(window);
@@ -165,8 +161,9 @@ private void Focus() {
165161
}
166162
}
167163

168-
public virtual void FocusLost() => active = false;
169-
public void FocusGained() => active = true;
164+
165+
public virtual void FocusLost() { }
166+
public virtual void Minimized() { }
170167

171168
public void SetNextRepaint(long nextRepaintTime) {
172169
if (this.nextRepaintTime > nextRepaintTime) {
@@ -180,7 +177,7 @@ public void ShowTooltip(Tooltip tooltip) {
180177
}
181178

182179
public void ShowTooltip(ImGui targetGui, Rect target, GuiBuilder builder, float width = 20f) {
183-
simpleTooltip ??= new SimpleTooltip(InputSystem);
180+
simpleTooltip ??= new SimpleTooltip();
184181
simpleTooltip.Show(builder, targetGui, target, width);
185182
ShowTooltip(simpleTooltip);
186183

@@ -192,7 +189,7 @@ public void ShowDropDown(DropDownPanel dropDown) {
192189
}
193190

194191
public void ShowDropDown(ImGui targetGui, Rect target, GuiBuilder builder, Padding padding, float width = 20f) {
195-
simpleDropDown ??= new SimpleDropDown(InputSystem);
192+
simpleDropDown ??= new SimpleDropDown();
196193
simpleDropDown.SetPadding(padding);
197194
simpleDropDown.SetFocus(targetGui, target, builder, width);
198195
ShowDropDown(simpleDropDown);
@@ -222,7 +219,7 @@ private void Build(ImGui gui) {
222219
protected abstract void BuildContents(ImGui gui);
223220
public virtual void Dispose() => rootGui.Dispose();
224221

225-
internal ImGui.DragOverlay GetDragOverlay() => draggingOverlay ??= new ImGui.DragOverlay(InputSystem);
222+
internal ImGui.DragOverlay GetDragOverlay() => draggingOverlay ??= new ImGui.DragOverlay();
226223
protected internal virtual void WindowMaximized() { }
227224
protected internal virtual void WindowRestored() { }
228225
}

Yafc.UI/ImGui/DropDownPanel.cs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public abstract class AttachedPanel {
99
protected float width;
1010
protected virtual SchemeColor background => SchemeColor.PureBackground;
1111

12-
protected AttachedPanel(Padding padding, float width, InputSystem inputSystem) {
13-
contents = new ImGui(BuildContents, padding, inputSystem) { boxColor = background, boxShadow = RectangleBorder.Thin };
12+
protected AttachedPanel(Padding padding, float width) {
13+
contents = new ImGui(BuildContents, padding) { boxColor = background, boxShadow = RectangleBorder.Thin };
1414
this.width = width;
1515
}
1616

@@ -49,13 +49,13 @@ public void Build(ImGui gui) {
4949
protected abstract void BuildContents(ImGui gui);
5050
}
5151

52-
public abstract class DropDownPanel(Padding padding, float width, InputSystem inputSystem) : AttachedPanel(padding, width, inputSystem), IMouseFocus {
52+
public abstract class DropDownPanel : AttachedPanel, IMouseFocus {
5353
private bool focused;
54-
54+
protected DropDownPanel(Padding padding, float width) : base(padding, width) { }
5555
protected override bool ShouldBuild(ImGui source, Rect sourceRect, ImGui parent, Rect parentRect) => focused;
5656

5757
public override void SetFocus(ImGui source, Rect rect) {
58-
source.inputSystem.SetMouseFocus(this);
58+
InputSystem.Instance.SetMouseFocus(this);
5959
base.SetFocus(source, rect);
6060
}
6161

@@ -80,7 +80,7 @@ public void FocusChanged(bool focused) {
8080
public class SimpleDropDown : DropDownPanel {
8181
private GuiBuilder? builder;
8282

83-
public SimpleDropDown(InputSystem inputSystem) : base(new Padding(1f), 20f, inputSystem) => contents.AddMessageHandler<ImGuiUtils.CloseDropdownEvent>(HandleDropdownClosed);
83+
public SimpleDropDown() : base(new Padding(1f), 20f) => contents.AddMessageHandler<ImGuiUtils.CloseDropdownEvent>(HandleDropdownClosed);
8484

8585
private bool HandleDropdownClosed(ImGuiUtils.CloseDropdownEvent _) {
8686
Close();
@@ -118,15 +118,10 @@ protected override void BuildContents(ImGui gui) {
118118
}
119119

120120
public abstract class Tooltip : AttachedPanel {
121-
private readonly InputSystem inputSystem;
122-
protected Tooltip(Padding padding, float width, InputSystem inputSystem) : base(padding, width, inputSystem) {
123-
contents.mouseCapture = false;
124-
this.inputSystem = inputSystem;
125-
}
126-
121+
protected Tooltip(Padding padding, float width) : base(padding, width) => contents.mouseCapture = false;
127122
protected override bool ShouldBuild(ImGui source, Rect sourceRect, ImGui parent, Rect parentRect) {
128123
var window = source.window;
129-
if (inputSystem.mouseOverWindow != window) {
124+
if (InputSystem.Instance.mouseOverWindow != window) {
130125
return false;
131126
}
132127

@@ -148,14 +143,16 @@ protected override Vector2 CalculatePosition(ImGui gui, Rect targetRect, Vector2
148143
}
149144
}
150145

151-
public class SimpleTooltip(InputSystem inputSystem) : Tooltip(new Padding(0.5f), 30f, inputSystem) {
146+
public class SimpleTooltip : Tooltip {
152147
private GuiBuilder? builder;
153148
public void Show(GuiBuilder builder, ImGui gui, Rect rect, float width = 30f) {
154149
this.width = width;
155150
this.builder = builder;
156151
base.SetFocus(gui, rect);
157152
}
158153

154+
public SimpleTooltip() : base(new Padding(0.5f), 30f) { }
155+
159156
protected override void BuildContents(ImGui gui) {
160157
gui.boxColor = SchemeColor.PureBackground;
161158
gui.textColor = SchemeColor.BackgroundText;

Yafc.UI/ImGui/ImGui.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public enum RectAllocator {
5050
public delegate void GuiBuilder(ImGui gui);
5151

5252
public sealed partial class ImGui : IDisposable, IPanel {
53-
public ImGui(GuiBuilder? guiBuilder, Padding padding, InputSystem inputSystem, RectAllocator defaultAllocator = RectAllocator.Stretch, bool clip = false) {
53+
public ImGui(GuiBuilder? guiBuilder, Padding padding, RectAllocator defaultAllocator = RectAllocator.Stretch, bool clip = false) {
5454
this.guiBuilder = guiBuilder;
5555
if (guiBuilder == null) {
5656
action = ImGuiAction.Build;
@@ -59,7 +59,6 @@ public ImGui(GuiBuilder? guiBuilder, Padding padding, InputSystem inputSystem, R
5959
this.defaultAllocator = defaultAllocator;
6060
this.clip = clip;
6161
initialPadding = padding;
62-
this.inputSystem = inputSystem ?? throw new ArgumentNullException(nameof(inputSystem));
6362
}
6463

6564
public readonly GuiBuilder? guiBuilder;
@@ -95,7 +94,7 @@ public Vector2 offset {
9594
screenRect -= (_offset - value);
9695
_offset = value;
9796
if (mousePresent) {
98-
MouseMove(inputSystem.mouseDownButton);
97+
MouseMove(InputSystem.Instance.mouseDownButton);
9998
}
10099
else {
101100
Repaint();

Yafc.UI/ImGui/ImGuiBuilding.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public void Deconstruct(out Rect rect, out T data, out SchemeColor color) {
3030
public SchemeColor boxColor { get; set; } = SchemeColor.None;
3131
public RectangleBorder boxShadow { get; set; } = RectangleBorder.None;
3232
public Padding initialPadding { get; set; }
33-
internal readonly InputSystem inputSystem;
3433

3534
public void DrawRectangle(Rect rect, SchemeColor color, RectangleBorder border = RectangleBorder.None) {
3635
if (action != ImGuiAction.Build) {
@@ -167,7 +166,7 @@ public void BuildIcon(Icon icon, float size = 1.5f, SchemeColor color = SchemeCo
167166
}
168167
}
169168

170-
public Vector2 mousePosition => inputSystem.mousePosition - screenRect.Position;
169+
public Vector2 mousePosition => InputSystem.Instance.mousePosition - screenRect.Position;
171170
public bool mousePresent { get; private set; }
172171
public Rect mouseDownRect { get; private set; }
173172
public Rect mouseOverRect { get; private set; } = Rect.VeryBig;
@@ -349,7 +348,7 @@ public bool ConsumeEvent(Rect rect) {
349348
public bool IsLastMouseDown(Rect rect) => rect == mouseDownRect;
350349

351350
public void SetTextInputFocus(Rect rect, string text) {
352-
if (textInputHelper != null && inputSystem.currentKeyboardFocus != textInputHelper) {
351+
if (textInputHelper != null && InputSystem.Instance.currentKeyboardFocus != textInputHelper) {
353352
Rebuild();
354353
textInputHelper.SetFocus(rect, text);
355354
}

Yafc.UI/ImGui/ImGuiDrag.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ public bool DoListReordering<T>(Rect moveHandle, Rect contents, T index, out T m
6565
}
6666

6767

68-
internal class DragOverlay(InputSystem inputSystem) {
69-
private readonly ImGui contents = new ImGui(null, default, inputSystem) { mouseCapture = false };
68+
internal class DragOverlay {
69+
private readonly ImGui contents = new ImGui(null, default) { mouseCapture = false };
7070

7171
private ImGui? currentSource;
7272
private Vector2 mouseOffset;
7373
private Rect realPosition;
7474

75+
7576
public bool ShouldConsumeDrag(ImGui source, Vector2 point) => currentSource == source && realPosition.Contains(source.ToWindowPosition(point));
7677

7778
private void ExtractDrawCommandsFrom<T>(List<DrawCommand<T>> sourceList, List<DrawCommand<T>> targetList, Rect rect) {
@@ -116,7 +117,7 @@ public void Build(ImGui screenGui) {
116117
return;
117118
}
118119

119-
if (inputSystem.mouseDownButton == -1) {
120+
if (InputSystem.Instance.mouseDownButton == -1) {
120121
currentSource = null;
121122
realPosition = default;
122123
return;
@@ -133,7 +134,7 @@ public void Build(ImGui screenGui) {
133134
}
134135

135136
public bool ShouldEnterDrag(Rect moveHandle) {
136-
if (action != ImGuiAction.MouseMove || !IsMouseDown(moveHandle) || isDragging || Vector2.DistanceSquared(inputSystem.mousePosition, inputSystem.mouseDownPosition) < 1f) {
137+
if (action != ImGuiAction.MouseMove || !IsMouseDown(moveHandle) || isDragging || Vector2.DistanceSquared(InputSystem.Instance.mousePosition, InputSystem.Instance.mouseDownPosition) < 1f) {
137138
return false;
138139
}
139140

Yafc.UI/ImGui/ImGuiTextInputHelper.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public void SetFocus(Rect boundingRect, string setText) {
3030
editHistory.Clear();
3131
text = setText;
3232
}
33-
gui.inputSystem.SetKeyboardFocus(this);
33+
InputSystem.Instance.SetKeyboardFocus(this);
3434
rect = boundingRect;
3535
caret = selectionAnchor = setText.Length;
3636
}
@@ -251,7 +251,7 @@ public bool KeyDown(SDL.SDL_Keysym key) {
251251
case SDL.SDL_Scancode.SDL_SCANCODE_RETURN2:
252252
case SDL.SDL_Scancode.SDL_SCANCODE_KP_ENTER:
253253
case SDL.SDL_Scancode.SDL_SCANCODE_ESCAPE:
254-
gui.inputSystem.SetKeyboardFocus(null);
254+
InputSystem.Instance.SetKeyboardFocus(null);
255255
return false;
256256
case SDL.SDL_Scancode.SDL_SCANCODE_LEFT:
257257
if (shift) {

0 commit comments

Comments
 (0)