MADS: Further fixes for hotspot highlighting

This commit is contained in:
Paul Gilbert 2014-03-22 21:55:36 -04:00
parent 06766e930b
commit 0b351f79d8
8 changed files with 112 additions and 61 deletions

View file

@ -136,13 +136,14 @@ void Font::setColorMode(int mode) {
int Font::writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt, int Font::writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt,
int spaceWidth, int width) { int spaceWidth, int width) {
int xEnd;
if (width > 0) if (width > 0)
width = MIN((int)surface->w, pt.x + width); xEnd = MIN((int)surface->w, pt.x + width);
else else
width = surface->w - pt.x; xEnd = surface->w - pt.x;
int x = pt.x + 1; int x = pt.x;
int y = pt.y + 1; int y = pt.y;
int skipY = 0; int skipY = 0;
if (y < 0) { if (y < 0) {
@ -174,7 +175,7 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
if (charWidth > 0) { if (charWidth > 0) {
if (xPos + charWidth >= width) if (xPos + charWidth > xEnd)
return xPos; return xPos;
uint8 *charData = &_charData[_charOffs[(byte)theChar]]; uint8 *charData = &_charData[_charOffs[(byte)theChar]];
@ -221,8 +222,12 @@ int Font::getWidth(const Common::String &msg, int spaceWidth) {
int width = 0; int width = 0;
const char *text = msg.c_str(); const char *text = msg.c_str();
while (*text) if (msg.size() > 0) {
width += _charWidths[*text++ & 0x7F] + spaceWidth; while (*text)
width += _charWidths[*text++ & 0x7F] + spaceWidth;
width -= spaceWidth;
}
return width; return width;
} }

View file

@ -146,8 +146,40 @@ void DynamicHotspots::refresh() {
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
void Hotspots::activate(int hotspotId, bool active) { Hotspot::Hotspot() {
warning("TODO: Hotspots::activate"); _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 } // End of namespace MADS

View file

@ -30,7 +30,6 @@ namespace MADS {
class MADSEngine; class MADSEngine;
class DynamicHotspot { class DynamicHotspot {
public: public:
bool _active; bool _active;
@ -74,6 +73,7 @@ public:
Common::Point _feetPos; Common::Point _feetPos;
int _facing; int _facing;
int _articleNumber; int _articleNumber;
bool _active;
CursorType _cursor; CursorType _cursor;
int _vocabId; int _vocabId;
int _verbId; int _verbId;
@ -83,8 +83,15 @@ public:
}; };
class Hotspots : public Common::Array<Hotspot> { class Hotspots : public Common::Array<Hotspot> {
private:
MADSEngine *_vm;
public: 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 } // End of namespace MADS

View file

@ -29,8 +29,8 @@
namespace MADS { namespace MADS {
Scene::Scene(MADSEngine *vm): _vm(vm), _action(_vm), _depthSurface(vm), Scene::Scene(MADSEngine *vm): _vm(vm), _action(_vm), _depthSurface(vm),
_dirtyAreas(_vm), _dynamicHotspots(vm), _kernelMessages(vm), _dirtyAreas(_vm), _dynamicHotspots(vm), _hotspots(vm),
_sequences(vm), _sprites(vm), _spriteSlots(vm), _kernelMessages(vm), _sequences(vm), _sprites(vm), _spriteSlots(vm),
_textDisplay(vm), _userInterface(vm) { _textDisplay(vm), _userInterface(vm) {
_priorSceneId = 0; _priorSceneId = 0;
_nextSceneId = 0; _nextSceneId = 0;

View file

@ -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) { void ARTHeader::load(Common::SeekableReadStream *f) {
// Read in dimensions of image // Read in dimensions of image
_width = f->readUint16LE(); _width = f->readUint16LE();

View file

@ -276,6 +276,7 @@ void ScreenObjects::add(const Common::Rect &bounds, Layer layer, ScrCategory cat
so._category = category; so._category = category;
so._descId = descId; so._descId = descId;
so._layer = layer; so._layer = layer;
so._active = true;
push_back(so); push_back(so);
} }
@ -361,9 +362,10 @@ void ScreenObjects::check(bool scanFlag) {
} }
int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) { int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) {
for (int i = (int)size() - 1; i >= 0; --i) { for (int i = (int)size(); i >= 1; --i) {
if ((*this)[i]._bounds.contains(pt) && ((*this)[i]._layer == layer)) ScreenObject &sObj = (*this)[i];
return i + 1; if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer)
return i;
} }
// Entry not found // Entry not found
@ -462,7 +464,7 @@ void ScreenObjects::elementHighlighted() {
int uiCount; int uiCount;
switch (userInterface._category) { switch (userInterface._category) {
case CAT_INV_LIST: case CAT_ACTION:
index = 10; index = 10;
indexEnd = 9; indexEnd = 9;
varA = 5; varA = 5;
@ -475,7 +477,7 @@ void ScreenObjects::elementHighlighted() {
var4 = _released && !_v7FECA ? 1 : 0; var4 = _released && !_v7FECA ? 1 : 0;
break; break;
case CAT_INV_VOCAB: case CAT_INV_LIST:
userInterface.scrollInventory(); userInterface.scrollInventory();
index = MIN((int)invList.size() - userInterface._inventoryTopIndex, 5); 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; var4 = (!_released || (_vm->_events->_mouseButtons && action._v83338 == 1)) ? 0 : 1;
break; break;
case CAT_HOTSPOT: case CAT_INV_VOCAB:
if (userInterface._selectedInvIndex >= 0) { if (userInterface._selectedInvIndex >= 0) {
InventoryObject &invObject = _vm->_game->_objects.getItem( InventoryObject &invObject = _vm->_game->_objects.getItem(
userInterface._selectedInvIndex); userInterface._selectedInvIndex);
@ -506,7 +508,7 @@ void ScreenObjects::elementHighlighted() {
var4 = _released && !_v7FECA ? 1 : 0; var4 = _released && !_v7FECA ? 1 : 0;
break; break;
case CAT_TALK_ENTRY: case CAT_INV_ANIM:
index = 1; index = 1;
indexEnd = invList.size() - 1; indexEnd = invList.size() - 1;
varA = 0; varA = 0;
@ -515,17 +517,7 @@ void ScreenObjects::elementHighlighted() {
var4 = -1; var4 = -1;
break; break;
case CAT_INV_SCROLLER: case CAT_TALK_ENTRY:
uiCount = size() - _uiCount;
index = scene._hotspots.size();
indexEnd = index - 1;
varA = 0;
topIndex = 0;
var6 = &var8;
var4 = -1;
break;
default:
index = 0; index = 0;
for (int idx = 0; idx < 5; ++idx) { for (int idx = 0; idx < 5; ++idx) {
if (!userInterface._talkStrings[idx].empty()) if (!userInterface._talkStrings[idx].empty())
@ -538,6 +530,16 @@ void ScreenObjects::elementHighlighted() {
var6 = &userInterface._v1A; var6 = &userInterface._v1A;
var4 = -1; var4 = -1;
break; break;
default:
uiCount = size() - _uiCount;
index = scene._hotspots.size();
indexEnd = index - 1;
varA = 0;
topIndex = 0;
var6 = &var8;
var4 = -1;
break;
} }
int newIndex = -1; int newIndex = -1;
@ -548,15 +550,19 @@ void ScreenObjects::elementHighlighted() {
for (int idx = 0; idx < index && newIndex < 0; ++idx) { for (int idx = 0; idx < index && newIndex < 0; ++idx) {
int scrObjIndex = (_category == CAT_HOTSPOT) ? catIndex - idx + index - 1 : int scrObjIndex = (_category == CAT_HOTSPOT) ? catIndex - idx + index - 1 :
catIndex + idx; catIndex + idx;
ScreenObject &scrObject = (*this)[scrObjIndex]; 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); newY = MAX((int)bounds.bottom, newY);
newX = MAX((int)bounds.left, newX); 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 (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; newIndex = scrObjIndex - catIndex;
if (_category == CAT_HOTSPOT && newIndex < (int)scene._hotspots.size()) if (_category == CAT_HOTSPOT && newIndex < (int)scene._hotspots.size())
newIndex = scene._hotspots.size() - newIndex - 1; newIndex = scene._hotspots.size() - newIndex - 1;
@ -602,6 +608,14 @@ void ScreenObjects::elementHighlighted() {
userInterface.drawInventory(_category, newIndex, var6); 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() { ScreenSurface::ScreenSurface() {

View file

@ -125,6 +125,7 @@ public:
class ScreenObject { class ScreenObject {
public: public:
bool _active;
Common::Rect _bounds; Common::Rect _bounds;
ScrCategory _category; ScrCategory _category;
int _descId; int _descId;
@ -179,6 +180,23 @@ public:
* Handle element being highlighted on the screen * Handle element being highlighted on the screen
*/ */
void elementHighlighted(); 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<ScreenObject>::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 { class ScreenSurface : public MSurface {

View file

@ -447,7 +447,7 @@ void UserInterface::loadElements() {
} }
if (!_vm->_game->_screenObjects._v832EC || _vm->_game->_screenObjects._v832EC == 2) { 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) { for (int hotspotIdx = scene._hotspots.size() - 1; hotspotIdx >= 0; --hotspotIdx) {
Hotspot &hs = scene._hotspots[hotspotIdx]; Hotspot &hs = scene._hotspots[hotspotIdx];
_vm->_game->_screenObjects.add(hs._bounds, LAYER_GUI, CAT_HOTSPOT, hotspotIdx); _vm->_game->_screenObjects.add(hs._bounds, LAYER_GUI, CAT_HOTSPOT, hotspotIdx);