From 0b351f79d8ad874ce07fed54eb745a277da28edc Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 22 Mar 2014 21:55:36 -0400 Subject: MADS: Further fixes for hotspot highlighting --- engines/mads/font.cpp | 19 +++++++++----- engines/mads/hotspots.cpp | 36 +++++++++++++++++++++++-- engines/mads/hotspots.h | 11 ++++++-- engines/mads/scene.cpp | 4 +-- engines/mads/scene_data.cpp | 25 ------------------ engines/mads/screen.cpp | 58 +++++++++++++++++++++++++---------------- engines/mads/screen.h | 18 +++++++++++++ engines/mads/user_interface.cpp | 2 +- 8 files changed, 112 insertions(+), 61 deletions(-) diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp index ed7542d2e5..e3497b3b14 100644 --- a/engines/mads/font.cpp +++ b/engines/mads/font.cpp @@ -136,13 +136,14 @@ void Font::setColorMode(int mode) { int Font::writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt, int spaceWidth, int width) { + int xEnd; if (width > 0) - width = MIN((int)surface->w, pt.x + width); + xEnd = MIN((int)surface->w, pt.x + width); else - width = surface->w - pt.x; + xEnd = surface->w - pt.x; - int x = pt.x + 1; - int y = pt.y + 1; + int x = pt.x; + int y = pt.y; int skipY = 0; if (y < 0) { @@ -174,7 +175,7 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common if (charWidth > 0) { - if (xPos + charWidth >= width) + if (xPos + charWidth > xEnd) return xPos; uint8 *charData = &_charData[_charOffs[(byte)theChar]]; @@ -221,8 +222,12 @@ int Font::getWidth(const Common::String &msg, int spaceWidth) { int width = 0; const char *text = msg.c_str(); - while (*text) - width += _charWidths[*text++ & 0x7F] + spaceWidth; + if (msg.size() > 0) { + while (*text) + width += _charWidths[*text++ & 0x7F] + spaceWidth; + width -= spaceWidth; + } + return width; } diff --git a/engines/mads/hotspots.cpp b/engines/mads/hotspots.cpp index 4356e787d6..e082a1e3ce 100644 --- a/engines/mads/hotspots.cpp +++ b/engines/mads/hotspots.cpp @@ -146,8 +146,40 @@ void DynamicHotspots::refresh() { /*------------------------------------------------------------------------*/ -void Hotspots::activate(int hotspotId, bool active) { - warning("TODO: Hotspots::activate"); +Hotspot::Hotspot() { + _facing = 0; + _articleNumber = 0; + _cursor = CURSOR_NONE; + _vocabId = 0; + _verbId = 0; + _active = false; +} + +Hotspot::Hotspot(Common::SeekableReadStream &f) { + _bounds.left = f.readSint16LE(); + _bounds.top = f.readSint16LE(); + _bounds.right = f.readSint16LE(); + _bounds.bottom = f.readSint16LE(); + _feetPos.x = f.readSint16LE(); + _feetPos.y = f.readSint16LE(); + _facing = f.readByte(); + _articleNumber = f.readByte(); + _active = f.readByte() != 0; + _cursor = (CursorType)f.readByte(); + _vocabId = f.readUint16LE(); + _verbId = f.readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +void Hotspots::activate(int vocabId, bool active) { + for (uint idx = 0; idx < size(); ++idx) { + Hotspot &hotspot = (*this)[idx]; + if (hotspot._vocabId == vocabId) { + hotspot._active = active; + _vm->_game->_screenObjects.setActive(CAT_HOTSPOT, idx, active); + } + } } } // End of namespace MADS diff --git a/engines/mads/hotspots.h b/engines/mads/hotspots.h index ed18fbf252..a53b86d880 100644 --- a/engines/mads/hotspots.h +++ b/engines/mads/hotspots.h @@ -30,7 +30,6 @@ namespace MADS { class MADSEngine; - class DynamicHotspot { public: bool _active; @@ -74,6 +73,7 @@ public: Common::Point _feetPos; int _facing; int _articleNumber; + bool _active; CursorType _cursor; int _vocabId; int _verbId; @@ -83,8 +83,15 @@ public: }; class Hotspots : public Common::Array { +private: + MADSEngine *_vm; public: - void activate(int hotspotId, bool active); + Hotspots(MADSEngine *vm) : _vm(vm) {} + + /** + * Sets the active state of a given hotspot + */ + void activate(int vocabId, bool active); }; } // End of namespace MADS diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp index e357f8b1ad..da64def95d 100644 --- a/engines/mads/scene.cpp +++ b/engines/mads/scene.cpp @@ -29,8 +29,8 @@ namespace MADS { Scene::Scene(MADSEngine *vm): _vm(vm), _action(_vm), _depthSurface(vm), - _dirtyAreas(_vm), _dynamicHotspots(vm), _kernelMessages(vm), - _sequences(vm), _sprites(vm), _spriteSlots(vm), + _dirtyAreas(_vm), _dynamicHotspots(vm), _hotspots(vm), + _kernelMessages(vm), _sequences(vm), _sprites(vm), _spriteSlots(vm), _textDisplay(vm), _userInterface(vm) { _priorSceneId = 0; _nextSceneId = 0; diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp index a1f273459c..712d065fb9 100644 --- a/engines/mads/scene_data.cpp +++ b/engines/mads/scene_data.cpp @@ -58,31 +58,6 @@ KernelMessage::KernelMessage() { /*------------------------------------------------------------------------*/ -Hotspot::Hotspot() { - _facing = 0; - _articleNumber = 0; - _cursor = CURSOR_NONE; - _vocabId = 0; - _verbId = 0; -} - -Hotspot::Hotspot(Common::SeekableReadStream &f) { - _bounds.left = f.readSint16LE(); - _bounds.top = f.readSint16LE(); - _bounds.right = f.readSint16LE(); - _bounds.bottom = f.readSint16LE(); - _feetPos.x = f.readSint16LE(); - _feetPos.y = f.readSint16LE(); - _facing = f.readByte(); - _articleNumber = f.readByte(); - f.skip(1); - _cursor = (CursorType)f.readByte(); - _vocabId = f.readUint16LE(); - _verbId = f.readUint16LE(); -} - -/*------------------------------------------------------------------------*/ - void ARTHeader::load(Common::SeekableReadStream *f) { // Read in dimensions of image _width = f->readUint16LE(); diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index d191f49f14..22896e011b 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -276,6 +276,7 @@ void ScreenObjects::add(const Common::Rect &bounds, Layer layer, ScrCategory cat so._category = category; so._descId = descId; so._layer = layer; + so._active = true; push_back(so); } @@ -361,9 +362,10 @@ void ScreenObjects::check(bool scanFlag) { } int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) { - for (int i = (int)size() - 1; i >= 0; --i) { - if ((*this)[i]._bounds.contains(pt) && ((*this)[i]._layer == layer)) - return i + 1; + for (int i = (int)size(); i >= 1; --i) { + ScreenObject &sObj = (*this)[i]; + if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer) + return i; } // Entry not found @@ -462,7 +464,7 @@ void ScreenObjects::elementHighlighted() { int uiCount; switch (userInterface._category) { - case CAT_INV_LIST: + case CAT_ACTION: index = 10; indexEnd = 9; varA = 5; @@ -475,7 +477,7 @@ void ScreenObjects::elementHighlighted() { var4 = _released && !_v7FECA ? 1 : 0; break; - case CAT_INV_VOCAB: + case CAT_INV_LIST: userInterface.scrollInventory(); index = MIN((int)invList.size() - userInterface._inventoryTopIndex, 5); @@ -486,7 +488,7 @@ void ScreenObjects::elementHighlighted() { var4 = (!_released || (_vm->_events->_mouseButtons && action._v83338 == 1)) ? 0 : 1; break; - case CAT_HOTSPOT: + case CAT_INV_VOCAB: if (userInterface._selectedInvIndex >= 0) { InventoryObject &invObject = _vm->_game->_objects.getItem( userInterface._selectedInvIndex); @@ -506,7 +508,7 @@ void ScreenObjects::elementHighlighted() { var4 = _released && !_v7FECA ? 1 : 0; break; - case CAT_TALK_ENTRY: + case CAT_INV_ANIM: index = 1; indexEnd = invList.size() - 1; varA = 0; @@ -515,17 +517,7 @@ void ScreenObjects::elementHighlighted() { var4 = -1; break; - case CAT_INV_SCROLLER: - uiCount = size() - _uiCount; - index = scene._hotspots.size(); - indexEnd = index - 1; - varA = 0; - topIndex = 0; - var6 = &var8; - var4 = -1; - break; - - default: + case CAT_TALK_ENTRY: index = 0; for (int idx = 0; idx < 5; ++idx) { if (!userInterface._talkStrings[idx].empty()) @@ -538,6 +530,16 @@ void ScreenObjects::elementHighlighted() { var6 = &userInterface._v1A; var4 = -1; break; + + default: + uiCount = size() - _uiCount; + index = scene._hotspots.size(); + indexEnd = index - 1; + varA = 0; + topIndex = 0; + var6 = &var8; + var4 = -1; + break; } int newIndex = -1; @@ -548,15 +550,19 @@ void ScreenObjects::elementHighlighted() { for (int idx = 0; idx < index && newIndex < 0; ++idx) { int scrObjIndex = (_category == CAT_HOTSPOT) ? catIndex - idx + index - 1 : catIndex + idx; - + ScreenObject &scrObject = (*this)[scrObjIndex]; - Common::Rect bounds = scrObject._bounds; + if (!scrObject._active) + continue; + + const Common::Rect &bounds = scrObject._bounds; newY = MAX((int)bounds.bottom, newY); newX = MAX((int)bounds.left, newX); - if (currentPos.y > newY && currentPos.y < bounds.bottom) { + if (currentPos.y >= bounds.top && currentPos.y < bounds.bottom) { if (var4) { - if (currentPos.x > newX && currentPos.x < bounds.right) { + if (currentPos.x >= bounds.left && currentPos.x < bounds.right) { + // Cursor is inside hotspot bounds newIndex = scrObjIndex - catIndex; if (_category == CAT_HOTSPOT && newIndex < (int)scene._hotspots.size()) newIndex = scene._hotspots.size() - newIndex - 1; @@ -602,6 +608,14 @@ void ScreenObjects::elementHighlighted() { userInterface.drawInventory(_category, newIndex, var6); } +void ScreenObjects::setActive(ScrCategory category, int descId, bool active) { + for (uint idx = 1; idx < size(); ++idx) { + ScreenObject &sObj = (*this)[idx]; + if (sObj._category == category && sObj._descId == descId) + sObj._active = active; + } +} + /*------------------------------------------------------------------------*/ ScreenSurface::ScreenSurface() { diff --git a/engines/mads/screen.h b/engines/mads/screen.h index 1d1e6d34f0..7fa5722e18 100644 --- a/engines/mads/screen.h +++ b/engines/mads/screen.h @@ -125,6 +125,7 @@ public: class ScreenObject { public: + bool _active; Common::Rect _bounds; ScrCategory _category; int _descId; @@ -179,6 +180,23 @@ public: * Handle element being highlighted on the screen */ void elementHighlighted(); + + /** + * Retrieve a ScreenObject from the list + * @remarks This array is 1-based indexed by the game + */ + ScreenObject &operator[](int idx) { + assert(idx > 0); + return Common::Array::operator[](idx - 1); + } + + /** + * Sets an item identified by category and Desc Id as active or not + * @param category Screen category + * @param descId Description for item + * @param active Whether to set item as active or not + */ + void setActive(ScrCategory category, int descId, bool active); }; class ScreenSurface : public MSurface { diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index cae5c116d2..4a35d24ad0 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -447,7 +447,7 @@ void UserInterface::loadElements() { } if (!_vm->_game->_screenObjects._v832EC || _vm->_game->_screenObjects._v832EC == 2) { - _categoryIndexes[CAT_HOTSPOT - 1] = _vm->_game->_screenObjects.size(); + _categoryIndexes[CAT_HOTSPOT - 1] = _vm->_game->_screenObjects.size() + 1; for (int hotspotIdx = scene._hotspots.size() - 1; hotspotIdx >= 0; --hotspotIdx) { Hotspot &hs = scene._hotspots[hotspotIdx]; _vm->_game->_screenObjects.add(hs._bounds, LAYER_GUI, CAT_HOTSPOT, hotspotIdx); -- cgit v1.2.3