Files
2026-02-02 04:50:13 +01:00

256 lines
6.3 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/scummsys.h"
#include "graphics/cursorman.h"
#include "common/events.h"
#include "common/endian.h"
#include "common/system.h"
#include "engines/util.h"
#include "ultima/shared/engine/events.h"
namespace Ultima {
namespace Shared {
EventsManager::EventsManager(EventsCallback *callback) : _callback(callback), _playTime(0),
_gameCounter(0), _frameCounter(0), _priorFrameCounterTime(0), _buttonsDown(0),
_specialButtons(0), _priorFrameTime(0) {
}
void EventsManager::showCursor() {
CursorMan.showMouse(true);
}
void EventsManager::hideCursor() {
CursorMan.showMouse(false);
}
bool EventsManager::isCursorVisible() {
return CursorMan.isVisible();
}
bool EventsManager::pollEvent(Common::Event &event) {
uint32 timer = g_system->getMillis();
if (timer >= (_priorFrameCounterTime + GAME_FRAME_TIME)) {
// Time to build up next game frame
_priorFrameCounterTime = timer;
nextFrame();
}
// Event handling
if (g_system->getEventManager()->pollEvent(event)) {
if (isMouseDownEvent(event.type)) {
setButtonDown(whichButton(event.type), true);
_mousePos = event.mouse;
} else if (isMouseUpEvent(event.type)) {
setButtonDown(whichButton(event.type), false);
_mousePos = event.mouse;
} else if (event.type == Common::EVENT_MOUSEMOVE) {
_mousePos = event.mouse;
}
switch (event.type) {
case Common::EVENT_KEYDOWN: {
handleKbdSpecial(event.kbd);
break;
}
case Common::EVENT_KEYUP:
handleKbdSpecial(event.kbd);
break;
case Common::EVENT_MOUSEMOVE:
_mousePos = event.mouse;
break;
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
break;
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
break;
default:
break;
}
return true;
}
return false;
}
void EventsManager::pollEvents() {
Common::Event event;
while (pollEvent(event)) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
eventTarget()->mouseMove(_mousePos);
break;
case Common::EVENT_LBUTTONDOWN:
eventTarget()->leftButtonDown(_mousePos);
break;
case Common::EVENT_LBUTTONUP:
eventTarget()->leftButtonUp(_mousePos);
break;
case Common::EVENT_MBUTTONDOWN:
eventTarget()->middleButtonDown(_mousePos);
break;
case Common::EVENT_MBUTTONUP:
eventTarget()->middleButtonUp(_mousePos);
break;
case Common::EVENT_RBUTTONDOWN:
eventTarget()->rightButtonDown(_mousePos);
break;
case Common::EVENT_RBUTTONUP:
eventTarget()->rightButtonUp(_mousePos);
break;
case Common::EVENT_WHEELUP:
case Common::EVENT_WHEELDOWN:
eventTarget()->mouseWheel(_mousePos, event.type == Common::EVENT_WHEELUP);
break;
case Common::EVENT_KEYDOWN:
eventTarget()->keyDown(event.kbd);
break;
case Common::EVENT_KEYUP:
eventTarget()->keyUp(event.kbd);
break;
default:
break;
}
}
}
void EventsManager::pollEventsAndWait() {
pollEvents();
g_system->delayMillis(10);
}
void EventsManager::nextFrame() {
++_frameCounter;
++_playTime;
// Handle any idle updates
if (!_eventTargets.empty())
eventTarget()->onIdle();
// Render anything pending for the screen
Graphics::Screen *screen = _callback->getScreen();
if (screen)
screen->update();
}
void EventsManager::setButtonDown(MouseButton button, bool isDown) {
assert(button != BUTTON_NONE);
byte mask = 0;
switch (button) {
case BUTTON_LEFT:
mask = MK_LBUTTON;
break;
case BUTTON_RIGHT:
mask = MK_RBUTTON;
break;
case BUTTON_MIDDLE:
mask = MK_MBUTTON;
break;
default:
break;
}
if (isDown) {
_buttonsDown |= BUTTON_MASK(button);
_specialButtons |= mask;
} else {
_buttonsDown &= ~BUTTON_MASK(button);
_specialButtons &= ~mask;
}
}
uint32 EventsManager::getTicksCount() const {
return _frameCounter * GAME_FRAME_TIME;
}
void EventsManager::sleep(uint time) {
uint32 delayEnd = g_system->getMillis() + time;
while (!g_engine->shouldQuit() && g_system->getMillis() < delayEnd)
pollEventsAndWait();
}
bool EventsManager::waitForPress(uint expiry) {
uint32 delayEnd = g_system->getMillis() + expiry;
CPressTarget pressTarget;
addTarget(&pressTarget);
while (!g_engine->shouldQuit() && g_system->getMillis() < delayEnd && !pressTarget._pressed) {
pollEventsAndWait();
}
removeTarget();
return pressTarget._pressed;
}
void EventsManager::setMousePos(const Point &pt) {
g_system->warpMouse(pt.x, pt.y);
_mousePos = pt;
eventTarget()->mouseMove(_mousePos);
}
void EventsManager::handleKbdSpecial(Common::KeyState keyState) {
if (keyState.flags & Common::KBD_CTRL)
_specialButtons |= MK_CONTROL;
else
_specialButtons &= ~MK_CONTROL;
if (keyState.flags & Common::KBD_SHIFT)
_specialButtons |= MK_SHIFT;
else
_specialButtons &= ~MK_SHIFT;
}
bool shouldQuit() {
return g_engine->shouldQuit();
}
bool isMouseDownEvent(Common::EventType type) {
return type == Common::EVENT_LBUTTONDOWN || type == Common::EVENT_RBUTTONDOWN
|| type == Common::EVENT_MBUTTONDOWN;
}
bool isMouseUpEvent(Common::EventType type) {
return type == Common::EVENT_LBUTTONUP || type == Common::EVENT_RBUTTONUP
|| type == Common::EVENT_MBUTTONUP;
}
MouseButton whichButton(Common::EventType type) {
if (type == Common::EVENT_LBUTTONDOWN || type == Common::EVENT_LBUTTONUP)
return BUTTON_LEFT;
else if (type == Common::EVENT_RBUTTONDOWN || type == Common::EVENT_RBUTTONUP)
return BUTTON_RIGHT;
else if (type == Common::EVENT_MBUTTONDOWN || type == Common::EVENT_MBUTTONUP)
return BUTTON_MIDDLE;
else
return BUTTON_NONE;
}
} // End of namespace Shared
} // End of namespace Ultima