Skip to content

Commit 42e8391

Browse files
committed
pointer & target work
1 parent c509002 commit 42e8391

File tree

5 files changed

+129
-61
lines changed

5 files changed

+129
-61
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Runtime.CompilerServices;
5+
using Silk.NET.Maths;
6+
7+
namespace Silk.NET.Input.SDL3.Devices.Pointers;
8+
9+
internal static class MathExtensions
10+
{
11+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
12+
public static Box2D<float> ExtendBy(this Box2D<float> box, Box2D<float> other) => new(Scalar.Min(box.Min, other.Min), Scalar.Max(box.Max, other.Max));
13+
}
Lines changed: 98 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Runtime.CompilerServices;
45
using Silk.NET.Maths;
56
using Silk.NET.SDL;
67

@@ -14,14 +15,16 @@ internal class SdlBoundedPointerTarget(SdlInputBackend backend) : IPointerTarget
1415
public Box3D<float> Bounds =>
1516
new(new Vector3D<float>(Bounds2D.Min, 0), new Vector3D<float>(Bounds2D.Max, 1));
1617

17-
public static Box2D<float> CalculateBounds(ISdl sdl)
18+
/// <inheritdoc />
19+
public int GetPointCount(IPointerDevice pointer) => PointerTargetExtensions.GetPointCount(this, pointer);
20+
21+
/// <inheritdoc />
22+
public TargetPoint GetPoint(IPointerDevice pointer, int point) => PointerTargetExtensions.GetPoint(this, pointer, point);
23+
24+
public static unsafe Box2D<float> CalculateAllDisplayBounds(ISdl sdl)
1825
{
19-
var minX = float.PositiveInfinity;
20-
var minY = float.PositiveInfinity;
21-
var maxX = float.NegativeInfinity;
22-
var maxY = float.NegativeInfinity;
2326
var displayCount = 0;
24-
var displays = sdl.GetDisplays(displayCount.AsRef());
27+
var displays = sdl.GetDisplays(&displayCount);
2528
if (displays == nullptr)
2629
{
2730
// Looks like we can't support windowed mouse input.
@@ -31,66 +34,124 @@ public static Box2D<float> CalculateBounds(ISdl sdl)
3134

3235
if (displayCount == 0) // ???
3336
{
34-
sdl.Free((Ref)displays);
37+
sdl.Free(displays);
3538
return default;
3639
}
3740

41+
var bounds = new Box2D<float>(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue);
42+
3843
for (var i = 0; i < displayCount; i++)
3944
{
40-
Rect rect = default;
41-
if (!sdl.GetDisplayBounds(displays[(nuint)i], rect.AsRef()))
42-
{
43-
return default;
44-
}
45+
var b = CalculateDisplayBounds(sdl, displays[i]);
46+
bounds = bounds.ExtendBy(b);
47+
}
48+
49+
sdl.Free(displays);
50+
return default;
51+
}
4552

46-
minX = float.Min(minX, rect.X);
47-
minY = float.Min(minY, rect.Y);
48-
maxX = float.Max(maxX, rect.X + rect.W);
49-
maxY = float.Max(maxY, rect.Y + rect.H);
53+
public static unsafe Box2D<float> CalculateDisplayBounds(ISdl sdl, uint sdlDisplayId)
54+
{
55+
if (sdlDisplayId == 0)
56+
{
57+
// https://wiki.libsdl.org/SDL3/SDL_DisplayID
58+
return default;
5059
}
5160

52-
sdl.Free((Ref)displays);
53-
if (minX <= maxX && minY <= maxY)
61+
Rect rect = default;
62+
var gotDisplayBounds = sdl.GetDisplayBounds(sdlDisplayId, &rect);
63+
if (gotDisplayBounds == 0)
5464
{
55-
return new Box2D<float>(minX, minY, maxX, maxY);
65+
SdlLog.Error($"Failed to get display from ID {sdlDisplayId}.");
66+
return default;
5667
}
5768

58-
return default;
69+
return new Box2D<float>(rect.X, rect.Y, rect.X + rect.W, rect.Y + rect.H);
5970
}
6071

61-
public int GetPointCount(IPointerDevice pointer)
72+
public static unsafe Box2D<float> CalculateWindowBounds(ISdl sdl, WindowHandle window)
6273
{
63-
if (pointer is not SdlBoundedPointerDevice { IsBounded: true } device)
74+
Vector2D<int> windowSize = default;
75+
var gotSize = sdl.GetWindowSize(window, &windowSize.X, &windowSize.Y);;
76+
if (gotSize == 0)
6477
{
65-
return 0;
78+
SdlLog.Error("Failed to get window size for window.");
79+
return default;
6680
}
6781

68-
if (device.Backend == Backend)
82+
Vector2D<int> windowPosition = default;
83+
var gotPos = sdl.GetWindowPosition(window, &windowPosition.X, &windowPosition.Y);
84+
if (gotPos == 0)
6985
{
70-
//return Bounds != default ? device.BoundedPoints.List.Count : 0;
86+
SdlLog.Error("Failed to get window position for window.");
87+
return default;
7188
}
7289

73-
throw new NotImplementedException();
74-
//return device.Backend.BoundedPointerTarget.GetPointCount(pointer);
90+
var windowEndPos = windowPosition + windowSize;
91+
return new Box2D<float>(windowPosition.X, windowPosition.Y, windowEndPos.X, windowEndPos.Y);
7592
}
7693

77-
public TargetPoint GetPoint(IPointerDevice pointer, int point)
94+
public static Box2D<float> CalculateWindowBounds(ISdl sdl, uint windowId)
7895
{
79-
if (
80-
pointer is not SdlBoundedPointerDevice { IsBounded: true } device
81-
|| point < 0
82-
//|| point >= device.BoundedPoints.List.Count
83-
)
96+
var window = sdl.GetWindowFromID(windowId);
97+
if (window == nullptr)
8498
{
99+
SdlLog.Error($"Failed to get window from ID {windowId}.");
85100
return default;
86101
}
87102

88-
if (device.Backend != Backend)
103+
return CalculateWindowBounds(sdl, window);
104+
}
105+
}
106+
107+
108+
internal static class PointerTargetExtensions
109+
{
110+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
111+
public static bool AppliesTo(this IPointerDevice device, IPointerTarget target) => device.Targets.Contains(target);
112+
113+
extension(IPointerTarget target)
114+
{
115+
/// <summary>
116+
/// A default implementation of <see cref="IPointerTarget.GetPointCount(IPointerDevice)"/>
117+
/// that iterates over all points.
118+
/// </summary>
119+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
120+
public int GetPointCount(IPointerDevice pointer)
89121
{
90-
// return device.Backend.BoundedPointerTarget.GetPoint(pointer, point);
122+
var points = pointer.State.Points;
123+
var count = 0;
124+
var pointerPointsCount = points.Count;
125+
for(var i = 0; i < pointerPointsCount; i++)
126+
{
127+
if (points[i].Target == target)
128+
{
129+
++count;
130+
}
131+
}
132+
133+
return count;
91134
}
92135

93-
throw new NotImplementedException();
94-
// return Bounds != default ? device.BoundedPoints.List[point] : default;
136+
/// <summary>
137+
/// A default implementation of <see cref="IPointerTarget.GetPoint(IPointerDevice, int)"/>
138+
/// that iterates over all points.
139+
/// </summary>
140+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
141+
public TargetPoint GetPoint(IPointerDevice pointer, int point)
142+
{
143+
var points = pointer.State.Points;
144+
var pointerPointsCount = points.Count;
145+
for(var i = 0; i < pointerPointsCount; i++)
146+
{
147+
var targetPoint = points[i];
148+
if (targetPoint.Target == target && point-- == 0)
149+
{
150+
return targetPoint;
151+
}
152+
}
153+
154+
return default;
155+
}
95156
}
96157
}

sources/Input/Input/Implementations/SDL3/Devices/Pointers/SdlSharedMouse.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ internal class SdlSharedMouse : SdlBoundedPointerDevice, IMouse, ISdlDevice<SdlS
1313

1414
private readonly MouseState _state;
1515

16-
private SdlSharedMouse(uint sdlDeviceId, nint uniqueId, SdlInputBackend backend)
16+
private SdlSharedMouse(uint sdlDeviceId, nint uniqueId, SdlInputBackend backend, IPointerTarget unboundedPointerTarget, ICursorConfiguration cursor)
1717
: base(backend, uniqueId, sdlDeviceId)
1818
{
19-
IPointerTarget unboundedPointerTarget = backend.UnboundedPointerTarget;
2019
_state = new MouseState(new ButtonReadOnlyList<PointerButton>(_buttons),
2120
new InputReadOnlyList<TargetPoint>(_points), Vector2.Zero);
22-
Cursor = backend.CursorConfiguration;
21+
Cursor = cursor;
2322
float x = 0, y = 0;
2423
var buttonMask = NativeBackend.GetMouseState(x.AsRef(), y.AsRef());
2524
var pos = new Vector2(x, y);
@@ -106,7 +105,7 @@ public static unsafe SdlSharedMouse CreateDevice(uint sdlDeviceId, SdlInputBacke
106105
}
107106

108107
backend.Sdl.Free(deviceName);
109-
return new SdlSharedMouse(sdlDeviceId, uniqueId, backend);
108+
return new SdlSharedMouse(sdlDeviceId, uniqueId, backend, backend.UnboundedPointerTarget, backend.CursorConfiguration);
110109
}
111110

112111
public override string Name => $"{Backend.Name}: Shared/Global Mouse";
@@ -195,7 +194,7 @@ public void AddWheelEvent(in MouseWheelEvent evtWheel)
195194
private static bool IsPointerButtonPressedSdl(PointerButton button, uint state)
196195
{
197196
var index = EnumInfo<PointerButton>.ValueIndexOf(button);
198-
if (index < 0 || index >= 32)
197+
if (index is < 0 or >= 32)
199198
{
200199
return false;
201200
}
@@ -204,8 +203,8 @@ private static bool IsPointerButtonPressedSdl(PointerButton button, uint state)
204203
}
205204

206205
private uint _mouseWindowId;
207-
private Vector2 _mouseScroll = default;
208-
private Vector2 _accumulatedMotion = default;
206+
private Vector2 _mouseScroll;
207+
private Vector2 _accumulatedMotion;
209208
private readonly List<Button<PointerButton>> _buttons = [];
210209
private readonly List<TargetPoint> _points = new();
211210
private readonly IPointerTarget[] _targetListNoWindow;

sources/Input/Input/Implementations/SDL3/Devices/Pointers/SdlUnboundedPointerTarget.cs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,28 @@ internal class SdlUnboundedPointerTarget(SdlInputBackend backend) : IPointerTarg
1818

1919
public Box3D<float> Bounds => _bounds;
2020

21-
public int GetPointCount(IPointerDevice pointer) => IsValidDevice(pointer) ? pointer.State.Points.Count : 0;
21+
public int GetPointCount(IPointerDevice pointer) => PointerTargetExtensions.GetPointCount(this, pointer);
2222

23-
public TargetPoint GetPoint(IPointerDevice pointer, int pointIdx)
23+
public TargetPoint GetPoint(IPointerDevice pointer, int pointIdx) => PointerTargetExtensions.GetPoint(this, pointer, pointIdx);
24+
/*
2425
{
2526
var point = pointer.State.Points[pointIdx];
2627
var valid = IsValidDevice(pointer);
2728
return new TargetPoint(
2829
Id: point.Id, // todo : follow spec with unique ids
2930
Flags: valid ? TargetPointFlags.PointingAtTarget : TargetPointFlags.NotPointingAtTarget,
30-
Position: point.Position,
31+
Position: point.Position, // in this case, should the position be provided at all?
3132
NormalizedPosition: default,
3233
Pointer: new Ray3D<float>(),
33-
Pressure: point.Pressure is > 1 or < 0
34-
? point.Pressure is 0
35-
? 0
36-
: 1
37-
: point.Pressure,
34+
Pressure: point.Pressure < 0 ? 0 : point.Pressure > 1 ? 1 : point.Pressure,
3835
Target: this
3936
);
4037
}
38+
*/
4139

42-
private bool IsValidDevice(IPointerDevice pointer)
43-
{
44-
// todo - do we really want to limit this to SDL devices? or to our specific sdl backend?
45-
// i dont think so, but.... technically...
46-
47-
var device = pointer as SdlDevice;
48-
return device is not null && device.Backend == backend && (device.Backend.CursorConfiguration.Mode & CursorModes.Unbounded) != 0;
49-
}
40+
// todo - do we really want to limit this to SDL devices? or to our specific sdl backend?
41+
// i dont think so, but.... technically...
42+
private bool IsValidDevice(IPointerDevice pointer) =>
43+
pointer is SdlDevice device && device.Backend == backend &&
44+
(device.Backend.CursorConfiguration.Mode & CursorModes.Unbounded) != 0;
5045
}

sources/Input/Input/Implementations/SDL3/SdlInputBackend.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ private void ProcessEvent(in Event evt, IInputHandler handler)
421421
case EventType.DisplayCurrentModeChanged:
422422
case EventType.DisplayContentScaleChanged:
423423
{
424-
var bounds = SdlBoundedPointerTarget.CalculateBounds(Sdl);
424+
var bounds = SdlBoundedPointerTarget.CalculateAllDisplayBounds(Sdl);
425425
var x = (QueuedEventType.BoundedPointerTargetUpdate,
426426
timestamp,
427427
bounds.Min.ToSystem(),

0 commit comments

Comments
 (0)