1 |
|
|
/* |
2 |
|
|
* The ManaPlus Client |
3 |
|
|
* Copyright (C) 2012-2019 The ManaPlus Developers |
4 |
|
|
* Copyright (C) 2019-2021 Andrei Karas |
5 |
|
|
* |
6 |
|
|
* This file is part of The ManaPlus Client. |
7 |
|
|
* |
8 |
|
|
* This program is free software; you can redistribute it and/or modify |
9 |
|
|
* it under the terms of the GNU General Public License as published by |
10 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
11 |
|
|
* any later version. |
12 |
|
|
* |
13 |
|
|
* This program is distributed in the hope that it will be useful, |
14 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
|
|
* GNU General Public License for more details. |
17 |
|
|
* |
18 |
|
|
* You should have received a copy of the GNU General Public License |
19 |
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#include "input/inputmanager.h" |
23 |
|
|
|
24 |
|
|
#include "configuration.h" |
25 |
|
|
#include "game.h" |
26 |
|
|
#include "settings.h" |
27 |
|
|
|
28 |
|
|
#include "being/localplayer.h" |
29 |
|
|
#include "being/playerinfo.h" |
30 |
|
|
|
31 |
|
|
#include "input/inputactionmap.h" |
32 |
|
|
#include "input/inputactionsortfunctor.h" |
33 |
|
|
#include "input/joystick.h" |
34 |
|
|
#include "input/keyboardconfig.h" |
35 |
|
|
#ifdef USE_SDL2 |
36 |
|
|
#include "input/touch/multitouchmanager.h" |
37 |
|
|
#endif // USE_SDL2 |
38 |
|
|
|
39 |
|
|
#include "input/touch/touchmanager.h" |
40 |
|
|
|
41 |
|
|
#include "gui/gui.h" |
42 |
|
|
#include "gui/sdlinput.h" |
43 |
|
|
|
44 |
|
|
#include "gui/widgets/selldialog.h" |
45 |
|
|
#include "gui/widgets/textfield.h" |
46 |
|
|
|
47 |
|
|
#include "gui/widgets/tabs/setup_input.h" |
48 |
|
|
|
49 |
|
|
#include "gui/windows/buydialog.h" |
50 |
|
|
#include "gui/windows/chatwindow.h" |
51 |
|
|
#include "gui/windows/inventorywindow.h" |
52 |
|
|
#include "gui/windows/npcdialog.h" |
53 |
|
|
#include "gui/windows/setupwindow.h" |
54 |
|
|
#include "gui/windows/textdialog.h" |
55 |
|
|
#include "gui/windows/tradewindow.h" |
56 |
|
|
|
57 |
|
|
#include "utils/checkutils.h" |
58 |
|
|
#include "utils/foreach.h" |
59 |
|
|
#include "utils/gettext.h" |
60 |
|
|
#include "utils/stdmove.h" |
61 |
|
|
#include "utils/timer.h" |
62 |
|
|
|
63 |
|
|
#include "gui/focushandler.h" |
64 |
|
|
|
65 |
|
|
#include <algorithm> |
66 |
|
|
|
67 |
|
|
#include "debug.h" |
68 |
|
|
|
69 |
|
1 |
InputManager inputManager; |
70 |
|
|
|
71 |
|
|
class QuitDialog; |
72 |
|
|
|
73 |
|
|
extern QuitDialog *quitDialog; |
74 |
|
|
|
75 |
|
|
namespace |
76 |
|
|
{ |
77 |
|
|
InputActionSortFunctor inputActionDataSorter; |
78 |
|
|
} // namespace |
79 |
|
|
|
80 |
|
1 |
InputManager::InputManager() : |
81 |
|
|
mSetupInput(nullptr), |
82 |
|
|
mNewKeyIndex(InputAction::NO_VALUE), |
83 |
|
|
mMask(1), |
84 |
|
|
mNameMap(), |
85 |
|
|
mChatMap(), |
86 |
✓✓✓✓ ✓✓ |
1343 |
mKey() |
87 |
|
|
{ |
88 |
|
1 |
} |
89 |
|
|
|
90 |
|
|
void InputManager::init() restrict2 |
91 |
|
|
{ |
92 |
|
|
#ifdef __SWITCH__ |
93 |
|
|
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1"); |
94 |
|
|
#endif |
95 |
|
|
for (size_t i = 0; |
96 |
|
|
i < CAST_SIZE(InputAction::TOTAL); |
97 |
|
|
i ++) |
98 |
|
|
{ |
99 |
|
|
InputFunction &kf = mKey[i]; |
100 |
|
|
mKeyStr[i].clear(); |
101 |
|
|
for (size_t f = 0; f < inputFunctionSize; f ++) |
102 |
|
|
{ |
103 |
|
|
InputItem &ki = kf.values[f]; |
104 |
|
|
ki.type = InputType::UNKNOWN; |
105 |
|
|
ki.value = -1; |
106 |
|
|
} |
107 |
|
|
} |
108 |
|
|
|
109 |
|
|
mNewKeyIndex = InputAction::NO_VALUE; |
110 |
|
|
|
111 |
|
|
resetKeys(); |
112 |
|
|
retrieve(); |
113 |
|
|
update(); |
114 |
|
|
} |
115 |
|
|
|
116 |
|
|
void InputManager::update() |
117 |
|
|
{ |
118 |
|
|
keyboard.update(); |
119 |
|
|
if (joystick != nullptr) |
120 |
|
|
joystick->update(); |
121 |
|
|
} |
122 |
|
|
|
123 |
|
|
void InputManager::retrieve() restrict2 |
124 |
|
|
{ |
125 |
|
|
for (int i = 0; i < CAST_S32(InputAction::TOTAL); i ++) |
126 |
|
|
{ |
127 |
|
|
const std::string &restrict cmd = inputActionData[i].chatCommand; |
128 |
|
|
if (!cmd.empty()) |
129 |
|
|
{ |
130 |
|
|
StringVect tokens; |
131 |
|
|
splitToStringVector(tokens, cmd, '|'); |
132 |
|
|
FOR_EACH (StringVectCIter, it, tokens) |
133 |
|
|
mChatMap[*it] = i; |
134 |
|
|
} |
135 |
|
|
#ifdef USE_SDL2 |
136 |
|
|
const std::string cf = std::string("sdl2") |
137 |
|
|
+ inputActionData[i].configField; |
138 |
|
|
#else // USE_SDL2 |
139 |
|
|
|
140 |
|
|
const std::string cf = inputActionData[i].configField; |
141 |
|
|
#endif // USE_SDL2 |
142 |
|
|
|
143 |
|
|
InputFunction &restrict kf = mKey[i]; |
144 |
|
|
if (!cf.empty()) |
145 |
|
|
{ |
146 |
|
|
mNameMap[cf] = static_cast<InputActionT>(i); |
147 |
|
|
const std::string keyStr = config.getValue(cf, ""); |
148 |
|
|
const size_t keyStrSize = keyStr.size(); |
149 |
|
|
if (keyStr.empty()) |
150 |
|
|
{ |
151 |
|
|
updateKeyString(kf, i); |
152 |
|
|
continue; |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
StringVect keys; |
156 |
|
|
splitToStringVector(keys, keyStr, ','); |
157 |
|
|
unsigned int i2 = 0; |
158 |
|
|
for (StringVectCIter it = keys.begin(), it_end = keys.end(); |
159 |
|
|
it != it_end && i2 < inputFunctionSize; ++ it) |
160 |
|
|
{ |
161 |
|
|
std::string keyStr2 = *it; |
162 |
|
|
if (keyStrSize < 2) |
163 |
|
|
continue; |
164 |
|
|
InputTypeT type = InputType::KEYBOARD; |
165 |
|
|
if ((keyStr2[0] < '0' || keyStr2[0] > '9') |
166 |
|
|
&& keyStr2[0] != '-') |
167 |
|
|
{ |
168 |
|
|
switch (keyStr2[0]) |
169 |
|
|
{ |
170 |
|
|
case 'm': |
171 |
|
|
type = InputType::MOUSE; |
172 |
|
|
break; |
173 |
|
|
case 'j': |
174 |
|
|
type = InputType::JOYSTICK; |
175 |
|
|
break; |
176 |
|
|
default: |
177 |
|
|
break; |
178 |
|
|
} |
179 |
|
|
keyStr2 = keyStr2.substr(1); |
180 |
|
|
} |
181 |
|
|
const int key = atoi(keyStr2.c_str()); |
182 |
|
|
if (key >= -255 && key < SDLK_LAST) |
183 |
|
|
{ |
184 |
|
|
kf.values[i2] = InputItem(type, key); |
185 |
|
|
i2 ++; |
186 |
|
|
} |
187 |
|
|
} |
188 |
|
|
for (; i2 < inputFunctionSize; i2 ++) |
189 |
|
|
kf.values[i2] = InputItem(); |
190 |
|
|
} |
191 |
|
|
updateKeyString(kf, i); |
192 |
|
|
} |
193 |
|
|
} |
194 |
|
|
|
195 |
|
|
void InputManager::store() const restrict2 |
196 |
|
|
{ |
197 |
|
|
for (int i = 0; i < CAST_S32(InputAction::TOTAL); i ++) |
198 |
|
|
{ |
199 |
|
|
#ifdef USE_SDL2 |
200 |
|
|
const std::string cf = std::string("sdl2") |
201 |
|
|
+ inputActionData[i].configField; |
202 |
|
|
#else // USE_SDL2 |
203 |
|
|
|
204 |
|
|
const std::string cf = inputActionData[i].configField; |
205 |
|
|
#endif // USE_SDL2 |
206 |
|
|
|
207 |
|
|
if (!cf.empty()) |
208 |
|
|
{ |
209 |
|
|
std::string keyStr; |
210 |
|
|
const InputFunction &restrict kf = mKey[i]; |
211 |
|
|
|
212 |
|
|
for (size_t i2 = 0; i2 < inputFunctionSize; i2 ++) |
213 |
|
|
{ |
214 |
|
|
const InputItem &restrict key = kf.values[i2]; |
215 |
|
|
if (key.type != InputType::UNKNOWN) |
216 |
|
|
{ |
217 |
|
|
std::string tmp("k"); |
218 |
|
|
switch (key.type) |
219 |
|
|
{ |
220 |
|
|
case InputType::MOUSE: |
221 |
|
|
tmp = "m"; |
222 |
|
|
break; |
223 |
|
|
case InputType::JOYSTICK: |
224 |
|
|
tmp = "j"; |
225 |
|
|
break; |
226 |
|
|
case InputType::KEYBOARD: |
227 |
|
|
case InputType::UNKNOWN: |
228 |
|
|
default: |
229 |
|
|
break; |
230 |
|
|
} |
231 |
|
|
if (key.value != -1) |
232 |
|
|
{ |
233 |
|
|
if (keyStr.empty()) |
234 |
|
|
{ |
235 |
|
|
keyStr.append(tmp).append(toString(key.value)); |
236 |
|
|
} |
237 |
|
|
else |
238 |
|
|
{ |
239 |
|
|
keyStr.append(strprintf(",%s%d", |
240 |
|
|
tmp.c_str(), key.value)); |
241 |
|
|
} |
242 |
|
|
} |
243 |
|
|
} |
244 |
|
|
} |
245 |
|
|
if (keyStr.empty()) |
246 |
|
|
keyStr = "-1"; |
247 |
|
|
|
248 |
|
|
config.setValue(cf, keyStr); |
249 |
|
|
} |
250 |
|
|
} |
251 |
|
|
} |
252 |
|
|
|
253 |
|
|
void InputManager::resetKey(const InputActionT i) restrict2 |
254 |
|
|
{ |
255 |
|
|
InputFunction &restrict key = mKey[CAST_SIZE(i)]; |
256 |
|
|
for (size_t i2 = 1; i2 < inputFunctionSize; i2 ++) |
257 |
|
|
{ |
258 |
|
|
InputItem &restrict ki2 = key.values[i2]; |
259 |
|
|
ki2.type = InputType::UNKNOWN; |
260 |
|
|
ki2.value = -1; |
261 |
|
|
} |
262 |
|
|
const InputActionData &restrict kd = |
263 |
|
|
inputActionData[CAST_SIZE(i)]; |
264 |
|
|
InputItem &restrict val0 = key.values[0]; |
265 |
|
|
val0.type = kd.defaultType1; |
266 |
|
|
InputItem &restrict val1 = key.values[1]; |
267 |
|
|
val1.type = kd.defaultType2; |
268 |
|
|
#ifdef USE_SDL2 |
269 |
|
|
if (kd.defaultType1 == InputType::KEYBOARD) |
270 |
|
|
{ |
271 |
|
|
val0.value = SDL_GetScancodeFromKey(kd.defaultValue1); |
272 |
|
|
if (val0.value == SDL_SCANCODE_UNKNOWN) |
273 |
|
|
val0.value = -1; |
274 |
|
|
} |
275 |
|
|
else |
276 |
|
|
val0.value = kd.defaultValue1; |
277 |
|
|
if (kd.defaultType2 == InputType::KEYBOARD) |
278 |
|
|
{ |
279 |
|
|
val1.value = SDL_GetScancodeFromKey(kd.defaultValue2); |
280 |
|
|
if (val1.value == SDL_SCANCODE_UNKNOWN) |
281 |
|
|
val1.value = -1; |
282 |
|
|
} |
283 |
|
|
else |
284 |
|
|
val1.value = kd.defaultValue2; |
285 |
|
|
#else // USE_SDL2 |
286 |
|
|
|
287 |
|
|
val0.value = kd.defaultValue1; |
288 |
|
|
val1.value = kd.defaultValue2; |
289 |
|
|
#endif // USE_SDL2 |
290 |
|
|
|
291 |
|
|
updateKeyString(key, CAST_SIZE(i)); |
292 |
|
|
} |
293 |
|
|
|
294 |
|
|
void InputManager::resetKeys() restrict2 |
295 |
|
|
{ |
296 |
|
|
for (int i = 0; i < CAST_S32(InputAction::TOTAL); i++) |
297 |
|
|
resetKey(static_cast<InputActionT>(i)); |
298 |
|
|
} |
299 |
|
|
|
300 |
|
|
void InputManager::makeDefault(const InputActionT i) restrict2 |
301 |
|
|
{ |
302 |
|
|
if (i > InputAction::NO_VALUE && i < InputAction::TOTAL) |
303 |
|
|
{ |
304 |
|
|
resetKey(i); |
305 |
|
|
update(); |
306 |
|
|
} |
307 |
|
|
} |
308 |
|
|
|
309 |
|
|
bool InputManager::hasConflicts(InputActionT &restrict key1, |
310 |
|
|
InputActionT &restrict key2) const restrict2 |
311 |
|
|
{ |
312 |
|
|
/** |
313 |
|
|
* No need to parse the square matrix: only check one triangle |
314 |
|
|
* that's enough to detect conflicts |
315 |
|
|
*/ |
316 |
|
|
for (int i = 0; i < CAST_S32(InputAction::TOTAL); i++) |
317 |
|
|
{ |
318 |
|
|
const InputActionData &restrict kdi = inputActionData[i]; |
319 |
|
|
if (*kdi.configField == 0) |
320 |
|
|
continue; |
321 |
|
|
|
322 |
|
|
const InputFunction &restrict ki = mKey[i]; |
323 |
|
|
for (size_t i2 = 0; i2 < inputFunctionSize; i2 ++) |
324 |
|
|
{ |
325 |
|
|
const InputItem &restrict vali2 = ki.values[i2]; |
326 |
|
|
if (vali2.value == -1) |
327 |
|
|
continue; |
328 |
|
|
|
329 |
|
|
size_t j; |
330 |
|
|
for (j = i, j++; j < CAST_S32(InputAction::TOTAL); j++) |
331 |
|
|
{ |
332 |
|
|
if ((kdi.grp & inputActionData[j].grp) == 0 |
333 |
|
|
|| (*kdi.configField == 0)) |
334 |
|
|
{ |
335 |
|
|
continue; |
336 |
|
|
} |
337 |
|
|
|
338 |
|
|
for (size_t j2 = 0; j2 < inputFunctionSize; j2 ++) |
339 |
|
|
{ |
340 |
|
|
const InputItem &restrict valj2 = mKey[j].values[j2]; |
341 |
|
|
// Allow for item shortcut and emote keys to overlap |
342 |
|
|
// as well as emote and ignore keys, but no other keys |
343 |
|
|
if (valj2.type != InputType::UNKNOWN |
344 |
|
|
&& vali2.value == valj2.value |
345 |
|
|
&& vali2.type == valj2.type) |
346 |
|
|
{ |
347 |
|
|
key1 = static_cast<InputActionT>(i); |
348 |
|
|
key2 = static_cast<InputActionT>(j); |
349 |
|
|
return true; |
350 |
|
|
} |
351 |
|
|
} |
352 |
|
|
} |
353 |
|
|
} |
354 |
|
|
} |
355 |
|
|
return false; |
356 |
|
|
} |
357 |
|
|
|
358 |
|
|
void InputManager::callbackNewKey() restrict2 |
359 |
|
|
{ |
360 |
|
|
#ifndef DYECMD |
361 |
|
|
mSetupInput->newKeyCallback(mNewKeyIndex); |
362 |
|
|
#endif // DYECMD |
363 |
|
|
} |
364 |
|
|
|
365 |
|
2 |
bool InputManager::isActionActive(const InputActionT index) const restrict2 |
366 |
|
|
{ |
367 |
✗✗✗✗ ✗✓ |
2 |
if (!isActionActive0(index)) |
368 |
|
|
return false; |
369 |
|
|
|
370 |
|
|
const InputActionData &restrict key = |
371 |
|
|
inputActionData[CAST_SIZE(index)]; |
372 |
|
|
// logger->log("isActionActive mask=%d, condition=%d, index=%d", |
373 |
|
|
// mMask, key.condition, index); |
374 |
|
|
if ((key.condition & mMask) != key.condition) |
375 |
|
|
return false; |
376 |
|
|
return true; |
377 |
|
|
} |
378 |
|
|
|
379 |
|
2 |
bool InputManager::isActionActive0(const InputActionT index) |
380 |
|
|
{ |
381 |
✓✗ |
2 |
if (keyboard.isActionActive(index)) |
382 |
|
|
return true; |
383 |
✗✓✗✗ ✓✗ |
2 |
if ((joystick != nullptr) && joystick->isActionActive(index)) |
384 |
|
|
return true; |
385 |
|
2 |
return touchManager.isActionActive(index); |
386 |
|
|
} |
387 |
|
|
|
388 |
|
|
InputFunction &InputManager::getKey(InputActionT index) restrict2 |
389 |
|
|
{ |
390 |
|
|
if (CAST_S32(index) < 0 || index >= InputAction::TOTAL) |
391 |
|
|
index = InputAction::MOVE_UP; |
392 |
|
|
return mKey[CAST_SIZE(index)]; |
393 |
|
|
} |
394 |
|
|
|
395 |
|
75 |
std::string InputManager::getKeyStringLong(const InputActionT index) const |
396 |
|
|
restrict2 |
397 |
|
|
{ |
398 |
|
150 |
std::string keyStr; |
399 |
|
75 |
const InputFunction &restrict ki = mKey[CAST_SIZE(index)]; |
400 |
|
|
|
401 |
✓✓ |
300 |
for (size_t i = 0; i < inputFunctionSize; i ++) |
402 |
|
|
{ |
403 |
|
225 |
const InputItem &restrict key = ki.values[i]; |
404 |
|
450 |
std::string str; |
405 |
✗✓ |
225 |
if (key.type == InputType::KEYBOARD) |
406 |
|
|
{ |
407 |
|
|
if (key.value >= 0) |
408 |
|
|
{ |
409 |
|
|
str = KeyboardConfig::getKeyName(key.value); |
410 |
|
|
} |
411 |
|
|
else if (key.value < -1) |
412 |
|
|
{ |
413 |
|
|
// TRANSLATORS: long key name. must be short. |
414 |
|
|
str = strprintf(_("key_%d"), -key.value); |
415 |
|
|
} |
416 |
|
|
} |
417 |
✗✓ |
225 |
else if (key.type == InputType::JOYSTICK) |
418 |
|
|
{ |
419 |
|
|
// TRANSLATORS: long joystick button name. must be short. |
420 |
|
|
str = strprintf(_("JButton%d"), key.value + 1); |
421 |
|
|
} |
422 |
✗✓ |
225 |
if (!str.empty()) |
423 |
|
|
{ |
424 |
|
|
if (keyStr.empty()) |
425 |
|
|
keyStr = str; |
426 |
|
|
else |
427 |
|
|
keyStr.append(", ").append(str); |
428 |
|
|
} |
429 |
|
|
} |
430 |
|
|
|
431 |
✓✗ |
75 |
if (keyStr.empty()) |
432 |
|
|
{ |
433 |
|
|
// TRANSLATORS: unknown long key type |
434 |
✓✗ |
150 |
return _("unknown key"); |
435 |
|
|
} |
436 |
|
|
return keyStr; |
437 |
|
|
} |
438 |
|
|
|
439 |
|
|
void InputManager::updateKeyString(const InputFunction &ki, |
440 |
|
|
const size_t actionIdx) restrict2 |
441 |
|
|
{ |
442 |
|
|
std::string keyStr; |
443 |
|
|
for (size_t i = 0; i < inputFunctionSize; i ++) |
444 |
|
|
{ |
445 |
|
|
const InputItem &restrict key = ki.values[i]; |
446 |
|
|
std::string str; |
447 |
|
|
if (key.type == InputType::KEYBOARD) |
448 |
|
|
{ |
449 |
|
|
if (key.value >= 0) |
450 |
|
|
{ |
451 |
|
|
str = KeyboardConfig::getKeyShortString( |
452 |
|
|
KeyboardConfig::getKeyName(key.value)); |
453 |
|
|
} |
454 |
|
|
else if (key.value < -1) |
455 |
|
|
{ |
456 |
|
|
// TRANSLATORS: short key name. must be very short. |
457 |
|
|
str = strprintf(_("key_%d"), -key.value); |
458 |
|
|
} |
459 |
|
|
} |
460 |
|
|
else if (key.type == InputType::JOYSTICK) |
461 |
|
|
{ |
462 |
|
|
// TRANSLATORS: short joystick button name. muse be very short |
463 |
|
|
str = strprintf(_("JB%d"), key.value + 1); |
464 |
|
|
} |
465 |
|
|
if (!str.empty()) |
466 |
|
|
{ |
467 |
|
|
if (keyStr.empty()) |
468 |
|
|
keyStr = str; |
469 |
|
|
else |
470 |
|
|
keyStr.append(", ").append(str); |
471 |
|
|
} |
472 |
|
|
} |
473 |
|
|
|
474 |
|
|
if (keyStr.empty()) |
475 |
|
|
{ |
476 |
|
|
// TRANSLATORS: unknown short key type. must be short |
477 |
|
|
mKeyStr[actionIdx] = _("u key"); |
478 |
|
|
} |
479 |
|
|
else |
480 |
|
|
{ |
481 |
|
|
mKeyStr[actionIdx] = STD_MOVE(keyStr); |
482 |
|
|
} |
483 |
|
|
} |
484 |
|
|
|
485 |
|
|
std::string InputManager::getKeyValueString(const InputActionT index) const |
486 |
|
|
restrict2 |
487 |
|
|
{ |
488 |
|
|
return mKeyStr[CAST_SIZE(index)]; |
489 |
|
|
} |
490 |
|
|
|
491 |
|
|
std::string InputManager::getKeyValueByName(const std::string &restrict |
492 |
|
|
keyName) restrict2 |
493 |
|
|
{ |
494 |
|
|
const StringInpActionMapCIter it = mNameMap.find(keyName); |
495 |
|
|
|
496 |
|
|
if (it == mNameMap.end()) |
497 |
|
|
return std::string(); |
498 |
|
|
return getKeyValueString((*it).second); |
499 |
|
|
} |
500 |
|
|
|
501 |
|
|
std::string InputManager::getKeyValueByNameLong(const std::string &restrict |
502 |
|
|
keyName) restrict2 |
503 |
|
|
{ |
504 |
|
|
const StringInpActionMapCIter it = mNameMap.find(keyName); |
505 |
|
|
|
506 |
|
|
if (it == mNameMap.end()) |
507 |
|
|
return std::string(); |
508 |
|
|
return getKeyStringLong((*it).second); |
509 |
|
|
} |
510 |
|
|
|
511 |
|
|
void InputManager::addActionKey(const InputActionT action, |
512 |
|
|
const InputTypeT type, |
513 |
|
|
const int val) restrict2 |
514 |
|
|
{ |
515 |
|
|
if (CAST_S32(action) < 0 || action >= InputAction::TOTAL) |
516 |
|
|
return; |
517 |
|
|
|
518 |
|
|
int idx = -1; |
519 |
|
|
InputFunction &restrict key = mKey[CAST_SIZE(action)]; |
520 |
|
|
for (size_t i = 0; i < inputFunctionSize; i ++) |
521 |
|
|
{ |
522 |
|
|
const InputItem &restrict val2 = key.values[i]; |
523 |
|
|
if (val2.type == InputType::UNKNOWN || |
524 |
|
|
(val2.type == type && val2.value == val)) |
525 |
|
|
{ |
526 |
|
|
idx = CAST_S32(i); |
527 |
|
|
break; |
528 |
|
|
} |
529 |
|
|
} |
530 |
|
|
if (idx == -1) |
531 |
|
|
{ |
532 |
|
|
for (size_t i = 1; i < inputFunctionSize; i ++) |
533 |
|
|
{ |
534 |
|
|
InputItem &restrict val1 = key.values[i - 1]; |
535 |
|
|
InputItem &restrict val2 = key.values[i]; |
536 |
|
|
val1.type = val2.type; |
537 |
|
|
val1.value = val2.value; |
538 |
|
|
} |
539 |
|
|
idx = inputFunctionSize - 1; |
540 |
|
|
} |
541 |
|
|
|
542 |
|
|
key.values[idx] = InputItem(type, val); |
543 |
|
|
updateKeyString(key, CAST_SIZE(action)); |
544 |
|
|
} |
545 |
|
|
|
546 |
|
|
void InputManager::setNewKey(const SDL_Event &event, |
547 |
|
|
const InputTypeT type) restrict2 |
548 |
|
|
{ |
549 |
|
|
int val = -1; |
550 |
|
|
if (type == InputType::KEYBOARD) |
551 |
|
|
val = KeyboardConfig::getKeyValueFromEvent(event); |
552 |
|
|
else if (type == InputType::JOYSTICK && (joystick != nullptr)) |
553 |
|
|
val = joystick->getButtonFromEvent(event); |
554 |
|
|
|
555 |
|
|
if (val != -1) |
556 |
|
|
{ |
557 |
|
|
addActionKey(mNewKeyIndex, type, val); |
558 |
|
|
update(); |
559 |
|
|
} |
560 |
|
|
} |
561 |
|
|
|
562 |
|
|
void InputManager::unassignKey() restrict2 |
563 |
|
|
{ |
564 |
|
|
InputFunction &restrict key = mKey[CAST_SIZE(mNewKeyIndex)]; |
565 |
|
|
for (size_t i = 0; i < inputFunctionSize; i ++) |
566 |
|
|
{ |
567 |
|
|
InputItem &restrict val = key.values[i]; |
568 |
|
|
val.type = InputType::UNKNOWN; |
569 |
|
|
val.value = -1; |
570 |
|
|
} |
571 |
|
|
updateKeyString(key, CAST_SIZE(mNewKeyIndex)); |
572 |
|
|
update(); |
573 |
|
|
} |
574 |
|
|
|
575 |
|
|
#ifndef DYECMD |
576 |
|
|
bool InputManager::handleAssignKey(const SDL_Event &restrict event, |
577 |
|
|
const InputTypeT type) restrict2 |
578 |
|
|
{ |
579 |
|
|
if ((setupWindow != nullptr) && setupWindow->isWindowVisible() && |
580 |
|
|
getNewKeyIndex() > InputAction::NO_VALUE) |
581 |
|
|
{ |
582 |
|
|
setNewKey(event, type); |
583 |
|
|
callbackNewKey(); |
584 |
|
|
setNewKeyIndex(InputAction::NO_VALUE); |
585 |
|
|
return true; |
586 |
|
|
} |
587 |
|
|
return false; |
588 |
|
|
} |
589 |
|
|
#else // DYECMD |
590 |
|
|
|
591 |
|
|
bool InputManager::handleAssignKey(const SDL_Event &restrict event A_UNUSED, |
592 |
|
|
const InputTypeT type A_UNUSED) restrict2 |
593 |
|
|
{ |
594 |
|
|
return false; |
595 |
|
|
} |
596 |
|
|
#endif // DYECMD |
597 |
|
|
|
598 |
|
|
bool InputManager::handleEvent(const SDL_Event &restrict event) restrict2 |
599 |
|
|
{ |
600 |
|
|
BLOCK_START("InputManager::handleEvent") |
601 |
|
|
switch (event.type) |
602 |
|
|
{ |
603 |
|
|
case SDL_KEYDOWN: |
604 |
|
|
{ |
605 |
|
|
#ifdef USE_SDL2 |
606 |
|
|
if (keyboard.ignoreKey(event)) |
607 |
|
|
{ |
608 |
|
|
BLOCK_END("InputManager::handleEvent") |
609 |
|
|
return true; |
610 |
|
|
} |
611 |
|
|
#endif // USE_SDL2 |
612 |
|
|
|
613 |
|
|
keyboard.refreshActiveKeys(); |
614 |
|
|
updateConditionMask(true); |
615 |
|
|
if (handleAssignKey(event, InputType::KEYBOARD)) |
616 |
|
|
{ |
617 |
|
|
BLOCK_END("InputManager::handleEvent") |
618 |
|
|
return true; |
619 |
|
|
} |
620 |
|
|
|
621 |
|
|
keyboard.handleActivateKey(event); |
622 |
|
|
// send straight to gui for certain windows |
623 |
|
|
#ifndef DYECMD |
624 |
|
|
if ((quitDialog != nullptr) || TextDialog::isActive()) |
625 |
|
|
{ |
626 |
|
|
if (guiInput != nullptr) |
627 |
|
|
guiInput->pushInput(event); |
628 |
|
|
if (gui != nullptr) |
629 |
|
|
gui->handleInput(); |
630 |
|
|
BLOCK_END("InputManager::handleEvent") |
631 |
|
|
return true; |
632 |
|
|
} |
633 |
|
|
#endif // DYECMD |
634 |
|
|
|
635 |
|
|
break; |
636 |
|
|
} |
637 |
|
|
case SDL_KEYUP: |
638 |
|
|
{ |
639 |
|
|
#ifdef USE_SDL2 |
640 |
|
|
if (keyboard.ignoreKey(event)) |
641 |
|
|
{ |
642 |
|
|
BLOCK_END("InputManager::handleEvent") |
643 |
|
|
return true; |
644 |
|
|
} |
645 |
|
|
#endif // USE_SDL2 |
646 |
|
|
|
647 |
|
|
keyboard.refreshActiveKeys(); |
648 |
|
|
updateConditionMask(false); |
649 |
|
|
keyboard.handleDeActicateKey(event); |
650 |
|
|
break; |
651 |
|
|
} |
652 |
|
|
case SDL_JOYBUTTONDOWN: |
653 |
|
|
{ |
654 |
|
|
updateConditionMask(true); |
655 |
|
|
// joystick.handleActicateButton(event); |
656 |
|
|
if (handleAssignKey(event, InputType::JOYSTICK)) |
657 |
|
|
{ |
658 |
|
|
BLOCK_END("InputManager::handleEvent") |
659 |
|
|
return true; |
660 |
|
|
} |
661 |
|
|
break; |
662 |
|
|
} |
663 |
|
|
case SDL_JOYBUTTONUP: |
664 |
|
|
{ |
665 |
|
|
updateConditionMask(false); |
666 |
|
|
// joystick.handleDeActicateButton(event); |
667 |
|
|
break; |
668 |
|
|
} |
669 |
|
|
#ifdef USE_SDL2 |
670 |
|
|
case SDL_FINGERDOWN: |
671 |
|
|
multiTouchManager.handleFingerDown(event); |
672 |
|
|
break; |
673 |
|
|
case SDL_FINGERUP: |
674 |
|
|
multiTouchManager.handleFingerUp(event); |
675 |
|
|
break; |
676 |
|
|
#else // USE_SDL2 |
677 |
|
|
#ifdef ANDROID |
678 |
|
|
case SDL_ACCELEROMETER: |
679 |
|
|
{ |
680 |
|
|
break; |
681 |
|
|
} |
682 |
|
|
#endif // ANDROID |
683 |
|
|
#endif // USE_SDL2 |
684 |
|
|
|
685 |
|
|
default: |
686 |
|
|
break; |
687 |
|
|
} |
688 |
|
|
|
689 |
|
|
if (guiInput != nullptr) |
690 |
|
|
guiInput->pushInput(event); |
691 |
|
|
if (gui != nullptr) |
692 |
|
|
{ |
693 |
|
|
const bool res = gui->handleInput(); |
694 |
|
|
if (res && event.type == SDL_KEYDOWN) |
695 |
|
|
{ |
696 |
|
|
BLOCK_END("InputManager::handleEvent") |
697 |
|
|
return true; |
698 |
|
|
} |
699 |
|
|
} |
700 |
|
|
|
701 |
|
|
switch (event.type) |
702 |
|
|
{ |
703 |
|
|
case SDL_KEYDOWN: |
704 |
|
|
if (isActionActive(InputAction::IGNORE_INPUT_1) || |
705 |
|
|
isActionActive(InputAction::IGNORE_INPUT_2)) |
706 |
|
|
{ |
707 |
|
|
BLOCK_END("InputManager::handleEvent") |
708 |
|
|
return true; |
709 |
|
|
} |
710 |
|
|
if (triggerAction(keyboard.getActionVector(event))) |
711 |
|
|
{ |
712 |
|
|
BLOCK_END("InputManager::handleEvent") |
713 |
|
|
return true; |
714 |
|
|
} |
715 |
|
|
break; |
716 |
|
|
|
717 |
|
|
// disabled temporary |
718 |
|
|
// case SDL_KEYUP: |
719 |
|
|
// if (triggerAction(keyboard.getActionVector(event))) |
720 |
|
|
// { |
721 |
|
|
// BLOCK_END("InputManager::handleEvent") |
722 |
|
|
// return true; |
723 |
|
|
// } |
724 |
|
|
// break; |
725 |
|
|
|
726 |
|
|
case SDL_JOYBUTTONDOWN: |
727 |
|
|
if ((joystick != nullptr) && joystick->validate()) |
728 |
|
|
{ |
729 |
|
|
if (triggerAction(joystick->getActionVector(event))) |
730 |
|
|
{ |
731 |
|
|
BLOCK_END("InputManager::handleEvent") |
732 |
|
|
return true; |
733 |
|
|
} |
734 |
|
|
} |
735 |
|
|
break; |
736 |
|
|
#ifdef ANDROID |
737 |
|
|
#ifndef USE_SDL2 |
738 |
|
|
case SDL_ACCELEROMETER: |
739 |
|
|
{ |
740 |
|
|
break; |
741 |
|
|
} |
742 |
|
|
#endif // USE_SDL2 |
743 |
|
|
#endif // ANDROID |
744 |
|
|
|
745 |
|
|
default: |
746 |
|
|
break; |
747 |
|
|
} |
748 |
|
|
|
749 |
|
|
BLOCK_END("InputManager::handleEvent") |
750 |
|
|
return false; |
751 |
|
|
} |
752 |
|
|
|
753 |
|
|
void InputManager::handleRepeat() |
754 |
|
|
{ |
755 |
|
|
const int time = tick_time; |
756 |
|
|
keyboard.handleRepeat(time); |
757 |
|
|
if (joystick != nullptr) |
758 |
|
|
joystick->handleRepeat(time); |
759 |
|
|
} |
760 |
|
|
|
761 |
|
|
void InputManager::updateConditionMask(const bool pressed A_UNUSED) restrict2 |
762 |
|
|
{ |
763 |
|
|
mMask = 1; |
764 |
|
|
if (keyboard.isEnabled()) |
765 |
|
|
mMask |= InputCondition::ENABLED; |
766 |
|
|
#ifndef DYECMD |
767 |
|
|
if (((chatWindow == nullptr) || !chatWindow->isInputFocused()) && |
768 |
|
|
!NpcDialog::isAnyInputFocused() && |
769 |
|
|
!InventoryWindow::isAnyInputFocused() && |
770 |
|
|
((tradeWindow == nullptr) || !tradeWindow->isInpupFocused())) |
771 |
|
|
{ |
772 |
|
|
if (gui != nullptr) |
773 |
|
|
{ |
774 |
|
|
FocusHandler *restrict const focus = gui->getFocusHandler(); |
775 |
|
|
if (focus != nullptr) |
776 |
|
|
{ |
777 |
|
|
if (dynamic_cast<TextField*>(focus->getFocused()) == nullptr) |
778 |
|
|
mMask |= InputCondition::NOINPUT; |
779 |
|
|
} |
780 |
|
|
else |
781 |
|
|
{ |
782 |
|
|
mMask |= InputCondition::NOINPUT; |
783 |
|
|
} |
784 |
|
|
} |
785 |
|
|
else |
786 |
|
|
{ |
787 |
|
|
mMask |= InputCondition::NOINPUT; |
788 |
|
|
} |
789 |
|
|
} |
790 |
|
|
|
791 |
|
|
if (!BuyDialog::isActive() && !SellDialog::isActive()) |
792 |
|
|
mMask |= InputCondition::NOBUYSELL; |
793 |
|
|
|
794 |
|
|
if (!PlayerInfo::isVending()) |
795 |
|
|
mMask |= InputCondition::NOVENDING; |
796 |
|
|
if (!PlayerInfo::isInRoom()) |
797 |
|
|
mMask |= InputCondition::NOROOM; |
798 |
|
|
|
799 |
|
|
const NpcDialog *restrict const dialog = NpcDialog::getActive(); |
800 |
|
|
if ((dialog == nullptr) || !dialog->isTextInputFocused()) |
801 |
|
|
mMask |= InputCondition::NONPCINPUT; |
802 |
|
|
if ((dialog == nullptr) || (dialog->isCloseState() != 0)) |
803 |
|
|
{ |
804 |
|
|
mMask |= InputCondition::NONPCDIALOG; |
805 |
|
|
if (!InventoryWindow::isStorageActive()) |
806 |
|
|
mMask |= InputCondition::NOTALKING; |
807 |
|
|
} |
808 |
|
|
if ((setupWindow == nullptr) || !setupWindow->isWindowVisible()) |
809 |
|
|
mMask |= InputCondition::NOSETUP; |
810 |
|
|
|
811 |
|
|
if ((Game::instance() != nullptr) && Game::instance()->getValidSpeed()) |
812 |
|
|
mMask |= InputCondition::VALIDSPEED; |
813 |
|
|
|
814 |
|
|
if (Game::instance() != nullptr) |
815 |
|
|
mMask |= InputCondition::INGAME; |
816 |
|
|
|
817 |
|
|
if (localPlayer != nullptr) |
818 |
|
|
{ |
819 |
|
|
if (localPlayer->getFollow().empty()) |
820 |
|
|
mMask |= InputCondition::NOFOLLOW; |
821 |
|
|
|
822 |
|
|
if (!localPlayer->isTrickDead()) |
823 |
|
|
mMask |= InputCondition::NOBLOCK; |
824 |
|
|
|
825 |
|
|
if (localPlayer->isAlive()) |
826 |
|
|
mMask |= InputCondition::ALIVE; |
827 |
|
|
} |
828 |
|
|
else |
829 |
|
|
{ |
830 |
|
|
mMask |= InputCondition::NOFOLLOW; |
831 |
|
|
mMask |= InputCondition::NOBLOCK; |
832 |
|
|
} |
833 |
|
|
#endif // DYECMD |
834 |
|
|
|
835 |
|
|
if (!settings.awayMode) |
836 |
|
|
mMask |= InputCondition::NOAWAY; |
837 |
|
|
|
838 |
|
|
if (gui != nullptr && gui->getFocusHandler()->getModalFocused() == nullptr) |
839 |
|
|
mMask |= InputCondition::NOMODAL; |
840 |
|
|
|
841 |
|
|
if (!settings.disableGameModifiers) |
842 |
|
|
mMask |= InputCondition::EMODS; |
843 |
|
|
|
844 |
|
|
if (!isActionActive0(InputAction::STOP_ATTACK) |
845 |
|
|
&& !isActionActive0(InputAction::UNTARGET)) |
846 |
|
|
{ |
847 |
|
|
mMask |= InputCondition::NOTARGET; |
848 |
|
|
} |
849 |
|
|
// enable it temporary |
850 |
|
|
mMask |= InputCondition::KEY_DOWN; |
851 |
|
|
// if (pressed == true) |
852 |
|
|
// mMask |= InputCondition::KEY_DOWN; |
853 |
|
|
// else |
854 |
|
|
// mMask |= InputCondition::KEY_UP; |
855 |
|
|
} |
856 |
|
|
|
857 |
|
|
bool InputManager::checkKey(const InputActionData *restrict const key) const |
858 |
|
|
restrict2 |
859 |
|
|
{ |
860 |
|
|
// logger->log("checkKey mask=%d, condition=%d", mMask, key->condition); |
861 |
|
|
if ((key == nullptr) || (key->condition & mMask) != key->condition) |
862 |
|
|
return false; |
863 |
|
|
|
864 |
|
|
return key->modKeyIndex == InputAction::NO_VALUE |
865 |
|
|
|| isActionActive0(key->modKeyIndex); |
866 |
|
|
} |
867 |
|
|
|
868 |
|
|
bool InputManager::invokeKey(const InputActionData *restrict const key, |
869 |
|
|
const InputActionT keyNum) restrict2 |
870 |
|
|
{ |
871 |
|
|
// no validation to keyNum because it validated in caller |
872 |
|
|
|
873 |
|
|
if (checkKey(key)) |
874 |
|
|
{ |
875 |
|
|
InputEvent evt(keyNum, mMask); |
876 |
|
|
ActionFuncPtr func = *(inputActionData[ |
877 |
|
|
CAST_SIZE(keyNum)].action); |
878 |
|
|
if ((func != nullptr) && func(evt)) |
879 |
|
|
return true; |
880 |
|
|
} |
881 |
|
|
return false; |
882 |
|
|
} |
883 |
|
|
|
884 |
|
|
void InputManager::executeAction(const InputActionT keyNum) restrict2 |
885 |
|
|
{ |
886 |
|
|
if (keyNum < InputAction::MOVE_UP || keyNum >= InputAction::TOTAL) |
887 |
|
|
return; |
888 |
|
|
|
889 |
|
|
ActionFuncPtr func = *(inputActionData[CAST_SIZE( |
890 |
|
|
keyNum)].action); |
891 |
|
|
if (func != nullptr) |
892 |
|
|
{ |
893 |
|
|
InputEvent evt(keyNum, mMask); |
894 |
|
|
func(evt); |
895 |
|
|
} |
896 |
|
|
} |
897 |
|
|
|
898 |
|
|
bool InputManager::executeChatCommand(const std::string &restrict cmd, |
899 |
|
|
const std::string &restrict args, |
900 |
|
|
ChatTab *restrict const tab) restrict2 |
901 |
|
|
{ |
902 |
|
|
const StringIntMapCIter it = mChatMap.find(cmd); |
903 |
|
|
if (it != mChatMap.end()) |
904 |
|
|
{ |
905 |
|
|
ActionFuncPtr func = *(inputActionData[(*it).second].action); |
906 |
|
|
if (func != nullptr) |
907 |
|
|
{ |
908 |
|
|
InputEvent evt(args, tab, mMask); |
909 |
|
|
func(evt); |
910 |
|
|
return true; |
911 |
|
|
} |
912 |
|
|
} |
913 |
|
|
else |
914 |
|
|
{ |
915 |
|
|
reportAlways("Unknown chat command: /%s %s", |
916 |
|
|
cmd.c_str(), |
917 |
|
|
args.c_str()) |
918 |
|
|
} |
919 |
|
|
return false; |
920 |
|
|
} |
921 |
|
|
|
922 |
|
|
bool InputManager::executeRemoteChatCommand(const std::string &restrict cmd, |
923 |
|
|
const std::string &restrict args, |
924 |
|
|
ChatTab *restrict const tab) |
925 |
|
|
restrict2 |
926 |
|
|
{ |
927 |
|
|
const StringIntMapCIter it = mChatMap.find(cmd); |
928 |
|
|
if (it != mChatMap.end()) |
929 |
|
|
{ |
930 |
|
|
const InputActionData &restrict data = inputActionData[(*it).second]; |
931 |
|
|
if (data.isProtected == Protected_true) |
932 |
|
|
return false; |
933 |
|
|
ActionFuncPtr func = *(data.action); |
934 |
|
|
if (func != nullptr) |
935 |
|
|
{ |
936 |
|
|
InputEvent evt(args, tab, mMask); |
937 |
|
|
func(evt); |
938 |
|
|
return true; |
939 |
|
|
} |
940 |
|
|
} |
941 |
|
|
return false; |
942 |
|
|
} |
943 |
|
|
|
944 |
|
|
bool InputManager::executeChatCommand(const InputActionT keyNum, |
945 |
|
|
const std::string &restrict args, |
946 |
|
|
ChatTab *restrict const tab) restrict2 |
947 |
|
|
{ |
948 |
|
|
if (CAST_S32(keyNum) < 0 || keyNum >= InputAction::TOTAL) |
949 |
|
|
return false; |
950 |
|
|
ActionFuncPtr func = *(inputActionData[CAST_SIZE( |
951 |
|
|
keyNum)].action); |
952 |
|
|
if (func != nullptr) |
953 |
|
|
{ |
954 |
|
|
InputEvent evt(args, tab, mMask); |
955 |
|
|
func(evt); |
956 |
|
|
return true; |
957 |
|
|
} |
958 |
|
|
return false; |
959 |
|
|
} |
960 |
|
|
|
961 |
|
1 |
void InputManager::updateKeyActionMap(KeyToActionMap &restrict actionMap, |
962 |
|
|
KeyToIdMap &restrict idMap, |
963 |
|
|
KeyTimeMap &restrict keyTimeMap, |
964 |
|
|
const InputTypeT type) const restrict2 |
965 |
|
|
{ |
966 |
|
1 |
actionMap.clear(); |
967 |
|
1 |
keyTimeMap.clear(); |
968 |
|
|
|
969 |
✓✓ |
671 |
for (size_t i = 0; i < CAST_SIZE(InputAction::TOTAL); i ++) |
970 |
|
|
{ |
971 |
|
670 |
const InputFunction &restrict key = mKey[i]; |
972 |
|
670 |
const InputActionData &restrict kd = inputActionData[i]; |
973 |
✓✓ |
670 |
if (kd.action != nullptr) |
974 |
|
|
{ |
975 |
✓✓ |
4312 |
for (size_t i2 = 0; i2 < inputFunctionSize; i2 ++) |
976 |
|
|
{ |
977 |
|
1848 |
const InputItem &restrict ki = key.values[i2]; |
978 |
✗✓✗✗
|
1848 |
if (ki.type == type && ki.value != -1) |
979 |
|
|
{ |
980 |
|
|
actionMap[ki.value].push_back( |
981 |
|
|
static_cast<InputActionT>(i)); |
982 |
|
|
} |
983 |
|
|
} |
984 |
|
|
} |
985 |
✓✗✓✓
|
670 |
if (kd.configField != nullptr && (kd.grp & Input::GRP_GUICHAN) != 0) |
986 |
|
|
{ |
987 |
✓✓ |
287 |
for (size_t i2 = 0; i2 < inputFunctionSize; i2 ++) |
988 |
|
|
{ |
989 |
|
123 |
const InputItem &restrict ki = key.values[i2]; |
990 |
✗✓✗✗
|
123 |
if (ki.type == type && ki.value != -1) |
991 |
|
|
idMap[ki.value] = static_cast<InputActionT>(i); |
992 |
|
|
} |
993 |
|
|
} |
994 |
✓✗✓✓
|
670 |
if (kd.configField != nullptr && (kd.grp & Input::GRP_REPEAT) != 0) |
995 |
|
|
{ |
996 |
✓✓ |
21 |
for (size_t i2 = 0; i2 < inputFunctionSize; i2 ++) |
997 |
|
|
{ |
998 |
|
9 |
const InputItem &restrict ki = key.values[i2]; |
999 |
✗✓✗✗
|
9 |
if (ki.type == type && ki.value != -1) |
1000 |
|
|
keyTimeMap[ki.value] = 0; |
1001 |
|
|
} |
1002 |
|
|
} |
1003 |
|
|
} |
1004 |
|
|
|
1005 |
|
1 |
inputActionDataSorter.keys = &inputActionData[0]; |
1006 |
✗✓ |
2 |
FOR_EACH (KeyToActionMapIter, it, actionMap) |
1007 |
|
|
{ |
1008 |
|
|
KeysVector *const keys = &it->second; |
1009 |
|
|
if (keys->size() > 1) |
1010 |
|
|
std::sort(keys->begin(), keys->end(), inputActionDataSorter); |
1011 |
|
|
} |
1012 |
|
1 |
} |
1013 |
|
|
|
1014 |
|
|
bool InputManager::triggerAction(const KeysVector *restrict const ptrs) |
1015 |
|
|
restrict2 |
1016 |
|
|
{ |
1017 |
|
|
if (ptrs == nullptr) |
1018 |
|
|
return false; |
1019 |
|
|
|
1020 |
|
|
// logger->log("ptrs: %d", (int)ptrs.size()); |
1021 |
|
|
|
1022 |
|
|
FOR_EACHP (KeysVectorCIter, it, ptrs) |
1023 |
|
|
{ |
1024 |
|
|
const InputActionT keyNum = *it; |
1025 |
|
|
if (CAST_S32(keyNum) < 0 || keyNum >= InputAction::TOTAL) |
1026 |
|
|
continue; |
1027 |
|
|
|
1028 |
|
|
if (invokeKey(&inputActionData[CAST_SIZE(keyNum)], keyNum)) |
1029 |
|
|
return true; |
1030 |
|
|
} |
1031 |
|
|
return false; |
1032 |
|
|
} |
1033 |
|
|
|
1034 |
|
|
InputActionT InputManager::getKeyIndex(const int value, |
1035 |
|
|
const int grp, |
1036 |
|
|
const InputTypeT type) const restrict2 |
1037 |
|
|
{ |
1038 |
|
|
for (size_t i = 0; i < CAST_SIZE(InputAction::TOTAL); i++) |
1039 |
|
|
{ |
1040 |
|
|
const InputFunction &restrict key = mKey[i]; |
1041 |
|
|
const InputActionData &restrict kd = inputActionData[i]; |
1042 |
|
|
for (size_t i2 = 0; i2 < inputFunctionSize; i2 ++) |
1043 |
|
|
{ |
1044 |
|
|
const InputItem &restrict vali2 = key.values[i2]; |
1045 |
|
|
if (value == vali2.value && |
1046 |
|
|
(grp & kd.grp) != 0 && vali2.type == type) |
1047 |
|
|
{ |
1048 |
|
|
return static_cast<InputActionT>(i); |
1049 |
|
|
} |
1050 |
|
|
} |
1051 |
|
|
} |
1052 |
|
|
return InputAction::NO_VALUE; |
1053 |
|
|
} |
1054 |
|
|
|
1055 |
|
|
InputActionT InputManager::getActionByKey(const SDL_Event &restrict event) |
1056 |
|
|
const restrict2 |
1057 |
|
|
{ |
1058 |
|
|
// for now support only keyboard events |
1059 |
|
|
if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) |
1060 |
|
|
{ |
1061 |
|
|
const InputActionT idx = keyboard.getActionId(event); |
1062 |
|
|
if (CAST_S32(idx) >= 0 && |
1063 |
|
|
checkKey(&inputActionData[CAST_SIZE(idx)])) |
1064 |
|
|
{ |
1065 |
|
|
return idx; |
1066 |
|
|
} |
1067 |
|
|
} |
1068 |
|
|
return InputAction::NO_VALUE; |
1069 |
|
|
} |
1070 |
|
|
|
1071 |
|
|
InputActionT InputManager::getActionByConfigField(const std::string &field) |
1072 |
|
|
{ |
1073 |
|
|
for (int i = 0; i < CAST_S32(InputAction::TOTAL); i ++) |
1074 |
|
|
{ |
1075 |
|
|
const std::string cf = inputActionData[i].configField; |
1076 |
|
|
if (field == cf) |
1077 |
|
|
return static_cast<InputActionT>(i); |
1078 |
|
|
} |
1079 |
|
|
return InputAction::NO_VALUE; |
1080 |
|
|
} |
1081 |
|
|
|
1082 |
|
2 |
void InputManager::addChatCommands(std::list<std::string> &restrict arr) |
1083 |
|
|
{ |
1084 |
|
2 |
const int sz = CAST_S32(InputAction::TOTAL); |
1085 |
✓✓ |
1342 |
for (int i = 0; i < sz; i++) |
1086 |
|
|
{ |
1087 |
|
1340 |
const InputActionData &restrict ad = inputActionData[i]; |
1088 |
|
4020 |
std::string cmd = ad.chatCommand; |
1089 |
✓✓ |
1340 |
if (!cmd.empty()) |
1090 |
|
|
{ |
1091 |
|
1284 |
StringVect tokens; |
1092 |
✓✗ |
642 |
splitToStringVector(tokens, cmd, '|'); |
1093 |
✓✓ |
4244 |
FOR_EACH (StringVectCIter, it, tokens) |
1094 |
|
|
{ |
1095 |
✓✗ |
6204 |
cmd = std::string("/").append(*it); |
1096 |
✓✓ |
1034 |
if (ad.useArgs == UseArgs_true) |
1097 |
✓✗ |
534 |
cmd.append(" "); |
1098 |
✓✗ |
1034 |
arr.push_back(cmd); |
1099 |
|
|
} |
1100 |
|
|
} |
1101 |
|
|
} |
1102 |
✓✗✓✗
|
5 |
} |