Skip to content

Commit 131da01

Browse files
authored
[GameController] Implement up to Xcode 16.3. (#22699)
This includes some older APIs as well. Fixes #15725.
1 parent 75749b6 commit 131da01

16 files changed

+851
-242
lines changed

src/GameController/GCInput.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
#nullable enable
5+
6+
using System;
7+
using System.Globalization;
8+
using System.Runtime.CompilerServices;
9+
using System.Runtime.InteropServices;
10+
using System.Runtime.Versioning;
11+
12+
using CoreFoundation;
13+
using CoreGraphics;
14+
using Foundation;
15+
using ObjCRuntime;
16+
17+
namespace GameController {
18+
public partial class GCInput {
19+
[SupportedOSPlatform ("ios17.4")]
20+
[SupportedOSPlatform ("macos14.4")]
21+
[SupportedOSPlatform ("tvos17.4")]
22+
[SupportedOSPlatform ("maccatalyst17.4")]
23+
[DllImport (Constants.GameControllerLibrary)]
24+
static extern IntPtr /* GCButtonElementName */ GCInputBackLeftButton (nint position);
25+
26+
// A strongly-typed API (the GCInputButtonName enum) is not possible, because it's not an exhaustive enum,
27+
// this method may return strings that aren't in the enum.
28+
/// <summary>Get the name of the back left button on the controller for the specified position.</summary>
29+
/// <param name="position">Zero-based position of the button.</param>
30+
/// <returns>The name of the back left button on the controller for the specified position.</returns>
31+
[SupportedOSPlatform ("ios17.4")]
32+
[SupportedOSPlatform ("macos14.4")]
33+
[SupportedOSPlatform ("tvos17.4")]
34+
[SupportedOSPlatform ("maccatalyst17.4")]
35+
public static NSString? GetBackLeftButtonName (nint position)
36+
{
37+
return Runtime.GetNSObject<NSString> (GCInputBackLeftButton (position));
38+
}
39+
40+
[SupportedOSPlatform ("ios17.4")]
41+
[SupportedOSPlatform ("macos14.4")]
42+
[SupportedOSPlatform ("tvos17.4")]
43+
[SupportedOSPlatform ("maccatalyst17.4")]
44+
[DllImport (Constants.GameControllerLibrary)]
45+
static extern IntPtr /* GCButtonElementName */ GCInputBackRightButton (nint position);
46+
47+
// A strongly-typed API (the GCInputButtonName enum) is not possible, because it's not an exhaustive enum,
48+
// this method may return strings that aren't in the enum.
49+
/// <summary>Get the name of the back right button on the controller for the specified position.</summary>
50+
/// <param name="position">Zero-based position of the button.</param>
51+
/// <returns>The name of the back rught button on the controller for the specified position.</returns>
52+
[SupportedOSPlatform ("ios17.4")]
53+
[SupportedOSPlatform ("macos14.4")]
54+
[SupportedOSPlatform ("tvos17.4")]
55+
[SupportedOSPlatform ("maccatalyst17.4")]
56+
public static NSString? GetBackRightButtonName (nint position)
57+
{
58+
return Runtime.GetNSObject<NSString> (GCInputBackRightButton (position));
59+
}
60+
61+
// headers claim macOS 13.0 / iOS 16.0, but introspection says macOS 14.0 / iOS 17.0, so use that.
62+
[SupportedOSPlatform ("ios17.0")]
63+
[SupportedOSPlatform ("macos14.0")]
64+
[SupportedOSPlatform ("tvos17.0")]
65+
[SupportedOSPlatform ("maccatalyst17.0")]
66+
[DllImport (Constants.GameControllerLibrary)]
67+
static extern IntPtr /* GCButtonElementName */ GCInputArcadeButtonName (nint row, nint column);
68+
69+
// A strongly-typed API (the GCInputButtonName enum) is not possible, because it's not an exhaustive enum,
70+
// this method may return strings that aren't in the enum.
71+
/// <summary>Get the name of the arcade button for the specified position.</summary>
72+
/// <param name="row">The row of the arcade button.</param>
73+
/// <param name="column">The column of the arcade button.</param>
74+
/// <returns>The name of the arcade button on the controller for the specified position.</returns>
75+
[SupportedOSPlatform ("ios17.0")]
76+
[SupportedOSPlatform ("macos14.0")]
77+
[SupportedOSPlatform ("tvos17.0")]
78+
[SupportedOSPlatform ("maccatalyst17.0")]
79+
public static NSString? GetArcadeButtonName (nint row, nint column)
80+
{
81+
return Runtime.GetNSObject<NSString> (GCInputArcadeButtonName (row, column));
82+
}
83+
}
84+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections;
6+
using System.Collections.Generic;
7+
8+
using Foundation;
9+
using ObjCRuntime;
10+
11+
#nullable enable
12+
13+
namespace GameController {
14+
public partial class GCPhysicalInputElementCollection<KeyIdentifierType, ElementIdentifierType> : IEnumerable<KeyIdentifierType> {
15+
#region IEnumerable<KeyIdentifierType>
16+
IEnumerator<KeyIdentifierType> IEnumerable<KeyIdentifierType>.GetEnumerator ()
17+
{
18+
return new NSFastEnumerator<KeyIdentifierType> (this);
19+
}
20+
#endregion
21+
22+
#region IEnumerable implementation
23+
IEnumerator IEnumerable.GetEnumerator ()
24+
{
25+
return new NSFastEnumerator<KeyIdentifierType> (this);
26+
}
27+
#endregion
28+
}
29+
}

src/GameController/GCPoint2.cs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
#nullable enable
5+
6+
using System;
7+
using System.Globalization;
8+
using System.Runtime.CompilerServices;
9+
using System.Runtime.InteropServices;
10+
using System.Runtime.Versioning;
11+
12+
using CoreFoundation;
13+
using CoreGraphics;
14+
using Foundation;
15+
using ObjCRuntime;
16+
17+
namespace GameController {
18+
/// <summary>Represents an ordered pair of floating-point x- and y-coordinates that defines a point in a two-dimensional plane.</summary>
19+
[SupportedOSPlatform ("ios")]
20+
[SupportedOSPlatform ("maccatalyst")]
21+
[SupportedOSPlatform ("macos")]
22+
[SupportedOSPlatform ("tvos")]
23+
public struct GCPoint2
24+
#if !COREBUILD
25+
: IEquatable<GCPoint2>
26+
#endif
27+
{
28+
float x;
29+
float y;
30+
31+
/// <summary>Gets or sets the x-coordinate of this <see cref="GCPoint2" />.</summary>
32+
/// <value>The x-coordinate of this <see cref="GCPoint2" />.</value>
33+
public float X {
34+
get { return x; }
35+
set { x = value; }
36+
}
37+
38+
/// <summary>Gets or sets the y-coordinate of this <see cref="GCPoint2" />.</summary>
39+
/// <value>The y-coordinate of this <see cref="GCPoint2" />.</value>
40+
public float Y {
41+
get { return y; }
42+
set { y = value; }
43+
}
44+
45+
#if !COREBUILD
46+
/// <summary>Represents a new instance of the <see cref="GCPoint2" /> where both the <see cref="X" /> and <see cref="Y"/> coordinates are 0.</summary>
47+
public static readonly GCPoint2 Zero;
48+
49+
/// <summary>Compares two <see cref="GCPoint2" /> values for equality.</summary>
50+
/// <param name="l">The left-hand side of the comparison.</param>
51+
/// <param name="r">The right-hand side of the comparison.</param>
52+
/// <returns><see langword="true" /> if <paramref name="l" /> and <paramref name="r" /> are equal, otherwise <see langword="false" />.</returns>
53+
public static bool operator == (GCPoint2 l, GCPoint2 r)
54+
{
55+
return l.Equals (r);
56+
}
57+
58+
/// <summary>Compares two <see cref="GCPoint2" /> values for inequality.</summary>
59+
/// <param name="l">The left-hand side of the comparison.</param>
60+
/// <param name="r">The right-hand side of the comparison.</param>
61+
/// <returns><see langword="true" /> if <paramref name="l" /> and <paramref name="r" /> are not equal, otherwise <see langword="false" />.</returns>
62+
public static bool operator != (GCPoint2 l, GCPoint2 r)
63+
{
64+
return !l.Equals (r);
65+
}
66+
67+
/// <summary>Gets a value indicating whether this <see cref="GCPoint2" /> is empty.</summary>
68+
/// <value><see langword="true" /> if both <see cref="X" /> and <see cref="Y" /> are 0,, otherwise <see langword="false" />.</value>
69+
public bool IsEmpty {
70+
get { return x == 0.0 && y == 0.0; }
71+
}
72+
73+
/// <summary>Initializes a new instance of the <see cref="GCPoint2" /> struct with the specified coordinates.</summary>
74+
/// <param name="x">The X coordinate of the point.</param>
75+
/// <param name="y">The X coordinate of the point.</param>
76+
public GCPoint2 (float x, float y)
77+
{
78+
this.x = x;
79+
this.y = y;
80+
}
81+
82+
/// <summary>Initializes a new instance of the <see cref="GCPoint2" /> struct from the specified <see cref="GCPoint2" />.</summary>
83+
/// <param name="point">The source point.</param>
84+
public GCPoint2 (GCPoint2 point)
85+
{
86+
this.x = point.x;
87+
this.y = point.y;
88+
}
89+
90+
/// <summary>Specifies whether this <see cref="GCPoint2" /> contains the same coordinates as the specified <see cref="object" />.</summary>
91+
/// <param name="obj">The <see cref="object" /> to compare with this object.</param>
92+
/// <returns><see langword="true" /> if <paramref name="obj" /> is a <see cref="GCPoint2" /> with the same coordinates as this point, otherwise <see langword="false" />.</returns>
93+
public override bool Equals (object? obj)
94+
{
95+
return (obj is GCPoint2 t) && Equals (t);
96+
}
97+
98+
/// <summary>Specifies whether this <see cref="GCPoint2" /> contains the same coordinates as the specified <see cref="GCPoint2" />.</summary>
99+
/// <param name="point">The <see cref="GCPoint2" /> to compare with this object.</param>
100+
/// <returns><see langword="true" /> if <paramref name="point" /> has the same coordinates as this point, otherwise <see langword="false" />.</returns>
101+
public bool Equals (GCPoint2 point)
102+
{
103+
return point.x == x && point.y == y;
104+
}
105+
106+
/// <summary>Returns a hash code for this <see cref="GCPoint2" /> structure.</summary>
107+
/// <returns>An integer value that specifies a hash value for this <see cref="GCPoint2" /> structure.</returns>
108+
public override int GetHashCode ()
109+
{
110+
return HashCode.Combine (x, y);
111+
}
112+
113+
/// <summary>Deconstructs <see cref="GCPoint2"/> by <see cref="X"/> and <see cref="Y"/>.</summary>
114+
/// <param name="x">Deconstructed parameter for <see cref="X"/>.</param>
115+
/// <param name="y">Deconstructed parameter for <see cref="Y"/>.</param>
116+
public void Deconstruct (out nfloat x, out nfloat y)
117+
{
118+
x = X;
119+
y = Y;
120+
}
121+
122+
/// <summary>Converts this <see cref="GCPoint2" /> to a human readable string.</summary>
123+
/// <returns>A string that represents this <see cref="GCPoint2" />.</returns>
124+
public override string? ToString ()
125+
{
126+
if (OperatingSystem.IsMacOSVersionAtLeast (14, 3) ||
127+
OperatingSystem.IsMacCatalystVersionAtLeast (17, 4) ||
128+
OperatingSystem.IsIOSVersionAtLeast (17, 4) ||
129+
OperatingSystem.IsTvOSVersionAtLeast (17, 4))
130+
return CFString.FromHandle (NSStringFromGCPoint2 (this));
131+
return $"{{{x}, {y}}}";
132+
}
133+
134+
[SupportedOSPlatform ("ios17.4")]
135+
[SupportedOSPlatform ("tvos17.4")]
136+
[SupportedOSPlatform ("maccatalyst17.4")]
137+
[SupportedOSPlatform ("macos14.3")]
138+
[DllImport (Constants.GameControllerLibrary)]
139+
extern static /* NSString* */ IntPtr NSStringFromGCPoint2 (/* GCPoint2 */ GCPoint2 point);
140+
#endif // !COREBUILD
141+
}
142+
}

src/frameworks.sources

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,12 +947,15 @@ GAMECONTROLLER_API_SOURCES = \
947947
GAMECONTROLLER_CORE_SOURCES = \
948948
GameController/GCController.cs \
949949
GameController/GCMotion.cs \
950+
GameController/GCPoint2.cs \
950951

951952
GAMECONTROLLER_SOURCES = \
952953
GameController/GCExtendedGamepadSnapshot.cs \
953954
GameController/GCGamepadSnapshot.cs \
955+
GameController/GCInput.cs \
954956
GameController/GCMicroGamepadSnapshot.cs \
955957
GameController/GCMouse.cs \
958+
GameController/GCPhysicalInputElementCollection.cs \
956959

957960
# GameKit
958961

0 commit comments

Comments
 (0)