aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sherlock/inventory.h6
-rw-r--r--engines/sherlock/tattoo/tattoo.cpp12
-rw-r--r--engines/sherlock/tattoo/tattoo.h4
-rw-r--r--engines/sherlock/tattoo/tattoo_map.cpp1
-rw-r--r--engines/sherlock/tattoo/tattoo_user_interface.cpp6
-rw-r--r--engines/sherlock/tattoo/tattoo_user_interface.h2
-rw-r--r--engines/sherlock/tattoo/widget_base.cpp55
-rw-r--r--engines/sherlock/tattoo/widget_base.h26
-rw-r--r--engines/sherlock/tattoo/widget_inventory.cpp365
-rw-r--r--engines/sherlock/tattoo/widget_inventory.h38
-rw-r--r--engines/sherlock/tattoo/widget_verbs.cpp4
-rw-r--r--engines/sherlock/tattoo/widget_verbs.h2
12 files changed, 490 insertions, 31 deletions
diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h
index a2c317f2a8..019f5ed6c9 100644
--- a/engines/sherlock/inventory.h
+++ b/engines/sherlock/inventory.h
@@ -62,7 +62,11 @@ struct InventoryItem {
Common::String _examine;
int _lookFlag;
- InventoryItem() : _requiredFlag(0), _lookFlag(0) {}
+ // Rose Tattoo fields
+ int _requiredFlag1;
+ UseType _verb;
+
+ InventoryItem() : _requiredFlag(0), _lookFlag(0), _requiredFlag1(0) {}
InventoryItem(int requiredFlag, const Common::String &name,
const Common::String &description, const Common::String &examine);
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 60705f6016..bc4e7d5042 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -24,6 +24,7 @@
#include "sherlock/tattoo/tattoo.h"
#include "sherlock/tattoo/tattoo_resources.h"
#include "sherlock/tattoo/tattoo_scene.h"
+#include "sherlock/tattoo/widget_base.h"
#include "sherlock/people.h"
namespace Sherlock {
@@ -38,6 +39,10 @@ TattooEngine::TattooEngine(OSystem *syst, const SherlockGameDescription *gameDes
_allowFastMode = true;
}
+TattooEngine::~TattooEngine() {
+ WidgetBase::freeInterfaceImages();
+}
+
void TattooEngine::showOpening() {
// TODO
}
@@ -48,6 +53,9 @@ void TattooEngine::initialize() {
// Initialize the base engine
SherlockEngine::initialize();
+ // Further initialization
+ WidgetBase::setInterfaceImages(new ImageFile("intrface.vgs"));
+
// Initialise the global flags
_flags.resize(3200);
_flags[1] = _flags[4] = _flags[76] = true;
@@ -105,6 +113,10 @@ void TattooEngine::eraseCredits() {
// TODO
}
+void TattooEngine::doHangManPuzzle() {
+ // TODO
+}
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h
index 39f49341a8..d7d2115588 100644
--- a/engines/sherlock/tattoo/tattoo.h
+++ b/engines/sherlock/tattoo/tattoo.h
@@ -59,7 +59,7 @@ public:
bool _fastMode, _allowFastMode;
public:
TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
- virtual ~TattooEngine() {}
+ virtual ~TattooEngine();
/**
* Draw credits on the screen
@@ -75,6 +75,8 @@ public:
* Erase any area of the screen covered by credits
*/
void eraseCredits();
+
+ void doHangManPuzzle();
};
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp
index b8f1b6c55d..365c14a79c 100644
--- a/engines/sherlock/tattoo/tattoo_map.cpp
+++ b/engines/sherlock/tattoo/tattoo_map.cpp
@@ -306,7 +306,6 @@ void TattooMap::drawMapIcons() {
void TattooMap::checkMapNames(bool slamIt) {
Events &events = *_vm->_events;
- Screen &screen = *_vm->_screen;
Common::Point mousePos = events.mousePos() + _currentScroll;
// See if the mouse is pointing at any of the map locations
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index d12f0e7a02..322655fa88 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -575,7 +575,7 @@ void TattooUserInterface::doFileControl() {
}
void TattooUserInterface::doInventoryControl() {
- warning("TODO: ui control (inventory)");
+ _inventoryWidget.handleEvents();
}
void TattooUserInterface::doVerbControl() {
@@ -644,6 +644,10 @@ void TattooUserInterface::freeMenu() {
}
}
+void TattooUserInterface::putMessage(const Common::String &str) {
+ // TODO
+}
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h
index 35e1cb8ef0..935e0769ed 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.h
+++ b/engines/sherlock/tattoo/tattoo_user_interface.h
@@ -188,6 +188,8 @@ public:
* Pick up the selected object
*/
void pickUpObject(int objNum);
+
+ void putMessage(const Common::String &str);
public:
/**
* Resets the user interface
diff --git a/engines/sherlock/tattoo/widget_base.cpp b/engines/sherlock/tattoo/widget_base.cpp
index a9422de998..682961fd4e 100644
--- a/engines/sherlock/tattoo/widget_base.cpp
+++ b/engines/sherlock/tattoo/widget_base.cpp
@@ -29,8 +29,18 @@ namespace Sherlock {
namespace Tattoo {
+ImageFile *WidgetBase::_interfaceImages;
+
+void WidgetBase::setInterfaceImages(ImageFile *images) {
+ _interfaceImages = images;
+}
+
+void WidgetBase::freeInterfaceImages() {
+ delete _interfaceImages;
+ _interfaceImages = nullptr;
+}
+
WidgetBase::WidgetBase(SherlockEngine *vm) : _vm(vm) {
- _images = nullptr;
}
void WidgetBase::summonWindow() {
@@ -135,32 +145,38 @@ void WidgetBase::checkMenuPosition() {
_bounds.moveTo(_bounds.left, SHERLOCK_SCREEN_HEIGHT - _bounds.height());
}
-void WidgetBase::makeInfoArea() {
+void WidgetBase::makeInfoArea(Surface &s) {
+ ImageFile &images = *_interfaceImages;
+
// Draw the four corners of the Info Box
- _surface.transBlitFrom((*_images)[0], Common::Point(0, 0));
- _surface.transBlitFrom((*_images)[1], Common::Point(_bounds.width() - (*_images)[1]._width, 0));
- _surface.transBlitFrom((*_images)[2], Common::Point(0, _bounds.height() - (*_images)[2]._height));
- _surface.transBlitFrom((*_images)[3], Common::Point(_bounds.width() - (*_images)[3]._width, _bounds.height()));
+ s.transBlitFrom(images[0], Common::Point(0, 0));
+ s.transBlitFrom(images[1], Common::Point(s.w() - images[1]._width, 0));
+ s.transBlitFrom(images[2], Common::Point(0, s.h() - images[2]._height));
+ s.transBlitFrom(images[3], Common::Point(s.w() - images[3]._width, s.h()));
// Draw the top of the Info Box
- _surface.hLine((*_images)[0]._width, 0, _bounds.width() - (*_images)[1]._width, INFO_TOP);
- _surface.hLine((*_images)[0]._width, 1, _bounds.width() - (*_images)[1]._width, INFO_MIDDLE);
- _surface.hLine((*_images)[0]._width, 2, _bounds.width() - (*_images)[1]._width, INFO_BOTTOM);
+ s.hLine(images[0]._width, 0, s.w() - images[1]._width, INFO_TOP);
+ s.hLine(images[0]._width, 1, s.w() - images[1]._width, INFO_MIDDLE);
+ s.hLine(images[0]._width, 2, s.w() - images[1]._width, INFO_BOTTOM);
// Draw the bottom of the Info Box
- _surface.hLine((*_images)[0]._width, _bounds.height()- 3, _bounds.width() - (*_images)[1]._width, INFO_TOP);
- _surface.hLine((*_images)[0]._width, _bounds.height()- 2, _bounds.width() - (*_images)[1]._width, INFO_MIDDLE);
- _surface.hLine((*_images)[0]._width, _bounds.height()- 1, _bounds.width() - (*_images)[1]._width, INFO_BOTTOM);
+ s.hLine(images[0]._width, s.h()- 3, s.w() - images[1]._width, INFO_TOP);
+ s.hLine(images[0]._width, s.h()- 2, s.w() - images[1]._width, INFO_MIDDLE);
+ s.hLine(images[0]._width, s.h()- 1, s.w() - images[1]._width, INFO_BOTTOM);
// Draw the left Side of the Info Box
- _surface.vLine(0, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_TOP);
- _surface.vLine(1, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_MIDDLE);
- _surface.vLine(2, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_BOTTOM);
+ s.vLine(0, images[0]._height, s.h()- images[2]._height, INFO_TOP);
+ s.vLine(1, images[0]._height, s.h()- images[2]._height, INFO_MIDDLE);
+ s.vLine(2, images[0]._height, s.h()- images[2]._height, INFO_BOTTOM);
// Draw the right Side of the Info Box
- _surface.vLine(_bounds.width() - 3, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_TOP);
- _surface.vLine(_bounds.width() - 2, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_MIDDLE);
- _surface.vLine(_bounds.width() - 1, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_BOTTOM);
+ s.vLine(s.w() - 3, images[0]._height, s.h()- images[2]._height, INFO_TOP);
+ s.vLine(s.w() - 2, images[0]._height, s.h()- images[2]._height, INFO_MIDDLE);
+ s.vLine(s.w() - 1, images[0]._height, s.h()- images[2]._height, INFO_BOTTOM);
+}
+
+void WidgetBase::makeInfoArea() {
+ makeInfoArea(_surface);
}
const Common::Point &WidgetBase::getCurrentScroll() const {
@@ -168,6 +184,9 @@ const Common::Point &WidgetBase::getCurrentScroll() const {
return ui._currentScroll;
}
+void WidgetBase::checkTabbingKeys(int numOptions) {
+}
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/widget_base.h b/engines/sherlock/tattoo/widget_base.h
index 7e546db248..9d2ddcfc23 100644
--- a/engines/sherlock/tattoo/widget_base.h
+++ b/engines/sherlock/tattoo/widget_base.h
@@ -39,10 +39,11 @@ class WidgetBase {
private:
Common::Rect _oldBounds;
protected:
+ static ImageFile *_interfaceImages;
+protected:
SherlockEngine *_vm;
Common::Rect _bounds;
Surface _surface;
- ImageFile *_images;
bool _outsideMenu;
/**
@@ -55,6 +56,14 @@ protected:
*/
void checkMenuPosition();
+ /**
+ * Draw a window frame around the dges of the passed surface
+ */
+ void makeInfoArea(Surface &s);
+
+ /**
+ * Draw a window frame around the widget's surface
+ */
void makeInfoArea();
/**
@@ -62,6 +71,16 @@ protected:
*/
virtual const Common::Point &getCurrentScroll() const;
public:
+ /**
+ * Sets the interface images used for drawing the various types of window elements
+ */
+ static void setInterfaceImages(ImageFile *images);
+
+ /**
+ * Frees the interface images
+ */
+ static void freeInterfaceImages();
+public:
WidgetBase(SherlockEngine *vm);
virtual ~WidgetBase() {}
@@ -76,6 +95,11 @@ public:
void draw();
/**
+ * Used by some descendents to check for keys to mouse the mouse within the dialog
+ */
+ void checkTabbingKeys(int numOptions);
+
+ /**
* Summon the window
*/
virtual void summonWindow();
diff --git a/engines/sherlock/tattoo/widget_inventory.cpp b/engines/sherlock/tattoo/widget_inventory.cpp
index dfa4736ccc..ee8faa3759 100644
--- a/engines/sherlock/tattoo/widget_inventory.cpp
+++ b/engines/sherlock/tattoo/widget_inventory.cpp
@@ -21,6 +21,7 @@
*/
#include "sherlock/tattoo/widget_inventory.h"
+#include "sherlock/tattoo/tattoo_scene.h"
#include "sherlock/tattoo/tattoo_user_interface.h"
#include "sherlock/tattoo/tattoo.h"
@@ -31,14 +32,26 @@ 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
#define BUTTON_SIZE 15 // Button width/height
-WidgetInventory::WidgetInventory(SherlockEngine *vm) : WidgetBase(vm) {
+// TODO: Refactor into FixedText
+#define S_INV6 "Foolscap"
+#define S_INV7 "Damp Paper"
+#define S_SOLVE "Solve"
+#define S_LOOK "Look"
+#define S_NO_EFFECT "No effect..."
+#define S_WITH "with"
+
+WidgetInventory::WidgetInventory(SherlockEngine *vm) : WidgetBase(vm), _tooltipWidget(vm) {
_invMode = 0;
_invVerbMode = 0;
_invSelect = _oldInvSelect = 0;
_selector = _oldSelector = 0;
+ _invVerbSelect = _oldInvVerbSelect = -1;
_dialogTimer = -1;
+ _scrollHighlight = 0;
+ _swapItems = false;
}
void WidgetInventory::load(int mode) {
@@ -72,7 +85,7 @@ void WidgetInventory::load(int mode) {
_surface.fill(TRANSPARENCY);
// Draw the window background and then the inventory on top of it
- makeInfoArea();
+ makeInfoArea(_surface);
drawInventory();
}
@@ -187,6 +200,354 @@ void WidgetInventory::drawDialogRect(const Common::Rect &r, bool raised) {
}
}
+void WidgetInventory::handleEvents() {
+ TattooEngine &vm = *(TattooEngine *)_vm;
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ People &people = *_vm->_people;
+ TattooScene &scene = *(TattooScene *)_vm->_scene;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+
+ if (_invVerbMode == 1)
+ checkTabbingKeys(MAX_INV_COMMANDS);
+ else if (_invVerbMode == 0)
+ checkInvTabbingKeys();
+
+ if (_invVerbMode != 1)
+ updateDescription();
+
+ // Flag is they started pressing outside of the menu
+ if (events._firstPress && !_bounds.contains(mousePos))
+ _outsideMenu = true;
+
+ if (_invVerbMode != 3)
+ highlightControls();
+
+ // See if they released a mouse button button
+ if (events._released || events._rightReleased || ui._keyState.keycode == Common::KEYCODE_ESCAPE) {
+ _dialogTimer = -1;
+ _scrollHighlight = 0;
+
+ // See if they have a Verb List open for an Inventry Item
+ if (_invVerbMode == 1) {
+ // An inventory item's Verb List is open
+
+ // See if they want to close the menu (by clicking outside the menu)
+ Common::Rect innerBounds = _bounds;
+ innerBounds.grow(-3);
+
+ if (_outsideMenu && !innerBounds.contains(mousePos)) {
+ banishWindow();
+ _invVerbMode = 0;
+ } else if (innerBounds.contains(mousePos)) {
+ _outsideMenu = false;
+
+ // Check if they are trying to solve the Foolscap puzzle, or looking at the completed puzzle
+ bool doHangman = !inv[_invSelect]._name.compareToIgnoreCase(S_INV6) &&
+ !_inventCommands[_invVerbSelect].compareToIgnoreCase(S_SOLVE);
+ doHangman |= (!inv[_invSelect]._name.compareToIgnoreCase(S_INV6) || !inv[_invSelect]._name.compareToIgnoreCase(S_INV7))
+ && _inventCommands[_invVerbSelect].compareToIgnoreCase(S_LOOK) && vm.readFlags(299);
+
+ if (doHangman) {
+ // Close the entire Inventory and return to Standard Mode
+ banishWindow();
+ _invVerbMode = 0;
+
+ _tooltipWidget.banishWindow();
+ banishWindow();
+ inv.freeInv();
+
+ events.clearEvents();
+ events.setCursor(ARROW);
+ ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+
+ scene.doBgAnim();
+ vm.doHangManPuzzle();
+ } else if (_invVerbSelect == 0) {
+ // They have released the mouse on the Look Verb command, so Look at the inventory item
+ ui._invLookFlag = true;
+ inv.freeInv();
+ ui._windowOpen = false;
+ ui._lookPos = mousePos;
+ ui.printObjectDesc(inv[_invSelect]._examine, true);
+ } else {
+ // Clear the window
+ banishWindow();
+ _invVerbMode = 3;
+ ui._oldBgFound = -1;
+
+ // See if the selected Verb with the selected Iventory Item, is to be used by itself
+ if (!_inventCommands[_invVerbSelect].compareToIgnoreCase(inv[_invSelect]._verb._verb) ||
+ !inv[_invSelect]._verb._target.compareToIgnoreCase("*SELF")) {
+ inv.freeInv();
+
+ ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+ events.clearEvents();
+ ui.checkAction(inv[_invSelect]._verb, 2000);
+ } else {
+ _invVerb = _inventCommands[_invVerbSelect];
+ }
+ }
+
+ // If we are still in Inventory Mode, setup the graphic to float in front of the mouse cursor
+ if (ui._menuMode == INV_MODE) {
+ ImageFrame &imgFrame = (*inv._invShapes[_invSelect - inv._invIndex])[0];
+ _invGraphicBounds = Common::Rect(imgFrame._width, imgFrame._height);
+ _invGraphicBounds.moveTo(mousePos.x - _invGraphicBounds.width() / 2,
+ mousePos.y - _invGraphicBounds.height() / 2);
+
+ // Constrain it to the screen
+ if (_invGraphicBounds.left < 0)
+ _invGraphicBounds.moveTo(0, _invGraphicBounds.top);
+ if (_invGraphicBounds.top < 0)
+ _invGraphicBounds.moveTo(_invGraphicBounds.left, 0);
+ if (_invGraphicBounds.right > SHERLOCK_SCREEN_WIDTH)
+ _invGraphicBounds.moveTo(SHERLOCK_SCREEN_WIDTH - _invGraphicBounds.width(), _invGraphicBounds.top);
+ if (_invGraphicBounds.bottom > SHERLOCK_SCREEN_HEIGHT)
+ _invGraphicBounds.moveTo(_invGraphicBounds.left, SHERLOCK_SCREEN_HEIGHT - _invGraphicBounds.height());
+
+ // Make a copy of the inventory image
+ _invGraphic.create(imgFrame._width, imgFrame._height);
+ _invGraphic.blitFrom(imgFrame, Common::Point(0, 0));
+ }
+ }
+ } else if (_invVerbMode == 3) {
+ // Selecting object after inventory verb has been selected
+ _tooltipWidget.banishWindow();
+ _invGraphic.free();
+ inv.freeInv();
+
+ ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+ events.clearEvents();
+
+ if (ui._keyState.keycode != Common::KEYCODE_ESCAPE) {
+ // If user pointed at an item, use the selected inventory item with this item
+ bool found = false;
+ if (ui._bgFound != -1) {
+ if (ui._personFound) {
+ for (int idx = 0; idx < 2; ++idx) {
+ if (!people[ui._bgFound - 1000]._use[idx]._verb.compareToIgnoreCase(_invVerb) &&
+ !people[ui._bgFound - 1000]._use[idx]._target.compareToIgnoreCase(_invTarget)) {
+ ui.checkAction(people[ui._bgFound - 1000]._use[idx], ui._bgFound);
+ found = true;
+ }
+ }
+ } else {
+ for (int idx = 0; idx < 6; ++idx) {
+ if (!ui._bgShape->_use[idx]._verb.compareToIgnoreCase(_invVerb) &&
+ !ui._bgShape->_use[idx]._target.compareToIgnoreCase(_invTarget)) {
+ ui.checkAction(ui._bgShape->_use[idx], ui._bgFound);
+ found = true;
+ }
+ }
+ }
+ }
+
+ if (!found)
+ ui.putMessage(S_NO_EFFECT);
+ }
+ } else if ((_outsideMenu && !_bounds.contains(mousePos)) || ui._keyState.keycode == Common::KEYCODE_ESCAPE) {
+ // Want to close the window (clicked outside of it). So close the window and return to Standard
+ banishWindow();
+ inv.freeInv();
+
+ events.clearEvents();
+ events.setCursor(ARROW);
+ banishWindow();
+ ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+ } else if (_bounds.contains(mousePos)) {
+ // Mouse button was released inside the inventory window
+ _outsideMenu = false;
+
+ // See if they are pointing at one of the inventory items
+ if (_invSelect != -1) {
+ // See if they are in Use Obj with Inv. Mode (they right clicked on an item
+ // in the room and selected "Use with Inv.")
+ if (_invMode == 1) {
+ _tooltipWidget.banishWindow();
+ banishWindow();
+
+ // See if the item in the room that they started with was a person
+ bool found = false;
+ if (ui._activeObj >= 1000) {
+ // Object was a person, activate anything in his two verb fields
+ for (int idx = 0; idx < 2; ++idx) {
+ if (!people[ui._activeObj - 1000]._use[idx]._target.compareToIgnoreCase(inv[_invSelect]._name)) {
+ ui.checkAction(people[ui._activeObj - 1000]._use[idx], ui._activeObj);
+ found = true;
+ }
+ }
+ } else {
+ // Object was a regular object, activate anything in its verb fields
+ for (int idx = 0; idx < 6; ++idx) {
+ if (!scene._bgShapes[ui._activeObj]._use[idx]._target.compareToIgnoreCase(inv[_invSelect]._name)) {
+ ui.checkAction(scene._bgShapes[ui._activeObj]._use[idx], ui._activeObj);
+ found = true;
+ }
+ }
+ }
+ if (!found)
+ ui.putMessage(S_NO_EFFECT);
+
+ } else {
+ // See if they right clicked on an item
+ if (events._rightReleased) {
+ _invVerbMode = 1;
+ _oldInvVerbSelect = -1;
+ _tooltipWidget.banishWindow();
+
+ // Keep track of the name of the inventory object so we can check it against the target fields
+ // of verbs when we activate it
+ _invTarget = inv[_invSelect]._name;
+
+ // Make the Verb List for this Inventory Item
+ _inventCommands.clear();
+ _inventCommands.push_back(S_LOOK);
+
+ // Default the Action word to "with"
+ _action = _vm->getLanguage() == Common::GR_GRE ? "" : S_WITH;
+ _swapItems = false;
+
+ // Search all the bgshapes for any matching Target Fields
+ for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
+ Object &obj = scene._bgShapes[idx];
+
+ if (obj._type != INVALID && obj._type != HIDDEN) {
+ for (int useNum = 0; useNum < 6; ++useNum) {
+ if (obj._use[useNum]._verb.hasPrefix("*") &&
+ !obj._use[useNum]._target.compareToIgnoreCase(inv[_invSelect]._name)) {
+ // Make sure the Verb is not already in the list
+ bool found1 = false;
+ for (uint cmdNum = 0; cmdNum < _inventCommands.size() && !found1; ++cmdNum) {
+ if (!_inventCommands[cmdNum].compareToIgnoreCase(obj._use[useNum]._verb))
+ found1 = true;
+ }
+
+ if (!found1) {
+ _inventCommands.push_back(obj._use[useNum]._verb);
+
+ // Check for any Special Action commands
+ for (int nameNum = 0; nameNum < 4; ++nameNum) {
+ if (!scumm_strnicmp(obj._use[useNum]._names[nameNum].c_str(), "*V", 2)) {
+ if (!scumm_strnicmp(obj._use[useNum]._names[nameNum].c_str(), "*VSWAP", 6))
+ _swapItems = true;
+ else
+ _action = Common::String(obj._use[useNum]._names[nameNum].c_str() + 2);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Search the NPCs for matches as well
+ for (int idx = 1; idx < MAX_CHARACTERS; ++idx) {
+ for (int useNum = 0; useNum < 2; ++useNum) {
+ if (!people[idx]._use[useNum]._target.compareToIgnoreCase(inv[_invSelect]._name) &&
+ !people[idx]._use[useNum]._verb.empty() && !people[idx]._use[useNum]._verb.hasPrefix(" ")) {
+ bool found1 = false;
+ for (uint cmdNum = 0; cmdNum < _inventCommands.size() && !found1; ++cmdNum) {
+ if (!_inventCommands[cmdNum].compareToIgnoreCase(people[idx]._use[cmdNum]._verb))
+ found1 = true;
+ }
+
+ if (!found1)
+ _inventCommands.push_back(people[idx]._use[useNum]._verb);
+ }
+ }
+ }
+
+ // Finally see if the item itself has a verb
+ if (!inv[_invSelect]._verb._verb.empty()) {
+ // Don't add "Solve" to the Foolscap if it's already been "Solved"
+ if (inv[_invSelect]._verb._verb.compareToIgnoreCase(S_SOLVE) || !vm.readFlags(299))
+ _inventCommands.push_back(inv[_invSelect]._verb._verb);
+ }
+
+ // Now find the widest command in the _inventCommands array
+ int width = 0;
+ for (uint idx = 0; idx < _inventCommands.size(); ++idx)
+ width = MAX(width, _surface.stringWidth(_inventCommands[idx]));
+
+ // Set up bounds for the menu
+ _menuBounds = Common::Rect(width + _surface.widestChar() * 2 + 6,
+ (_surface.fontHeight() + 7) * _inventCommands.size() + 3);
+ _menuBounds.moveTo(mousePos.x + _menuBounds.width() / 2, mousePos.y + _menuBounds.height() / 2);
+
+ // Create the surface
+ _menuSurface.create(_menuBounds.width(), _menuBounds.height());
+ _surface.fill(TRANSPARENCY);
+ makeInfoArea(_menuSurface);
+
+ // Draw the Verb commands and the lines separating them
+ ImageFile &images = *_interfaceImages;
+ for (int idx = 0; idx < (int)_inventCommands.size(); ++idx) {
+ _menuSurface.writeString(_inventCommands[idx], Common::Point((_menuBounds.width() -
+ _menuSurface.stringWidth(_inventCommands[idx])) / 2, (_menuSurface.fontHeight() + 7) * idx + 5), INFO_TOP);
+
+ if (idx < (int)_inventCommands.size()- 1) {
+ _menuSurface.vLine(3, (_menuSurface.fontHeight() + 7) * (idx + 1), _menuBounds.right - 4, INFO_TOP);
+ _menuSurface.vLine(3, (_menuSurface.fontHeight() + 7) * (idx + 1) + 1, _menuBounds.right - 4, INFO_MIDDLE);
+ _menuSurface.vLine(3, (_menuSurface.fontHeight() + 7) * (idx + 1) + 2, _menuBounds.right - 4, INFO_BOTTOM);
+
+ _menuSurface.transBlitFrom(images[4], Common::Point(0, (_menuSurface.fontHeight() + 7) * (idx + 1)));
+ _menuSurface.transBlitFrom(images[5], Common::Point(_menuBounds.width() - images[5]._width,
+ (_menuSurface.fontHeight() + 7) * (idx + 1) - 1));
+ }
+ }
+ } else {
+ // They left clicked on an inventory item, so Look at it
+
+ // Check if they are looking at the solved Foolscap
+ if ((!inv[_invSelect]._name.compareToIgnoreCase(S_INV6) || !inv[_invSelect]._name.compareToIgnoreCase(S_INV7))
+ && vm.readFlags(299)) {
+ banishWindow();
+ _tooltipWidget.erase();
+
+ _invVerbMode = 0;
+ inv.freeInv();
+
+ events.clearEvents();
+ events.setCursor(ARROW);
+ ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+
+ scene.doBgAnim();
+ vm.doHangManPuzzle();
+ } else {
+ ui._invLookFlag = true;
+ inv.freeInv();
+
+ _tooltipWidget.banishWindow();
+ ui._windowOpen = false;
+ ui._lookPos = mousePos;
+ ui.printObjectDesc(inv[_invSelect]._examine, true);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void WidgetInventory::updateDescription() {
+
+}
+
+void WidgetInventory::checkInvTabbingKeys() {
+}
+
+void WidgetInventory::highlightControls() {
+ // TODO
+}
+
+void WidgetInventory::banishWindow() {
+ WidgetBase::banishWindow();
+
+ _menuSurface.free();
+ _menuBounds = _oldMenuBounds = Common::Rect(0, 0, 0, 0);
+}
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/widget_inventory.h b/engines/sherlock/tattoo/widget_inventory.h
index 34e25eeaa0..29bcdaa0ea 100644
--- a/engines/sherlock/tattoo/widget_inventory.h
+++ b/engines/sherlock/tattoo/widget_inventory.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "sherlock/tattoo/widget_base.h"
+#include "sherlock/tattoo/widget_tooltip.h"
namespace Sherlock {
@@ -37,7 +38,19 @@ private:
int _invVerbMode;
int _invSelect, _oldInvSelect;
int _selector, _oldSelector;
+ int _invVerbSelect, _oldInvVerbSelect;
int _dialogTimer;
+ int _scrollHighlight;
+ Common::StringArray _inventCommands;
+ WidgetTooltip _tooltipWidget;
+ Common::String _invVerb;
+ Common::String _invTarget;
+ Common::String _action;
+ Common::Rect _invGraphicBounds;
+ Surface _invGraphic;
+ bool _swapItems;
+ Common::Rect _menuBounds, _oldMenuBounds;
+ Surface _menuSurface;
/**
* Draw the scrollbar for the dialog
@@ -48,6 +61,21 @@ private:
* Draws all the dialog rectangles for any items that need them
*/
void drawDialogRect(const Common::Rect &r, bool raised);
+
+ /**
+ * Displays the description of any inventory item the moues cursor is over
+ */
+ void updateDescription();
+
+ /**
+ * Check for keys to mouse the mouse within the inventory dialog
+ */
+ void checkInvTabbingKeys();
+
+ /**
+ * Highlights the controls
+ */
+ void highlightControls();
public:
int _invMode;
public:
@@ -60,6 +88,16 @@ public:
* Draw the inventory on the surface
*/
void drawInventory();
+
+ /**
+ * Handle events whilst the widget is on-screen
+ */
+ virtual void handleEvents();
+
+ /**
+ * Close a currently active menu
+ */
+ virtual void banishWindow();
};
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/widget_verbs.cpp b/engines/sherlock/tattoo/widget_verbs.cpp
index dfe317b099..9cf4794fc0 100644
--- a/engines/sherlock/tattoo/widget_verbs.cpp
+++ b/engines/sherlock/tattoo/widget_verbs.cpp
@@ -230,10 +230,6 @@ void WidgetVerbs::execute() {
}
}
-void WidgetVerbs::checkTabbingKeys(int numOptions) {
- // TODO
-}
-
void WidgetVerbs::highlightVerbControls() {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
diff --git a/engines/sherlock/tattoo/widget_verbs.h b/engines/sherlock/tattoo/widget_verbs.h
index 82b9325681..fa41b3e42c 100644
--- a/engines/sherlock/tattoo/widget_verbs.h
+++ b/engines/sherlock/tattoo/widget_verbs.h
@@ -58,8 +58,6 @@ public:
* Process input for the dialog
*/
void execute();
-
- void checkTabbingKeys(int numOptions);
};
} // End of namespace Tattoo