aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock/events.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sherlock/events.cpp')
-rw-r--r--engines/sherlock/events.cpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
new file mode 100644
index 0000000000..a8912f6f1e
--- /dev/null
+++ b/engines/sherlock/events.cpp
@@ -0,0 +1,318 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/events.h"
+#include "common/system.h"
+#include "engines/util.h"
+#include "graphics/cursorman.h"
+#include "sherlock/sherlock.h"
+#include "sherlock/events.h"
+
+namespace Sherlock {
+
+enum ButtonFlag { LEFT_BUTTON = 1, RIGHT_BUTTON = 2 };
+
+Events::Events(SherlockEngine *vm): _vm(vm) {
+ _cursorImages = nullptr;
+ _cursorId = INVALID_CURSOR;
+ _frameCounter = 1;
+ _priorFrameTime = 0;
+ _mouseButtons = 0;
+ _pressed = _released = false;
+ _rightPressed = _rightReleased = false;
+ _oldButtons = _oldRightButton = false;
+ _firstPress = false;
+
+ if (_vm->_interactiveFl)
+ loadCursors("rmouse.vgs");
+}
+
+Events::~Events() {
+ delete _cursorImages;
+}
+
+void Events::loadCursors(const Common::String &filename) {
+ hideCursor();
+ delete _cursorImages;
+
+ if (!IS_3DO) {
+ // PC
+ _cursorImages = new ImageFile(filename);
+ } else {
+ // 3DO
+ _cursorImages = new ImageFile3DO(filename, kImageFile3DOType_RoomFormat);
+ }
+ _cursorId = INVALID_CURSOR;
+}
+
+void Events::setCursor(CursorId cursorId) {
+ if (cursorId == _cursorId)
+ return;
+
+ int hotspotX, hotspotY;
+
+ if (cursorId == MAGNIFY) {
+ hotspotX = 8;
+ hotspotY = 8;
+ } else {
+ hotspotX = 0;
+ hotspotY = 0;
+ }
+
+ // Set the cursor data
+ Graphics::Surface &s = (*_cursorImages)[cursorId]._frame;
+
+ setCursor(s, hotspotX, hotspotY);
+
+ _cursorId = cursorId;
+}
+
+void Events::setCursor(const Graphics::Surface &src, int hotspotX, int hotspotY) {
+ _cursorId = INVALID_CURSOR;
+ _hotspotPos = Common::Point(hotspotX, hotspotY);
+
+ if (!IS_3DO) {
+ // PC 8-bit palettized
+ CursorMan.replaceCursor(src.getPixels(), src.w, src.h, hotspotX, hotspotY, 0xff);
+ } else {
+ // 3DO RGB565
+ CursorMan.replaceCursor(src.getPixels(), src.w, src.h, hotspotX, hotspotY, 0x0000, false, &src.format);
+ }
+ showCursor();
+}
+
+void Events::setCursor(CursorId cursorId, const Graphics::Surface &surface) {
+ _cursorId = cursorId;
+
+ int hotspotX, hotspotY;
+ if (cursorId == MAGNIFY) {
+ hotspotX = 8;
+ hotspotY = 8;
+ } else {
+ hotspotX = 0;
+ hotspotY = 0;
+ }
+
+ // Get the standard cursor frame
+ Graphics::Surface &surface2 = (*_cursorImages)[cursorId]._frame;
+
+ // Form a single surface containing both frames
+ int maxWidth = MAX(surface.w, surface2.w);
+ Graphics::Surface s;
+ s.create(maxWidth, surface.h + surface2.h, Graphics::PixelFormat::createFormatCLUT8());
+ s.fillRect(Common::Rect(0, 0, maxWidth, surface.h + surface2.h), TRANSPARENCY);
+
+ s.copyRectToSurface(surface, (maxWidth - surface.w) / 2, 0, Common::Rect(0, 0, surface.w, surface.h));
+ s.copyRectToSurface(surface2, (maxWidth - surface2.w) / 2, surface.h, Common::Rect(0, 0, surface2.w, surface2.h));
+
+ // Adjust hotspot position
+ hotspotX += (maxWidth - surface2.w) / 2;
+ hotspotY += surface.h;
+
+ // Set the cursor
+ setCursor(s, hotspotX, hotspotY);
+}
+
+void Events::animateCursorIfNeeded() {
+ if (_cursorId >= WAIT && _cursorId < (WAIT + 3)) {
+ CursorId newId = (_cursorId == WAIT + 2) ? WAIT : (CursorId)((int)_cursorId + 1);
+ setCursor(newId);
+ }
+}
+
+
+void Events::showCursor() {
+ CursorMan.showMouse(true);
+}
+
+void Events::hideCursor() {
+ CursorMan.showMouse(false);
+}
+
+CursorId Events::getCursor() const {
+ return _cursorId;
+}
+
+bool Events::isCursorVisible() const {
+ return CursorMan.isVisible();
+}
+
+void Events::moveMouse(const Common::Point &pt) {
+ g_system->warpMouse(pt.x, pt.y);
+}
+
+void Events::pollEvents() {
+ checkForNextFrameCounter();
+
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ // Handle keypress
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RTL:
+ return;
+
+ case Common::EVENT_KEYDOWN:
+ // Check for debugger
+ if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) {
+ // Attach to the debugger
+ _vm->_debugger->attach();
+ _vm->_debugger->onFrame();
+ } else {
+ _pendingKeys.push(event.kbd);
+ }
+ return;
+ case Common::EVENT_KEYUP:
+ return;
+ case Common::EVENT_LBUTTONDOWN:
+ _mouseButtons |= LEFT_BUTTON;
+ return;
+ case Common::EVENT_RBUTTONDOWN:
+ _mouseButtons |= RIGHT_BUTTON;
+ return;
+ case Common::EVENT_LBUTTONUP:
+ _mouseButtons &= ~LEFT_BUTTON;
+ return;
+ case Common::EVENT_RBUTTONUP:
+ _mouseButtons &= ~RIGHT_BUTTON;
+ return;
+ default:
+ break;
+ }
+ }
+}
+
+void Events::pollEventsAndWait() {
+ pollEvents();
+ g_system->delayMillis(10);
+}
+
+void Events::warpMouse(const Common::Point &pt) {
+ g_system->warpMouse(pt.x, pt.y);
+}
+
+bool Events::checkForNextFrameCounter() {
+ // Check for next game frame
+ uint32 milli = g_system->getMillis();
+ if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) {
+ ++_frameCounter;
+ _priorFrameTime = milli;
+
+ // Give time to the debugger
+ _vm->_debugger->onFrame();
+
+ // Display the frame
+ _vm->_screen->update();
+
+ return true;
+ }
+
+ return false;
+}
+
+Common::Point Events::screenMousePos() const {
+ return g_system->getEventManager()->getMousePos();
+}
+
+Common::Point Events::mousePos() const {
+ return screenMousePos() + _vm->_screen->_currentScroll;
+}
+
+Common::KeyState Events::getKey() {
+ return _pendingKeys.pop();
+}
+
+void Events::clearEvents() {
+ _pendingKeys.clear();
+ _mouseButtons = 0;
+ _pressed = _released = false;
+ _rightPressed = _rightReleased = false;
+ _oldButtons = _oldRightButton = false;
+ _firstPress = false;
+}
+
+void Events::clearKeyboard() {
+ _pendingKeys.clear();
+}
+
+void Events::wait(int numFrames) {
+ uint32 totalMilli = numFrames * 1000 / GAME_FRAME_RATE;
+ delay(totalMilli);
+}
+
+bool Events::delay(uint32 time, bool interruptable) {
+ // Different handling for really short versus extended times
+ if (time < 10) {
+ // For really short periods, simply delay by the desired amount
+ pollEvents();
+ g_system->delayMillis(time);
+ bool result = !(interruptable && (kbHit() || _pressed || _vm->shouldQuit()));
+
+ clearEvents();
+ return result;
+ } else {
+ // For long periods go into a loop where we delay by 10ms at a time and then
+ // check for events. This ensures for longer delays that responsiveness is
+ // maintained
+ uint32 delayEnd = g_system->getMillis() + time;
+
+ while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) {
+ pollEventsAndWait();
+
+ if (interruptable && (kbHit() || _pressed)) {
+ clearEvents();
+ return false;
+ }
+ }
+
+ return !_vm->shouldQuit();
+ }
+}
+
+void Events::setButtonState() {
+ _firstPress = ((_mouseButtons & 1) && !_pressed) || ((_mouseButtons & 2) && !_rightPressed);
+
+ _released = _rightReleased = false;
+ if (_mouseButtons & LEFT_BUTTON)
+ _pressed = _oldButtons = true;
+
+ if ((_mouseButtons & LEFT_BUTTON) == 0 && _oldButtons) {
+ _pressed = _oldButtons = false;
+ _released = true;
+ }
+
+ if (_mouseButtons & RIGHT_BUTTON)
+ _rightPressed = _oldRightButton = true;
+
+ if ((_mouseButtons & RIGHT_BUTTON) == 0 && _oldRightButton) {
+ _rightPressed = _oldRightButton = false;
+ _rightReleased = true;
+ }
+}
+
+bool Events::checkInput() {
+ setButtonState();
+ return kbHit() || _pressed || _released || _rightPressed || _rightReleased;
+}
+
+} // End of namespace Sherlock