From 73085bf57034adc2dbf5994ce2c6930b416eee7d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 23 Mar 2015 20:34:34 -0400 Subject: SHERLOCK: Beginnings of UserInterface class --- engines/sherlock/animation.cpp | 4 +- engines/sherlock/events.cpp | 56 ++++--- engines/sherlock/events.h | 14 +- engines/sherlock/module.mk | 3 +- engines/sherlock/objects.cpp | 44 ++++-- engines/sherlock/objects.h | 3 + engines/sherlock/resources.cpp | 2 +- engines/sherlock/scene.cpp | 78 ++++----- engines/sherlock/scene.h | 22 +-- engines/sherlock/screen.h | 4 + engines/sherlock/sherlock.cpp | 15 +- engines/sherlock/sherlock.h | 3 +- engines/sherlock/user_interface.cpp | 306 ++++++++++++++++++++++++++++++++++++ engines/sherlock/user_interface.h | 91 +++++++++++ 14 files changed, 534 insertions(+), 111 deletions(-) create mode 100644 engines/sherlock/user_interface.cpp create mode 100644 engines/sherlock/user_interface.h diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp index 9d32746de4..e1687b5238 100644 --- a/engines/sherlock/animation.cpp +++ b/engines/sherlock/animation.cpp @@ -151,14 +151,14 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f events.wait(speed); } - if (events.isKeyPressed()) { + if (events.kbHit()) { Common::KeyState keyState = events.getKey(); if (keyState.keycode == Common::KEYCODE_ESCAPE || keyState.keycode == Common::KEYCODE_SPACE) { skipped = true; break; } - } else if (events._mouseClicked) { + } else if (events._pressed) { skipped = true; break; } diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 1a09f0600e..a6b3c899cb 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -36,8 +36,10 @@ Events::Events(SherlockEngine *vm) { _cursorId = INVALID_CURSOR; _frameCounter = 1; _priorFrameTime = 0; - _mouseClicked = false; _mouseButtons = 0; + _pressed = _released = false; + _rightPressed = _rightReleased = false; + _oldButtons = _oldRightButton = false; } Events::~Events() { @@ -125,12 +127,16 @@ void Events::pollEvents() { case Common::EVENT_KEYUP: return; case Common::EVENT_LBUTTONDOWN: + _mouseButtons |= 1; + return; case Common::EVENT_RBUTTONDOWN: - _mouseClicked = true; + _mouseButtons |= 2; return; case Common::EVENT_LBUTTONUP: + _mouseButtons &= ~1; + return; case Common::EVENT_RBUTTONUP: - _mouseClicked = false; + _mouseButtons &= ~2; return; case Common::EVENT_MOUSEMOVE: _mousePos = event.mouse; @@ -180,7 +186,9 @@ bool Events::checkForNextFrameCounter() { */ void Events::clearEvents() { _pendingKeys.clear(); - _mouseClicked = false; + _pressed = _rightPressed = false; + _rightPressed = _rightReleased = false; + _oldButtons = _oldRightButton = false; } /** @@ -197,7 +205,7 @@ bool Events::delay(uint32 time, bool interruptable) { // For really short periods, simply delay by the desired amount pollEvents(); g_system->delayMillis(time); - bool result = !(interruptable && (isKeyPressed() || _mouseClicked)); + bool result = !(interruptable && (kbHit() || _pressed)); clearEvents(); return result; @@ -210,7 +218,7 @@ bool Events::delay(uint32 time, bool interruptable) { while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { pollEventsAndWait(); - if (interruptable && (isKeyPressed() || _mouseClicked)) { + if (interruptable && (kbHit() || _pressed)) { clearEvents(); return false; } @@ -221,25 +229,33 @@ bool Events::delay(uint32 time, bool interruptable) { } /** - * Wait for the next frame + * Sets the pressed and released button flags depending on the value passed */ -void Events::waitForNextFrame() { - _mouseClicked = false; - _mouseButtons = 0; - - bool mouseClicked = false; - int mouseButtons = 0; +void Events::setButtonState() { + _released = _rightReleased = false; + if (_mouseButtons & 1) + _pressed = _oldButtons = true; + + if ((_mouseButtons & 1) == 0 && _oldButtons) { + _pressed = _oldButtons = false; + _released = true; + } - uint32 frameCtr = getFrameCounter(); - while (!_vm->shouldQuit() && frameCtr == _frameCounter) { - pollEventsAndWait(); + if (_mouseButtons & 2) + _rightPressed = _oldRightButton = true; - mouseClicked |= _mouseClicked; - mouseButtons |= _mouseButtons; + if ((_mouseButtons & 2) == 0 && _oldRightButton) { + _rightPressed = _oldRightButton = false; + _rightReleased = true; } +} - _mouseClicked = mouseClicked; - _mouseButtons = mouseButtons; +/** + * Checks to see to see if a key or a mouse button is pressed. + */ +bool Events::checkInput() { + setButtonState(); + return kbHit() || _pressed || _released || _rightPressed || _rightReleased; } } // End of namespace MADS diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index e939b5768f..1c5fbc5be4 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -44,12 +44,17 @@ private: uint32 _priorFrameTime; Common::Point _mousePos; ImageFile *_cursorImages; + int _mouseButtons; bool checkForNextFrameCounter(); public: CursorId _cursorId; - byte _mouseButtons; - bool _mouseClicked; + bool _pressed; + bool _released; + bool _rightPressed; + bool _rightReleased; + bool _oldButtons; + bool _oldRightButton; Common::Stack _pendingKeys; public: Events(SherlockEngine *vm); @@ -75,7 +80,7 @@ public: uint32 getFrameCounter() const { return _frameCounter; } - bool isKeyPressed() const { return !_pendingKeys.empty(); } + bool kbHit() const { return !_pendingKeys.empty(); } Common::KeyState getKey() { return _pendingKeys.pop(); } @@ -85,8 +90,9 @@ public: bool delay(uint32 time, bool interruptable = false); - void waitForNextFrame(); + void setButtonState(); + bool checkInput(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index aa8f495742..4101769a80 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -20,7 +20,8 @@ MODULE_OBJS = \ screen.o \ sherlock.o \ sound.o \ - talk.o + talk.o \ + user_interface.o # This module can be built as a plugin ifdef BUILD_PLUGINS diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 7d86c45e15..e0a24c5b7d 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -39,10 +39,6 @@ namespace Sherlock { #define CLEAR_DIST_X 5 #define CLEAR_DIST_Y 0 -#define INFO_FOREGROUND 11 -#define INFO_BACKGROUND 1 - - SherlockEngine *Sprite::_vm; /** @@ -779,6 +775,7 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; bool printed = false; char ch; const char *p; @@ -852,19 +849,19 @@ int Object::checkNameForCodes(const Common::String &name, Common::StringArray *m } else if (name.hasPrefix("!")) { // Message attached to canimation int messageNum = atoi(name.c_str() + 1); - scene._infoFlag++; - scene.clearInfo(); + ui._infoFlag++; + ui.clearInfo(); screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, (*messages)[messageNum].c_str()); - _vm->_menuCounter = 25; + ui._menuCounter = 25; } else if (name.hasPrefix("@")) { // Message attached to canimation - scene._infoFlag++; - scene.clearInfo(); + ui._infoFlag++; + ui.clearInfo(); screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND, "%s", name.c_str() + 1); printed = true; - _vm->_menuCounter = 25; + ui._menuCounter = 25; } return printed; @@ -922,6 +919,33 @@ void Object::adjustObject() { } } +/** + * Returns the current bounds for the sprite + */ +const Common::Rect Object::getNewBounds() const { + Common::Point pt = _position; + if (_imageFrame) + pt += _imageFrame->_offset; + + return Common::Rect(pt.x, pt.y, pt.x + frameWidth(), pt.y + frameHeight()); +} + +/** + * Returns the bounds for a sprite without a shape + */ +const Common::Rect Object::getNoShapeBounds() const { + return Common::Rect(_position.x, _position.y, + _position.x + _noShapeSize.x, _position.y + _noShapeSize.y); +} + +/** + * Returns the old bounsd for the sprite from the previous frame + */ +const Common::Rect Object::getOldBounds() const { + return Common::Rect(_oldPosition.x, _oldPosition.y, + _oldPosition.x + _oldSize.x, _oldPosition.y + _oldSize.y); +} + /*----------------------------------------------------------------*/ void CAnim::synchronize(Common::SeekableReadStream &s) { diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index 8099c6b74f..4944681ab3 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -212,6 +212,9 @@ public: int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; } int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; } + const Common::Rect getNewBounds() const; + const Common::Rect getNoShapeBounds() const; + const Common::Rect getOldBounds() const; }; struct CAnim { diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index e499b698c1..878747a63c 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -354,7 +354,7 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) { if (frame._paletteBase) { // Nibble-packed byte *pDest = (byte *)frame._frame.getPixels(); - for (int idx = 0; idx < frame._size; ++idx, ++src) { + for (uint idx = 0; idx < frame._size; ++idx, ++src) { *pDest++ = *src & 0xF; *pDest++ = (*src >> 4); } diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 9f549b4312..6e09693807 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -27,37 +27,6 @@ namespace Sherlock { -// Main Menu control locations -const int MENU_POINTS[12][4] = { - { 13, 153, 72, 165 }, - { 13, 169, 72, 181 }, - { 13, 185, 72, 197 }, - { 88, 153, 152, 165 }, - { 88, 169, 152, 181 }, - { 88, 185, 152, 197 }, - { 165, 153, 232, 165 }, - { 165, 169, 232, 181 }, - { 165, 185, 233, 197 }, - { 249, 153, 305, 165 }, - { 249, 169, 305, 181 }, - { 249, 185, 305, 197 } -}; - -// Inventory control locations */ -const int INVENTORY_POINTS[8][3] = { - { 4, 50, 28 }, - { 52, 99, 76 }, - { 101, 140, 122 }, - { 142, 187, 165 }, - { 189, 219, 197 }, - { 221, 251, 233 }, - { 253, 283, 265 }, - { 285, 315, 293 } -}; - -/*----------------------------------------------------------------*/ - - void BgFileHeader::synchronize(Common::SeekableReadStream &s) { _numStructs = s.readUint16LE(); _numImages = s.readUint16LE(); @@ -121,8 +90,6 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _goToScene = -1; _changes = false; _charPoint = _oldCharPoint = 0; - _windowOpen = false; - _infoFlag = false; _keyboardInput = 0; _walkedInScene = false; _ongoingCans = 0; @@ -132,23 +99,19 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _hsavedPos = Common::Point(-1, -1); _hsavedFs = -1; _cAnimFramePause = 0; - _menuMode = STD_MODE; _invMode = INVMODE_0; _restoreFlag = false; _invLookFlag = false; _lookHelp = false; _animating = 0; _doBgAnimDone = true; - _oldLook = 0; _tempFadeStyle = 0; _controlPanel = new ImageFile("controls.vgs"); - _controls = nullptr; // new ImageFile("menu.all"); } Scene::~Scene() { delete _controlPanel; - delete _controls; freeScene(); } @@ -159,10 +122,11 @@ void Scene::selectScene() { Events &events = *_vm->_events; People &people = *_vm->_people; Screen &screen = *_vm->_screen; + UserInterface &ui = *_vm->_ui; // Reset fields - _windowOpen = _infoFlag = false; - _menuMode = STD_MODE; + ui._windowOpen = ui._infoFlag = false; + ui._menuMode = STD_MODE; _keyboardInput = 0; _oldKey = _help = _oldHelp = 0; _oldTemp = _temp = 0; @@ -1135,6 +1099,7 @@ void Scene::doBgAnim() { Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; Talk &talk = *_vm->_talk; + UserInterface &ui = *_vm->_ui; Surface surface = screen._backBuffer.getSubArea(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); int cursorId = events.getCursor(); @@ -1151,7 +1116,7 @@ void Scene::doBgAnim() { } // Check for setting magnifying glass cursor - if (_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) { + if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) { if (_invMode == INVMODE_1) { // Only show Magnifying glass cursor if it's not on the inventory command line if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13)) @@ -1434,20 +1399,33 @@ void Scene::doBgAnim() { } } +void Scene::saveSceneStatus() { + // TODO +} + /** - * Clears the info line of the screen + * Attempts to find a background shape within the passed bounds. If found, + * it will return the shape number, or -1 on failure. */ -void Scene::clearInfo() { - if (_infoFlag) { - _vm->_screen->fillRect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 200, INFO_LINE + 9, - INFO_BLACK); - _infoFlag = false; - _oldLook = -1; +int Scene::findBgShape(const Common::Rect &r) { + if (!_doBgAnimDone) + // New frame hasn't been drawn yet + return -1; + + for (int idx = (int)_bgShapes.size() - 1; idx >= 0; --idx) { + Object &o = _bgShapes[idx]; + if (o._type != INVALID && o._type != NO_SHAPE && o._type != HIDDEN + && o._aType <= PERSON) { + if (r.intersects(o.getNewBounds())) + return idx; + } else if (o._type == NO_SHAPE) { + if (r.intersects(o.getNoShapeBounds())) + return idx; + } } -} -void Scene::saveSceneStatus() { - // TODO + return -1; } + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index a6e4f51b99..785ed63106 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -37,22 +37,6 @@ namespace Sherlock { #define CONTROLS_Y 138 #define CONTROLS_Y1 151 -enum MenuMode { - STD_MODE = 0, - LOOK_MODE = 1, - MOVE_MODE = 2, - TALK_MODE = 3, - PICKUP_MODE = 4, - OPEN_MODE = 5, - CLOSE_MODE = 6, - INV_MODE = 7, - USE_MODE = 8, - GIVE_MODE = 9, - JOURNAL_MODE = 10, - FILES_MODE = 11, - SETUP_MODE = 12 -}; - enum InvMode { INVMODE_0 = 0, INVMODE_1 = 1, @@ -114,13 +98,11 @@ private: Common::String _rrmName; int _cAnimFramePause; Common::String _cAnimStr; - MenuMode _menuMode; InvMode _invMode; bool _lookScriptFlag; int _selector; bool _invLookFlag; bool _lookHelp; - int _oldLook; bool loadScene(const Common::String &filename); @@ -144,9 +126,7 @@ public: Common::Point _bigPos; Common::Point _overPos; int _charPoint, _oldCharPoint; - ImageFile *_controls; ImageFile *_controlPanel; - bool _windowOpen, _infoFlag; int _keyboardInput; int _oldKey, _help, _oldHelp; int _oldTemp, _temp; @@ -195,6 +175,8 @@ public: void doBgAnim(); void clearInfo(); + + int findBgShape(const Common::Rect &r); }; } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 87453ba36d..419ae681c2 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -34,7 +34,11 @@ namespace Sherlock { #define PALETTE_SIZE 768 #define PALETTE_COUNT 256 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63) + #define INFO_BLACK 1 +#define INFO_FOREGROUND 11 +#define INFO_BACKGROUND 1 + class SherlockEngine; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 5bb6500cf9..eea40f33a6 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -41,12 +41,12 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _screen = nullptr; _sound = nullptr; _talk = nullptr; + _ui = nullptr; _useEpilogue2 = false; _justLoaded = false; _loadingSavedGame = false; _onChessboard = false; _slowChess = false; - _menuCounter = 0; _scriptMoreFlag = 0; } @@ -60,6 +60,7 @@ SherlockEngine::~SherlockEngine() { delete _screen; delete _sound; delete _talk; + delete _ui; delete _inventory; delete _res; } @@ -83,6 +84,7 @@ void SherlockEngine::initialize() { _screen = new Screen(this); _sound = new Sound(this); _talk = new Talk(this); + _ui = new UserInterface(this); } Common::Error SherlockEngine::run() { @@ -132,9 +134,18 @@ void SherlockEngine::sceneLoop() { } +/** + * Handle all player input + */ void SherlockEngine::handleInput() { - // TODO + bool personFound; + _events->pollEventsAndWait(); + + // See if a key or mouse button is pressed + _events->setButtonState(); + + _ui->handleInput(); } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index b84f6d7429..392f55839e 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -42,6 +42,7 @@ #include "sherlock/screen.h" #include "sherlock/sound.h" #include "sherlock/talk.h" +#include "sherlock/user_interface.h" namespace Sherlock { @@ -90,6 +91,7 @@ public: Screen *_screen; Sound *_sound; Talk *_talk; + UserInterface *_ui; Common::RandomSource _randomSource; Common::Array _flags; Common::String _soundOverride; @@ -102,7 +104,6 @@ public: Common::Array _map; // Map locations for each scene bool _onChessboard; bool _slowChess; - int _menuCounter; int _scriptMoreFlag; Common::String _scriptName; public: diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp new file mode 100644 index 0000000000..d80aaecb54 --- /dev/null +++ b/engines/sherlock/user_interface.cpp @@ -0,0 +1,306 @@ +/* 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 "sherlock/user_interface.h" +#include "sherlock/sherlock.h" + +namespace Sherlock { + +// Main user interface menu control locations +const int MENU_POINTS[12][4] = { + { 13, 153, 72, 165 }, + { 13, 169, 72, 181 }, + { 13, 185, 72, 197 }, + { 88, 153, 152, 165 }, + { 88, 169, 152, 181 }, + { 88, 185, 152, 197 }, + { 165, 153, 232, 165 }, + { 165, 169, 232, 181 }, + { 165, 185, 233, 197 }, + { 249, 153, 305, 165 }, + { 249, 169, 305, 181 }, + { 249, 185, 305, 197 } +}; + +// Inventory control locations */ +const int INVENTORY_POINTS[8][3] = { + { 4, 50, 28 }, + { 52, 99, 76 }, + { 101, 140, 122 }, + { 142, 187, 165 }, + { 189, 219, 197 }, + { 221, 251, 233 }, + { 253, 283, 265 }, + { 285, 315, 293 } +}; + +const char COMMANDS[13] = "LMTPOCIUGJFS"; + +/*----------------------------------------------------------------*/ + +UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) { + _bgFound = 0; + _oldBgFound = -1; + _keycode = Common::KEYCODE_INVALID; + _helpStyle = 0; + _menuCounter = 0; + _menuMode = STD_MODE; + _help = _oldHelp = 0; + _lookHelp = 0; + _key = _oldKey = 0; + _temp = _oldTemp = 0; + _invLookFlag = 0; + _windowOpen = false; + _oldLook = false; + _keyboardInput = false; + + _controls = nullptr; // new ImageFile("menu.all"); +} + +UserInterface::~UserInterface() { + delete _controls; +} + +void UserInterface::handleInput() { + Events &events = *_vm->_events; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + + if (_menuCounter) + whileMenuCounter(); + + Common::Point pt = events.mousePos(); + _bgFound = scene.findBgShape(Common::Rect(pt.x, pt.y, pt.x + 1, pt.y + 1)); + _keycode = Common::KEYCODE_INVALID; + + // Check kbd and set the mouse released flag if Enter or space is pressed. + // Otherwise, the pressed key is stored for later use + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + + if (keyState.keycode == Common::KEYCODE_x && keyState.flags & Common::KBD_ALT) { + _vm->quitGame(); + return; + } else if (keyState.keycode == Common::KEYCODE_SPACE || + keyState.keycode == Common::KEYCODE_RETURN) { + events._pressed = events._oldButtons = 0; + _keycode = Common::KEYCODE_INVALID; + } + } + + // Do button highlighting check + if (!_vm->_scriptMoreFlag) { // Don't if scripts are running + if (((events._rightPressed || events._rightReleased) && _helpStyle) || + (!_helpStyle && !_menuCounter)) { + // Handle any default commands if we're in STD_MODE + if (_menuMode == STD_MODE) { + if (pt.y < CONTROLS_Y && + (events._rightPressed || (!_helpStyle && !events._released)) && + (_bgFound != -1) && (_bgFound < 1000) && + (scene._bgShapes[_bgFound]._defaultCommand || + scene._bgShapes[_bgFound]._description[0])) { + // If there is no default command, so set it to Look + if (scene._bgShapes[_bgFound]._defaultCommand) + _help = scene._bgShapes[_bgFound]._defaultCommand - 1; + else + _help = 0; + + // Reset 'help' if it is an invalid command + if (_help > 5) + _help = -1; + } else if (pt.y < CONTROLS_Y && + ((events._rightReleased && _helpStyle) || (events._released && !_helpStyle)) && + (_bgFound != -1 && _bgFound < 1000) && + (scene._bgShapes[_bgFound]._defaultCommand || + scene._bgShapes[_bgFound]._description[0])) { + // If there is no default command, set it to Look + if (scene._bgShapes[_bgFound]._defaultCommand) + _menuMode = (MenuMode)scene._bgShapes[_bgFound]._defaultCommand; + else + _menuMode = LOOK_MODE; + events._released = true; + events._pressed = events._oldButtons = false; + _help = _oldHelp = -1; + + if (_menuMode == LOOK_MODE) { + // Set the flag to tell the game that this was a right-click + // call to look and should exit without the look button being pressed + _lookHelp = true; + } + } else { + _help = -1; + } + + // Check if highlighting a different button than last time + if (_help != _oldHelp) { + // If another button was highlighted previously, restore it + if (_oldHelp != -1) + restoreButton(_oldHelp); + + // If we're highlighting a new button, then draw it pressed + if (_help != -1) + depressButton(_help); + + _help = _oldHelp; + } + + if (_bgFound != _oldBgFound) { + _infoFlag = true; + clearInfo(); + + if (_help != -1 && (scene._bgShapes[_bgFound]._description[0] != 32 && + scene._bgShapes[_bgFound]._description[0])) + screen.print(Common::Point(0, INFO_LINE + 1), + INFO_FOREGROUND, INFO_BACKGROUND, "%s", + scene._bgShapes[_bgFound]._description); + } + } else { + // We're not in STD_MODE + // If there isn't a window open, then revert back to STD_MODE + if (!_windowOpen && events._rightReleased) { + // Restore all buttons + for (int idx = 0; idx < 12; ++idx) + restoreButton(idx); + + _menuMode = STD_MODE; + _key = _oldKey = -1; + _temp = _oldTemp = _lookHelp = _invLookFlag = 0; + events.clearEvents(); + } + } + } + } + + // TODO +} + +/** + * Draws the image for a user interface button in the down/pressed state. + */ +void UserInterface::depressButton(int num) { + Screen &screen = *_vm->_screen; + Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); + + Graphics::Surface &s = (*_controls)[num]._frame; + screen._backBuffer.transBlitFrom(s, pt); + screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h); +} + +/** + * Draws the image for the given user interface button in the up + * (not selected) position + */ +void UserInterface::restoreButton(int num) { + Screen &screen = *_vm->_screen; + Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); + + screen._backBuffer.blitFrom(screen._backBuffer2, pt, + Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19)); + screen._backBuffer.blitFrom(screen._backBuffer, pt, + Common::Rect(pt.x, pt.y, pt.x + (*_controls)[num]._frame.w, + (*_controls)[num]._frame.h)); + + if (!_menuCounter) { + _infoFlag++; + clearInfo(); + } +} + +/** + * If he mouse button is pressed, then calls depressButton to draw the button + * as pressed; if not, it will show it as released with a call to "restoreButton". + */ +void UserInterface::pushButton(int num) { + Events &events = *_vm->_events; + _oldKey = -1; + + if (!events._released) { + if (_oldHelp != -1) + restoreButton(_oldHelp); + if (_help != -1) + restoreButton(_help); + + depressButton(num); + events.wait(6); + } + + restoreButton(num); +} + +/** + * By the time this method has been called, the graphics for the button change + * have already been drawn. This simply takes care of switching the mode around + * accordingly + */ +void UserInterface::toggleButton(int num) { + Screen &screen = *_vm->_screen; + + if (_menuMode != (num + 1)) { + _menuMode = (MenuMode)(num + 1); + _oldKey = COMMANDS[num]; + _oldTemp = num; + + if (_keyboardInput) { + if (_oldHelp != -1 && _oldHelp != num) + restoreButton(_oldHelp); + if (_help != -1 && _help != num) + restoreButton(_help); + + _keyboardInput = false; + + Graphics::Surface &s = (*_controls)[num]._frame; + Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]); + screen._backBuffer.transBlitFrom(s, pt); + screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h); + } + } else { + _menuMode = STD_MODE; + _oldKey = -1; + restoreButton(num); + } +} + + +/** + * Clears the info line of the screen + */ +void UserInterface::clearInfo() { + if (_infoFlag) { + _vm->_screen->fillRect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 200, INFO_LINE + 9, + INFO_BLACK); + _infoFlag = false; + _oldLook = -1; + } +} + +/** + * Handles counting down whilst checking for input, then clears the info line. + */ +void UserInterface::whileMenuCounter() { + if (!(--_menuCounter) || _vm->_events->checkInput()) { + _menuCounter = 0; + ++_infoFlag; + clearInfo(); + } +} + +} // End of namespace Sherlock diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h new file mode 100644 index 0000000000..4a98a5be89 --- /dev/null +++ b/engines/sherlock/user_interface.h @@ -0,0 +1,91 @@ +/* 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. + * + */ + +#ifndef SHERLOCK_UI_H +#define SHERLOCK_UI_H + +#include "common/scummsys.h" +#include "common/events.h" +#include "sherlock/resources.h" + +namespace Sherlock { + +enum MenuMode { + STD_MODE = 0, + LOOK_MODE = 1, + MOVE_MODE = 2, + TALK_MODE = 3, + PICKUP_MODE = 4, + OPEN_MODE = 5, + CLOSE_MODE = 6, + INV_MODE = 7, + USE_MODE = 8, + GIVE_MODE = 9, + JOURNAL_MODE = 10, + FILES_MODE = 11, + SETUP_MODE = 12 +}; + +class SherlockEngine; + +class UserInterface { +private: + SherlockEngine *_vm; + int _bgFound; + int _oldBgFound; + Common::KeyCode _keycode; + int _helpStyle; + int _lookHelp; + int _help, _oldHelp; + int _key, _oldKey; + int _temp, _oldTemp; + int _invLookFlag; + ImageFile *_controls; + int _oldLook; + bool _keyboardInput; +private: + void depressButton(int num); + + void restoreButton(int num); + + void pushButton(int num); + + void toggleButton(int num); +public: + MenuMode _menuMode; + int _menuCounter; + bool _infoFlag; + bool _windowOpen; +public: + UserInterface(SherlockEngine *vm); + ~UserInterface(); + + void handleInput(); + + void clearInfo(); + + void whileMenuCounter(); +}; + +} // End of namespace Sherlock + +#endif -- cgit v1.2.3