scummvm/engines/illusions/input.cpp
2021-12-26 18:48:43 +01:00

253 lines
6.1 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "illusions/input.h"
#include "common/system.h"
namespace Illusions {
// KeyMap
void KeyMap::addKey(Common::KeyCode key) {
add(key, MOUSE_NONE);
}
void KeyMap::addMouseButton(int mouseButton) {
add(Common::KEYCODE_INVALID, mouseButton);
}
void KeyMap::add(Common::KeyCode key, int mouseButton) {
KeyMapping keyMapping;
keyMapping._key = key;
keyMapping._mouseButton = mouseButton;
keyMapping._down = false;
push_back(keyMapping);
}
// InputEvent
InputEvent::InputEvent() : _bitMask(0) {
}
InputEvent& InputEvent::setBitMask(uint bitMask) {
_bitMask = bitMask;
return *this;
}
InputEvent& InputEvent::addKey(Common::KeyCode key) {
_keyMap.addKey(key);
return *this;
}
InputEvent& InputEvent::addMouseButton(int mouseButton) {
_keyMap.addMouseButton(mouseButton);
return *this;
}
uint InputEvent::handle(Common::KeyCode key, int mouseButton, bool down) {
uint newKeys = 0;
for (KeyMap::iterator it = _keyMap.begin(); it != _keyMap.end(); ++it) {
KeyMapping &keyMapping = *it;
if ((keyMapping._key != Common::KEYCODE_INVALID && keyMapping._key == key) ||
(keyMapping._mouseButton != MOUSE_NONE && keyMapping._mouseButton == mouseButton)) {
if (down && !keyMapping._down) {
newKeys |= _bitMask;
keyMapping._down = true;
} else if (!down)
keyMapping._down = false;
}
}
return newKeys;
}
// Input
const uint kAllButtons = 0xFFFF;
static const char kCheatCode[] = "gosanta";
Input::Input() {
_buttonStates = 0;
_newButtons = 0;
_buttonsDown = 0;
_newKeys = 0;
_enabledButtons = kAllButtons;
_cursorPos.x = 0;
_cursorPos.y = 0;
_prevCursorPos.x = 0;
_prevCursorPos.y = 0;
_cursorMovedByKeyboard = false;
_cheatCodeIndex = 0;
}
void Input::processEvent(Common::Event event) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
handleKey(event.kbd.keycode, MOUSE_NONE, true);
break;
case Common::EVENT_KEYUP:
handleKey(event.kbd.keycode, MOUSE_NONE, false);
break;
case Common::EVENT_MOUSEMOVE:
_cursorMovedByKeyboard = false;
_cursorPos.x = event.mouse.x;
_cursorPos.y = event.mouse.y;
break;
case Common::EVENT_LBUTTONDOWN:
handleMouseButton(MOUSE_LEFT_BUTTON, true);
break;
case Common::EVENT_LBUTTONUP:
handleMouseButton(MOUSE_LEFT_BUTTON, false);
break;
case Common::EVENT_RBUTTONDOWN:
handleMouseButton(MOUSE_RIGHT_BUTTON, true);
break;
case Common::EVENT_RBUTTONUP:
handleMouseButton(MOUSE_RIGHT_BUTTON, false);
break;
default:
break;
}
}
bool Input::pollEvent(uint evt) {
return pollButton(_inputEvents[evt].getBitMask());
}
bool Input::hasNewEvents() {
return lookNewButtons(kAllButtons);
}
void Input::discardEvent(uint evt) {
discardButtons(_inputEvents[evt].getBitMask());
}
void Input::discardAllEvents() {
discardButtons(kAllButtons);
}
void Input::activateButton(uint bitMask) {
_enabledButtons |= bitMask;
_buttonStates &= ~bitMask;
}
void Input::deactivateButton(uint bitMask) {
_enabledButtons &= ~bitMask;
}
Common::Point Input::getCursorPosition() {
return _cursorPos;
}
void Input::setCursorPosition(Common::Point mousePos) {
_prevCursorPos = _cursorPos = mousePos;
}
Common::Point Input::getCursorDelta() {
Common::Point deltaPos;
deltaPos.x = _prevCursorPos.x - _cursorPos.x;
deltaPos.y = _prevCursorPos.y - _cursorPos.y;
_prevCursorPos = _cursorPos;
return deltaPos;
}
InputEvent& Input::setInputEvent(uint evt, uint bitMask) {
InputEvent& inputEvent = _inputEvents[evt];
return inputEvent.setBitMask(bitMask);
}
void Input::handleKey(Common::KeyCode key, int mouseButton, bool down) {
switch (key) {
case Common::KEYCODE_UP:
moveCursorByKeyboard(0, -4);
break;
case Common::KEYCODE_DOWN:
moveCursorByKeyboard(0, 4);
break;
case Common::KEYCODE_RIGHT:
moveCursorByKeyboard(4, 0);
break;
case Common::KEYCODE_LEFT:
moveCursorByKeyboard(-4, 0);
break;
default:
break;
}
for (uint i = 0; i < kEventMax; ++i) {
_newKeys |= _inputEvents[i].handle(key, mouseButton, down);
}
uint prevButtonStates = _buttonStates;
_buttonStates |= _newKeys;
_newKeys = 0;
_newButtons = ~prevButtonStates & _buttonStates;
if ( !down && !isCheatModeActive()) {
if ( _cheatCodeIndex < 7 && key == kCheatCode[_cheatCodeIndex]) {
_cheatCodeIndex++;
} else {
_cheatCodeIndex = 0;
}
}
}
void Input::handleMouseButton(int mouseButton, bool down) {
if (down)
_buttonsDown |= mouseButton;
else
_buttonsDown &= ~mouseButton;
handleKey(Common::KEYCODE_INVALID, mouseButton, down);
}
bool Input::pollButton(uint bitMask) {
if (lookButtonStates(bitMask)) {
_buttonStates &= ~bitMask;
return true;
}
return false;
}
bool Input::lookButtonStates(uint bitMask) {
return (bitMask & (_buttonStates & _enabledButtons)) != 0;
}
bool Input::lookNewButtons(uint bitMask) {
return (bitMask & (_newButtons & _enabledButtons)) != 0;
}
void Input::setButtonState(uint bitMask) {
_buttonStates |= _enabledButtons & bitMask;
}
void Input::discardButtons(uint bitMask) {
_buttonStates &= ~bitMask;
}
void Input::moveCursorByKeyboard(int deltaX, int deltaY) {
_cursorMovedByKeyboard = true;
_cursorPos.x = CLIP(_cursorPos.x + deltaX, 0, g_system->getWidth() - 1);
_cursorPos.y = CLIP(_cursorPos.y + deltaY, 0, g_system->getHeight() - 1);
}
bool Input::isCheatModeActive() {
return _cheatCodeIndex == 7;
}
} // End of namespace Illusions