-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathControllerManager.cs
More file actions
158 lines (127 loc) · 3.12 KB
/
ControllerManager.cs
File metadata and controls
158 lines (127 loc) · 3.12 KB
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
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace ControlLauncher;
internal sealed class ControllerManager : IDisposable
{
private readonly CancellationTokenSource _cts = new();
private bool _initialized;
private const int MAX_CONTROLLER_INDEX = 4;
private const int SLEEP_TIME = 1000 / 60;
[DllImport("XInputWrapper.dll")]
private static extern bool XInputWrapper_init();
[DllImport("XInputWrapper.dll")]
private static extern bool XInputWrapper_updateControllerState(int index);
[DllImport("XInputWrapper.dll")]
private static extern bool XInputWrapper_wasAPressed(int index);
[DllImport("XInputWrapper.dll")]
private static extern bool XInputWrapper_wasDPadUpPressed(int index);
[DllImport("XInputWrapper.dll")]
private static extern bool XInputWrapper_wasDPadDownPressed(int index);
public event ButtonPressedEventHandler? ButtonPressed;
public void Dispose()
{
this._cts.Dispose();
}
public bool Initialize()
{
try
{
if (!XInputWrapper_init())
return false;
}
catch (DllNotFoundException)
{
return false;
}
this._initialized = true;
return true;
}
public void Start()
{
if (!this._initialized)
{
Debug.WriteLine("ControllerManager has not been initialized!");
return;
}
ThreadPool.QueueUserWorkItem(this.Update, this._cts.Token);
}
public void Stop()
{
if (!this._initialized)
{
Debug.WriteLine("ControllerManager has not been initialized!");
return;
}
this._cts.Cancel();
}
private void Update(object? cts)
{
if (cts is null)
return;
var token = (CancellationToken)cts;
while (true)
{
if (token.IsCancellationRequested)
break;
for (var i = 0; i < MAX_CONTROLLER_INDEX; i++)
{
if (!XInputWrapper_updateControllerState(i))
continue;
if (XInputWrapper_wasAPressed(i))
{
this.OnButtonPressed(new ButtonPressedEventArgs(GamepadButton.ButtonA));
break;
}
if (XInputWrapper_wasDPadDownPressed(i))
{
this.OnButtonPressed(new ButtonPressedEventArgs(GamepadButton.ButtonDPadDown));
break;
}
if (XInputWrapper_wasDPadUpPressed(i))
{
this.OnButtonPressed(new ButtonPressedEventArgs(GamepadButton.ButtonDPadUp));
break;
}
}
Thread.Sleep(SLEEP_TIME);
}
}
internal void OnButtonPressed(ButtonPressedEventArgs e)
{
if (this.ButtonPressed == null)
return;
foreach (var @delegate in this.ButtonPressed.GetInvocationList())
{
var invocation = (ButtonPressedEventHandler)@delegate;
try
{
if (invocation.Target is ISynchronizeInvoke { InvokeRequired: true } target)
target.Invoke(invocation, new object[] { this, e });
else
invocation(this, e);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}
public delegate void ButtonPressedEventHandler(object sender, ButtonPressedEventArgs e);
}
public enum GamepadButton
{
ButtonA,
ButtonDPadUp,
ButtonDPadDown,
}
public class ButtonPressedEventArgs : EventArgs
{
public GamepadButton ButtonPressed;
public ButtonPressedEventArgs(GamepadButton btn)
{
this.ButtonPressed = btn;
}
}