scummvm/engines/m4/platform/events.cpp

251 lines
5.7 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 "common/system.h"
#include "m4/platform/events.h"
#include "m4/vars.h"
#include "m4/m4.h"
#include "m4/platform/timer.h"
namespace M4 {
/*
* Define call mask bit fields
*/
enum {
CursorPositionChanged = 0,
LeftButtonPressed, LeftButtonReleased, RightButtonPressed,
RightButtonReleased
};
/*
* Define call mask values
*/
#define CPC ((uint16)(1 << CursorPositionChanged))
#define LBD ((uint16)(1 << LeftButtonPressed))
#define LBU ((uint16)(1 << LeftButtonReleased))
#define LBH ((uint16)(1 << LeftButtonHold))
#define RBD ((uint16)(1 << RightButtonPressed))
#define RBU ((uint16)(1 << RightButtonReleased))
#define RBH ((uint16)(1 << RightButtonHold))
#define LBC (LBD + LBU)
#define RBC (RBD + RBU)
#define MBC (MBD + MBU)
#define MSA (LBC + RBC + CPC)
#define OEMA (LBC + RBC + MBC + CPC)
#define _MLD (_mouseStateEvent & LBD)
#define _ClearMLD _mouseStateEvent &= ~LBD
#define _MLU (_mouseStateEvent & LBU)
#define _ClearMLU _mouseStateEvent &= ~LBU
#define _MRD (_mouseStateEvent & RBD)
#define _ClearMRD _mouseStateEvent &= ~RBD
#define _MRU (_mouseStateEvent & RBU)
#define _ClearMRU _mouseStateEvent &= ~RBU
#define _MMOVE ((_mouseX != _oldX) || (_mouseY != _oldY))
#define _MSAVE _oldX = _mouseX; _oldY = _mouseY
Events *g_events;
Events::Events() {
g_events = this;
}
Events::~Events() {
g_events = nullptr;
}
void Events::process() {
pollEvents();
}
void Events::pollEvents() {
Common::Event ev;
while (g_system->getEventManager()->pollEvent(ev)) {
if (ev.type == Common::EVENT_QUIT || ev.type == Common::EVENT_RETURN_TO_LAUNCHER) {
_G(kernel).going = false;
} else if (ev.type >= Common::EVENT_MOUSEMOVE && ev.type <= Common::EVENT_MBUTTONUP) {
handleMouseEvent(ev);
} else if (ev.type == Common::EVENT_KEYDOWN || ev.type == Common::EVENT_KEYUP) {
handleKeyboardEvent(ev);
}
}
}
void Events::handleMouseEvent(const Common::Event &ev) {
_mouseX = ev.mouse.x;
_mouseY = ev.mouse.y;
switch (ev.type) {
case Common::EVENT_MOUSEMOVE:
_mouseStateEvent |= CPC;
break;
case Common::EVENT_LBUTTONDOWN:
_mouseStateEvent |= LBD;
ButtonState = 1;
break;
case Common::EVENT_LBUTTONUP:
_mouseStateEvent |= LBU;
ButtonState = 0;
break;
case Common::EVENT_RBUTTONDOWN:
_mouseStateEvent |= RBD;
ButtonState = 2;
break;
case Common::EVENT_RBUTTONUP:
_mouseStateEvent |= RBU;
ButtonState = 0;
break;
case Common::EVENT_WHEELDOWN:
_G(toggle_cursor) = CURSCHANGE_NEXT;
break;
case Common::EVENT_WHEELUP:
_G(toggle_cursor) = CURSCHANGE_PREVIOUS;
break;
case Common::EVENT_MBUTTONDOWN:
_G(toggle_cursor) = CURSCHANGE_TOGGLE;
break;
default:
break;
}
}
void Events::handleKeyboardEvent(const Common::Event &ev) {
if (ev.type == Common::EVENT_KEYDOWN && _pendingKeys.size() < 16)
_pendingKeys.push(ev.kbd);
}
MouseEvent Events::mouse_get_event() {
process();
switch (_mouse_state) {
case _MS_no_event:
if (_MLD) {
_ClearMLD;
if (_dclickTime && (timer_read_60() < _dclickTime)) {
_mouse_state = _MS_doubleclick_Down;
_dclickTime = 0;
return _ME_doubleclick;
}
_dclickTime = 0;
_mouse_state = _MS_L_clickDown;
return _ME_L_click;
}
if (_MRD) {
_ClearMRD;
_mouse_state = _MS_R_clickDown;
return _ME_R_click;
}
if (_MMOVE) {
_MSAVE;
return _ME_move;
}
return _ME_no_event;
case _MS_L_clickDown:
if (_MLU || !ButtonState) {
_dclickTime = timer_read_60() + 15;
_ClearMLU;
_mouse_state = _MS_no_event;
return _ME_L_release;
}
if (_MMOVE) {
_MSAVE;
return _ME_L_drag;
}
return _ME_L_hold;
case _MS_R_clickDown:
if (_MRU) {
_ClearMRU;
_mouse_state = _MS_no_event;
_G(toggle_cursor) = CURSCHANGE_NEXT;
return _ME_R_release;
}
if (_MMOVE) {
_MSAVE;
return _ME_R_drag;
}
return _ME_R_hold;
case _MS_doubleclick_Down:
if (_MLU) {
_ClearMLU; _ClearMLD;
_mouse_state = _MS_no_event;
return _ME_doubleclick_release;
}
if (_MMOVE) {
_MSAVE;
return _ME_doubleclick_drag;
}
return _ME_doubleclick_hold;
default:
return _ME_no_event;
}
return _ME_no_event;
}
bool Events::util_kbd_check(int32 *parm1) {
process();
if (!parm1 || _pendingKeys.empty())
return false;
Common::KeyState ks = _pendingKeys.pop();
if (is_mod_key(ks))
return false;
int flags = ks.flags & (Common::KBD_CTRL | Common::KBD_ALT);
int key = (ks.ascii >= 32 && ks.ascii <= 127 && !flags) ? ks.ascii : (int)ks.keycode;
*parm1 = key | (flags << 16);
return true;
}
void Events::delay(uint amount) {
uint32 beginTime = g_system->getMillis(), newTime;
do {
krn_pal_game_task();
g_system->delayMillis(5);
process();
newTime = g_system->getMillis();
} while (!g_engine->shouldQuit() && newTime < (beginTime + amount));
}
MouseEvent mouse_get_event() {
return g_events->mouse_get_event();
}
bool util_kbd_check(int32 *parm1) {
return g_events->util_kbd_check(parm1);
}
} // namespace M4