From 92ac962718b07e9b82199d39bb5ce970717da57d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 25 Jun 2015 20:42:02 -0400 Subject: SHERLOCK: RT: Further split-off of Scalpel-specific code --- engines/sherlock/inventory.cpp | 240 +----------------- engines/sherlock/inventory.h | 29 +-- engines/sherlock/module.mk | 3 + engines/sherlock/saveload.cpp | 233 +----------------- engines/sherlock/saveload.h | 20 +- engines/sherlock/scalpel/scalpel.h | 5 + engines/sherlock/scalpel/scalpel_inventory.cpp | 271 +++++++++++++++++++++ engines/sherlock/scalpel/scalpel_inventory.h | 68 ++++++ engines/sherlock/scalpel/scalpel_journal.cpp | 12 +- engines/sherlock/scalpel/scalpel_saveload.cpp | 261 ++++++++++++++++++++ engines/sherlock/scalpel/scalpel_saveload.h | 69 ++++++ engines/sherlock/scalpel/scalpel_screen.cpp | 93 +++++++ engines/sherlock/scalpel/scalpel_screen.h | 66 +++++ engines/sherlock/scalpel/scalpel_talk.cpp | 241 +++++++++++++++++- engines/sherlock/scalpel/scalpel_talk.h | 20 ++ .../sherlock/scalpel/scalpel_user_interface.cpp | 24 +- engines/sherlock/scalpel/settings.cpp | 6 +- engines/sherlock/screen.cpp | 66 +---- engines/sherlock/screen.h | 25 +- engines/sherlock/sherlock.cpp | 6 +- engines/sherlock/talk.cpp | 231 +----------------- engines/sherlock/talk.h | 40 +-- engines/sherlock/tattoo/tattoo.h | 5 +- engines/sherlock/tattoo/tattoo_user_interface.cpp | 1 - engines/sherlock/tattoo/widget_inventory.cpp | 1 - engines/sherlock/tattoo/widget_inventory.h | 2 + 26 files changed, 1183 insertions(+), 855 deletions(-) create mode 100644 engines/sherlock/scalpel/scalpel_inventory.cpp create mode 100644 engines/sherlock/scalpel/scalpel_inventory.h create mode 100644 engines/sherlock/scalpel/scalpel_saveload.cpp create mode 100644 engines/sherlock/scalpel/scalpel_saveload.h create mode 100644 engines/sherlock/scalpel/scalpel_screen.cpp create mode 100644 engines/sherlock/scalpel/scalpel_screen.h diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index 692b05773b..492ac736b1 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -22,6 +22,7 @@ #include "sherlock/inventory.h" #include "sherlock/sherlock.h" +#include "sherlock/scalpel/scalpel_inventory.h" #include "sherlock/scalpel/scalpel_user_interface.h" namespace Sherlock { @@ -42,6 +43,13 @@ void InventoryItem::synchronize(Serializer &s) { /*----------------------------------------------------------------*/ +Inventory *Inventory::init(SherlockEngine *vm) { + if (vm->getGameID() == GType_SerratedScalpel) + return new Scalpel::ScalpelInventory(vm); + else + return new Inventory(vm); +} + Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(vm) { Common::fill(&_invShapes[0], &_invShapes[MAX_VISIBLE_INVENTORY], (ImageFile *)nullptr); _invGraphicsLoaded = false; @@ -128,238 +136,6 @@ int Inventory::findInv(const Common::String &name) { error("Couldn't find inventory item - %s", name.c_str()); } -void Inventory::putInv(InvSlamMode slamIt) { - Screen &screen = *_vm->_screen; - UserInterface &ui = *_vm->_ui; - - // If an inventory item has disappeared (due to using it or giving it), - // a blank space slot may have appeared. If so, adjust the inventory - if (_invIndex > 0 && _invIndex > (_holdings - 6)) { - --_invIndex; - freeGraphics(); - loadGraphics(); - } - - if (slamIt != SLAM_SECONDARY_BUFFER) { - screen.makePanel(Common::Rect(6, 163, 54, 197)); - screen.makePanel(Common::Rect(58, 163, 106, 197)); - screen.makePanel(Common::Rect(110, 163, 158, 197)); - screen.makePanel(Common::Rect(162, 163, 210, 197)); - screen.makePanel(Common::Rect(214, 163, 262, 197)); - screen.makePanel(Common::Rect(266, 163, 314, 197)); - } - - // Iterate through displaying up to 6 objects at a time - for (int idx = _invIndex; idx < _holdings && (idx - _invIndex) < MAX_VISIBLE_INVENTORY; ++idx) { - int itemNum = idx - _invIndex; - Surface &bb = slamIt == SLAM_SECONDARY_BUFFER ? screen._backBuffer2 : screen._backBuffer1; - Common::Rect r(8 + itemNum * 52, 165, 51 + itemNum * 52, 194); - - // Draw the background - if (idx == ui._selector) { - bb.fillRect(r, BUTTON_BACKGROUND); - } else if (slamIt == SLAM_SECONDARY_BUFFER) { - bb.fillRect(r, BUTTON_MIDDLE); - } - - // Draw the item image - ImageFrame &frame = (*_invShapes[itemNum])[0]; - bb.transBlitFrom(frame, Common::Point(6 + itemNum * 52 + ((47 - frame._width) / 2), - 163 + ((33 - frame._height) / 2))); - } - - if (slamIt == SLAM_DISPLAY) - screen.slamArea(6, 163, 308, 34); - - if (slamIt != SLAM_SECONDARY_BUFFER) - ui.clearInfo(); - - if (slamIt == 0) { - invCommands(0); - } else if (slamIt == SLAM_SECONDARY_BUFFER) { - screen._backBuffer = &screen._backBuffer2; - invCommands(0); - screen._backBuffer = &screen._backBuffer1; - } -} - -void Inventory::drawInventory(InvNewMode mode) { - FixedText &fixedText = *_vm->_fixedText; - Screen &screen = *_vm->_screen; - UserInterface &ui = *_vm->_ui; - InvNewMode tempMode = mode; - - loadInv(); - - if (mode == INVENTORY_DONT_DISPLAY) { - screen._backBuffer = &screen._backBuffer2; - } - - // Draw the window background - Surface &bb = *screen._backBuffer; - bb.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 10), BORDER_COLOR); - bb.fillRect(Common::Rect(0, CONTROLS_Y1 + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 10, - SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, - SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - bb.fillRect(Common::Rect(2, CONTROLS_Y1 + 10, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT - 2), - INV_BACKGROUND); - - // Draw the buttons - Common::String fixedText_Exit = fixedText.getText(kFixedText_Inventory_Exit); - Common::String fixedText_Look = fixedText.getText(kFixedText_Inventory_Look); - Common::String fixedText_Use = fixedText.getText(kFixedText_Inventory_Use); - Common::String fixedText_Give = fixedText.getText(kFixedText_Inventory_Give); - - screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[0][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[0][1], - CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[0][2] - screen.stringWidth(fixedText_Exit) / 2, fixedText_Exit); - screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[1][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[1][1], - CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[1][2] - screen.stringWidth(fixedText_Look) / 2, fixedText_Look); - screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[2][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[2][1], - CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[2][2] - screen.stringWidth(fixedText_Use) / 2, fixedText_Use); - screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[3][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[3][1], - CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[3][2] - screen.stringWidth(fixedText_Give) / 2, fixedText_Give); - screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[4][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[4][1], - CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[4][2], "^^"); // 2 arrows pointing to the left - screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[5][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[5][1], - CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[5][2], "^"); // 1 arrow pointing to the left - screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[6][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[6][1], - CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[6][2], "_"); // 1 arrow pointing to the right - screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[7][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[7][1], - CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[7][2], "__"); // 2 arrows pointing to the right - - if (tempMode == INVENTORY_DONT_DISPLAY) - mode = LOOK_INVENTORY_MODE; - _invMode = (InvMode)mode; - - if (mode != PLAIN_INVENTORY) { - ui._oldKey = Scalpel::INVENTORY_COMMANDS[(int)mode]; - } else { - ui._oldKey = -1; - } - - invCommands(0); - putInv(SLAM_DONT_DISPLAY); - - if (tempMode != INVENTORY_DONT_DISPLAY) { - if (!ui._slideWindows) { - screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - } else { - ui.summonWindow(false, CONTROLS_Y1); - } - - ui._windowOpen = true; - } else { - // Reset the screen back buffer to the first buffer now that drawing is done - screen._backBuffer = &screen._backBuffer1; - } - - assert(IS_SERRATED_SCALPEL); - ((Scalpel::ScalpelUserInterface *)_vm->_ui)->_oldUse = -1; -} - -void Inventory::invCommands(bool slamIt) { - FixedText &fixedText = *_vm->_fixedText; - Screen &screen = *_vm->_screen; - UserInterface &ui = *_vm->_ui; - - Common::String fixedText_Exit = fixedText.getText(kFixedText_Inventory_Exit); - Common::String fixedText_Look = fixedText.getText(kFixedText_Inventory_Look); - Common::String fixedText_Use = fixedText.getText(kFixedText_Inventory_Use); - Common::String fixedText_Give = fixedText.getText(kFixedText_Inventory_Give); - - if (slamIt) { - screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[0][2], CONTROLS_Y1), - _invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND, - true, fixedText_Exit); - screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[1][2], CONTROLS_Y1), - _invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND, - true, fixedText_Look); - screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[2][2], CONTROLS_Y1), - _invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, - true, fixedText_Use); - screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[3][2], CONTROLS_Y1), - _invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, - true, fixedText_Give); - screen.print(Common::Point(Scalpel::INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), - _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, - "^^"); // 2 arrows pointing to the left - screen.print(Common::Point(Scalpel::INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), - _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, - "^"); // 2 arrows pointing to the left - screen.print(Common::Point(Scalpel::INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), - (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND, - "_"); // 1 arrow pointing to the right - screen.print(Common::Point(Scalpel::INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), - (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND, - "__"); // 2 arrows pointing to the right - if (_invMode != INVMODE_LOOK) - ui.clearInfo(); - } else { - screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[0][2], CONTROLS_Y1), - _invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, - false, fixedText_Exit); - screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[1][2], CONTROLS_Y1), - _invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, - false, fixedText_Look); - screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[2][2], CONTROLS_Y1), - _invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, - false, fixedText_Use); - screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[3][2], CONTROLS_Y1), - _invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, - false, fixedText_Give); - screen.gPrint(Common::Point(Scalpel::INVENTORY_POINTS[4][2], CONTROLS_Y1), - _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, - "^^"); // 2 arrows pointing to the left - screen.gPrint(Common::Point(Scalpel::INVENTORY_POINTS[5][2], CONTROLS_Y1), - _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, - "^"); // 1 arrow pointing to the left - screen.gPrint(Common::Point(Scalpel::INVENTORY_POINTS[6][2], CONTROLS_Y1), - (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND, - "_"); // 1 arrow pointing to the right - screen.gPrint(Common::Point(Scalpel::INVENTORY_POINTS[7][2], CONTROLS_Y1), - (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND, - "__"); // 2 arrows pointing to the right - } -} - -void Inventory::highlight(int index, byte color) { - Screen &screen = *_vm->_screen; - Surface &bb = *screen._backBuffer; - int slot = index - _invIndex; - ImageFrame &frame = (*_invShapes[slot])[0]; - - bb.fillRect(Common::Rect(8 + slot * 52, 165, (slot + 1) * 52, 194), color); - bb.transBlitFrom(frame, Common::Point(6 + slot * 52 + ((47 - frame._width) / 2), - 163 + ((33 - frame._height) / 2))); - screen.slamArea(8 + slot * 52, 165, 44, 30); -} - -void Inventory::refreshInv() { - if (IS_ROSE_TATTOO) - return; - - Screen &screen = *_vm->_screen; - Talk &talk = *_vm->_talk; - Scalpel::ScalpelUserInterface &ui = *(Scalpel::ScalpelUserInterface *)_vm->_ui; - - ui._invLookFlag = true; - freeInv(); - - ui._infoFlag = true; - ui.clearInfo(); - - screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y), - Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - ui.examine(); - - if (!talk._talkToAbort) { - screen._backBuffer2.blitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y)); - loadInv(); - } -} - int Inventory::putNameInInventory(const Common::String &name) { Scene &scene = *_vm->_scene; int matches = 0; diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index 019f5ed6c9..20eb6c067b 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -77,7 +77,7 @@ struct InventoryItem { }; class Inventory : public Common::Array { -private: +protected: SherlockEngine *_vm; Common::StringArray _names; @@ -97,6 +97,7 @@ public: */ void freeGraphics(); public: + static Inventory *init(SherlockEngine *vm); Inventory(SherlockEngine *vm); ~Inventory(); @@ -122,32 +123,6 @@ public: */ int findInv(const Common::String &name); - /** - * Display the character's inventory. The slamIt parameter specifies: - */ - void putInv(InvSlamMode slamIt); - - /** - * Put the game into inventory mode and open the interface window. - */ - void drawInventory(InvNewMode flag); - - /** - * Prints the line of inventory commands at the top of an inventory window with - * the correct highlighting - */ - void invCommands(bool slamIt); - - /** - * Set the highlighting color of a given inventory item - */ - void highlight(int index, byte color); - - /** - * Support method for refreshing the display of the inventory - */ - void refreshInv(); - /** * Adds a shape from the scene to the player's inventory */ diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 8bbee9d701..badd288fab 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -8,10 +8,13 @@ MODULE_OBJS = \ scalpel/drivers/mt32.o \ scalpel/tsage/logo.o \ scalpel/tsage/resources.o \ + scalpel/scalpel_inventory.o \ scalpel/scalpel_journal.o \ scalpel/scalpel_map.o \ scalpel/scalpel_people.o \ + scalpel/scalpel_saveload.o \ scalpel/scalpel_scene.o \ + scalpel/scalpel_screen.o \ scalpel/scalpel_talk.o \ scalpel/scalpel_user_interface.o \ scalpel/settings.o \ diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index c863f8c4ee..fae8196dc1 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -23,27 +23,26 @@ #include "sherlock/saveload.h" #include "sherlock/surface.h" #include "sherlock/sherlock.h" +#include "sherlock/scalpel/scalpel_saveload.h" #include "common/system.h" #include "graphics/scaler.h" #include "graphics/thumbnail.h" namespace Sherlock { -const int ENV_POINTS[6][3] = { - { 41, 80, 61 }, // Exit - { 81, 120, 101 }, // Load - { 121, 160, 141 }, // Save - { 161, 200, 181 }, // Up - { 201, 240, 221 }, // Down - { 241, 280, 261 } // Quit -}; - -static const char *const EMPTY_SAVEGAME_SLOT = "-EMPTY-"; +const char *const EMPTY_SAVEGAME_SLOT = "-EMPTY-"; static const char *const SAVEGAME_STR = "SHLK"; #define SAVEGAME_STR_SIZE 4 /*----------------------------------------------------------------*/ +SaveManager *SaveManager::init(SherlockEngine *vm, const Common::String &target) { + if (vm->getGameID() == GType_SerratedScalpel) + return new Scalpel::ScalpelSaveManager(vm, target); + else + return new SaveManager(vm, target); +} + SaveManager::SaveManager(SherlockEngine *vm, const Common::String &target) : _vm(vm), _target(target) { _saveThumb = nullptr; @@ -59,54 +58,6 @@ SaveManager::~SaveManager() { } } -void SaveManager::drawInterface() { - Screen &screen = *_vm->_screen; - UserInterface &ui = *_vm->_ui; - - // Create a list of savegame slots - createSavegameList(); - - screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + 10), BORDER_COLOR); - screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - screen._backBuffer1.fillRect(Common::Rect(318, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - screen._backBuffer1.fillRect(Common::Rect(0, 199, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); - - screen.makeButton(Common::Rect(ENV_POINTS[0][0], CONTROLS_Y, ENV_POINTS[0][1], CONTROLS_Y + 10), - ENV_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); - screen.makeButton(Common::Rect(ENV_POINTS[1][0], CONTROLS_Y, ENV_POINTS[1][1], CONTROLS_Y + 10), - ENV_POINTS[1][2] - screen.stringWidth("Load") / 2, "Load"); - screen.makeButton(Common::Rect(ENV_POINTS[2][0], CONTROLS_Y, ENV_POINTS[2][1], CONTROLS_Y + 10), - ENV_POINTS[2][2] - screen.stringWidth("Save") / 2, "Save"); - screen.makeButton(Common::Rect(ENV_POINTS[3][0], CONTROLS_Y, ENV_POINTS[3][1], CONTROLS_Y + 10), - ENV_POINTS[3][2] - screen.stringWidth("Up") / 2, "Up"); - screen.makeButton(Common::Rect(ENV_POINTS[4][0], CONTROLS_Y, ENV_POINTS[4][1], CONTROLS_Y + 10), - ENV_POINTS[4][2] - screen.stringWidth("Down") / 2, "Down"); - screen.makeButton(Common::Rect(ENV_POINTS[5][0], CONTROLS_Y, ENV_POINTS[5][1], CONTROLS_Y + 10), - ENV_POINTS[5][2] - screen.stringWidth("Quit") / 2, "Quit"); - - if (!_savegameIndex) - screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_NULL, 0, "Up"); - - if (_savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) - screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_NULL, 0, "Down"); - - for (int idx = _savegameIndex; idx < _savegameIndex + ONSCREEN_FILES_COUNT; ++idx) { - screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), - INV_FOREGROUND, "%d.", idx + 1); - screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), - INV_FOREGROUND, "%s", _savegames[idx].c_str()); - } - - if (!ui._slideWindows) { - screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - } else { - ui.summonWindow(); - } - - _envMode = SAVEMODE_NONE; -} - void SaveManager::createSavegameList() { Screen &screen = *_vm->_screen; @@ -249,49 +200,6 @@ void SaveManager::createThumbnail() { } } -int SaveManager::getHighlightedButton() const { - Common::Point pt = _vm->_events->mousePos(); - - for (int idx = 0; idx < 6; ++idx) { - if (pt.x > ENV_POINTS[idx][0] && pt.x < ENV_POINTS[idx][1] && pt.y > CONTROLS_Y - && pt.y < (CONTROLS_Y + 10)) - return idx; - } - - return -1; -} - -void SaveManager::highlightButtons(int btnIndex) { - Screen &screen = *_vm->_screen; - byte color = (btnIndex == 0) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND; - - screen.buttonPrint(Common::Point(ENV_POINTS[0][2], CONTROLS_Y), color, 1, "Exit"); - - if ((btnIndex == 1) || ((_envMode == SAVEMODE_LOAD) && (btnIndex != 2))) - screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Load"); - else - screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Load"); - - if ((btnIndex == 2) || ((_envMode == SAVEMODE_SAVE) && (btnIndex != 1))) - screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Save"); - else - screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Save"); - - if (btnIndex == 3 && _savegameIndex) - screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Up"); - else - if (_savegameIndex) - screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Up"); - - if ((btnIndex == 4) && (_savegameIndex < MAX_SAVEGAME_SLOTS - 5)) - screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Down"); - else if (_savegameIndex < (MAX_SAVEGAME_SLOTS - 5)) - screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Down"); - - color = (btnIndex == 5) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND; - screen.buttonPrint(Common::Point(ENV_POINTS[5][2], CONTROLS_Y), color, 1, "Quit"); -} - void SaveManager::loadGame(int slot) { Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( generateSaveName(slot)); @@ -363,129 +271,6 @@ void SaveManager::synchronize(Serializer &s) { _justLoaded = true; } -bool SaveManager::checkGameOnScreen(int slot) { - Screen &screen = *_vm->_screen; - - // Check if it's already on-screen - if (slot != -1 && (slot < _savegameIndex || slot >= (_savegameIndex + ONSCREEN_FILES_COUNT))) { - _savegameIndex = slot; - - screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, - SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); - - for (int idx = _savegameIndex; idx < (_savegameIndex + 5); ++idx) { - screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), - INV_FOREGROUND, "%d.", idx + 1); - screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), - INV_FOREGROUND, "%s", _savegames[idx].c_str()); - } - - screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, 318, SHERLOCK_SCREEN_HEIGHT)); - - byte color = !_savegameIndex ? COMMAND_NULL : COMMAND_FOREGROUND; - screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, 1, "Up"); - - color = (_savegameIndex == (MAX_SAVEGAME_SLOTS - 5)) ? COMMAND_NULL : COMMAND_FOREGROUND; - screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, 1, "Down"); - - return true; - } - - return false; -} - -bool SaveManager::promptForDescription(int slot) { - Events &events = *_vm->_events; - Scene &scene = *_vm->_scene; - Screen &screen = *_vm->_screen; - Talk &talk = *_vm->_talk; - int xp, yp; - bool flag = false; - - screen.buttonPrint(Common::Point(ENV_POINTS[0][2], CONTROLS_Y), COMMAND_NULL, true, "Exit"); - screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_NULL, true, "Load"); - screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_NULL, true, "Save"); - screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_NULL, true, "Up"); - screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_NULL, true, "Down"); - screen.buttonPrint(Common::Point(ENV_POINTS[5][2], CONTROLS_Y), COMMAND_NULL, true, "Quit"); - - Common::String saveName = _savegames[slot]; - if (isSlotEmpty(slot)) { - // It's an empty slot, so start off with an empty save name - saveName = ""; - - yp = CONTROLS_Y + 12 + (slot - _savegameIndex) * 10; - screen.vgaBar(Common::Rect(24, yp, 85, yp + 9), INV_BACKGROUND); - } - - screen.print(Common::Point(6, CONTROLS_Y + 12 + (slot - _savegameIndex) * 10), TALK_FOREGROUND, "%d.", slot + 1); - screen.print(Common::Point(24, CONTROLS_Y + 12 + (slot - _savegameIndex) * 10), TALK_FOREGROUND, "%s", saveName.c_str()); - xp = 24 + screen.stringWidth(saveName); - yp = CONTROLS_Y + 12 + (slot - _savegameIndex) * 10; - - int done = 0; - do { - while (!_vm->shouldQuit() && !events.kbHit()) { - scene.doBgAnim(); - - if (talk._talkToAbort) - return false; - - // Allow event processing - events.pollEventsAndWait(); - events.setButtonState(); - - flag = !flag; - if (flag) - screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); - else - screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); - } - if (_vm->shouldQuit()) - return false; - - // Get the next keypress - Common::KeyState keyState = events.getKey(); - - if (keyState.keycode == Common::KEYCODE_BACKSPACE && saveName.size() > 0) { - // Delete character of save name - screen.vgaBar(Common::Rect(xp - screen.charWidth(saveName.lastChar()), yp - 1, - xp + 8, yp + 9), INV_BACKGROUND); - xp -= screen.charWidth(saveName.lastChar()); - screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); - saveName.deleteLastChar(); - - } else if (keyState.keycode == Common::KEYCODE_RETURN && saveName.compareToIgnoreCase(EMPTY_SAVEGAME_SLOT)) { - done = 1; - - } else if (keyState.keycode == Common::KEYCODE_ESCAPE) { - screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); - done = -1; - - } else if (keyState.ascii >= ' ' && keyState.ascii <= 'z' && saveName.size() < 50 - && (xp + screen.charWidth(keyState.ascii)) < 308) { - char c = (char)keyState.ascii; - - screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); - screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", c); - xp += screen.charWidth(c); - screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); - saveName += c; - } - } while (!done); - - if (done == 1) { - // Enter key perssed - _savegames[slot] = saveName; - } else { - done = 0; - _envMode = SAVEMODE_NONE; - highlightButtons(-1); - } - - return done == 1; -} - bool SaveManager::isSlotEmpty(int slot) const { return _savegames[slot].equalsIgnoreCase(EMPTY_SAVEGAME_SLOT); } diff --git a/engines/sherlock/saveload.h b/engines/sherlock/saveload.h index 49ccc508ef..e485cfc606 100644 --- a/engines/sherlock/saveload.h +++ b/engines/sherlock/saveload.h @@ -42,7 +42,7 @@ enum { enum SaveMode { SAVEMODE_NONE = 0, SAVEMODE_LOAD = 1, SAVEMODE_SAVE = 2 }; -extern const int ENV_POINTS[6][3]; +extern const char *const EMPTY_SAVEGAME_SLOT; struct SherlockSavegameHeader { uint8 _version; @@ -70,7 +70,7 @@ public: }; class SaveManager { -private: +protected: SherlockEngine *_vm; Common::String _target; Graphics::Surface *_saveThumb; @@ -90,14 +90,10 @@ public: SaveMode _envMode; bool _justLoaded; public: + static SaveManager *init(SherlockEngine *vm, const Common::String &target); SaveManager(SherlockEngine *vm, const Common::String &target); ~SaveManager(); - /** - * Shows the in-game dialog interface for loading and saving games - */ - void drawInterface(); - /** * Creates a thumbnail for the current on-screen contents */ @@ -144,16 +140,6 @@ public: */ void saveGame(int slot, const Common::String &name); - /** - * Make sure that the selected savegame is on-screen - */ - bool checkGameOnScreen(int slot); - - /** - * Prompts the user to enter a description in a given slot - */ - bool promptForDescription(int slot); - /** * Returns true if the given save slot is empty */ diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 8a10094a52..0747e7d8f8 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -30,6 +30,11 @@ namespace Sherlock { namespace Scalpel { +enum { + COMMAND_HIGHLIGHTED = 10, + COMMAND_NULL = 248 +}; + class ScalpelEngine : public SherlockEngine { private: Darts *_darts; diff --git a/engines/sherlock/scalpel/scalpel_inventory.cpp b/engines/sherlock/scalpel/scalpel_inventory.cpp new file mode 100644 index 0000000000..bf12a16025 --- /dev/null +++ b/engines/sherlock/scalpel/scalpel_inventory.cpp @@ -0,0 +1,271 @@ +/* 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/scalpel/scalpel_inventory.h" +#include "sherlock/scalpel/scalpel_screen.h" +#include "sherlock/scalpel/scalpel_user_interface.h" +#include "sherlock/scalpel/scalpel.h" + +namespace Sherlock { + +namespace Scalpel { + +ScalpelInventory::ScalpelInventory(SherlockEngine *vm) : Inventory(vm) { +} + +ScalpelInventory::~ScalpelInventory() { +} + +void ScalpelInventory::drawInventory(InvNewMode mode) { + FixedText &fixedText = *_vm->_fixedText; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + UserInterface &ui = *_vm->_ui; + InvNewMode tempMode = mode; + + loadInv(); + + if (mode == INVENTORY_DONT_DISPLAY) { + screen._backBuffer = &screen._backBuffer2; + } + + // Draw the window background + Surface &bb = *screen._backBuffer; + bb.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 10), BORDER_COLOR); + bb.fillRect(Common::Rect(0, CONTROLS_Y1 + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 10, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, + SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(2, CONTROLS_Y1 + 10, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT - 2), + INV_BACKGROUND); + + // Draw the buttons + Common::String fixedText_Exit = fixedText.getText(kFixedText_Inventory_Exit); + Common::String fixedText_Look = fixedText.getText(kFixedText_Inventory_Look); + Common::String fixedText_Use = fixedText.getText(kFixedText_Inventory_Use); + Common::String fixedText_Give = fixedText.getText(kFixedText_Inventory_Give); + + screen.makeButton(Common::Rect(INVENTORY_POINTS[0][0], CONTROLS_Y1, INVENTORY_POINTS[0][1], + CONTROLS_Y1 + 10), INVENTORY_POINTS[0][2] - screen.stringWidth(fixedText_Exit) / 2, fixedText_Exit); + screen.makeButton(Common::Rect(INVENTORY_POINTS[1][0], CONTROLS_Y1, INVENTORY_POINTS[1][1], + CONTROLS_Y1 + 10), INVENTORY_POINTS[1][2] - screen.stringWidth(fixedText_Look) / 2, fixedText_Look); + screen.makeButton(Common::Rect(INVENTORY_POINTS[2][0], CONTROLS_Y1, INVENTORY_POINTS[2][1], + CONTROLS_Y1 + 10), INVENTORY_POINTS[2][2] - screen.stringWidth(fixedText_Use) / 2, fixedText_Use); + screen.makeButton(Common::Rect(INVENTORY_POINTS[3][0], CONTROLS_Y1, INVENTORY_POINTS[3][1], + CONTROLS_Y1 + 10), INVENTORY_POINTS[3][2] - screen.stringWidth(fixedText_Give) / 2, fixedText_Give); + screen.makeButton(Common::Rect(INVENTORY_POINTS[4][0], CONTROLS_Y1, INVENTORY_POINTS[4][1], + CONTROLS_Y1 + 10), INVENTORY_POINTS[4][2], "^^"); // 2 arrows pointing to the left + screen.makeButton(Common::Rect(INVENTORY_POINTS[5][0], CONTROLS_Y1, INVENTORY_POINTS[5][1], + CONTROLS_Y1 + 10), INVENTORY_POINTS[5][2], "^"); // 1 arrow pointing to the left + screen.makeButton(Common::Rect(INVENTORY_POINTS[6][0], CONTROLS_Y1, INVENTORY_POINTS[6][1], + CONTROLS_Y1 + 10), INVENTORY_POINTS[6][2], "_"); // 1 arrow pointing to the right + screen.makeButton(Common::Rect(INVENTORY_POINTS[7][0], CONTROLS_Y1, INVENTORY_POINTS[7][1], + CONTROLS_Y1 + 10), INVENTORY_POINTS[7][2], "__"); // 2 arrows pointing to the right + + if (tempMode == INVENTORY_DONT_DISPLAY) + mode = LOOK_INVENTORY_MODE; + _invMode = (InvMode)mode; + + if (mode != PLAIN_INVENTORY) { + ui._oldKey = INVENTORY_COMMANDS[(int)mode]; + } else { + ui._oldKey = -1; + } + + invCommands(0); + putInv(SLAM_DONT_DISPLAY); + + if (tempMode != INVENTORY_DONT_DISPLAY) { + if (!ui._slideWindows) { + screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(false, CONTROLS_Y1); + } + + ui._windowOpen = true; + } else { + // Reset the screen back buffer to the first buffer now that drawing is done + screen._backBuffer = &screen._backBuffer1; + } + + assert(IS_SERRATED_SCALPEL); + ((ScalpelUserInterface *)_vm->_ui)->_oldUse = -1; +} + +void ScalpelInventory::invCommands(bool slamIt) { + FixedText &fixedText = *_vm->_fixedText; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + UserInterface &ui = *_vm->_ui; + + Common::String fixedText_Exit = fixedText.getText(kFixedText_Inventory_Exit); + Common::String fixedText_Look = fixedText.getText(kFixedText_Inventory_Look); + Common::String fixedText_Use = fixedText.getText(kFixedText_Inventory_Use); + Common::String fixedText_Give = fixedText.getText(kFixedText_Inventory_Give); + + if (slamIt) { + screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), + _invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND, + true, fixedText_Exit); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), + _invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND, + true, fixedText_Look); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), + _invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + true, fixedText_Use); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), + _invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + true, fixedText_Give); + screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), + _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + "^^"); // 2 arrows pointing to the left + screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), + _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + "^"); // 2 arrows pointing to the left + screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), + (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND, + "_"); // 1 arrow pointing to the right + screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), + (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND, + "__"); // 2 arrows pointing to the right + if (_invMode != INVMODE_LOOK) + ui.clearInfo(); + } else { + screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), + _invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + false, fixedText_Exit); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), + _invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + false, fixedText_Look); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), + _invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + false, fixedText_Use); + screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), + _invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND, + false, fixedText_Give); + screen.gPrint(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1), + _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + "^^"); // 2 arrows pointing to the left + screen.gPrint(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1), + _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND, + "^"); // 1 arrow pointing to the left + screen.gPrint(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1), + (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND, + "_"); // 1 arrow pointing to the right + screen.gPrint(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1), + (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND, + "__"); // 2 arrows pointing to the right + } +} + +void ScalpelInventory::highlight(int index, byte color) { + Screen &screen = *_vm->_screen; + Surface &bb = *screen._backBuffer; + int slot = index - _invIndex; + ImageFrame &frame = (*_invShapes[slot])[0]; + + bb.fillRect(Common::Rect(8 + slot * 52, 165, (slot + 1) * 52, 194), color); + bb.transBlitFrom(frame, Common::Point(6 + slot * 52 + ((47 - frame._width) / 2), + 163 + ((33 - frame._height) / 2))); + screen.slamArea(8 + slot * 52, 165, 44, 30); +} + +void ScalpelInventory::refreshInv() { + Screen &screen = *_vm->_screen; + Talk &talk = *_vm->_talk; + ScalpelUserInterface &ui = *(ScalpelUserInterface *)_vm->_ui; + + ui._invLookFlag = true; + freeInv(); + + ui._infoFlag = true; + ui.clearInfo(); + + screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y), + Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + ui.examine(); + + if (!talk._talkToAbort) { + screen._backBuffer2.blitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y)); + loadInv(); + } +} + +void ScalpelInventory::putInv(InvSlamMode slamIt) { + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + UserInterface &ui = *_vm->_ui; + + // If an inventory item has disappeared (due to using it or giving it), + // a blank space slot may have appeared. If so, adjust the inventory + if (_invIndex > 0 && _invIndex > (_holdings - 6)) { + --_invIndex; + freeGraphics(); + loadGraphics(); + } + + if (slamIt != SLAM_SECONDARY_BUFFER) { + screen.makePanel(Common::Rect(6, 163, 54, 197)); + screen.makePanel(Common::Rect(58, 163, 106, 197)); + screen.makePanel(Common::Rect(110, 163, 158, 197)); + screen.makePanel(Common::Rect(162, 163, 210, 197)); + screen.makePanel(Common::Rect(214, 163, 262, 197)); + screen.makePanel(Common::Rect(266, 163, 314, 197)); + } + + // Iterate through displaying up to 6 objects at a time + for (int idx = _invIndex; idx < _holdings && (idx - _invIndex) < MAX_VISIBLE_INVENTORY; ++idx) { + int itemNum = idx - _invIndex; + Surface &bb = slamIt == SLAM_SECONDARY_BUFFER ? screen._backBuffer2 : screen._backBuffer1; + Common::Rect r(8 + itemNum * 52, 165, 51 + itemNum * 52, 194); + + // Draw the background + if (idx == ui._selector) { + bb.fillRect(r, BUTTON_BACKGROUND); + } + else if (slamIt == SLAM_SECONDARY_BUFFER) { + bb.fillRect(r, BUTTON_MIDDLE); + } + + // Draw the item image + ImageFrame &frame = (*_invShapes[itemNum])[0]; + bb.transBlitFrom(frame, Common::Point(6 + itemNum * 52 + ((47 - frame._width) / 2), + 163 + ((33 - frame._height) / 2))); + } + + if (slamIt == SLAM_DISPLAY) + screen.slamArea(6, 163, 308, 34); + + if (slamIt != SLAM_SECONDARY_BUFFER) + ui.clearInfo(); + + if (slamIt == 0) { + invCommands(0); + } + else if (slamIt == SLAM_SECONDARY_BUFFER) { + screen._backBuffer = &screen._backBuffer2; + invCommands(0); + screen._backBuffer = &screen._backBuffer1; + } +} + +} // End of namespace Scalpel + +} // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel_inventory.h b/engines/sherlock/scalpel/scalpel_inventory.h new file mode 100644 index 0000000000..953e02452f --- /dev/null +++ b/engines/sherlock/scalpel/scalpel_inventory.h @@ -0,0 +1,68 @@ +/* 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_SCALPEL_INVENTORY_H +#define SHERLOCK_SCALPEL_INVENTORY_H + +#include "sherlock/inventory.h" + +namespace Sherlock { + +namespace Scalpel { + +class ScalpelInventory : public Inventory { +public: + ScalpelInventory(SherlockEngine *vm); + ~ScalpelInventory(); + + /** + * Put the game into inventory mode and open the interface window. + */ + void drawInventory(InvNewMode flag); + + /** + * Prints the line of inventory commands at the top of an inventory window with + * the correct highlighting + */ + void invCommands(bool slamIt); + + /** + * Set the highlighting color of a given inventory item + */ + void highlight(int index, byte color); + + /** + * Support method for refreshing the display of the inventory + */ + void refreshInv(); + + /** + * Display the character's inventory. The slamIt parameter specifies: + */ + void putInv(InvSlamMode slamIt); +}; + +} // End of namespace Scalpel + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/scalpel/scalpel_journal.cpp b/engines/sherlock/scalpel/scalpel_journal.cpp index 12ebe6f0f2..8bb74e977d 100644 --- a/engines/sherlock/scalpel/scalpel_journal.cpp +++ b/engines/sherlock/scalpel/scalpel_journal.cpp @@ -23,6 +23,8 @@ #include "sherlock/journal.h" #include "sherlock/sherlock.h" #include "sherlock/scalpel/scalpel_journal.h" +#include "sherlock/scalpel/scalpel_screen.h" +#include "sherlock/scalpel/scalpel.h" #include "sherlock/tattoo/tattoo_journal.h" namespace Sherlock { @@ -147,7 +149,7 @@ void ScalpelJournal::loadLocations() { void ScalpelJournal::drawFrame() { FixedText &fixedText = *_vm->_fixedText; Resources &res = *_vm->_res; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; byte palette[PALETTE_SIZE]; // Load in the journal background @@ -211,7 +213,7 @@ void ScalpelJournal::drawFrame() { } void ScalpelJournal::drawInterface() { - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; drawFrame(); @@ -229,7 +231,7 @@ void ScalpelJournal::drawInterface() { void ScalpelJournal::doArrows() { FixedText &fixedText = *_vm->_fixedText; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; byte color; Common::String fixedText_Back10 = fixedText.getText(kFixedText_Journal_Back10); @@ -301,7 +303,7 @@ JournalButton ScalpelJournal::getHighlightedButton(const Common::Point &pt) { bool ScalpelJournal::handleEvents(int key) { Events &events = *_vm->_events; FixedText &fixedText = *_vm->_fixedText; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; bool doneFlag = false; Common::Point pt = events.mousePos(); @@ -484,7 +486,7 @@ int ScalpelJournal::getSearchString(bool printError) { Events &events = *_vm->_events; FixedText &fixedText = *_vm->_fixedText; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; Talk &talk = *_vm->_talk; int xp; int yp = 174; diff --git a/engines/sherlock/scalpel/scalpel_saveload.cpp b/engines/sherlock/scalpel/scalpel_saveload.cpp new file mode 100644 index 0000000000..01ba149813 --- /dev/null +++ b/engines/sherlock/scalpel/scalpel_saveload.cpp @@ -0,0 +1,261 @@ +/* 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/scalpel/scalpel_saveload.h" +#include "sherlock/scalpel/scalpel_screen.h" +#include "sherlock/scalpel/scalpel.h" + +namespace Sherlock { + +namespace Scalpel { + +const int ENV_POINTS[6][3] = { + { 41, 80, 61 }, // Exit + { 81, 120, 101 }, // Load + { 121, 160, 141 }, // Save + { 161, 200, 181 }, // Up + { 201, 240, 221 }, // Down + { 241, 280, 261 } // Quit +}; + +/*----------------------------------------------------------------*/ + +ScalpelSaveManager::ScalpelSaveManager(SherlockEngine *vm, const Common::String &target) : SaveManager(vm, target) { +} + +void ScalpelSaveManager::drawInterface() { + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + UserInterface &ui = *_vm->_ui; + + // Create a list of savegame slots + createSavegameList(); + + screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + 10), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(318, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(0, 199, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); + + screen.makeButton(Common::Rect(ENV_POINTS[0][0], CONTROLS_Y, ENV_POINTS[0][1], CONTROLS_Y + 10), + ENV_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit"); + screen.makeButton(Common::Rect(ENV_POINTS[1][0], CONTROLS_Y, ENV_POINTS[1][1], CONTROLS_Y + 10), + ENV_POINTS[1][2] - screen.stringWidth("Load") / 2, "Load"); + screen.makeButton(Common::Rect(ENV_POINTS[2][0], CONTROLS_Y, ENV_POINTS[2][1], CONTROLS_Y + 10), + ENV_POINTS[2][2] - screen.stringWidth("Save") / 2, "Save"); + screen.makeButton(Common::Rect(ENV_POINTS[3][0], CONTROLS_Y, ENV_POINTS[3][1], CONTROLS_Y + 10), + ENV_POINTS[3][2] - screen.stringWidth("Up") / 2, "Up"); + screen.makeButton(Common::Rect(ENV_POINTS[4][0], CONTROLS_Y, ENV_POINTS[4][1], CONTROLS_Y + 10), + ENV_POINTS[4][2] - screen.stringWidth("Down") / 2, "Down"); + screen.makeButton(Common::Rect(ENV_POINTS[5][0], CONTROLS_Y, ENV_POINTS[5][1], CONTROLS_Y + 10), + ENV_POINTS[5][2] - screen.stringWidth("Quit") / 2, "Quit"); + + if (!_savegameIndex) + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_NULL, 0, "Up"); + + if (_savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_NULL, 0, "Down"); + + for (int idx = _savegameIndex; idx < _savegameIndex + ONSCREEN_FILES_COUNT; ++idx) { + screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), + INV_FOREGROUND, "%d.", idx + 1); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), + INV_FOREGROUND, "%s", _savegames[idx].c_str()); + } + + if (!ui._slideWindows) { + screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(); + } + + _envMode = SAVEMODE_NONE; +} + +int ScalpelSaveManager::getHighlightedButton() const { + Common::Point pt = _vm->_events->mousePos(); + + for (int idx = 0; idx < 6; ++idx) { + if (pt.x > ENV_POINTS[idx][0] && pt.x < ENV_POINTS[idx][1] && pt.y > CONTROLS_Y + && pt.y < (CONTROLS_Y + 10)) + return idx; + } + + return -1; +} + +void ScalpelSaveManager::highlightButtons(int btnIndex) { + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + byte color = (btnIndex == 0) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND; + + screen.buttonPrint(Common::Point(ENV_POINTS[0][2], CONTROLS_Y), color, 1, "Exit"); + + if ((btnIndex == 1) || ((_envMode == SAVEMODE_LOAD) && (btnIndex != 2))) + screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Load"); + else + screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Load"); + + if ((btnIndex == 2) || ((_envMode == SAVEMODE_SAVE) && (btnIndex != 1))) + screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Save"); + else + screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Save"); + + if (btnIndex == 3 && _savegameIndex) + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Up"); + else + if (_savegameIndex) + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Up"); + + if ((btnIndex == 4) && (_savegameIndex < MAX_SAVEGAME_SLOTS - 5)) + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Down"); + else if (_savegameIndex < (MAX_SAVEGAME_SLOTS - 5)) + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Down"); + + color = (btnIndex == 5) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[5][2], CONTROLS_Y), color, 1, "Quit"); +} + +bool ScalpelSaveManager::checkGameOnScreen(int slot) { + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + + // Check if it's already on-screen + if (slot != -1 && (slot < _savegameIndex || slot >= (_savegameIndex + ONSCREEN_FILES_COUNT))) { + _savegameIndex = slot; + + screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND); + + for (int idx = _savegameIndex; idx < (_savegameIndex + 5); ++idx) { + screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), + INV_FOREGROUND, "%d.", idx + 1); + screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10), + INV_FOREGROUND, "%s", _savegames[idx].c_str()); + } + + screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, 318, SHERLOCK_SCREEN_HEIGHT)); + + byte color = !_savegameIndex ? COMMAND_NULL : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, 1, "Up"); + + color = (_savegameIndex == (MAX_SAVEGAME_SLOTS - 5)) ? COMMAND_NULL : COMMAND_FOREGROUND; + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, 1, "Down"); + + return true; + } + + return false; +} + +bool ScalpelSaveManager::promptForDescription(int slot) { + Events &events = *_vm->_events; + Scene &scene = *_vm->_scene; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + Talk &talk = *_vm->_talk; + int xp, yp; + bool flag = false; + + screen.buttonPrint(Common::Point(ENV_POINTS[0][2], CONTROLS_Y), COMMAND_NULL, true, "Exit"); + screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_NULL, true, "Load"); + screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_NULL, true, "Save"); + screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_NULL, true, "Up"); + screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_NULL, true, "Down"); + screen.buttonPrint(Common::Point(ENV_POINTS[5][2], CONTROLS_Y), COMMAND_NULL, true, "Quit"); + + Common::String saveName = _savegames[slot]; + if (isSlotEmpty(slot)) { + // It's an empty slot, so start off with an empty save name + saveName = ""; + + yp = CONTROLS_Y + 12 + (slot - _savegameIndex) * 10; + screen.vgaBar(Common::Rect(24, yp, 85, yp + 9), INV_BACKGROUND); + } + + screen.print(Common::Point(6, CONTROLS_Y + 12 + (slot - _savegameIndex) * 10), TALK_FOREGROUND, "%d.", slot + 1); + screen.print(Common::Point(24, CONTROLS_Y + 12 + (slot - _savegameIndex) * 10), TALK_FOREGROUND, "%s", saveName.c_str()); + xp = 24 + screen.stringWidth(saveName); + yp = CONTROLS_Y + 12 + (slot - _savegameIndex) * 10; + + int done = 0; + do { + while (!_vm->shouldQuit() && !events.kbHit()) { + scene.doBgAnim(); + + if (talk._talkToAbort) + return false; + + // Allow event processing + events.pollEventsAndWait(); + events.setButtonState(); + + flag = !flag; + if (flag) + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); + else + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); + } + if (_vm->shouldQuit()) + return false; + + // Get the next keypress + Common::KeyState keyState = events.getKey(); + + if (keyState.keycode == Common::KEYCODE_BACKSPACE && saveName.size() > 0) { + // Delete character of save name + screen.vgaBar(Common::Rect(xp - screen.charWidth(saveName.lastChar()), yp - 1, + xp + 8, yp + 9), INV_BACKGROUND); + xp -= screen.charWidth(saveName.lastChar()); + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); + saveName.deleteLastChar(); + + } else if (keyState.keycode == Common::KEYCODE_RETURN && saveName.compareToIgnoreCase(EMPTY_SAVEGAME_SLOT)) { + done = 1; + + } else if (keyState.keycode == Common::KEYCODE_ESCAPE) { + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); + done = -1; + + } else if (keyState.ascii >= ' ' && keyState.ascii <= 'z' && saveName.size() < 50 + && (xp + screen.charWidth(keyState.ascii)) < 308) { + char c = (char)keyState.ascii; + + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND); + screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", c); + xp += screen.charWidth(c); + screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND); + saveName += c; + } + } while (!done); + + if (done == 1) { + // Enter key perssed + _savegames[slot] = saveName; + } else { + done = 0; + _envMode = SAVEMODE_NONE; + highlightButtons(-1); + } + + return done == 1; +} + +} // End of namespace Scalpel + +} // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel_saveload.h b/engines/sherlock/scalpel/scalpel_saveload.h new file mode 100644 index 0000000000..db4fa1a2ab --- /dev/null +++ b/engines/sherlock/scalpel/scalpel_saveload.h @@ -0,0 +1,69 @@ +/* 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_SCALPEL_SAVELOAD_H +#define SHERLOCK_SCALPEL_SAVELOAD_H + +#include "sherlock/saveload.h" + +namespace Sherlock { + +namespace Scalpel { + +extern const int ENV_POINTS[6][3]; + +class ScalpelSaveManager: public SaveManager { +public: + ScalpelSaveManager(SherlockEngine *vm, const Common::String &target); + virtual ~ScalpelSaveManager() {} + + /** + * Shows the in-game dialog interface for loading and saving games + */ + void drawInterface(); + + /** + * Return the index of the button the mouse is over, if any + */ + int getHighlightedButton() const; + + /** + * Handle highlighting buttons + */ + void highlightButtons(int btnIndex); + + /** + * Make sure that the selected savegame is on-screen + */ + bool checkGameOnScreen(int slot); + + /** + * Prompts the user to enter a description in a given slot + */ + bool promptForDescription(int slot); +}; + +} // End of namespace Scalpel + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/scalpel/scalpel_screen.cpp b/engines/sherlock/scalpel/scalpel_screen.cpp new file mode 100644 index 0000000000..2096dabcdf --- /dev/null +++ b/engines/sherlock/scalpel/scalpel_screen.cpp @@ -0,0 +1,93 @@ +/* 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/scalpel/scalpel_screen.h" +#include "sherlock/scalpel/scalpel.h" + +namespace Sherlock { + +namespace Scalpel { + +ScalpelScreen::ScalpelScreen(SherlockEngine *vm) : Screen(vm) { +} + +void ScalpelScreen::makeButton(const Common::Rect &bounds, int textX, + const Common::String &str) { + + Surface &bb = *_backBuffer; + bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); + bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); + bb.fillRect(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); + bb.fillRect(Common::Rect(bounds.left + 1, bounds.bottom - 1, bounds.right, bounds.bottom), BUTTON_BOTTOM); + bb.fillRect(Common::Rect(bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1), BUTTON_MIDDLE); + + gPrint(Common::Point(textX, bounds.top), COMMAND_HIGHLIGHTED, "%c", str[0]); + gPrint(Common::Point(textX + charWidth(str[0]), bounds.top), + COMMAND_FOREGROUND, "%s", str.c_str() + 1); +} + +void ScalpelScreen::buttonPrint(const Common::Point &pt, byte color, bool slamIt, + const Common::String &str) { + int xStart = pt.x - stringWidth(str) / 2; + + if (color == COMMAND_FOREGROUND) { + // First character needs to be highlighted + if (slamIt) { + print(Common::Point(xStart, pt.y + 1), COMMAND_HIGHLIGHTED, "%c", str[0]); + print(Common::Point(xStart + charWidth(str[0]), pt.y + 1), + COMMAND_FOREGROUND, "%s", str.c_str() + 1); + } else { + gPrint(Common::Point(xStart, pt.y), COMMAND_HIGHLIGHTED, "%c", str[0]); + gPrint(Common::Point(xStart + charWidth(str[0]), pt.y), + COMMAND_FOREGROUND, "%s", str.c_str() + 1); + } + } else if (slamIt) { + print(Common::Point(xStart, pt.y + 1), color, "%s", str.c_str()); + } else { + gPrint(Common::Point(xStart, pt.y), color, "%s", str.c_str()); + } +} + +void ScalpelScreen::makePanel(const Common::Rect &r) { + _backBuffer->fillRect(r, BUTTON_MIDDLE); + _backBuffer->hLine(r.left, r.top, r.right - 2, BUTTON_TOP); + _backBuffer->hLine(r.left + 1, r.top + 1, r.right - 3, BUTTON_TOP); + _backBuffer->vLine(r.left, r.top, r.bottom - 1, BUTTON_TOP); + _backBuffer->vLine(r.left + 1, r.top + 1, r.bottom - 2, BUTTON_TOP); + + _backBuffer->vLine(r.right - 1, r.top, r.bottom - 1, BUTTON_BOTTOM); + _backBuffer->vLine(r.right - 2, r.top + 1, r.bottom - 2, BUTTON_BOTTOM); + _backBuffer->hLine(r.left, r.bottom - 1, r.right - 1, BUTTON_BOTTOM); + _backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM); +} + +void ScalpelScreen::makeField(const Common::Rect &r) { + _backBuffer->fillRect(r, BUTTON_MIDDLE); + _backBuffer->hLine(r.left, r.top, r.right - 1, BUTTON_BOTTOM); + _backBuffer->hLine(r.left + 1, r.bottom - 1, r.right - 1, BUTTON_TOP); + _backBuffer->vLine(r.left, r.top + 1, r.bottom - 1, BUTTON_BOTTOM); + _backBuffer->vLine(r.right - 1, r.top + 1, r.bottom - 2, BUTTON_TOP); +} + +} // End of namespace Scalpel + +} // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel_screen.h b/engines/sherlock/scalpel/scalpel_screen.h new file mode 100644 index 0000000000..472fe9e220 --- /dev/null +++ b/engines/sherlock/scalpel/scalpel_screen.h @@ -0,0 +1,66 @@ +/* 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_SCALPEL_SCREEN_H +#define SHERLOCK_SCALPEL_SCREEN_H + +#include "sherlock/screen.h" + +namespace Sherlock { + +class SherlockEngine; + +namespace Scalpel { + +class ScalpelScreen : public Screen { +public: + ScalpelScreen(SherlockEngine *vm); + virtual ~ScalpelScreen() {} + + /** + * Draws a button for use in the inventory, talk, and examine dialogs. + */ + void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); + + /** + * Prints an interface command with the first letter highlighted to indicate + * what keyboard shortcut is associated with it + */ + void buttonPrint(const Common::Point &pt, byte color, bool slamIt, const Common::String &str); + + /** + * Draw a panel in the back buffer with a raised area effect around the edges + */ + void makePanel(const Common::Rect &r); + + /** + * Draw a field in the back buffer with a raised area effect around the edges, + * suitable for text input. + */ + void makeField(const Common::Rect &r); +}; + +} // End of namespace Scalpel + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/scalpel/scalpel_talk.cpp b/engines/sherlock/scalpel/scalpel_talk.cpp index 5a2427cac2..33d0e4a3ad 100644 --- a/engines/sherlock/scalpel/scalpel_talk.cpp +++ b/engines/sherlock/scalpel/scalpel_talk.cpp @@ -24,8 +24,9 @@ #include "sherlock/scalpel/scalpel_map.h" #include "sherlock/scalpel/scalpel_people.h" #include "sherlock/scalpel/scalpel_scene.h" +#include "sherlock/scalpel/scalpel_screen.h" #include "sherlock/scalpel/scalpel_user_interface.h" -#include "sherlock/sherlock.h" +#include "sherlock/scalpel/scalpel.h" #include "sherlock/screen.h" #include "sherlock/scalpel/3do/movie_decoder.h" @@ -173,7 +174,7 @@ ScalpelTalk::ScalpelTalk(SherlockEngine *vm) : Talk(vm) { void ScalpelTalk::talkInterface(const byte *&str) { FixedText &fixedText = *_vm->_fixedText; People &people = *_vm->_people; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; UserInterface &ui = *_vm->_ui; // If the window isn't yet open, draw the window before printing starts @@ -504,7 +505,7 @@ OpcodeReturn ScalpelTalk::cmdSfxCommand(const byte *&str) { OpcodeReturn ScalpelTalk::cmdSummonWindow(const byte *&str) { Events &events = *_vm->_events; FixedText &fixedText = *_vm->_fixedText; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; drawInterface(); events._pressed = events._released = false; @@ -597,6 +598,240 @@ void ScalpelTalk::talk3DOMovieTrigger(int subIndex) { _vm->_screen->makeAllDirty(); } +void ScalpelTalk::drawInterface() { + FixedText &fixedText = *_vm->_fixedText; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + Surface &bb = *screen._backBuffer; + + bb.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 10), BORDER_COLOR); + bb.fillRect(Common::Rect(0, CONTROLS_Y + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 10, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); + bb.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, + SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); + + if (_talkTo != -1) { + Common::String fixedText_Exit = fixedText.getText(kFixedText_Window_Exit); + Common::String fixedText_Up = fixedText.getText(kFixedText_Window_Up); + Common::String fixedText_Down = fixedText.getText(kFixedText_Window_Down); + + screen.makeButton(Common::Rect(99, CONTROLS_Y, 139, CONTROLS_Y + 10), + 119 - screen.stringWidth(fixedText_Exit) / 2, fixedText_Exit); + screen.makeButton(Common::Rect(140, CONTROLS_Y, 180, CONTROLS_Y + 10), + 159 - screen.stringWidth(fixedText_Up) / 2, fixedText_Up); + screen.makeButton(Common::Rect(181, CONTROLS_Y, 221, CONTROLS_Y + 10), + 200 - screen.stringWidth(fixedText_Down) / 2, fixedText_Down); + } else { + int strWidth = screen.stringWidth(Scalpel::PRESS_KEY_TO_CONTINUE); + screen.makeButton(Common::Rect(46, CONTROLS_Y, 273, CONTROLS_Y + 10), + 160 - strWidth / 2, Scalpel::PRESS_KEY_TO_CONTINUE); + screen.gPrint(Common::Point(160 - strWidth / 2, CONTROLS_Y), COMMAND_FOREGROUND, "P"); + } +} + +bool ScalpelTalk::displayTalk(bool slamIt) { + FixedText &fixedText = *_vm->_fixedText; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + int yp = CONTROLS_Y + 14; + int lineY = -1; + _moreTalkDown = _moreTalkUp = false; + + for (uint idx = 0; idx < _statements.size(); ++idx) { + _statements[idx]._talkPos.top = _statements[idx]._talkPos.bottom = -1; + } + + if (_talkIndex) { + for (int idx = 0; idx < _talkIndex && !_moreTalkUp; ++idx) { + if (_statements[idx]._talkMap != -1) + _moreTalkUp = true; + } + } + + // Display the up arrow and enable Up button if the first option is scrolled off-screen + Common::String fixedText_Up = fixedText.getText(kFixedText_Window_Up); + Common::String fixedText_Down = fixedText.getText(kFixedText_Window_Down); + if (_moreTalkUp) { + if (slamIt) { + screen.print(Common::Point(5, CONTROLS_Y + 13), INV_FOREGROUND, "~"); + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, true, fixedText_Up); + } else { + screen.gPrint(Common::Point(5, CONTROLS_Y + 12), INV_FOREGROUND, "~"); + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, false, fixedText_Up); + } + } else { + if (slamIt) { + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, true, fixedText_Up); + screen.vgaBar(Common::Rect(5, CONTROLS_Y + 11, 15, CONTROLS_Y + 22), INV_BACKGROUND); + } else { + screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, fixedText_Up); + screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, + 15, CONTROLS_Y + 22), INV_BACKGROUND); + } + } + + // Loop through the statements + bool done = false; + for (uint idx = _talkIndex; idx < _statements.size() && !done; ++idx) { + Statement &statement = _statements[idx]; + + if (statement._talkMap != -1) { + bool flag = _talkHistory[_converseNum][idx]; + lineY = talkLine(idx, statement._talkMap, flag ? TALK_NULL : INV_FOREGROUND, + yp, slamIt); + + if (lineY != -1) { + statement._talkPos.top = yp; + yp = lineY; + statement._talkPos.bottom = yp; + + if (yp == SHERLOCK_SCREEN_HEIGHT) + done = true; + } else { + done = true; + } + } + } + + // Display the down arrow and enable down button if there are more statements available down off-screen + if (lineY == -1 || lineY == SHERLOCK_SCREEN_HEIGHT) { + _moreTalkDown = true; + + if (slamIt) { + screen.print(Common::Point(5, 190), INV_FOREGROUND, "|"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, true, fixedText_Down); + } else { + screen.gPrint(Common::Point(5, 189), INV_FOREGROUND, "|"); + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, false, fixedText_Down); + } + } else { + if (slamIt) { + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, true, fixedText_Down); + screen.vgaBar(Common::Rect(5, 189, 16, 199), INV_BACKGROUND); + } else { + screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, fixedText_Down); + screen._backBuffer1.fillRect(Common::Rect(5, 189, 16, 199), INV_BACKGROUND); + } + } + + return done; +} + +int ScalpelTalk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt) { + Screen &screen = *_vm->_screen; + int idx = lineNum; + Common::String msg, number; + bool numberFlag = false; + + // Get the statement to display as well as optional number prefix + if (idx < SPEAKER_REMOVE) { + number = Common::String::format("%d.", stateNum + 1); + numberFlag = true; + } else { + idx -= SPEAKER_REMOVE; + } + msg = _statements[idx]._statement; + + // Handle potentially multiple lines needed to display entire statement + const char *lineStartP = msg.c_str(); + int maxWidth = 298 - (numberFlag ? 18 : 0); + for (;;) { + // Get as much of the statement as possible will fit on the + Common::String sLine; + const char *lineEndP = lineStartP; + int width = 0; + do { + width += screen.charWidth(*lineEndP); + } while (*++lineEndP && width < maxWidth); + + // Check if we need to wrap the line + if (width >= maxWidth) { + // Work backwards to the prior word's end + while (*--lineEndP != ' ') + ; + + sLine = Common::String(lineStartP, lineEndP++); + } else { + // Can display remainder of the statement on the current line + sLine = Common::String(lineStartP); + } + + + if (lineY <= (SHERLOCK_SCREEN_HEIGHT - 10)) { + // Need to directly display on-screen? + if (slamIt) { + // See if a numer prefix is needed or not + if (numberFlag) { + // Are we drawing the first line? + if (lineStartP == msg.c_str()) { + // We are, so print the number and then the text + screen.print(Common::Point(16, lineY), color, "%s", number.c_str()); + } + + // Draw the line with an indent + screen.print(Common::Point(30, lineY), color, "%s", sLine.c_str()); + } else { + screen.print(Common::Point(16, lineY), color, "%s", sLine.c_str()); + } + } else { + if (numberFlag) { + if (lineStartP == msg.c_str()) { + screen.gPrint(Common::Point(16, lineY - 1), color, "%s", number.c_str()); + } + + screen.gPrint(Common::Point(30, lineY - 1), color, "%s", sLine.c_str()); + } else { + screen.gPrint(Common::Point(16, lineY - 1), color, "%s", sLine.c_str()); + } + } + + // Move to next line, if any + lineY += 9; + lineStartP = lineEndP; + + if (!*lineEndP) + break; + } else { + // We're close to the bottom of the screen, so stop display + lineY = -1; + break; + } + } + + if (lineY == -1 && lineStartP != msg.c_str()) + lineY = SHERLOCK_SCREEN_HEIGHT; + + // Return the Y position of the next line to follow this one + return lineY; +} + +void ScalpelTalk::showTalk() { + FixedText &fixedText = *_vm->_fixedText; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; + ScalpelUserInterface &ui = *(ScalpelUserInterface *)_vm->_ui; + Common::String fixedText_Exit = fixedText.getText(kFixedText_Window_Exit); + byte color = ui._endKeyActive ? COMMAND_FOREGROUND : COMMAND_NULL; + + // If the window is already open, simply draw. Otherwise, do it + // to the back buffer and then summon the window + if (ui._windowOpen) { + screen.buttonPrint(Common::Point(119, CONTROLS_Y), color, true, fixedText_Exit); + } else { + screen.buttonPrint(Common::Point(119, CONTROLS_Y), color, false, fixedText_Exit); + + if (!ui._slideWindows) { + screen.slamRect(Common::Rect(0, CONTROLS_Y, + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + } else { + ui.summonWindow(); + } + + ui._windowOpen = true; + } + +} + } // End of namespace Scalpel } // End of namespace Sherlock diff --git a/engines/sherlock/scalpel/scalpel_talk.h b/engines/sherlock/scalpel/scalpel_talk.h index 2f8e412795..01e7c053dd 100644 --- a/engines/sherlock/scalpel/scalpel_talk.h +++ b/engines/sherlock/scalpel/scalpel_talk.h @@ -68,9 +68,29 @@ protected: */ virtual void talk3DOMovieTrigger(int subIndex); + /** + * Show the talk display + */ + virtual void showTalk(); public: ScalpelTalk(SherlockEngine *vm); virtual ~ScalpelTalk() {} + + /** + * Draws the interface for conversation display + */ + void drawInterface(); + + /** + * Display a list of statements in a window at the bottom of the screen that the + * player can select from. + */ + bool displayTalk(bool slamIt); + + /** + * Prints a single conversation option in the interface window + */ + int talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt); }; } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp index f85c95e25b..9a07a40ee5 100644 --- a/engines/sherlock/scalpel/scalpel_user_interface.cpp +++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp @@ -21,9 +21,13 @@ */ #include "sherlock/scalpel/scalpel_user_interface.h" +#include "sherlock/scalpel/scalpel_inventory.h" #include "sherlock/scalpel/scalpel_journal.h" #include "sherlock/scalpel/scalpel_people.h" +#include "sherlock/scalpel/scalpel_saveload.h" +#include "sherlock/scalpel/scalpel_screen.h" #include "sherlock/scalpel/settings.h" +#include "sherlock/scalpel/scalpel.h" #include "sherlock/sherlock.h" namespace Sherlock { @@ -666,9 +670,9 @@ void ScalpelUserInterface::lookInv() { void ScalpelUserInterface::doEnvControl() { Events &events = *_vm->_events; - SaveManager &saves = *_vm->_saves; + ScalpelSaveManager &saves = *(ScalpelSaveManager *)_vm->_saves; Scene &scene = *_vm->_scene; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; Talk &talk = *_vm->_talk; Common::Point mousePos = events.mousePos(); static const char ENV_COMMANDS[7] = "ELSUDQ"; @@ -969,9 +973,9 @@ void ScalpelUserInterface::doEnvControl() { void ScalpelUserInterface::doInvControl() { Events &events = *_vm->_events; FixedText &fixedText = *_vm->_fixedText; - Inventory &inv = *_vm->_inventory; + ScalpelInventory &inv = *(ScalpelInventory *)_vm->_inventory; Scene &scene = *_vm->_scene; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; Talk &talk = *_vm->_talk; int colors[8]; Common::Point mousePos = events.mousePos(); @@ -1197,7 +1201,7 @@ void ScalpelUserInterface::doInvControl() { void ScalpelUserInterface::doLookControl() { Events &events = *_vm->_events; - Inventory &inv = *_vm->_inventory; + ScalpelInventory &inv = *(ScalpelInventory *)_vm->_inventory; Screen &screen = *_vm->_screen; _key = _oldKey = -1; @@ -1259,8 +1263,8 @@ void ScalpelUserInterface::doLookControl() { void ScalpelUserInterface::doMainControl() { Events &events = *_vm->_events; - Inventory &inv = *_vm->_inventory; - SaveManager &saves = *_vm->_saves; + ScalpelInventory &inv = *(ScalpelInventory *)_vm->_inventory; + ScalpelSaveManager &saves = *(ScalpelSaveManager *)_vm->_saves; Common::Point pt = events.mousePos(); if ((events._pressed || events._released) && pt.y > CONTROLS_Y) { @@ -1476,7 +1480,7 @@ void ScalpelUserInterface::doTalkControl() { FixedText &fixedText = *_vm->_fixedText; ScalpelJournal &journal = *(ScalpelJournal *)_vm->_journal; ScalpelPeople &people = *(ScalpelPeople *)_vm->_people; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; Sound &sound = *_vm->_sound; Talk &talk = *_vm->_talk; Common::Point mousePos = events.mousePos(); @@ -1781,8 +1785,8 @@ void ScalpelUserInterface::journalControl() { void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool firstTime) { Events &events = *_vm->_events; - Inventory &inv = *_vm->_inventory; - Screen &screen = *_vm->_screen; + ScalpelInventory &inv = *(ScalpelInventory *)_vm->_inventory; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; Talk &talk = *_vm->_talk; if (str.hasPrefix("_")) { diff --git a/engines/sherlock/scalpel/settings.cpp b/engines/sherlock/scalpel/settings.cpp index aa8033d25e..f6769a4b99 100644 --- a/engines/sherlock/scalpel/settings.cpp +++ b/engines/sherlock/scalpel/settings.cpp @@ -22,7 +22,9 @@ #include "sherlock/sherlock.h" #include "sherlock/scalpel/settings.h" +#include "sherlock/scalpel/scalpel_screen.h" #include "sherlock/scalpel/scalpel_user_interface.h" +#include "sherlock/scalpel/scalpel.h" namespace Sherlock { @@ -56,7 +58,7 @@ static const char *const SETUP_NAMES[12] = { void Settings::drawInteface(bool flag) { People &people = *_vm->_people; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; Sound &sound = *_vm->_sound; Music &music = *_vm->_music; UserInterface &ui = *_vm->_ui; @@ -138,7 +140,7 @@ void Settings::drawInteface(bool flag) { int Settings::drawButtons(const Common::Point &pt, int _key) { Events &events = *_vm->_events; People &people = *_vm->_people; - Screen &screen = *_vm->_screen; + ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen; Music &music = *_vm->_music; Sound &sound = *_vm->_sound; UserInterface &ui = *_vm->_ui; diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index fdc10fdf33..4c6e0ef748 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -22,12 +22,20 @@ #include "sherlock/screen.h" #include "sherlock/sherlock.h" +#include "sherlock/scalpel/scalpel_screen.h" #include "common/system.h" #include "common/util.h" #include "graphics/palette.h" namespace Sherlock { +Screen *Screen::init(SherlockEngine *vm) { + if (vm->getGameID() == GType_SerratedScalpel) + return new Scalpel::ScalpelScreen(vm); + else + return new Screen(vm); +} + Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->getHeight()), _vm(vm), _backBuffer1(g_system->getWidth(), g_system->getHeight()), _backBuffer2(g_system->getWidth(), g_system->getHeight()), @@ -486,64 +494,6 @@ void Screen::vgaBar(const Common::Rect &r, int color) { slamRect(r); } -void Screen::makeButton(const Common::Rect &bounds, int textX, - const Common::String &str) { - - Surface &bb = *_backBuffer; - bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); - bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); - bb.fillRect(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); - bb.fillRect(Common::Rect(bounds.left + 1, bounds.bottom - 1, bounds.right, bounds.bottom), BUTTON_BOTTOM); - bb.fillRect(Common::Rect(bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1), BUTTON_MIDDLE); - - gPrint(Common::Point(textX, bounds.top), COMMAND_HIGHLIGHTED, "%c", str[0]); - gPrint(Common::Point(textX + charWidth(str[0]), bounds.top), - COMMAND_FOREGROUND, "%s", str.c_str() + 1); -} - -void Screen::buttonPrint(const Common::Point &pt, byte color, bool slamIt, - const Common::String &str) { - int xStart = pt.x - stringWidth(str) / 2; - - if (color == COMMAND_FOREGROUND) { - // First character needs to be highlighted - if (slamIt) { - print(Common::Point(xStart, pt.y + 1), COMMAND_HIGHLIGHTED, "%c", str[0]); - print(Common::Point(xStart + charWidth(str[0]), pt.y + 1), - COMMAND_FOREGROUND, "%s", str.c_str() + 1); - } else { - gPrint(Common::Point(xStart, pt.y), COMMAND_HIGHLIGHTED, "%c", str[0]); - gPrint(Common::Point(xStart + charWidth(str[0]), pt.y), - COMMAND_FOREGROUND, "%s", str.c_str() + 1); - } - } else if (slamIt) { - print(Common::Point(xStart, pt.y + 1), color, "%s", str.c_str()); - } else { - gPrint(Common::Point(xStart, pt.y), color, "%s", str.c_str()); - } -} - -void Screen::makePanel(const Common::Rect &r) { - _backBuffer->fillRect(r, BUTTON_MIDDLE); - _backBuffer->hLine(r.left, r.top, r.right - 2, BUTTON_TOP); - _backBuffer->hLine(r.left + 1, r.top + 1, r.right - 3, BUTTON_TOP); - _backBuffer->vLine(r.left, r.top, r.bottom - 1, BUTTON_TOP); - _backBuffer->vLine(r.left + 1, r.top + 1, r.bottom - 2, BUTTON_TOP); - - _backBuffer->vLine(r.right - 1, r.top, r.bottom - 1, BUTTON_BOTTOM); - _backBuffer->vLine(r.right - 2, r.top + 1, r.bottom - 2, BUTTON_BOTTOM); - _backBuffer->hLine(r.left, r.bottom - 1, r.right - 1, BUTTON_BOTTOM); - _backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM); -} - -void Screen::makeField(const Common::Rect &r) { - _backBuffer->fillRect(r, BUTTON_MIDDLE); - _backBuffer->hLine(r.left, r.top, r.right - 1, BUTTON_BOTTOM); - _backBuffer->hLine(r.left + 1, r.bottom - 1, r.right - 1, BUTTON_TOP); - _backBuffer->vLine(r.left, r.top + 1, r.bottom - 1, BUTTON_BOTTOM); - _backBuffer->vLine(r.right - 1, r.top + 1, r.bottom - 2, BUTTON_TOP); -} - void Screen::setDisplayBounds(const Common::Rect &r) { assert(r.left == 0 && r.top == 0); _sceneSurface.setPixels(_backBuffer1.getPixels(), r.width(), r.height(), _backBuffer1.getPixelFormat()); diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index a4b1a837b8..b67361e339 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -44,10 +44,8 @@ enum { BORDER_COLOR = 237, INV_FOREGROUND = 14, INV_BACKGROUND = 1, - COMMAND_HIGHLIGHTED = 10, COMMAND_FOREGROUND = 15, COMMAND_BACKGROUND = 4, - COMMAND_NULL = 248, BUTTON_TOP = 233, BUTTON_MIDDLE = 244, BUTTON_BOTTOM = 248, @@ -94,6 +92,7 @@ public: byte _tMap[PALETTE_SIZE]; bool _flushScreen; public: + static Screen *init(SherlockEngine *vm); Screen(SherlockEngine *vm); virtual ~Screen(); @@ -209,28 +208,6 @@ public: */ void vgaBar(const Common::Rect &r, int color); - /** - * Draws a button for use in the inventory, talk, and examine dialogs. - */ - void makeButton(const Common::Rect &bounds, int textX, const Common::String &str); - - /** - * Prints an interface command with the first letter highlighted to indicate - * what keyboard shortcut is associated with it - */ - void buttonPrint(const Common::Point &pt, byte color, bool slamIt, const Common::String &str); - - /** - * Draw a panel in the back buffer with a raised area effect around the edges - */ - void makePanel(const Common::Rect &r); - - /** - * Draw a field in the back buffer with a raised area effect around the edges, - * suitable for text input. - */ - void makeField(const Common::Rect &r); - /** * Sets the active back buffer pointer to a restricted sub-area of the first back buffer */ diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index aac6986ac8..f491023718 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -96,14 +96,14 @@ void SherlockEngine::initialize() { _debugger = new Debugger(this); _events = new Events(this); _fixedText = new FixedText(this); - _inventory = new Inventory(this); + _inventory = Inventory::init(this); _map = Map::init(this); _music = new Music(this, _mixer); _journal = Journal::init(this); _people = People::init(this); - _saves = new SaveManager(this, _targetName); + _saves = SaveManager::init(this, _targetName); _scene = Scene::init(this); - _screen = new Screen(this); + _screen = Screen::init(this); _sound = new Sound(this, _mixer); _talk = Talk::init(this); _ui = UserInterface::init(this); diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 050d319cfb..1195ba0b6b 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -23,9 +23,11 @@ #include "sherlock/talk.h" #include "sherlock/sherlock.h" #include "sherlock/screen.h" +#include "sherlock/scalpel/scalpel.h" #include "sherlock/scalpel/scalpel_people.h" #include "sherlock/scalpel/scalpel_talk.h" #include "sherlock/scalpel/scalpel_user_interface.h" +#include "sherlock/tattoo/tattoo.h" #include "sherlock/tattoo/tattoo_people.h" #include "sherlock/tattoo/tattoo_talk.h" @@ -133,7 +135,6 @@ Talk::Talk(SherlockEngine *vm) : _vm(vm) { void Talk::talkTo(const Common::String &filename) { Events &events = *_vm->_events; - FixedText &fixedText = *_vm->_fixedText; Inventory &inv = *_vm->_inventory; Journal &journal = *_vm->_journal; People &people = *_vm->_people; @@ -389,25 +390,7 @@ void Talk::talkTo(const Common::String &filename) { displayTalk(true); } - byte color = ui._endKeyActive ? COMMAND_FOREGROUND : COMMAND_NULL; - - // If the window is already open, simply draw. Otherwise, do it - // to the back buffer and then summon the window - Common::String fixedText_Exit = fixedText.getText(kFixedText_Window_Exit); - if (ui._windowOpen) { - screen.buttonPrint(Common::Point(119, CONTROLS_Y), color, true, fixedText_Exit); - } else { - screen.buttonPrint(Common::Point(119, CONTROLS_Y), color, false, fixedText_Exit); - - if (!ui._slideWindows) { - screen.slamRect(Common::Rect(0, CONTROLS_Y, - SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); - } else { - ui.summonWindow(); - } - - ui._windowOpen = true; - } + showTalk(); // Break out of loop now that we're waiting for player input events.setCursor(ARROW); @@ -635,214 +618,6 @@ void Talk::setTalkMap() { } } -void Talk::drawInterface() { - FixedText &fixedText = *_vm->_fixedText; - Screen &screen = *_vm->_screen; - Surface &bb = *screen._backBuffer; - - bb.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 10), BORDER_COLOR); - bb.fillRect(Common::Rect(0, CONTROLS_Y + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 10, - SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 2, - SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR); - bb.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2, - SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND); - - if (_talkTo != -1) { - Common::String fixedText_Exit = fixedText.getText(kFixedText_Window_Exit); - Common::String fixedText_Up = fixedText.getText(kFixedText_Window_Up); - Common::String fixedText_Down = fixedText.getText(kFixedText_Window_Down); - - screen.makeButton(Common::Rect(99, CONTROLS_Y, 139, CONTROLS_Y + 10), - 119 - screen.stringWidth(fixedText_Exit) / 2, fixedText_Exit); - screen.makeButton(Common::Rect(140, CONTROLS_Y, 180, CONTROLS_Y + 10), - 159 - screen.stringWidth(fixedText_Up) / 2, fixedText_Up); - screen.makeButton(Common::Rect(181, CONTROLS_Y, 221, CONTROLS_Y + 10), - 200 - screen.stringWidth(fixedText_Down) / 2, fixedText_Down); - } else { - int strWidth = screen.stringWidth(Scalpel::PRESS_KEY_TO_CONTINUE); - screen.makeButton(Common::Rect(46, CONTROLS_Y, 273, CONTROLS_Y + 10), - 160 - strWidth / 2, Scalpel::PRESS_KEY_TO_CONTINUE); - screen.gPrint(Common::Point(160 - strWidth / 2, CONTROLS_Y), COMMAND_FOREGROUND, "P"); - } -} - -bool Talk::displayTalk(bool slamIt) { - FixedText &fixedText = *_vm->_fixedText; - Screen &screen = *_vm->_screen; - int yp = CONTROLS_Y + 14; - int lineY = -1; - _moreTalkDown = _moreTalkUp = false; - - for (uint idx = 0; idx < _statements.size(); ++idx) { - _statements[idx]._talkPos.top = _statements[idx]._talkPos.bottom = -1; - } - - if (_talkIndex) { - for (int idx = 0; idx < _talkIndex && !_moreTalkUp; ++idx) { - if (_statements[idx]._talkMap != -1) - _moreTalkUp = true; - } - } - - // Display the up arrow and enable Up button if the first option is scrolled off-screen - Common::String fixedText_Up = fixedText.getText(kFixedText_Window_Up); - Common::String fixedText_Down = fixedText.getText(kFixedText_Window_Down); - if (_moreTalkUp) { - if (slamIt) { - screen.print(Common::Point(5, CONTROLS_Y + 13), INV_FOREGROUND, "~"); - screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, true, fixedText_Up); - } else { - screen.gPrint(Common::Point(5, CONTROLS_Y + 12), INV_FOREGROUND, "~"); - screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, false, fixedText_Up); - } - } else { - if (slamIt) { - screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, true, fixedText_Up); - screen.vgaBar(Common::Rect(5, CONTROLS_Y + 11, 15, CONTROLS_Y + 22), INV_BACKGROUND); - } else { - screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, fixedText_Up); - screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, - 15, CONTROLS_Y + 22), INV_BACKGROUND); - } - } - - // Loop through the statements - bool done = false; - for (uint idx = _talkIndex; idx < _statements.size() && !done; ++idx) { - Statement &statement = _statements[idx]; - - if (statement._talkMap != -1) { - bool flag = _talkHistory[_converseNum][idx]; - lineY = talkLine(idx, statement._talkMap, flag ? TALK_NULL : INV_FOREGROUND, - yp, slamIt); - - if (lineY != -1) { - statement._talkPos.top = yp; - yp = lineY; - statement._talkPos.bottom = yp; - - if (yp == SHERLOCK_SCREEN_HEIGHT) - done = true; - } else { - done = true; - } - } - } - - // Display the down arrow and enable down button if there are more statements available down off-screen - if (lineY == -1 || lineY == SHERLOCK_SCREEN_HEIGHT) { - _moreTalkDown = true; - - if (slamIt) { - screen.print(Common::Point(5, 190), INV_FOREGROUND, "|"); - screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, true, fixedText_Down); - } else { - screen.gPrint(Common::Point(5, 189), INV_FOREGROUND, "|"); - screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, false, fixedText_Down); - } - } else { - if (slamIt) { - screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, true, fixedText_Down); - screen.vgaBar(Common::Rect(5, 189, 16, 199), INV_BACKGROUND); - } else { - screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, fixedText_Down); - screen._backBuffer1.fillRect(Common::Rect(5, 189, 16, 199), INV_BACKGROUND); - } - } - - return done; -} - -int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt) { - Screen &screen = *_vm->_screen; - int idx = lineNum; - Common::String msg, number; - bool numberFlag = false; - - // Get the statement to display as well as optional number prefix - if (idx < SPEAKER_REMOVE) { - number = Common::String::format("%d.", stateNum + 1); - numberFlag = true; - } else { - idx -= SPEAKER_REMOVE; - } - msg = _statements[idx]._statement; - - // Handle potentially multiple lines needed to display entire statement - const char *lineStartP = msg.c_str(); - int maxWidth = 298 - (numberFlag ? 18 : 0); - for (;;) { - // Get as much of the statement as possible will fit on the - Common::String sLine; - const char *lineEndP = lineStartP; - int width = 0; - do { - width += screen.charWidth(*lineEndP); - } while (*++lineEndP && width < maxWidth); - - // Check if we need to wrap the line - if (width >= maxWidth) { - // Work backwards to the prior word's end - while (*--lineEndP != ' ') - ; - - sLine = Common::String(lineStartP, lineEndP++); - } else { - // Can display remainder of the statement on the current line - sLine = Common::String(lineStartP); - } - - - if (lineY <= (SHERLOCK_SCREEN_HEIGHT - 10)) { - // Need to directly display on-screen? - if (slamIt) { - // See if a numer prefix is needed or not - if (numberFlag) { - // Are we drawing the first line? - if (lineStartP == msg.c_str()) { - // We are, so print the number and then the text - screen.print(Common::Point(16, lineY), color, "%s", number.c_str()); - } - - // Draw the line with an indent - screen.print(Common::Point(30, lineY), color, "%s", sLine.c_str()); - } else { - screen.print(Common::Point(16, lineY), color, "%s", sLine.c_str()); - } - } else { - if (numberFlag) { - if (lineStartP == msg.c_str()) { - screen.gPrint(Common::Point(16, lineY - 1), color, "%s", number.c_str()); - } - - screen.gPrint(Common::Point(30, lineY - 1), color, "%s", sLine.c_str()); - } else { - screen.gPrint(Common::Point(16, lineY - 1), color, "%s", sLine.c_str()); - } - } - - // Move to next line, if any - lineY += 9; - lineStartP = lineEndP; - - if (!*lineEndP) - break; - } else { - // We're close to the bottom of the screen, so stop display - lineY = -1; - break; - } - } - - if (lineY == -1 && lineStartP != msg.c_str()) - lineY = SHERLOCK_SCREEN_HEIGHT; - - // Return the Y position of the next line to follow this one - return lineY; -} - void Talk::clearSequences() { _sequenceStack.clear(); } diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index 62a839e4ea..ef11551d52 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -185,17 +185,6 @@ private: */ void setTalkMap(); - /** - * Display a list of statements in a window at the bottom of the screen that the - * player can select from. - */ - bool displayTalk(bool slamIt); - - /** - * Prints a single conversation option in the interface window - */ - int talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt); - /** * Parses a reply for control codes and display text. The found text is printed within * the text window, handles delays, animations, and animating portraits. @@ -207,7 +196,6 @@ private: * the amount of text that's been displayed */ int waitForMore(int delay); - protected: SherlockEngine *_vm; OpcodeMethod *_opcodeTable; @@ -273,7 +261,11 @@ protected: * Trigger to play a 3DO talk dialog movie */ virtual void talk3DOMovieTrigger(int subIndex) {}; - + + /** + * Show the talk display + */ + virtual void showTalk() {} public: TalkSequence _talkSequenceStack[TALK_SEQUENCE_STACK_SIZE]; Common::Array _statements; @@ -286,7 +278,6 @@ public: bool _moreTalkUp, _moreTalkDown; int _converseNum; const byte *_opcodes; - public: static Talk *init(SherlockEngine *vm); virtual ~Talk() {} @@ -319,11 +310,6 @@ public: */ void freeTalkVars(); - /** - * Draws the interface for conversation display - */ - void drawInterface(); - /** * Opens the talk file 'talk.tlk' and searches the index for the specified * conversation. If found, the data for that conversation is loaded @@ -372,6 +358,22 @@ public: * Synchronize the data for a savegame */ void synchronize(Serializer &s); + + /** + * Draws the interface for conversation display + */ + virtual void drawInterface() {} + + /** + * Display a list of statements in a window at the bottom of the screen that the + * player can select from. + */ + virtual bool displayTalk(bool slamIt) { return false; } + + /** + * Prints a single conversation option in the interface window + */ + virtual int talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt) { return 0; } }; } // End of namespace Sherlock diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h index 9ef2e0a563..aa07d857c4 100644 --- a/engines/sherlock/tattoo/tattoo.h +++ b/engines/sherlock/tattoo/tattoo.h @@ -33,7 +33,10 @@ enum { INFO_TOP = 185, INFO_MIDDLE = 186, INFO_BOTTOM = 188, - MENU_BACKGROUND = 225 + MENU_BACKGROUND = 225, + COMMAND_HIGHLIGHTED = 254, + COMMAND_NULL = 193 + }; class TattooEngine : public SherlockEngine { diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp index e3df27dfbe..ade9861c4c 100644 --- a/engines/sherlock/tattoo/tattoo_user_interface.cpp +++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp @@ -587,7 +587,6 @@ void TattooUserInterface::freeMenu() { void TattooUserInterface::putMessage(const char *formatStr, ...) { Events &events = *_vm->_events; - Screen &screen = *_vm->_screen; Common::Point mousePos = events.mousePos(); // Create the string to display diff --git a/engines/sherlock/tattoo/widget_inventory.cpp b/engines/sherlock/tattoo/widget_inventory.cpp index ac30fe3c9c..fe6fa09bff 100644 --- a/engines/sherlock/tattoo/widget_inventory.cpp +++ b/engines/sherlock/tattoo/widget_inventory.cpp @@ -31,7 +31,6 @@ namespace Tattoo { #define INVENTORY_XSIZE 70 // Width of the box that surrounds inventory items #define INVENTORY_YSIZE 70 // Height of the box that surrounds inventory items -#define NUM_INVENTORY_SHOWN 8 // Number of Inventory Items Shown #define MAX_INV_COMMANDS 10 // Maximum elements in dialog // TODO: Refactor into FixedText diff --git a/engines/sherlock/tattoo/widget_inventory.h b/engines/sherlock/tattoo/widget_inventory.h index b3e914caf7..41930779bc 100644 --- a/engines/sherlock/tattoo/widget_inventory.h +++ b/engines/sherlock/tattoo/widget_inventory.h @@ -33,6 +33,8 @@ class SherlockEngine; namespace Tattoo { +#define NUM_INVENTORY_SHOWN 8 // Number of Inventory Items Shown + class WidgetInventory: public WidgetBase { private: int _invVerbMode; -- cgit v1.2.3