Skip to content

Commit 20b50cc

Browse files
committed
generic target creation and updating
1 parent a1e793c commit 20b50cc

File tree

7 files changed

+406
-8
lines changed

7 files changed

+406
-8
lines changed

sources/Input/Input/Implementations/SDL3/Devices/Pointers/Targets/SdlBoundedPointerTarget.cs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,38 @@
66

77
namespace Silk.NET.Input.SDL3.Devices.Pointers.Targets;
88

9-
internal class SdlBoundedPointerTarget(SdlInputBackend backend) : IPointerTarget
9+
internal interface ISdlBoundedPointerTarget<out T, THandle>
10+
where T : SdlBoundedPointerTarget
11+
where THandle : unmanaged
1012
{
11-
internal SdlInputBackend Backend { get; } = backend;
12-
private Box2D<float> Bounds2D { get; set; }
13+
uint Id { get; }
14+
THandle Handle { get; }
1315

14-
public Box3D<float> Bounds =>
15-
new(new Vector3D<float>(Bounds2D.Min, 0), new Vector3D<float>(Bounds2D.Max, 1));
16+
public static abstract T? Create(SdlInputBackend backend, uint id, THandle handle);
17+
public void UpdateBounds();
18+
}
19+
20+
internal abstract class SdlBoundedPointerTarget : IPointerTarget
21+
{
22+
protected SdlBoundedPointerTarget(SdlInputBackend backend)
23+
{
24+
Backend = backend;
25+
}
26+
27+
internal SdlInputBackend Backend { get; }
28+
private Box2D<float> Bounds2D
29+
{
30+
get
31+
{
32+
var bounds = Bounds;
33+
return new Box2D<float>(bounds.Min.X, bounds.Min.Y, bounds.Max.X, bounds.Max.Y);
34+
}
35+
}
36+
37+
public Box3D<float> Bounds { get; private set; }
38+
39+
public void UpdateBounds() => Bounds = CalculateBounds();
40+
protected abstract Box3D<float> CalculateBounds();
1641

1742
/// <inheritdoc />
1843
public int GetPointCount(IPointerDevice pointer) => PointerTargetExtensions.GetPointCount(this, pointer);
@@ -101,4 +126,9 @@ public static Box2D<float> CalculateWindowBounds(ISdl sdl, uint windowId)
101126

102127
return CalculateWindowBounds(sdl, window);
103128
}
129+
130+
public void Dispose()
131+
{
132+
throw new NotImplementedException();
133+
}
104134
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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 Silk.NET.Maths;
5+
6+
namespace Silk.NET.Input.SDL3.Devices.Pointers.Targets;
7+
8+
internal sealed class SdlDisplayTarget : SdlBoundedPointerTarget, ISdlBoundedPointerTarget<SdlDisplayTarget, SilkSdlDisplayHandle>
9+
{
10+
private SdlDisplayTarget(SdlInputBackend backend, SilkSdlDisplayHandle id) : base(backend)
11+
{
12+
Id = id.Id;
13+
Handle = id;
14+
}
15+
16+
protected override Box3D<float> CalculateBounds()
17+
{
18+
var bounds2d = CalculateDisplayBounds(Backend.Sdl, Id);
19+
return new Box3D<float>(bounds2d.Min.X, bounds2d.Min.Y, 0, bounds2d.Max.X, bounds2d.Max.Y, 1);
20+
}
21+
22+
public uint Id { get; }
23+
public SilkSdlDisplayHandle Handle { get; }
24+
public static SdlDisplayTarget? Create(SdlInputBackend backend, uint id, SilkSdlDisplayHandle handle) => new(backend, handle);
25+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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 Silk.NET.Maths;
5+
using Silk.NET.SDL;
6+
7+
namespace Silk.NET.Input.SDL3.Devices.Pointers.Targets;
8+
9+
internal sealed class SdlWindowTarget : SdlBoundedPointerTarget, ISdlBoundedPointerTarget<SdlWindowTarget, WindowHandle>
10+
{
11+
private SdlWindowTarget(SdlInputBackend backend, uint id, WindowHandle handle) : base(backend)
12+
{
13+
Id = id;
14+
Handle = handle;
15+
}
16+
17+
protected override Box3D<float> CalculateBounds()
18+
{
19+
var bounds2d = SdlBoundedPointerTarget.CalculateWindowBounds(Backend.Sdl, Handle);
20+
return new Box3D<float>(bounds2d.Min.X, bounds2d.Min.Y, 0, bounds2d.Max.X, bounds2d.Max.Y, 1);
21+
}
22+
23+
public uint Id { get; }
24+
public WindowHandle Handle { get; }
25+
public static SdlWindowTarget? Create(SdlInputBackend backend, uint id, WindowHandle handle) => new(backend, id, handle);
26+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
namespace Silk.NET.Input.SDL3.Devices.Pointers.Targets;
5+
6+
internal readonly struct SilkSdlDisplayHandle
7+
{
8+
public static readonly SilkSdlDisplayHandle AllDisplays = new(uint.MaxValue);
9+
public uint Id { get; }
10+
public SilkSdlDisplayHandle(uint id) => Id = id;
11+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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.Collections;
5+
using System.Diagnostics.CodeAnalysis;
6+
using System.Runtime.CompilerServices;
7+
using Silk.NET.SDL;
8+
9+
namespace Silk.NET.Input.SDL3;
10+
11+
// note - this probably doesn't need to be a ref struct, but is bc that's the extents
12+
// of the struct's current use cases
13+
// todo - can this struct be represented as a NativeArray<T, TBackend> where TBackend has a
14+
// Free(void*) or Free(void*, int) method?
15+
internal readonly unsafe ref struct SdlArray<T> : IDisposable, IEquatable<SdlArray<T>>, IReadOnlyList<T> where T : unmanaged
16+
{
17+
private readonly Ptr<T> _ptr;
18+
public int Count { get; }
19+
private readonly ISdl? _sdl;
20+
21+
[MemberNotNullWhen(true, nameof(_sdl))]
22+
private bool CanDispose { get; }
23+
24+
public static SdlArray<T> Null => default;
25+
26+
public SdlArray(Ptr<T> ptr, int count, ISdl? sdl, bool consumerCanDispose = true)
27+
{
28+
if (consumerCanDispose)
29+
{
30+
ArgumentNullException.ThrowIfNull(ptr.Native);
31+
ArgumentNullException.ThrowIfNull(sdl);
32+
}
33+
34+
ArgumentOutOfRangeException.ThrowIfNegative(count);
35+
36+
_ptr = ptr;
37+
Count = count;
38+
_sdl = sdl;
39+
CanDispose = consumerCanDispose;
40+
}
41+
42+
public void Dispose()
43+
{
44+
if (!CanDispose)
45+
{
46+
return;
47+
}
48+
49+
if (_ptr.Native == null)
50+
{
51+
return;
52+
}
53+
54+
_sdl.Free(_ptr.Native);
55+
}
56+
57+
public static implicit operator Ptr<T>(SdlArray<T> array) => array._ptr;
58+
public static implicit operator Span<T>(SdlArray<T> array) => array.AsSpan();
59+
public static implicit operator ReadOnlySpan<T>(SdlArray<T> array) => array.AsReadOnlySpan();
60+
61+
// equality operators against null and other collections
62+
public static bool operator ==(SdlArray<T> left, SdlArray<T> right) => left._sdl == right._sdl && left._ptr == right._ptr;
63+
public static bool operator !=(SdlArray<T> left, SdlArray<T> right) => left._sdl == right._sdl && left._ptr != right._ptr;
64+
public static bool operator ==(SdlArray<T> left, NullPtr right) => left._ptr == right;
65+
public static bool operator !=(SdlArray<T> left, NullPtr right) => left._ptr != right;
66+
67+
public bool IsNull => _ptr.Native == null;
68+
69+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
70+
public Span<T> AsSpan() => _ptr.Native == null ? default : new Span<T>(_ptr.Native, Count);
71+
72+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
73+
public ReadOnlySpan<T> AsReadOnlySpan() => _ptr.Native == null ? default : new ReadOnlySpan<T>(_ptr.Native, Count);
74+
75+
T IReadOnlyList<T>.this[int index] => this[index];
76+
77+
public ref T this[int index]
78+
{
79+
get
80+
{
81+
if (_ptr.Native == null)
82+
{
83+
throw new NullReferenceException();
84+
}
85+
86+
if (Count <= index)
87+
{
88+
throw new IndexOutOfRangeException(nameof(index));
89+
}
90+
91+
ArgumentOutOfRangeException.ThrowIfNegative(index);
92+
93+
return ref _ptr.Native[index];
94+
}
95+
}
96+
97+
public ref T this[uint index]
98+
{
99+
get
100+
{
101+
if (_ptr.Native == null)
102+
{
103+
throw new NullReferenceException();
104+
}
105+
106+
if (Count <= index)
107+
{
108+
throw new IndexOutOfRangeException(nameof(index));
109+
}
110+
111+
return ref _ptr.Native[index];
112+
}
113+
}
114+
115+
public bool Equals(SdlArray<T> other) => this == other;
116+
117+
public IEnumerator<T> GetEnumerator()
118+
{
119+
if (_ptr == nullptr)
120+
{
121+
throw new NullReferenceException();
122+
}
123+
124+
return (IEnumerator<T>)AsReadOnlySpan().ToArray().GetEnumerator();
125+
}
126+
127+
public override bool Equals(object? obj) => obj == null && _ptr.Native == null;
128+
public override int GetHashCode() => HashCode.Combine(_ptr, Count, _sdl);
129+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
130+
}

0 commit comments

Comments
 (0)