-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbcController.py
181 lines (152 loc) · 7.01 KB
/
bcController.py
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
# Utility class for querying joystick/controller
import platform
import wx.adv
from typing import List
class bcController(wx.adv.Joystick):
def __init__(self):
wx.adv.Joystick.__init__(self)
self.CodeTable = self.SetCodeTable()
self.CurrentAxisPercents = []
# Don't even poll axes if we're not joysticking
if self.IsOk():
self.CurrentAxisPercents = [0] * self.GetNumberAxes()
def GetAllAxisCodes(self):
all_axis_codes = []
if self.IsOk():
for pair in self.CodeTable:
for axis_code in pair:
if axis_code != '': all_axis_codes.append(axis_code)
return all_axis_codes
def SetCurrentAxisPercents(self):
for axis in range(len(self.CurrentAxisPercents)):
# TODO - this code makes assumptions about the range/location of the dpad.
# This works for my Logitech 310 but possibly nothing else.
# This will take some third-party testing
apos = self.GetPosition(axis)
if axis == 0:
amin, amax = self.GetXMin(), self.GetXMax()
self.CurrentAxisPercents[axis]= self.AxisPercent(amin, amax, apos)
# Joystick1_LEFT, Joystick1_RIGHT
elif axis == 1:
amin, amax = self.GetYMin(), self.GetYMax()
self.CurrentAxisPercents[axis]= self.AxisPercent(amin, amax, apos)
# Joystick1_UP, Joystick1_DOWN
elif axis == 2:
# So far, looks like on MacOS, axis 2 is Z
if platform.system() == "Darwin":
amin, amax = self.GetZMin(), self.GetZMax()
else:
amin, amax = self.GetRudderMin(), self.GetRudderMax()
# normalize this on Linux and Mac. Find a better way if needed
if platform.system() == "Linux" or platform.system() == "Darwin":
corr = (amax - amin) / 2
apos = apos + corr
amin = amin - corr
amax = amax + corr
self.CurrentAxisPercents[axis]= self.AxisPercent(amin, amax, apos)
# Joystick2_LEFT
elif axis == 3:
amin, amax = self.GetZMin(), self.GetZMax()
self.CurrentAxisPercents[axis]= self.AxisPercent(amin, amax, apos)
# Joystick3_LEFT, Joystick3_RIGHT
elif axis == 4:
amin, amax = self.GetUMin(), self.GetUMax()
self.CurrentAxisPercents[axis]= self.AxisPercent(amin, amax, apos)
# Joystick3_UP, Joystick3_DOWN
elif axis == 5:
amin, amax = self.GetVMin(), self.GetVMax()
# normalize this on Linux and Mac. Find a better way if needed
if platform.system() == "Linux" or platform.system() == "Darwin":
corr = (amax - amin) / 2
apos = apos + corr
amin = amin - corr
amax = amax + corr
self.CurrentAxisPercents[axis]= self.AxisPercent(amin, amax, apos)
# Joystick2_LEFT
elif axis in [6,7]:
amin, amax = -32767, 32767
self.CurrentAxisPercents[axis]= self.AxisPercent(amin, amax, apos)
# JOYPAD_*
def GetCurrentAxis(self):
povpos = code = None
if self.HasPOV4Dir():
povpos = self.GetPOVPosition()
if povpos != None and povpos < 60000: # 65535 seems to mean "at center"
if povpos == 0 : code = "JP_U"
elif povpos == 9000 : code = "JP_R"
elif povpos == 18000 : code = "JP_D"
elif povpos == 27000 : code = "JP_L"
else:
self.SetCurrentAxisPercents()
if self.CurrentAxisPercents: # might be empty list if we have no controller.
current_axis = self.CurrentAxisPercents.index(max(self.CurrentAxisPercents, key=abs))
current_dir = None
if self.CurrentAxisPercents[current_axis] < -50:
current_dir = 0
elif self.CurrentAxisPercents[current_axis] > 50:
current_dir = 1
if current_dir != None:
code = self.CodeTable[current_axis][current_dir]
return code
def StickIsNearCenter(self):
return abs(max(self.CurrentAxisPercents, key=abs)) < 50
def AxisPercent(self, amin, amax, apos):
center = amin + ((amax - amin) / 2)
# (apos - center) is the distance, positive or negative, from the center
# (amax - center) is the (positive) total throw on one side of center
return int((apos - center) / (amax - center) * 100)
def ListOfPossibleMods(self):
# return a list of strings of controls that might be used as controller_modifiers
# or extra_modifiers
if not self.IsOk(): return []
possible_mods = ["", "LTrigger", "RTrigger"] # assume everybody has triggers
for bnum in range(1, self.GetNumberButtons()):
bname = "JOY" + str(bnum)
# TODO - should keep these mappings in this class somewhere
if bnum == 5: bname = "LeftBumper"
if bnum == 6: bname = "RightBumper"
possible_mods.append(bname)
# windows vs linux treatment of dpad
if self.HasPOV4Dir() or self.GetMaxAxes() > 6:
possible_mods = possible_mods + ["Joypad_Up", "Joypad_Down", "Joypad_Left", "Joypad_Right"]
return possible_mods
def SetCodeTable(self):
# sets the Code table, which is a list, indexed by axis number,
# of lists of [negative direction, positive direction] codes
CodeTable : List[List] = []
if platform.system() == 'Windows':
CodeTable = [
['J1_L', 'J1_R'],
['J1_U', 'J1_D'],
['J2_L', 'J2_R'],
['J3_U', 'J3_D'],
['J3_L', 'J3_R'],
['J2_L', 'J2_R'],
['JP_L', 'JP_R'],
['JP_U', 'JP_D'],
]
elif platform.system() == 'Linux':
CodeTable = [
['J1_L', 'J1_R'],
['J1_U', 'J1_D'],
['' , 'J2_R'],
['J3_L', 'J3_R'],
['J3_U', 'J3_D'],
['' , 'J2_L'],
['JP_L', 'JP_R'],
['JP_U', 'JP_D'],
]
# TODO this is utterly untested
elif platform.system() == 'Darwin':
CodeTable = [
['J1_L', 'J1_R'],
['J1_U', 'J1_D'],
['J3_L', 'J3_R'],
# Currently no way to test more than three axes on Mac
# ['J3_L', 'J3_R'],
# ['J3_U', 'J3_D'],
# ['J2_L', 'J2_R'],
# ['JP_L', 'JP_R'],
# ['JP_U', 'JP_D'],
]
return CodeTable