-
Notifications
You must be signed in to change notification settings - Fork 0
/
WiiBoard.cs
214 lines (192 loc) · 7.17 KB
/
WiiBoard.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
namespace WiiBoardLib;
using SharpDX.DirectInput;
using System;
using System.Diagnostics;
using System.Numerics;
/// <summary>
/// Class <see cref="WiiBoard"/>, requires <see cref="SharpDX.DirectInput"/>.
/// </summary>
public class WiiBoard
{
private static DirectInput input = new DirectInput();
private Vector2 normalizer;
/// <summary>
/// The <see cref="Joystick"/> object assosiated with the <see cref="WiiBoard"/>.
/// </summary>
public Joystick Gamepad { get; private set; }
/// <summary>
/// The area in which the balancepoint is in the center. <br/>
/// It is good practice to not count inputs that are inside of the <see cref="Deadzone"/> to accomodate for slight innacuracies in the state readings.
/// </summary>
public float Deadzone { get; set; }
/// <summary>
/// Constructor for the <see cref="WiiBoard"/> object.
/// Requires the <paramref name="deviceGuid"/> which can be retreived with the help of <see cref="SharpDX.DirectInput"/>.
/// </summary>
public WiiBoard(Guid deviceGuid, float deadzone, bool calibrate = true)
{
Gamepad = new Joystick(input, deviceGuid);
Gamepad.Acquire();
Deadzone = deadzone;
if (calibrate)
Calibrate();
}
/// <summary>
/// Automatically searches for a connected wiiboard and creates a <see cref="WiiBoard"/> object from it.<br/>
/// If no <see cref="WiiBoard"/> can be found within <paramref name="timeout"/> seconds an exception will be thrown.
/// </summary>
/// <returns>
/// the <see cref="WiiBoard"/> object if a connected <see cref="WiiBoard"/> has been found.
/// </returns>
/// <exception cref="TimeoutException">
/// Thrown when no connected wiiboard can be found.
/// </exception>
public static WiiBoard FindWiiBoard(double timeout, float deadzone, bool calibrate = true)
{
DeviceInstance? wiiboard = null;
Stopwatch watch = new();
watch.Start();
while(wiiboard == null)
{
if (watch.Elapsed.TotalSeconds > timeout)
throw new TimeoutException("Could not locate the wiiboard.");
foreach (var device in input.GetDevices())
{
if (device.ProductName == "Nintendo RVL-CNT-01")
{
wiiboard = device;
break;
}
}
}
return new WiiBoard(wiiboard.InstanceGuid, deadzone, calibrate);
}
/// <summary>
/// Calibrates the <see cref="WiiBoard"/>.
/// </summary>
/// <remarks>
/// The <see cref="WiiBoard"/> may not be touched when being calibrated.
/// </remarks>
public void Calibrate()
{
var state = Gamepad.GetCurrentState();
normalizer = new Vector2(state.X, state.Y);
}
/// <summary>
/// Gets the current state of the <see cref="WiiBoard"/>, this state is the balancepoint.
/// </summary>
/// <returns>
/// a <see cref="Vector2"/> containg the state of the <see cref="WiiBoard"/>.
/// </returns>
public Vector2 GetState()
{
var state = Gamepad.GetCurrentState();
return new Vector2(state.X / normalizer.X - 1, -(state.Y / normalizer.Y - 1)); // Flip Y around because uhh some dumb stuff just turst me on this one okay
}
/// <summary>
/// Whether or not the balancepoint is in the right area of the <see cref="WiiBoard"/> and outside of the <see cref="Deadzone"/>.
/// </summary>
/// <returns>
/// <see langword="true"/> if the balancepoint is at the right of the <see cref="WiiBoard"/> and outside of the <see cref="Deadzone"/>; otherwise, false.
/// </returns>
public bool GetRight()
{
return GetState().X >= 0 && !InDeadZone();
}
/// <summary>
/// Whether or not the balancepoint is in the left area of the <see cref="WiiBoard"/> and outside of the <see cref="Deadzone"/>.
/// </summary>
/// <returns>
/// <see langword="true"/> if the balancepoint is at the left of the <see cref="WiiBoard"/> and outside of the <see cref="Deadzone"/>; otherwise, false.
/// </returns>
public bool GetLeft()
{
return GetState().X < 0 && !InDeadZone();
}
/// <summary>
/// Whether or not the balancepoint is in the top area of the <see cref="WiiBoard"/> and outside of the <see cref="Deadzone"/>.
/// </summary>
/// <returns>
/// <see langword="true"/> if the balancepoint is at the top of the <see cref="WiiBoard"/> and outside of the <see cref="Deadzone"/>; otherwise, false.
/// </returns>
public bool GetTop()
{
return GetState().Y >= 0 && !InDeadZone();
}
/// <summary>
/// Whether or not the balancepoint is in the bottom area of the <see cref="WiiBoard"/> and outside of the <see cref="Deadzone"/>.
/// </summary>
/// <returns>
/// <see langword="true"/> if the balancepoint is at the bottom of the <see cref="WiiBoard"/> and outside of the <see cref="Deadzone"/>; otherwise, false.
/// </returns>
public bool GetBottom()
{
return GetState().Y < 0 && !InDeadZone();
}
/// <summary>
/// Determines whether the balancepoint is inside of the <see cref="Deadzone"/> or not.
/// </summary>
/// <returns>
/// <see langword="true"/> if the balancepoint is inside of the <see cref="Deadzone"/>; otherwise, <see langword="false"/>.
/// </returns>
public bool InDeadZone()
{
return GetState().LengthSquared() < Deadzone*Deadzone;
}
/// <summary>
/// Determines on which <see cref="Areas"/> of the <see cref="WiiBoard"/> the balancepoint lays.
/// </summary>
/// <returns>
/// the <see cref="Areas"/> on which the balancepoint lays.
/// </returns>
public Areas GetAreas()
{
if (InDeadZone())
return Areas.Center;
Areas top = GetState().Y >= 0 ? Areas.Top : Areas.Bottom;
Areas right = GetState().X >= 0 ? Areas.Right : Areas.Left;
return top | right;
}
/// <summary>
/// Determines whether the balancepoint is inside of the given area of the <see cref="WiiBoard"/> or not.
/// </summary>
/// <param name="area">
/// An area of the <see cref="WiiBoard"/>.
/// </param>
/// <returns>
/// <see langword="true"/> if the balancepoint is inside of the given <paramref name="area"/>; otherwise, <see langword="false"/>.
/// </returns>
/// <exception cref="ArgumentException"></exception>
public bool InArea(Areas area)
{
return GetAreas().HasFlag(area);
}
}
/// <summary>
/// An <see langword="enum"/> used to tell in which area of the <see cref="WiiBoard"/> the balancepoint is.<br/>
/// Should be checked against using <see cref="Enum.HasFlag(Enum)"/>.
/// </summary>
[Flags]
public enum Areas
{
/// <summary>
/// Left area of the board.
/// </summary>
Left = 1,
/// <summary>
/// Right area of the board.
/// </summary>
Right = 2,
/// <summary>
/// Top area of the board.
/// </summary>
Top = 4,
/// <summary>
/// Bottom area of the board.
/// </summary>
Bottom = 8,
/// <summary>
/// Center of the board, inside the deadzone.
/// </summary>
Center = 16
}