1 | //============================================================================ |
2 | // |
3 | // SSSS tt lll lll |
4 | // SS SS tt ll ll |
5 | // SS tttttt eeee ll ll aaaa |
6 | // SSSS tt ee ee ll ll aa |
7 | // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" |
8 | // SS SS tt ee ll ll aa aa |
9 | // SSSS ttt eeeee llll llll aaaaa |
10 | // |
11 | // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony |
12 | // and the Stella Team |
13 | // |
14 | // See the file "License.txt" for information on usage and redistribution of |
15 | // this file, and for a DISCLAIMER OF ALL WARRANTIES. |
16 | //============================================================================ |
17 | |
18 | #include "JoyMap.hxx" |
19 | |
20 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
21 | JoyMap::JoyMap(void) |
22 | { |
23 | } |
24 | |
25 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
26 | void JoyMap::add(const Event::Type event, const JoyMapping& mapping) |
27 | { |
28 | myMap[mapping] = event; |
29 | } |
30 | |
31 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
32 | void JoyMap::add(const Event::Type event, const EventMode mode, const int button, |
33 | const JoyAxis axis, const JoyDir adir, |
34 | const int hat, const JoyHatDir hdir) |
35 | { |
36 | add(event, JoyMapping(mode, button, axis, adir, hat, hdir)); |
37 | } |
38 | |
39 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
40 | void JoyMap::add(const Event::Type event, const EventMode mode, const int button, |
41 | const int hat, const JoyHatDir hdir) |
42 | { |
43 | add(event, JoyMapping(mode, button, hat, hdir)); |
44 | } |
45 | |
46 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
47 | void JoyMap::erase(const JoyMapping& mapping) |
48 | { |
49 | myMap.erase(mapping); |
50 | } |
51 | |
52 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
53 | void JoyMap::erase(const EventMode mode, const int button, |
54 | const JoyAxis axis, const JoyDir adir) |
55 | { |
56 | erase(JoyMapping(mode, button, axis, adir)); |
57 | } |
58 | |
59 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
60 | void JoyMap::erase(const EventMode mode, const int button, |
61 | const int hat, const JoyHatDir hdir) |
62 | { |
63 | erase(JoyMapping(mode, button, hat, hdir)); |
64 | } |
65 | |
66 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
67 | Event::Type JoyMap::get(const JoyMapping& mapping) const |
68 | { |
69 | auto find = myMap.find(mapping); |
70 | if (find != myMap.end()) |
71 | return find->second; |
72 | |
73 | // try without button as modifier |
74 | JoyMapping m = mapping; |
75 | |
76 | m.button = JOY_CTRL_NONE; |
77 | |
78 | find = myMap.find(m); |
79 | if (find != myMap.end()) |
80 | return find->second; |
81 | |
82 | return Event::Type::NoType; |
83 | } |
84 | |
85 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
86 | Event::Type JoyMap::get(const EventMode mode, const int button, |
87 | const JoyAxis axis, const JoyDir adir) const |
88 | { |
89 | return get(JoyMapping(mode, button, axis, adir)); |
90 | } |
91 | |
92 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
93 | Event::Type JoyMap::get(const EventMode mode, const int button, |
94 | const int hat, const JoyHatDir hdir) const |
95 | { |
96 | return get(JoyMapping(mode, button, hat, hdir)); |
97 | } |
98 | |
99 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
100 | bool JoyMap::check(const JoyMapping & mapping) const |
101 | { |
102 | auto find = myMap.find(mapping); |
103 | |
104 | return (find != myMap.end()); |
105 | } |
106 | |
107 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
108 | bool JoyMap::check(const EventMode mode, const int button, |
109 | const JoyAxis axis, const JoyDir adir, |
110 | const int hat, const JoyHatDir hdir) const |
111 | { |
112 | return check(JoyMapping(mode, button, axis, adir, hat, hdir)); |
113 | } |
114 | |
115 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
116 | string JoyMap::getDesc(const Event::Type event, const JoyMapping& mapping) const |
117 | { |
118 | ostringstream buf; |
119 | |
120 | // button description |
121 | if (mapping.button != JOY_CTRL_NONE) |
122 | buf << "/B" << mapping.button; |
123 | |
124 | // axis description |
125 | if (mapping.axis != JoyAxis::NONE) |
126 | { |
127 | buf << "/A" ; |
128 | switch (mapping.axis) |
129 | { |
130 | case JoyAxis::X: buf << "X" ; break; |
131 | case JoyAxis::Y: buf << "Y" ; break; |
132 | case JoyAxis::Z: buf << "Z" ; break; |
133 | default: buf << int(mapping.axis); break; |
134 | } |
135 | |
136 | if (Event::isAnalog(event)) |
137 | buf << "+|-" ; |
138 | else if (mapping.adir == JoyDir::NEG) |
139 | buf << "-" ; |
140 | else |
141 | buf << "+" ; |
142 | } |
143 | |
144 | // hat description |
145 | if (mapping.hat != JOY_CTRL_NONE) |
146 | { |
147 | buf << "/H" << mapping.hat; |
148 | switch (mapping.hdir) |
149 | { |
150 | case JoyHatDir::UP: buf << "Y+" ; break; |
151 | case JoyHatDir::DOWN: buf << "Y-" ; break; |
152 | case JoyHatDir::LEFT: buf << "X-" ; break; |
153 | case JoyHatDir::RIGHT: buf << "X+" ; break; |
154 | default: break; |
155 | } |
156 | } |
157 | |
158 | return buf.str(); |
159 | } |
160 | |
161 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
162 | string JoyMap::getEventMappingDesc(int stick, const Event::Type event, const EventMode mode) const |
163 | { |
164 | ostringstream buf; |
165 | |
166 | for (auto item : myMap) |
167 | { |
168 | if (item.second == event && item.first.mode == mode) |
169 | { |
170 | if (buf.str() != "" ) |
171 | buf << ", " ; |
172 | buf << "J" << stick << getDesc(event, item.first); |
173 | } |
174 | } |
175 | return buf.str(); |
176 | } |
177 | |
178 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
179 | JoyMap::JoyMappingArray JoyMap::getEventMapping(const Event::Type event, const EventMode mode) const |
180 | { |
181 | JoyMappingArray map; |
182 | |
183 | for (auto item : myMap) |
184 | if (item.second == event && item.first.mode == mode) |
185 | map.push_back(item.first); |
186 | |
187 | return map; |
188 | } |
189 | |
190 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
191 | string JoyMap::saveMapping(const EventMode mode) const |
192 | { |
193 | ostringstream buf; |
194 | |
195 | for (auto item : myMap) |
196 | { |
197 | if (item.first.mode == mode) |
198 | { |
199 | if (buf.str() != "" ) |
200 | buf << "|" ; |
201 | buf << item.second << ":" << item.first.button << "," |
202 | << int(item.first.axis) << "," << int(item.first.adir) << "," |
203 | << item.first.hat << "," << int(item.first.hdir); |
204 | } |
205 | } |
206 | return buf.str(); |
207 | } |
208 | |
209 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
210 | int JoyMap::loadMapping(string& list, const EventMode mode) |
211 | { |
212 | // Since istringstream swallows whitespace, we have to make the |
213 | // delimiters be spaces |
214 | std::replace(list.begin(), list.end(), '|', ' '); |
215 | std::replace(list.begin(), list.end(), ':', ' '); |
216 | std::replace(list.begin(), list.end(), ',', ' '); |
217 | istringstream buf(list); |
218 | int event, button, axis, adir, hat, hdir, i = 0; |
219 | |
220 | while (buf >> event && buf >> button |
221 | && buf >> axis && buf >> adir |
222 | && buf >> hat && buf >> hdir && ++i) |
223 | add(Event::Type(event), EventMode(mode), button, JoyAxis(axis), JoyDir(adir), hat, JoyHatDir(hdir)); |
224 | |
225 | return i; |
226 | } |
227 | |
228 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
229 | void JoyMap::eraseMode(const EventMode mode) |
230 | { |
231 | for (auto item = myMap.begin(); item != myMap.end();) |
232 | if (item->first.mode == mode) { |
233 | auto _item = item++; |
234 | erase(_item->first); |
235 | } |
236 | else item++; |
237 | } |
238 | |
239 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
240 | void JoyMap::eraseEvent(const Event::Type event, const EventMode mode) |
241 | { |
242 | for (auto item = myMap.begin(); item != myMap.end();) |
243 | if (item->second == event && item->first.mode == mode) { |
244 | auto _item = item++; |
245 | erase(_item->first); |
246 | } |
247 | else item++; |
248 | } |
249 | |