mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-28 12:46:56 +00:00
7ca439f410
svn-id: r31600
352 lines
9.2 KiB
C++
352 lines
9.2 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 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.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
// TODO: There is a 'please_hyperwalk' variable that gets accessed that is meant to be global, but
|
|
// at the moment it's implemented as a local variable
|
|
|
|
#include "graphics/cursorman.h"
|
|
|
|
#include "m4/events.h"
|
|
#include "m4/graphics.h"
|
|
#include "m4/scene.h"
|
|
#include "m4/viewmgr.h"
|
|
#include "m4/m4.h"
|
|
|
|
namespace M4 {
|
|
|
|
bool please_hyperwalk = false;
|
|
|
|
/*--------------------------------------------------------------------------*
|
|
* Events *
|
|
* *
|
|
* Implements an interface to the event system *
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
Events::Events(M4Engine *vm) : _vm(vm) {
|
|
_mouseState = MSTATE_NO_EVENT;
|
|
quitFlag = false;
|
|
_keyCode = 0;
|
|
_console = new Console(_vm);
|
|
_mouseButtons = 0;
|
|
}
|
|
|
|
M4EventType Events::handleEvents() {
|
|
static int oldX = -1, oldY = -1;
|
|
static uint32 dclickTime = 0;
|
|
|
|
// Handle event types
|
|
while (g_system->getEventManager()->pollEvent(_event)) {
|
|
switch (_event.type) {
|
|
case Common::EVENT_QUIT:
|
|
quitFlag = true;
|
|
break;
|
|
case Common::EVENT_KEYDOWN:
|
|
if (_event.kbd.flags == Common::KBD_CTRL) {
|
|
if (_event.kbd.keycode == Common::KEYCODE_d)
|
|
_console->attach();
|
|
_console->onFrame();
|
|
}
|
|
_keyCode = (int)_event.kbd.keycode;
|
|
|
|
break;
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
case Common::EVENT_LBUTTONUP:
|
|
case Common::EVENT_RBUTTONDOWN:
|
|
case Common::EVENT_RBUTTONUP:
|
|
case Common::EVENT_MBUTTONDOWN:
|
|
case Common::EVENT_MBUTTONUP:
|
|
case Common::EVENT_MOUSEMOVE:
|
|
case Common::EVENT_WHEELUP:
|
|
case Common::EVENT_WHEELDOWN:
|
|
_vm->_mouse->handleEvent(_event);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
_mouseButtons = g_system->getEventManager()->getButtonState();
|
|
|
|
// State machine for moving between states
|
|
switch (_mouseState) {
|
|
case MSTATE_NO_EVENT:
|
|
if (_mouseButtons & LEFT_BUTTON_DOWN) {
|
|
if ((dclickTime != 0) && (g_system->getMillis() < dclickTime)) {
|
|
_mouseState = MSTATE_DOUBLECLICK_DOWN;
|
|
dclickTime = 0;
|
|
return MEVENT_DOUBLECLICK;
|
|
}
|
|
dclickTime = 0;
|
|
_mouseState = MSTATE_LEFT_CLICK_DOWN;
|
|
return MEVENT_LEFT_CLICK;
|
|
}
|
|
if (_mouseButtons & RIGHT_BUTTON_DOWN) {
|
|
_mouseState = MSTATE_RIGHT_CLICK_DOWN;
|
|
return MEVENT_RIGHT_CLICK;
|
|
}
|
|
if ((_event.mouse.x != oldX) || (_event.mouse.y != oldY)) {
|
|
oldX = _event.mouse.x; oldY = _event.mouse.y;
|
|
return MEVENT_MOVE;
|
|
}
|
|
return MEVENT_NO_EVENT;
|
|
|
|
case MSTATE_LEFT_CLICK_DOWN:
|
|
if (!(_mouseButtons & LEFT_BUTTON_DOWN)) {
|
|
dclickTime = g_system->getMillis() + 1000 * 15 / 60;
|
|
_mouseState = MSTATE_NO_EVENT;
|
|
return MEVENT_LEFT_RELEASE;
|
|
}
|
|
if ((_event.mouse.x != oldX) || (_event.mouse.y != oldY)) {
|
|
oldX = _event.mouse.x; oldY = _event.mouse.y;
|
|
return MEVENT_LEFT_DRAG;
|
|
}
|
|
return MEVENT_LEFT_HOLD;
|
|
|
|
case MSTATE_RIGHT_CLICK_DOWN:
|
|
if (!(_mouseButtons & RIGHT_BUTTON_DOWN)) {
|
|
_mouseState = MSTATE_NO_EVENT;
|
|
please_hyperwalk = true;
|
|
return MEVENT_RIGHT_RELEASE;
|
|
}
|
|
if ((_event.mouse.x != oldX) || (_event.mouse.y != oldY)) {
|
|
oldX = _event.mouse.x; oldY = _event.mouse.y;
|
|
return MEVENT_RIGHT_DRAG;
|
|
}
|
|
return MEVENT_RIGHT_HOLD;
|
|
|
|
case MSTATE_DOUBLECLICK_DOWN:
|
|
if (!(_mouseButtons & LEFT_BUTTON_DOWN)) {
|
|
_mouseState = MSTATE_NO_EVENT;
|
|
return MEVENT_DOUBLECLICK_RELEASE;
|
|
}
|
|
if ((_event.mouse.x != oldX) || (_event.mouse.y != oldY)) {
|
|
oldX = _event.mouse.x; oldY = _event.mouse.y;
|
|
return MEVENT_DOUBLECLICK_DRAG;
|
|
}
|
|
return MEVENT_DOUBLECLICK_HOLD;
|
|
|
|
default:
|
|
return MEVENT_NO_EVENT;
|
|
}
|
|
}
|
|
|
|
bool Events::kbdCheck(uint32 &keyCode) {
|
|
if (_keyCode == 0)
|
|
return false;
|
|
|
|
keyCode = _keyCode;
|
|
_keyCode = 0;
|
|
return true;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*
|
|
* Mouse *
|
|
* *
|
|
* Implements an interface to the mouse *
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
Mouse::Mouse(M4Engine *vm) : _vm(vm) {
|
|
_locked = false;
|
|
_cursorOn = false;
|
|
_cursor = NULL;
|
|
_cursorSprites = NULL;
|
|
resetMouse();
|
|
}
|
|
|
|
Mouse::~Mouse() {
|
|
if (_cursorSprites)
|
|
delete _cursorSprites;
|
|
}
|
|
|
|
bool Mouse::init(const char *seriesName, RGB8 *palette) {
|
|
Common::SeekableReadStream *stream = _vm->res()->get(seriesName);
|
|
int colorCount = 0;
|
|
RGB8* cursorPalette;
|
|
|
|
_cursorSprites = new SpriteAsset(_vm, stream, stream->size(), seriesName);
|
|
|
|
// Remove cursor special pixels and set the mouse cursor hotspot in MADS games
|
|
if (!_vm->isM4()) {
|
|
byte *data = NULL;
|
|
for (int i = 0; i < _cursorSprites->getCount(); i++) {
|
|
bool hotSpotSet = false;
|
|
|
|
for (int x = 0; x < _cursorSprites->getFrame(i)->width(); x++) {
|
|
for (int y = 0; y < _cursorSprites->getFrame(i)->height(); y++) {
|
|
data = _cursorSprites->getFrame(i)->getBasePtr(x, y);
|
|
if (*data == 1) {
|
|
// It seems that some cursors have more than one hotspot
|
|
// In such a case, the first hotspot seems to set the x and
|
|
// the second one the y hotspot offset
|
|
if (!hotSpotSet) {
|
|
_cursorSprites->getFrame(i)->xOffset = x;
|
|
_cursorSprites->getFrame(i)->yOffset = y;
|
|
hotSpotSet = true;
|
|
} else {
|
|
_cursorSprites->getFrame(i)->yOffset = y;
|
|
}
|
|
*data = 0;
|
|
}
|
|
} // for y
|
|
} // for x
|
|
} // for i
|
|
}
|
|
|
|
colorCount = _cursorSprites->getColorCount();
|
|
cursorPalette = _cursorSprites->getPalette();
|
|
_vm->_palette->setPalette(cursorPalette, 0, colorCount);
|
|
|
|
//printf("Cursor count: %d\n", _cursorSprites->getCount());
|
|
|
|
_vm->res()->toss(seriesName);
|
|
|
|
_currentCursor = -1;
|
|
return true;
|
|
}
|
|
|
|
bool Mouse::setCursorNum(int cursorIndex) {
|
|
if ((cursorIndex < 0) || (cursorIndex >= (int)_cursorSprites->getCount()))
|
|
return false;
|
|
|
|
_lockedCursor = cursorIndex;
|
|
if (_locked)
|
|
// Cursor is locked, so don't go ahead with changing cursor
|
|
return true;
|
|
|
|
_currentCursor = _lockedCursor;
|
|
_cursor = _cursorSprites->getFrame(cursorIndex);
|
|
|
|
// Set the cursor to the sprite
|
|
CursorMan.replaceCursor((const byte *)_cursor->getData(), _cursor->w, _cursor->h, _cursor->xOffset, _cursor->yOffset, 0);
|
|
|
|
return true;
|
|
}
|
|
|
|
int Mouse::cursorCount() {
|
|
return _cursorSprites->getCount();
|
|
}
|
|
|
|
void Mouse::cursorOn() {
|
|
_cursorOn = true;
|
|
CursorMan.showMouse(!inHideArea());
|
|
}
|
|
|
|
void Mouse::cursorOff() {
|
|
_cursorOn = false;
|
|
CursorMan.showMouse(false);
|
|
}
|
|
|
|
void Mouse::lockCursor(int cursorIndex) {
|
|
_locked = false;
|
|
setCursorNum(cursorIndex);
|
|
_locked = true;
|
|
}
|
|
|
|
void Mouse::unlockCursor() {
|
|
_locked = false;
|
|
setCursorNum(_lockedCursor);
|
|
}
|
|
|
|
const char *Mouse::getVerb() {
|
|
switch (_vm->_mouse->getCursorNum()) {
|
|
case CURSOR_LOOK:
|
|
return "LOOK AT";
|
|
case CURSOR_TAKE:
|
|
return "TAKE";
|
|
case CURSOR_USE:
|
|
return "GEAR";
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void Mouse::resetMouse() {
|
|
_hideRect.left = -1;
|
|
_hideRect.top = -1;
|
|
_hideRect.right = -1;
|
|
_hideRect.bottom = -1;
|
|
_showRect.left = -1;
|
|
_showRect.top = -1;
|
|
_showRect.right = -1;
|
|
_showRect.bottom = -1;
|
|
}
|
|
|
|
void Mouse::setHideRect(Common::Rect &r) {
|
|
_hideRect = r;
|
|
}
|
|
|
|
void Mouse::setShowRect(Common::Rect &r) {
|
|
_showRect = r;
|
|
}
|
|
|
|
const Common::Rect *Mouse::getHideRect() {
|
|
return &_hideRect;
|
|
}
|
|
|
|
const Common::Rect *Mouse::getShowRect() {
|
|
if ((_showRect.top == -1) || (_showRect.left == -1)) {
|
|
// Show rectangle uninitialised - set it to current screen dimensions
|
|
_showRect.top = 0;
|
|
_showRect.left = 0;
|
|
_showRect.right = _vm->_screen->width() - 1;
|
|
_showRect.bottom = _vm->_screen->height() -1;
|
|
}
|
|
|
|
return &_showRect;
|
|
}
|
|
|
|
void Mouse::handleEvent(Common::Event &event) {
|
|
_currentPos.x = event.mouse.x;
|
|
_currentPos.y = event.mouse.y;
|
|
|
|
// If mouse is turned on, check to see if the position is in the hide rect, or outside the show rect.
|
|
// If so, handle toggling the visibility of the mouse
|
|
bool showFlag = !inHideArea();
|
|
if (_cursorOn && (CursorMan.isVisible() != showFlag)) {
|
|
CursorMan.showMouse(showFlag);
|
|
}
|
|
}
|
|
|
|
bool Mouse::inHideArea() {
|
|
// Returns true if the mouse is inside a specified hide rect, or if a show rect is specified and
|
|
// the mouse is currently outside it
|
|
if ((_currentPos.x >= _hideRect.left) && (_currentPos.x <= _hideRect.right) &&
|
|
(_currentPos.y >= _hideRect.top) && (_currentPos.y <= _hideRect.bottom))
|
|
// Inside a hide area
|
|
return true;
|
|
|
|
|
|
if ((_showRect.top == -1) && (_showRect.left == -1))
|
|
// No show rect defined
|
|
return false;
|
|
|
|
// Return true if the mouse is outside the show area
|
|
return (_currentPos.x < _showRect.left) || (_currentPos.x > _showRect.right) ||
|
|
(_currentPos.y < _showRect.top) || (_currentPos.y > _showRect.bottom);
|
|
}
|
|
|
|
} // End of namespace M4
|