diff options
author | Matthew Hoops | 2012-05-11 11:36:24 -0400 |
---|---|---|
committer | Matthew Hoops | 2012-05-11 11:37:47 -0400 |
commit | 974eb12fcce42067b5a52bc7f50a1edccf0d5f39 (patch) | |
tree | 08535d4d7d305196e2785f6d775bb0f480c9c854 | |
parent | e80d622fa5b3a834faff22ac777838388c0cdf10 (diff) | |
download | scummvm-rg350-974eb12fcce42067b5a52bc7f50a1edccf0d5f39.tar.gz scummvm-rg350-974eb12fcce42067b5a52bc7f50a1edccf0d5f39.tar.bz2 scummvm-rg350-974eb12fcce42067b5a52bc7f50a1edccf0d5f39.zip |
PEGASUS: Rewrite the input code to more closely emulate what the original did
Now the easter egg key works better and so does striding.
-rw-r--r-- | engines/pegasus/input.cpp | 216 | ||||
-rw-r--r-- | engines/pegasus/input.h | 11 | ||||
-rw-r--r-- | engines/pegasus/pegasus.cpp | 1 |
3 files changed, 139 insertions, 89 deletions
diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp index 492b02b85e..0ec8907489 100644 --- a/engines/pegasus/input.cpp +++ b/engines/pegasus/input.cpp @@ -37,95 +37,88 @@ DECLARE_SINGLETON(Pegasus::InputDeviceManager); namespace Pegasus { InputDeviceManager::InputDeviceManager() { + // Set all keys to "not down" + _keyMap[Common::KEYCODE_UP] = false; + _keyMap[Common::KEYCODE_KP8] = false; + _keyMap[Common::KEYCODE_LEFT] = false; + _keyMap[Common::KEYCODE_KP4] = false; + _keyMap[Common::KEYCODE_DOWN] = false; + _keyMap[Common::KEYCODE_KP5] = false; + _keyMap[Common::KEYCODE_RIGHT] = false; + _keyMap[Common::KEYCODE_KP6] = false; + _keyMap[Common::KEYCODE_RETURN] = false; + _keyMap[Common::KEYCODE_SPACE] = false; + _keyMap[Common::KEYCODE_t] = false; + _keyMap[Common::KEYCODE_KP_EQUALS] = false; + _keyMap[Common::KEYCODE_i] = false; + _keyMap[Common::KEYCODE_KP_DIVIDE] = false; + _keyMap[Common::KEYCODE_q] = false; + _keyMap[Common::KEYCODE_ESCAPE] = false; + _keyMap[Common::KEYCODE_p] = false; + _keyMap[Common::KEYCODE_TILDE] = false; + _keyMap[Common::KEYCODE_BACKQUOTE] = false; + _keyMap[Common::KEYCODE_NUMLOCK] = false; + _keyMap[Common::KEYCODE_BACKSPACE] = false; + _keyMap[Common::KEYCODE_KP_MULTIPLY] = false; + _keyMap[Common::KEYCODE_LALT] = false; + _keyMap[Common::KEYCODE_RALT] = false; + _keyMap[Common::KEYCODE_e] = false; + + g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 2, false); _lastRawBits = kAllUpBits; + _consoleRequested = false; +} + +InputDeviceManager::~InputDeviceManager() { + g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); } void InputDeviceManager::getInput(Input &input, const InputBits filter) { + // Poll for events, but ignore them! + // We'll pick them up in notifyEvent() + // We do that so that any pollEvent() call can update the variables + // (ie. if one uses enter to access the restore menu, we never receive + // the key up event, which leads to bad things) + // This is to closely emulate what the GetKeys() function did on Mac OS + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) + ; + + // Now create the bitfield InputBits currentBits = 0; - bool consoleRequested = false; - bool altDown = false; - Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) { - // We only care about key down here - // We're mapping from ScummVM events to pegasus events, which - // are based on pippin events. - if (event.type == Common::EVENT_KEYDOWN) { - switch (event.kbd.keycode) { - case Common::KEYCODE_UP: - case Common::KEYCODE_KP8: - currentBits |= (kRawButtonDown << kUpButtonShift); - break; - case Common::KEYCODE_LEFT: - case Common::KEYCODE_KP4: - currentBits |= (kRawButtonDown << kLeftButtonShift); - break; - case Common::KEYCODE_DOWN: - case Common::KEYCODE_KP5: - currentBits |= (kRawButtonDown << kDownButtonShift); - break; - case Common::KEYCODE_RIGHT: - case Common::KEYCODE_KP6: - currentBits |= (kRawButtonDown << kRightButtonShift); - break; - case Common::KEYCODE_RETURN: - case Common::KEYCODE_SPACE: - currentBits |= (kRawButtonDown << kTwoButtonShift); - break; - case Common::KEYCODE_t: - case Common::KEYCODE_KP_EQUALS: - currentBits |= (kRawButtonDown << kThreeButtonShift); - break; - case Common::KEYCODE_i: - case Common::KEYCODE_KP_DIVIDE: - currentBits |= (kRawButtonDown << kFourButtonShift); - break; - case Common::KEYCODE_q: - currentBits |= (kRawButtonDown << kMod1ButtonShift); - break; - case Common::KEYCODE_ESCAPE: - case Common::KEYCODE_p: - currentBits |= (kRawButtonDown << kMod3ButtonShift); - break; - case Common::KEYCODE_TILDE: - case Common::KEYCODE_BACKQUOTE: - case Common::KEYCODE_NUMLOCK: // Yes, the original uses Num Lock/Clear on the Mac... - currentBits |= (kRawButtonDown << kLeftFireButtonShift); - break; - case Common::KEYCODE_BACKSPACE: - case Common::KEYCODE_KP_MULTIPLY: - currentBits |= (kRawButtonDown << kRightFireButtonShift); - break; - case Common::KEYCODE_d: - if (event.kbd.flags & Common::KBD_CTRL) // Console! - consoleRequested = true; - break; - case Common::KEYCODE_s: - // We support meta where available and control elsewhere - if (event.kbd.flags & (Common::KBD_CTRL|Common::KBD_META)) - ((PegasusEngine *)g_engine)->requestSave(); - break; - case Common::KEYCODE_o: // o for open (original) - case Common::KEYCODE_l: // l for load (ScummVM terminology) - // We support meta where available and control elsewhere - if (event.kbd.flags & (Common::KBD_CTRL|Common::KBD_META)) - ((PegasusEngine *)g_engine)->requestLoad(); - break; - default: - break; - } - - // WORKAROUND: The original had a specific key for this, but - // pressing alt would count as an event (and mess up someone - // trying to do alt+enter or something). Since it's only used - // as an easter egg, I'm just going to handle it as a separate - // bool value. - // WORKAROUND x2: I'm also accepting control here since an - // alt+click is often intercepted by the OS. - if (event.kbd.flags & (Common::KBD_ALT|Common::KBD_CTRL)) - altDown = true; - } - } + if (_keyMap[Common::KEYCODE_UP] || _keyMap[Common::KEYCODE_KP8]) + currentBits |= (kRawButtonDown << kUpButtonShift); + + if (_keyMap[Common::KEYCODE_DOWN] || _keyMap[Common::KEYCODE_KP5]) + currentBits |= (kRawButtonDown << kDownButtonShift); + + if (_keyMap[Common::KEYCODE_LEFT] || _keyMap[Common::KEYCODE_KP4]) + currentBits |= (kRawButtonDown << kLeftButtonShift); + + if (_keyMap[Common::KEYCODE_RIGHT] || _keyMap[Common::KEYCODE_KP6]) + currentBits |= (kRawButtonDown << kRightButtonShift); + + if (_keyMap[Common::KEYCODE_SPACE] || _keyMap[Common::KEYCODE_RETURN]) + currentBits |= (kRawButtonDown << kTwoButtonShift); + + if (_keyMap[Common::KEYCODE_t] || _keyMap[Common::KEYCODE_KP_EQUALS]) + currentBits |= (kRawButtonDown << kThreeButtonShift); + + if (_keyMap[Common::KEYCODE_i] || _keyMap[Common::KEYCODE_KP_DIVIDE]) + currentBits |= (kRawButtonDown << kFourButtonShift); + + if (_keyMap[Common::KEYCODE_q]) + currentBits |= (kRawButtonDown << kMod1ButtonShift); + + if (_keyMap[Common::KEYCODE_ESCAPE] || _keyMap[Common::KEYCODE_p]) + currentBits |= (kRawButtonDown << kMod3ButtonShift); + + if (_keyMap[Common::KEYCODE_TILDE] || _keyMap[Common::KEYCODE_BACKQUOTE] || _keyMap[Common::KEYCODE_NUMLOCK]) + currentBits |= (kRawButtonDown << kLeftFireButtonShift); + + if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY]) + currentBits |= (kRawButtonDown << kRightFireButtonShift); // Update mouse button state // Note that we don't use EVENT_LBUTTONUP/EVENT_LBUTTONDOWN because @@ -145,10 +138,17 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) { _lastRawBits = currentBits; // Set the console to be requested or not - input.setConsoleRequested(consoleRequested); - - // Same for alt - input.setAltDown(altDown); + input.setConsoleRequested(_consoleRequested); + + // WORKAROUND: The original had this in currentBits, but then + // pressing alt would count as an event (and mess up someone + // trying to do alt+enter or something). Since it's only used + // as an easter egg, I'm just going to handle it as a separate + // bool value. + // WORKAROUND x2: I'm also accepting 'e' here since an + // alt+click is often intercepted by the OS. 'e' is used as the + // easter egg key in Buried in Time and Legacy of Time. + input.setAltDown(_keyMap[Common::KEYCODE_LALT] || _keyMap[Common::KEYCODE_RALT] || _keyMap[Common::KEYCODE_e]); } // Wait until the input device stops returning input allowed by filter... @@ -163,6 +163,48 @@ void InputDeviceManager::waitInput(const InputBits filter) { } } +bool InputDeviceManager::notifyEvent(const Common::Event &event) { + // We're mapping from ScummVM events to pegasus events, which + // are based on pippin events. + _consoleRequested = false; + + switch (event.type) { + case Common::EVENT_KEYDOWN: + switch (event.kbd.keycode) { + case Common::KEYCODE_d: + if (event.kbd.flags & Common::KBD_CTRL) // Console! + _consoleRequested = true; + break; + case Common::KEYCODE_s: + // We support meta where available and control elsewhere + if (event.kbd.flags & (Common::KBD_CTRL|Common::KBD_META)) + ((PegasusEngine *)g_engine)->requestSave(); + break; + case Common::KEYCODE_o: // o for open (original) + case Common::KEYCODE_l: // l for load (ScummVM terminology) + // We support meta where available and control elsewhere + if (event.kbd.flags & (Common::KBD_CTRL|Common::KBD_META)) + ((PegasusEngine *)g_engine)->requestLoad(); + break; + default: + // Otherwise, set the key to down if we have it + if (_keyMap.contains(event.kbd.keycode)) + _keyMap[event.kbd.keycode] = true; + break; + } + break; + case Common::EVENT_KEYUP: + // Set the key to up if we have it + if (_keyMap.contains(event.kbd.keycode)) + _keyMap[event.kbd.keycode] = false; + break; + default: + break; + } + + return false; +} + int operator==(const Input &arg1, const Input &arg2) { return arg1._inputState == arg2._inputState; } diff --git a/engines/pegasus/input.h b/engines/pegasus/input.h index 0ee01f1949..f6c29e7780 100644 --- a/engines/pegasus/input.h +++ b/engines/pegasus/input.h @@ -26,6 +26,8 @@ #ifndef PEGASUS_INPUT_H #define PEGASUS_INPUT_H +#include "common/events.h" +#include "common/hashmap.h" #include "common/rect.h" #include "common/singleton.h" @@ -37,10 +39,12 @@ namespace Pegasus { class Hotspot; class Input; -class InputDeviceManager : public Common::Singleton<InputDeviceManager> { +class InputDeviceManager : public Common::Singleton<InputDeviceManager>, public Common::EventObserver { public: InputDeviceManager(); - ~InputDeviceManager() {} + ~InputDeviceManager(); + + bool notifyEvent(const Common::Event &event); void getInput(Input &, const InputBits); @@ -49,7 +53,10 @@ public: protected: friend class Common::Singleton<SingletonBaseType>; + // Keep track of which keys are down (= true) or not + Common::HashMap<uint, bool> _keyMap; InputBits _lastRawBits; + bool _consoleRequested; }; enum { diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index d2d1973a66..701c4161bb 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -104,6 +104,7 @@ PegasusEngine::~PegasusEngine() { delete _rnd; delete _introTimer; delete _aiSaveStream; + InputDeviceManager::destroy(); // NOTE: This must be deleted last! delete _gfx; |