~ubuntu-branches/ubuntu/trusty/manaplus/trusty-proposed

« back to all changes in this revision

Viewing changes to src/inputmanager.cpp

  • Committer: Package Import Robot
  • Author(s): Patrick Matthäi
  • Date: 2013-09-17 10:35:51 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20130917103551-az7p3nz9jgxwqjfn
Tags: 1.3.9.15-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  The ManaPlus Client
3
 
 *  Copyright (C) 2012-2013  The ManaPlus Developers
4
 
 *
5
 
 *  This file is part of The ManaPlus Client.
6
 
 *
7
 
 *  This program is free software; you can redistribute it and/or modify
8
 
 *  it under the terms of the GNU General Public License as published by
9
 
 *  the Free Software Foundation; either version 2 of the License, or
10
 
 *  any later version.
11
 
 *
12
 
 *  This program is distributed in the hope that it will be useful,
13
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 *  GNU General Public License for more details.
16
 
 *
17
 
 *  You should have received a copy of the GNU General Public License
18
 
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 
 */
20
 
 
21
 
#include "inputmanager.h"
22
 
 
23
 
#include "client.h"
24
 
#include "configuration.h"
25
 
#include "game.h"
26
 
#include "joystick.h"
27
 
#include "keyboardconfig.h"
28
 
#include "keyboarddata.h"
29
 
#include "localplayer.h"
30
 
#include "touchmanager.h"
31
 
 
32
 
#include "gui/chatwindow.h"
33
 
#include "gui/gui.h"
34
 
#include "gui/inventorywindow.h"
35
 
#include "gui/npcdialog.h"
36
 
#include "gui/npcpostdialog.h"
37
 
#include "gui/sdlinput.h"
38
 
#include "gui/setup.h"
39
 
#include "gui/setup_input.h"
40
 
#include "gui/textdialog.h"
41
 
#include "gui/tradewindow.h"
42
 
 
43
 
#include <guichan/exception.hpp>
44
 
#include <guichan/focushandler.hpp>
45
 
 
46
 
#include <algorithm>
47
 
 
48
 
#include "debug.h"
49
 
 
50
 
InputManager inputManager;
51
 
 
52
 
extern QuitDialog *quitDialog;
53
 
 
54
 
static class KeyFunctor final
55
 
{
56
 
    public:
57
 
        bool operator() (const int key1, const int key2) const
58
 
        {
59
 
            return keys[key1].priority >= keys[key2].priority;
60
 
        }
61
 
 
62
 
        const KeyData *keys;
63
 
} keyDataSorter;
64
 
 
65
 
 
66
 
InputManager::InputManager() :
67
 
    mSetupInput(nullptr),
68
 
    mNewKeyIndex(Input::KEY_NO_VALUE),
69
 
    mMask(1),
70
 
    mNameMap()
71
 
{
72
 
}
73
 
 
74
 
void InputManager::init()
75
 
{
76
 
    for (unsigned int i = 0; i < Input::KEY_TOTAL; i++)
77
 
    {
78
 
        KeyFunction &kf = mKey[i];
79
 
        for (unsigned int f = 0; f < KeyFunctionSize; f ++)
80
 
        {
81
 
            KeyItem &ki = kf.values[f];
82
 
            ki.type = INPUT_UNKNOWN;
83
 
            ki.value = -1;
84
 
        }
85
 
    }
86
 
 
87
 
    mNewKeyIndex = Input::KEY_NO_VALUE;
88
 
 
89
 
    resetKeys();
90
 
    retrieve();
91
 
    update();
92
 
}
93
 
 
94
 
void InputManager::update() const
95
 
{
96
 
    keyboard.update();
97
 
    if (joystick)
98
 
        joystick->update();
99
 
}
100
 
 
101
 
void InputManager::retrieve()
102
 
{
103
 
    for (int i = 0; i < Input::KEY_TOTAL; i++)
104
 
    {
105
 
#ifdef USE_SDL2
106
 
        const std::string cf = std::string("sdl2") + keyData[i].configField;
107
 
#else
108
 
        const std::string cf = keyData[i].configField;
109
 
#endif
110
 
        if (!cf.empty())
111
 
        {
112
 
            mNameMap[cf] = i;
113
 
            KeyFunction &kf = mKey[i];
114
 
            const std::string keyStr = config.getValue(cf, "");
115
 
            const int keyStrSize = keyStr.size();
116
 
            if (keyStr.empty())
117
 
                continue;
118
 
 
119
 
            StringVect keys;
120
 
            splitToStringVector(keys, keyStr, ',');
121
 
            unsigned int i2 = 0;
122
 
            for (StringVectCIter it = keys.begin(), it_end = keys.end();
123
 
                 it != it_end && i2 < KeyFunctionSize; ++ it)
124
 
            {
125
 
                std::string keyStr2 = *it;
126
 
                if (keyStrSize < 2)
127
 
                    continue;
128
 
                int type = INPUT_KEYBOARD;
129
 
                if ((keyStr2[0] < '0' || keyStr2[0] > '9')
130
 
                    && keyStr2[0] != '-')
131
 
                {
132
 
                    switch (keyStr2[0])
133
 
                    {
134
 
                        case 'm':
135
 
                            type = INPUT_MOUSE;
136
 
                            break;
137
 
                        case 'j':
138
 
                            type = INPUT_JOYSTICK;
139
 
                            break;
140
 
                        default:
141
 
                            break;
142
 
                    }
143
 
                    keyStr2 = keyStr2.substr(1);
144
 
                }
145
 
                const int key = atoi(keyStr2.c_str());
146
 
                if (key >= -255 && key < SDLK_LAST)
147
 
                {
148
 
                    kf.values[i2] = KeyItem(type, key);
149
 
                    i2 ++;
150
 
                }
151
 
            }
152
 
        }
153
 
    }
154
 
}
155
 
 
156
 
void InputManager::store() const
157
 
{
158
 
    for (int i = 0; i < Input::KEY_TOTAL; i++)
159
 
    {
160
 
#ifdef USE_SDL2
161
 
        const std::string cf = std::string("sdl2") + keyData[i].configField;
162
 
#else
163
 
        const std::string cf = keyData[i].configField;
164
 
#endif
165
 
        if (!cf.empty())
166
 
        {
167
 
            std::string keyStr;
168
 
            const KeyFunction &kf = mKey[i];
169
 
 
170
 
            for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
171
 
            {
172
 
                const KeyItem &key = kf.values[i2];
173
 
                if (key.type != INPUT_UNKNOWN)
174
 
                {
175
 
                    std::string tmp = "k";
176
 
                    switch (key.type)
177
 
                    {
178
 
                        case INPUT_MOUSE:
179
 
                            tmp = "m";
180
 
                            break;
181
 
                        case INPUT_JOYSTICK:
182
 
                            tmp = "j";
183
 
                            break;
184
 
                        default:
185
 
                            break;
186
 
                    }
187
 
                    if (key.value != -1)
188
 
                    {
189
 
                        if (keyStr.empty())
190
 
                        {
191
 
                            keyStr.append(tmp).append(toString(key.value));
192
 
                        }
193
 
                        else
194
 
                        {
195
 
                            keyStr.append(strprintf(",%s%d",
196
 
                                tmp.c_str(), key.value));
197
 
                        }
198
 
                    }
199
 
                }
200
 
            }
201
 
            if (keyStr.empty())
202
 
                keyStr = "-1";
203
 
 
204
 
            config.setValue(cf, keyStr);
205
 
        }
206
 
    }
207
 
}
208
 
 
209
 
void InputManager::resetKeys()
210
 
{
211
 
    for (int i = 0; i < Input::KEY_TOTAL; i++)
212
 
    {
213
 
        KeyFunction &key = mKey[i];
214
 
        for (size_t i2 = 1; i2 < KeyFunctionSize; i2 ++)
215
 
        {
216
 
            KeyItem &ki2 = key.values[i2];
217
 
            ki2.type = INPUT_UNKNOWN;
218
 
            ki2.value = -1;
219
 
        }
220
 
        const KeyData &kd = keyData[i];
221
 
        KeyItem &val0 = key.values[0];
222
 
        val0.type = kd.defaultType1;
223
 
        KeyItem &val1 = key.values[1];
224
 
        val1.type = kd.defaultType2;
225
 
#ifdef USE_SDL2
226
 
        if (kd.defaultType1 == INPUT_KEYBOARD)
227
 
            val0.value = SDL_GetScancodeFromKey(kd.defaultValue1);
228
 
        else
229
 
            val0.value = kd.defaultValue1;
230
 
        if (kd.defaultType2 == INPUT_KEYBOARD)
231
 
            val1.value = SDL_GetScancodeFromKey(kd.defaultValue2);
232
 
        else
233
 
            val1.value = kd.defaultValue2;
234
 
#else
235
 
        val0.value = kd.defaultValue1;
236
 
        val1.value = kd.defaultValue2;
237
 
#endif
238
 
    }
239
 
}
240
 
 
241
 
void InputManager::makeDefault(const int i)
242
 
{
243
 
    if (i >= 0 && i < Input::KEY_TOTAL)
244
 
    {
245
 
        KeyFunction &key = mKey[i];
246
 
        for (size_t i2 = 1; i2 < KeyFunctionSize; i2 ++)
247
 
        {
248
 
            KeyItem &ki2 = key.values[i2];
249
 
            ki2.type = INPUT_UNKNOWN;
250
 
            ki2.value = -1;
251
 
        }
252
 
        const KeyData &kd = keyData[i];
253
 
        KeyItem &val0 = key.values[0];
254
 
        val0.type = kd.defaultType1;
255
 
        KeyItem &val1 = key.values[1];
256
 
        val1.type = kd.defaultType2;
257
 
 
258
 
#ifdef USE_SDL2
259
 
        if (kd.defaultType1 == INPUT_KEYBOARD)
260
 
            val0.value = SDL_GetScancodeFromKey(kd.defaultValue1);
261
 
        else
262
 
            val0.value = kd.defaultValue1;
263
 
        if (kd.defaultType2 == INPUT_KEYBOARD)
264
 
            val1.value = SDL_GetScancodeFromKey(kd.defaultValue2);
265
 
        else
266
 
            val1.value = kd.defaultValue2;
267
 
#else
268
 
        val0.value = kd.defaultValue1;
269
 
        val1.value = kd.defaultValue2;
270
 
#endif
271
 
 
272
 
        update();
273
 
    }
274
 
}
275
 
 
276
 
bool InputManager::hasConflicts(int &key1, int &key2) const
277
 
{
278
 
    /**
279
 
     * No need to parse the square matrix: only check one triangle
280
 
     * that's enough to detect conflicts
281
 
     */
282
 
    for (int i = 0; i < Input::KEY_TOTAL; i++)
283
 
    {
284
 
        const KeyData &kdi = keyData[i];
285
 
        if (!*kdi.configField)
286
 
            continue;
287
 
 
288
 
        const KeyFunction &ki = mKey[i];
289
 
        for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
290
 
        {
291
 
            const KeyItem &vali2 = ki.values[i2];
292
 
            if (vali2.value == Input::KEY_NO_VALUE)
293
 
                continue;
294
 
 
295
 
            size_t j;
296
 
            for (j = i, j++; j < Input::KEY_TOTAL; j++)
297
 
            {
298
 
                if ((kdi.grp & keyData[j].grp) == 0 || !*kdi.configField)
299
 
                    continue;
300
 
 
301
 
                for (size_t j2 = 0; j2 < KeyFunctionSize; j2 ++)
302
 
                {
303
 
                    const KeyItem &valj2 = mKey[j].values[j2];
304
 
                    // Allow for item shortcut and emote keys to overlap
305
 
                    // as well as emote and ignore keys, but no other keys
306
 
                    if (valj2.type != INPUT_UNKNOWN
307
 
                        && vali2.value == valj2.value
308
 
                        && vali2.type == valj2.type)
309
 
                    {
310
 
                        key1 = static_cast<int>(i);
311
 
                        key2 = static_cast<int>(j);
312
 
                        return true;
313
 
                    }
314
 
                }
315
 
            }
316
 
        }
317
 
    }
318
 
    return false;
319
 
}
320
 
 
321
 
void InputManager::callbackNewKey()
322
 
{
323
 
    mSetupInput->newKeyCallback(mNewKeyIndex);
324
 
}
325
 
 
326
 
bool InputManager::isActionActive(const int index)
327
 
{
328
 
    if (keyboard.isActionActive(index))
329
 
        return true;
330
 
    if (joystick && joystick->isActionActive(index))
331
 
        return true;
332
 
    return touchManager.isActionActive(index);
333
 
}
334
 
 
335
 
KeyFunction &InputManager::getKey(int index)
336
 
{
337
 
    if (index < 0 || index >= Input::KEY_TOTAL)
338
 
        index = 0;
339
 
    return mKey[index];
340
 
}
341
 
 
342
 
std::string InputManager::getKeyStringLong(const int index) const
343
 
{
344
 
    std::string keyStr;
345
 
    const KeyFunction &ki = mKey[index];
346
 
 
347
 
    for (size_t i = 0; i < KeyFunctionSize; i ++)
348
 
    {
349
 
        const KeyItem &key = ki.values[i];
350
 
        std::string str;
351
 
        if (key.type == INPUT_KEYBOARD)
352
 
        {
353
 
            if (key.value >= 0)
354
 
            {
355
 
                str = keyboard.getKeyName(key.value);
356
 
            }
357
 
            else if (key.value < -1)
358
 
            {
359
 
                // TRANSLATORS: long key name. must be short.
360
 
                str = strprintf(_("key_%d"), -key.value);
361
 
            }
362
 
        }
363
 
        else if (key.type == INPUT_JOYSTICK)
364
 
        {
365
 
            // TRANSLATORS: long joystick button name. must be short.
366
 
            str = strprintf(_("JButton%d"), key.value + 1);
367
 
        }
368
 
        if (!str.empty())
369
 
        {
370
 
            if (keyStr.empty())
371
 
                keyStr = str;
372
 
            else
373
 
                keyStr.append(" ").append(str);
374
 
        }
375
 
    }
376
 
 
377
 
    if (keyStr.empty())
378
 
    {
379
 
        // TRANSLATORS: unknown long key type
380
 
        return _("unknown key");
381
 
    }
382
 
    return keyStr;
383
 
}
384
 
 
385
 
std::string InputManager::getKeyValueString(const int index) const
386
 
{
387
 
    std::string keyStr;
388
 
    const KeyFunction &ki = mKey[index];
389
 
 
390
 
    for (size_t i = 0; i < KeyFunctionSize; i ++)
391
 
    {
392
 
        const KeyItem &key = ki.values[i];
393
 
        std::string str;
394
 
        if (key.type == INPUT_KEYBOARD)
395
 
        {
396
 
            if (key.value >= 0)
397
 
            {
398
 
                str = keyboard.getKeyShortString(
399
 
                    keyboard.getKeyName(key.value));
400
 
            }
401
 
            else if (key.value < -1)
402
 
            {
403
 
                // TRANSLATORS: short key name. must be very short.
404
 
                str = strprintf(_("key_%d"), -key.value);
405
 
            }
406
 
        }
407
 
        else if (key.type == INPUT_JOYSTICK)
408
 
        {
409
 
            // TRANSLATORS: short joystick button name. muse be very short
410
 
            str = strprintf(_("JB%d"), key.value + 1);
411
 
        }
412
 
        if (!str.empty())
413
 
        {
414
 
            if (keyStr.empty())
415
 
                keyStr = str;
416
 
            else
417
 
                keyStr.append(" ").append(str);
418
 
        }
419
 
    }
420
 
 
421
 
    if (keyStr.empty())
422
 
    {
423
 
        // TRANSLATORS: unknown short key type. must be short
424
 
        return _("u key");
425
 
    }
426
 
    return keyStr;
427
 
}
428
 
 
429
 
std::string InputManager::getKeyValueByName(const std::string &keyName)
430
 
{
431
 
    const std::map<std::string, int>::const_iterator
432
 
        it = mNameMap.find(keyName);
433
 
 
434
 
    if (it == mNameMap.end())
435
 
        return std::string();
436
 
    return getKeyValueString((*it).second);
437
 
}
438
 
 
439
 
void InputManager::addActionKey(const int action, const int type,
440
 
                                const int val)
441
 
{
442
 
    if (action < 0 || action >= Input::KEY_TOTAL)
443
 
        return;
444
 
 
445
 
    int idx = -1;
446
 
    KeyFunction &key = mKey[action];
447
 
    for (size_t i = 0; i < KeyFunctionSize; i ++)
448
 
    {
449
 
        const KeyItem &val2 = key.values[i];
450
 
        if (val2.type == INPUT_UNKNOWN || (val2.type == type
451
 
            && val2.value == val))
452
 
        {
453
 
            idx = static_cast<int>(i);
454
 
            break;
455
 
        }
456
 
    }
457
 
    if (idx == -1)
458
 
    {
459
 
        for (size_t i = 1; i < KeyFunctionSize; i ++)
460
 
        {
461
 
            KeyItem &val1 = key.values[i - 1];
462
 
            KeyItem &val2 = key.values[i];
463
 
            val1.type = val2.type;
464
 
            val1.value = val2.value;
465
 
        }
466
 
        idx = KeyFunctionSize - 1;
467
 
    }
468
 
 
469
 
    key.values[idx] = KeyItem(type, val);
470
 
}
471
 
 
472
 
void InputManager::setNewKey(const SDL_Event &event, const int type)
473
 
{
474
 
    int val = -1;
475
 
    if (type == INPUT_KEYBOARD)
476
 
        val = keyboard.getKeyValueFromEvent(event);
477
 
    else if (type == INPUT_JOYSTICK && joystick)
478
 
        val = joystick->getButtonFromEvent(event);
479
 
 
480
 
    if (val != -1)
481
 
    {
482
 
        addActionKey(mNewKeyIndex, type, val);
483
 
        update();
484
 
    }
485
 
}
486
 
 
487
 
void InputManager::unassignKey()
488
 
{
489
 
    KeyFunction &key = mKey[mNewKeyIndex];
490
 
    for (size_t i = 0; i < KeyFunctionSize; i ++)
491
 
    {
492
 
        KeyItem &val = key.values[i];
493
 
        val.type = INPUT_UNKNOWN;
494
 
        val.value = -1;
495
 
    }
496
 
    update();
497
 
}
498
 
 
499
 
bool InputManager::handleAssignKey(const SDL_Event &event, const int type)
500
 
{
501
 
    if (setupWindow && setupWindow->isWindowVisible() &&
502
 
        getNewKeyIndex() > Input::KEY_NO_VALUE)
503
 
    {
504
 
        setNewKey(event, type);
505
 
        callbackNewKey();
506
 
        setNewKeyIndex(Input::KEY_NO_VALUE);
507
 
        return true;
508
 
    }
509
 
    return false;
510
 
}
511
 
 
512
 
bool InputManager::handleEvent(const SDL_Event &event)
513
 
{
514
 
    switch (event.type)
515
 
    {
516
 
        case SDL_KEYDOWN:
517
 
        {
518
 
            updateConditionMask();
519
 
            if (handleAssignKey(event, INPUT_KEYBOARD))
520
 
                return true;
521
 
 
522
 
            keyboard.handleActicateKey(event);
523
 
            // send straight to gui for certain windows
524
 
            if (quitDialog || TextDialog::isActive() ||
525
 
                NpcPostDialog::isActive())
526
 
            {
527
 
                try
528
 
                {
529
 
                    if (guiInput)
530
 
                        guiInput->pushInput(event);
531
 
                    if (gui)
532
 
                        gui->handleInput();
533
 
                }
534
 
                catch (const gcn::Exception &e)
535
 
                {
536
 
                    const char *const err = e.getMessage().c_str();
537
 
                    logger->log("Warning: guichan input exception: %s", err);
538
 
                }
539
 
                return true;
540
 
            }
541
 
            break;
542
 
        }
543
 
        case SDL_KEYUP:
544
 
        {
545
 
            updateConditionMask();
546
 
            keyboard.handleDeActicateKey(event);
547
 
            break;
548
 
        }
549
 
        case SDL_JOYBUTTONDOWN:
550
 
        {
551
 
            updateConditionMask();
552
 
//            joystick.handleActicateButton(event);
553
 
            if (handleAssignKey(event, INPUT_JOYSTICK))
554
 
                return true;
555
 
            break;
556
 
        }
557
 
        case SDL_JOYBUTTONUP:
558
 
        {
559
 
            updateConditionMask();
560
 
//            joystick.handleDeActicateButton(event);
561
 
            break;
562
 
        }
563
 
#ifdef ANDROID
564
 
        case SDL_ACCELEROMETER:
565
 
        {
566
 
            break;
567
 
        }
568
 
#endif
569
 
        default:
570
 
            break;
571
 
    }
572
 
 
573
 
    try
574
 
    {
575
 
        if (guiInput)
576
 
            guiInput->pushInput(event);
577
 
    }
578
 
    catch (const gcn::Exception &e)
579
 
    {
580
 
        const char *const err = e.getMessage().c_str();
581
 
        logger->log("Warning: guichan input exception: %s", err);
582
 
    }
583
 
    if (gui)
584
 
    {
585
 
        const bool res = gui->handleInput();
586
 
        if (res && event.type == SDL_KEYDOWN)
587
 
            return true;
588
 
    }
589
 
 
590
 
    switch (event.type)
591
 
    {
592
 
        case SDL_KEYDOWN:
593
 
            if (triggerAction(keyboard.getActionVector(event)))
594
 
                return true;
595
 
            break;
596
 
 
597
 
        case SDL_JOYBUTTONDOWN:
598
 
            if (joystick && joystick->validate())
599
 
            {
600
 
                if (triggerAction(joystick->getActionVector(event)))
601
 
                    return true;
602
 
            }
603
 
            break;
604
 
#ifdef ANDROID
605
 
        case SDL_ACCELEROMETER:
606
 
        {
607
 
            break;
608
 
        }
609
 
#endif
610
 
        default:
611
 
            break;
612
 
    }
613
 
 
614
 
    return false;
615
 
}
616
 
 
617
 
void InputManager::handleRepeat() const
618
 
{
619
 
    const int time = tick_time;
620
 
    keyboard.handleRepeat(time);
621
 
    if (joystick)
622
 
        joystick->handleRepeat(time);
623
 
}
624
 
 
625
 
void InputManager::updateConditionMask()
626
 
{
627
 
    mMask = 1;
628
 
    if (keyboard.isEnabled())
629
 
        mMask |= COND_ENABLED;
630
 
    if ((!chatWindow || !chatWindow->isInputFocused()) &&
631
 
        !NpcDialog::isAnyInputFocused() &&
632
 
        !InventoryWindow::isAnyInputFocused() &&
633
 
        (!tradeWindow || !tradeWindow->isInpupFocused()))
634
 
    {
635
 
        mMask |= COND_NOINPUT;
636
 
    }
637
 
 
638
 
    if (!player_node || !player_node->getAway())
639
 
        mMask |= COND_NOAWAY;
640
 
 
641
 
    if (!setupWindow || !setupWindow->isWindowVisible())
642
 
        mMask |= COND_NOSETUP;
643
 
 
644
 
    if (Game::instance() && Game::instance()->getValidSpeed())
645
 
        mMask |= COND_VALIDSPEED;
646
 
 
647
 
    if (gui && !gui->getFocusHandler()->getModalFocused())
648
 
        mMask |= COND_NOMODAL;
649
 
 
650
 
    const NpcDialog *const dialog = NpcDialog::getActive();
651
 
    if (!dialog || !dialog->isTextInputFocused())
652
 
        mMask |= COND_NONPCINPUT;
653
 
 
654
 
    if (!player_node || !player_node->getDisableGameModifiers())
655
 
        mMask |= COND_EMODS;
656
 
 
657
 
    if (!isActionActive(Input::KEY_STOP_ATTACK)
658
 
        && !isActionActive(Input::KEY_UNTARGET))
659
 
    {
660
 
        mMask |= COND_NOTARGET;
661
 
    }
662
 
    if (Game::instance())
663
 
        mMask |= COND_INGAME;
664
 
 
665
 
    if (!player_node || player_node->getFollow().empty())
666
 
        mMask |= COND_NOFOLLOW;
667
 
}
668
 
 
669
 
bool InputManager::checkKey(const KeyData *const key) const
670
 
{
671
 
//    logger->log("mask=%d, condition=%d", mMask, key->condition);
672
 
    if (!key || (key->condition & mMask) != key->condition)
673
 
        return false;
674
 
 
675
 
    return (key->modKeyIndex == Input::KEY_NO_VALUE
676
 
        || isActionActive(key->modKeyIndex));
677
 
}
678
 
 
679
 
bool InputManager::invokeKey(const KeyData *const key, const int keyNum)
680
 
{
681
 
    // no validation to keyNum because it validated in caller
682
 
 
683
 
    if (checkKey(key))
684
 
    {
685
 
        InputEvent evt(keyNum, mMask);
686
 
        ActionFuncPtr func = *(keyData[keyNum].action);
687
 
        if (func && func(evt))
688
 
            return true;
689
 
    }
690
 
    return false;
691
 
}
692
 
 
693
 
void InputManager::executeAction(const int keyNum)
694
 
{
695
 
    if (keyNum < 0 || keyNum >= Input::KEY_TOTAL)
696
 
        return;
697
 
 
698
 
    InputEvent evt(keyNum, mMask);
699
 
    ActionFuncPtr func = *(keyData[keyNum].action);
700
 
    if (func)
701
 
        func(evt);
702
 
}
703
 
 
704
 
void InputManager::updateKeyActionMap(KeyToActionMap &actionMap,
705
 
                                      KeyToIdMap &idMap,
706
 
                                      KeyTimeMap &keyTimeMap,
707
 
                                      const int type) const
708
 
{
709
 
    actionMap.clear();
710
 
    keyTimeMap.clear();
711
 
 
712
 
    for (size_t i = 0; i < Input::KEY_TOTAL; i ++)
713
 
    {
714
 
        const KeyFunction &key = mKey[i];
715
 
        const KeyData &kd = keyData[i];
716
 
        if (kd.action)
717
 
        {
718
 
            for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
719
 
            {
720
 
                const KeyItem &ki = key.values[i2];
721
 
                if (ki.type == type && ki.value != -1)
722
 
                    actionMap[ki.value].push_back(static_cast<int>(i));
723
 
            }
724
 
        }
725
 
        if (kd.configField && (kd.grp & Input::GRP_GUICHAN))
726
 
        {
727
 
            for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
728
 
            {
729
 
                const KeyItem &ki = key.values[i2];
730
 
                if (ki.type == type && ki.value != -1)
731
 
                    idMap[ki.value] = static_cast<int>(i);
732
 
            }
733
 
        }
734
 
        if (kd.configField && (kd.grp & Input::GRP_REPEAT))
735
 
        {
736
 
            for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
737
 
            {
738
 
                const KeyItem &ki = key.values[i2];
739
 
                if (ki.type == type && ki.value != -1)
740
 
                    keyTimeMap[ki.value] = 0;
741
 
            }
742
 
        }
743
 
    }
744
 
 
745
 
    keyDataSorter.keys = &keyData[0];
746
 
    FOR_EACH (KeyToActionMapIter, it, actionMap)
747
 
    {
748
 
        KeysVector *const keys = &it->second;
749
 
        if (keys && keys->size() > 1)
750
 
            std::sort(keys->begin(), keys->end(), keyDataSorter);
751
 
    }
752
 
}
753
 
 
754
 
bool InputManager::triggerAction(const KeysVector *const ptrs)
755
 
{
756
 
    if (!ptrs)
757
 
        return false;
758
 
 
759
 
//    logger->log("ptrs: %d", (int)ptrs.size());
760
 
 
761
 
    FOR_EACHP (KeysVectorCIter, it, ptrs)
762
 
    {
763
 
        const int keyNum = *it;
764
 
        if (keyNum < 0 || keyNum >= Input::KEY_TOTAL)
765
 
            continue;
766
 
 
767
 
        if (invokeKey(&keyData[keyNum], keyNum))
768
 
            return true;
769
 
    }
770
 
    return false;
771
 
}
772
 
 
773
 
int InputManager::getKeyIndex(const int value, const int grp,
774
 
                              const int type) const
775
 
{
776
 
    for (size_t i = 0; i < Input::KEY_TOTAL; i++)
777
 
    {
778
 
        const KeyFunction &key = mKey[i];
779
 
        const KeyData &kd = keyData[i];
780
 
        for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
781
 
        {
782
 
            const KeyItem &vali2 = key.values[i2];
783
 
            if (value == vali2.value && (grp & kd.grp) != 0
784
 
                && vali2.type == type)
785
 
            {
786
 
                return static_cast<int>(i);
787
 
            }
788
 
        }
789
 
    }
790
 
    return Input::KEY_NO_VALUE;
791
 
}
792
 
 
793
 
int InputManager::getActionByKey(const SDL_Event &event) const
794
 
{
795
 
    // for now support only keyboard events
796
 
    if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
797
 
    {
798
 
        const int idx = keyboard.getActionId(event);
799
 
        if (idx >= 0 && checkKey(&keyData[idx]))
800
 
            return idx;
801
 
    }
802
 
    return Input::KEY_NO_VALUE;
803
 
}