diff options
author | Paul Gilbert | 2015-06-10 20:54:05 -0400 |
---|---|---|
committer | Paul Gilbert | 2015-06-10 20:54:05 -0400 |
commit | 6780c63e538d28c13a5fc1db8c282d00a95bcaaa (patch) | |
tree | e32e766468349d1bd3830281635cfb2fa86c8e44 /engines/sherlock | |
parent | dd1781a3f29fdcaad7b3551872e5246e4f694389 (diff) | |
download | scummvm-rg350-6780c63e538d28c13a5fc1db8c282d00a95bcaaa.tar.gz scummvm-rg350-6780c63e538d28c13a5fc1db8c282d00a95bcaaa.tar.bz2 scummvm-rg350-6780c63e538d28c13a5fc1db8c282d00a95bcaaa.zip |
SHERLOCK: Implemented more support methods for RT map
Diffstat (limited to 'engines/sherlock')
-rw-r--r-- | engines/sherlock/fonts.h | 2 | ||||
-rw-r--r-- | engines/sherlock/screen.h | 17 | ||||
-rw-r--r-- | engines/sherlock/surface.h | 10 | ||||
-rw-r--r-- | engines/sherlock/tattoo/tattoo_map.cpp | 262 | ||||
-rw-r--r-- | engines/sherlock/tattoo/tattoo_map.h | 28 |
5 files changed, 305 insertions, 14 deletions
diff --git a/engines/sherlock/fonts.h b/engines/sherlock/fonts.h index 50d89f3c46..0c8c51c4bd 100644 --- a/engines/sherlock/fonts.h +++ b/engines/sherlock/fonts.h @@ -82,7 +82,7 @@ public: */ int fontHeight() const { return _fontHeight; } - + int fontNumber() const { return _fontNumber; } }; } // End of namespace Sherlock diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 9d3ed0c60c..c660fefe8c 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -37,6 +37,7 @@ namespace Sherlock { #define BG_GREYSCALE_RANGE_END 229 enum { + BLACK = 0, INFO_BLACK = 1, INFO_FOREGROUND = 11, INFO_BACKGROUND = 1, @@ -52,7 +53,8 @@ enum { BUTTON_BOTTOM = 248, TALK_FOREGROUND = 12, TALK_NULL = 16, - PEN_COLOR = 250 + PEN_COLOR = 250, + MAP_NAME_COLOR = 131 }; class SherlockEngine; @@ -77,11 +79,6 @@ private: * Returns the union of two dirty area rectangles */ bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2); - - /** - * Draws the given string into the back buffer using the images stored in _font - */ - virtual void writeString(const Common::String &str, const Common::Point &pt, byte overrideColor); protected: /** * Adds a rectangle to the list of modified areas of the screen during the @@ -244,13 +241,17 @@ public: */ Common::Rect getDisplayBounds(); - int fontNumber() const { return _fontNumber; } - /** * Synchronize the data for a savegame */ void synchronize(Serializer &s); + /** + * Draws the given string into the back buffer using the images stored in _font + */ + virtual void writeString(const Common::String &str, const Common::Point &pt, byte overrideColor); + + // Rose Tattoo specific methods void initPaletteFade(int bytesToRead); diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h index d42dd5c21e..49726d55fa 100644 --- a/engines/sherlock/surface.h +++ b/engines/sherlock/surface.h @@ -71,11 +71,6 @@ protected: Graphics::Surface _surface; virtual void addDirtyRect(const Common::Rect &r) {} - - /** - * Draws the given string into the back buffer using the images stored in _font - */ - virtual void writeString(const Common::String &str, const Common::Point &pt, byte overrideColor); public: Surface(uint16 width, uint16 height, Common::Platform platform); Surface(); @@ -164,6 +159,11 @@ public: */ void setPixels(byte *pixels, int width, int height); + /** + * Draws the given string into the back buffer using the images stored in _font + */ + virtual void writeString(const Common::String &str, const Common::Point &pt, byte overrideColor); + inline uint16 w() const { return _surface.w; } inline uint16 h() const { return _surface.h; } inline const byte *getPixels() const { return (const byte *)_surface.getPixels(); } diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp index 3a02d5b7ce..57c10ca86d 100644 --- a/engines/sherlock/tattoo/tattoo_map.cpp +++ b/engines/sherlock/tattoo/tattoo_map.cpp @@ -35,6 +35,10 @@ void MapEntry::clear() { /*-------------------------------------------------------------------------*/ TattooMap::TattooMap(SherlockEngine *vm) : Map(vm) { + _iconImages = nullptr; + _bgFound = _oldBgFound = 0; + _textBuffer = nullptr; + loadData(); } @@ -104,6 +108,264 @@ void TattooMap::loadData() { } while (stream->pos() < stream->size()); } +void TattooMap::drwaMapIcons() { + Screen &screen = *_vm->_screen; + + for (uint idx = 0; idx < _data.size(); ++idx) { + if (_data[idx]._iconNum != -1 && _vm->readFlags(idx + 1)) { + MapEntry &mapEntry = _data[idx]; + ImageFrame &img = (*_iconImages)[mapEntry._iconNum]; + screen._backBuffer1.transBlitFrom(img._frame, Common::Point(mapEntry.x - img._width / 2, + mapEntry.y - img._height / 2)); + } + } +} + +void TattooMap::checkMapNames(bool slamIt) { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + Common::Point mousePos = events.mousePos(); + int dif = 10000; + + // See if the mouse is pointing at any of the map locations + _bgFound = -1; + + for (uint idx = 0; idx < _data.size(); ++idx) { + if (_data[idx]._iconNum != -1 && _vm->readFlags(idx + 1)) { + MapEntry &mapEntry = _data[idx]; + ImageFrame &img = (*_iconImages)[mapEntry._iconNum]; + Common::Rect r(mapEntry.x - img._width / 2, mapEntry.y - img._height / 2, + mapEntry.x + img._width / 2, mapEntry.y + img._height / 2); + + if (r.contains(mousePos)) { + _bgFound = idx; + break; + } + } + } + + // Store the previous bounds that were drawn + _oldTextBounds = _textBounds; + + // See if thay are pointing at a different location and we need to change the display + if (_bgFound != _oldBgFound || (_bgFound != -1 && _textBuffer == nullptr)) { + // See if there is a new image to be displayed + if (_bgFound != -1 && (_bgFound != _oldBgFound || _textBuffer == nullptr)) { + const Common::String &desc = _data[_bgFound]._description; + const char *space = nullptr; + int width = screen.stringWidth(desc) + 2; + int height = 0; + + // See if we need to split it into two lines + if (width > 150) { + const char *s = desc.c_str(); + + for (;;) { + // Move to end of next word + s = strchr(s, ' '); + + if (s == nullptr) { + // Reached end of description + if (space == nullptr) { + height = screen.stringHeight(desc) + 2; + } else { + Common::String line1(desc.c_str(), space); + Common::String line2(space + 1); + + height = screen.stringHeight(line1) + screen.stringHeight(line2); + } + break; + } else { + // Reached space separating words within the description + // Get width before and after word + int width1 = screen.stringWidth(Common::String(desc.c_str(), s)); + int width2 = screen.stringWidth(Common::String(s + 1)); + + if (ABS(width1 - width2) < dif) { + space = s; + dif = ABS(width1 - width2); + width = MAX(width1, width) + 2; + } + + ++s; + } + } + } else { + height = screen.stringHeight(desc) + 2; + } + + // Delete any previous saved area + delete _textBuffer; + + // Allocate a new surface + _textBuffer = new Surface(width, height, _vm->getPlatform()); + + _textBuffer->fillRect(Common::Rect(0, 0, width, height), 255); + if (space == nullptr) { + // The whole text can be drawn on a single line + _textBuffer->writeString(desc, Common::Point(0, 0), BLACK); + _textBuffer->writeString(desc, Common::Point(1, 0), BLACK); + _textBuffer->writeString(desc, Common::Point(2, 0), BLACK); + _textBuffer->writeString(desc, Common::Point(0, 1), BLACK); + _textBuffer->writeString(desc, Common::Point(2, 1), BLACK); + _textBuffer->writeString(desc, Common::Point(0, 2), BLACK); + _textBuffer->writeString(desc, Common::Point(1, 2), BLACK); + _textBuffer->writeString(desc, Common::Point(2, 2), BLACK); + _textBuffer->writeString(desc, Common::Point(1, 1), MAP_NAME_COLOR); + } else { + // The text needs to be split up over two lines + Common::String line1(desc.c_str(), space); + Common::String line2(space + 1); + int xp, yp; + + // Draw the first line + xp = (width - screen.stringWidth(desc)) / 2; + _textBuffer->writeString(line1, Common::Point(xp + 0, 0), BLACK); + _textBuffer->writeString(line1, Common::Point(xp + 1, 0), BLACK); + _textBuffer->writeString(line1, Common::Point(xp + 2, 0), BLACK); + _textBuffer->writeString(line1, Common::Point(xp + 0, 1), BLACK); + _textBuffer->writeString(line1, Common::Point(xp + 2, 1), BLACK); + _textBuffer->writeString(line1, Common::Point(xp + 0, 2), BLACK); + _textBuffer->writeString(line1, Common::Point(xp + 1, 2), BLACK); + _textBuffer->writeString(line1, Common::Point(xp + 2, 2), BLACK); + _textBuffer->writeString(line1, Common::Point(xp + 1, 1), MAP_NAME_COLOR); + + yp = screen.stringHeight(line2); + xp = (width - screen.stringWidth(line2)) / 2; + _textBuffer->writeString(line2, Common::Point(xp + 0, 0), BLACK); + _textBuffer->writeString(line2, Common::Point(xp + 1, 0), BLACK); + _textBuffer->writeString(line2, Common::Point(xp + 2, 0), BLACK); + _textBuffer->writeString(line2, Common::Point(xp + 0, 1), BLACK); + _textBuffer->writeString(line2, Common::Point(xp + 2, 1), BLACK); + _textBuffer->writeString(line2, Common::Point(xp + 0, 2), BLACK); + _textBuffer->writeString(line2, Common::Point(xp + 1, 2), BLACK); + _textBuffer->writeString(line2, Common::Point(xp + 2, 2), BLACK); + _textBuffer->writeString(line2, Common::Point(xp + 1, 1), MAP_NAME_COLOR); + } + + // Set the position of the Text Tag + // TODO: take current scroll into account + int xp = (mousePos.x - width / 2); + int yp = (mousePos.y - height / 2); + + _textBounds = Common::Rect(xp, yp, xp + width, yp + height); + } else if (_bgFound == -1 && _oldBgFound != -1) { + // We need to clear a currently displayed name + delete _textBuffer; + } + + _oldBgFound = _bgFound; + } else { + // Set the new text position + // TODO: take current scroll into account + int xp = (mousePos.x - _textBounds.width() / 2); + int yp = (mousePos.y - _textBounds.height() / 2); + + _textBounds.moveTo(xp, yp); + } + + // If the text tag was displayed, restore the graphics underneath it + if (_oldTextBounds.width() > 0) + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTextBounds.left, _oldTextBounds.top), _oldTextBounds); + + // See if we need to draw a Text Tag floating with the cursor + if (_textBuffer != nullptr) + screen.transBlitFrom(*_textBuffer, Common::Point(_textBounds.left, _textBounds.top)); + + // See if we need to flush the areas associated with the text + if (_oldTextBounds.width() > 0) { + if (slamIt) + // TODO: Take into account scroll + screen.slamRect(_oldTextBounds); + + // If there's no text to display, reset the tag and old tag bounds + if (_textBuffer == nullptr) { + _textBounds.left = _textBounds.top = _textBounds.right = _textBounds.bottom = 0; + _oldTextBounds.left = _oldTextBounds.top = _oldTextBounds.right = _oldTextBounds.bottom = 0; + } + } + + // If there's a text to display, then copy the drawn area to the screen + if (_textBuffer != nullptr && slamIt) + // TODO: Handle scroll + screen.slamRect(_textBounds); +} + +void TattooMap::restoreArea(const Common::Rect &bounds) { + Screen &screen = *_vm->_screen; + + Common::Rect r = bounds; + r.clip(Common::Rect(0, 0, screen._backBuffer1.w(), screen._backBuffer1.h())); + + if (!r.isEmpty()) + screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(r.left, r.top), r); +} + +void TattooMap::showCloseUp(int closeUpNum) { + Screen &screen = *_vm->_screen; + + // Get the closeup images + Common::String fname = Common::String::format("res%02d.vgs", closeUpNum + 1); + ImageFile pic(fname); + + Common::Point closeUp(_data[closeUpNum].x * 100, _data[closeUpNum].y * 100); + Common::Point delta((SHERLOCK_SCREEN_WIDTH / 2 - closeUp.x / 100) * 100 / CLOSEUP_STEPS, + (SHERLOCK_SCREEN_HEIGHT / 2 - closeUp.y / 100) * 100 / CLOSEUP_STEPS); + Common::Rect oldBounds(closeUp.x / 100, closeUp.y / 100, closeUp.x / 100 + 1, closeUp.y / 100 + 1); + int size = 64; + int n = 256; + int deltaVal = 512; + bool minimize = false; + int scaleVal, newSize; + + do + { + scaleVal = n; + newSize = pic[0].sDrawXSize(n); + + if (newSize > size) { + if (minimize) + deltaVal /= 2; + n += deltaVal; + } else { + minimize = true; + deltaVal /= 2; + n -= deltaVal; + if (n < 1) + n = 1; + } + } while (deltaVal && size != newSize); + + int deltaScale = (SCALE_THRESHOLD - scaleVal) / CLOSEUP_STEPS; + + for (int step = 0; step < CLOSEUP_STEPS; ++step) { + Common::Point picSize(pic[0].sDrawXSize(scaleVal), pic[0].sDrawYSize(scaleVal)); + Common::Point pt(closeUp.x / 100 - picSize.x, closeUp.y / 100 - picSize.y); + + restoreArea(oldBounds); + screen._backBuffer1.transBlitFrom(pic[0], pt, false, 0, scaleVal); + + // TODO: handle scrolling + screen.slamRect(_oldTextBounds); + screen.slamArea(pt.x, pt.y, picSize.x, picSize.y); + + oldBounds = Common::Rect(pt.x, pt.y, pt.x + picSize.x + 1, pt.y + picSize.y + 1); + closeUp += delta; + scaleVal += deltaScale; + } + + // Handle final drawing of closeup + // TODO: Handle scrolling + Common::Rect r(SHERLOCK_SCREEN_WIDTH / 2 - pic[0]._width / 2, SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2, + SHERLOCK_SCREEN_WIDTH / 2 + pic[0]._width / 2 + pic[0]._width, + SHERLOCK_SCREEN_HEIGHT / 2 + pic[0]._height / 2 + pic[0]._height); + + restoreArea(oldBounds); + screen._backBuffer1.transBlitFrom(pic[0], Common::Point(r.left, r.top)); + screen.slamRect(oldBounds); + screen.slamRect(r); +} + } // End of namespace Tattoo } // End of namespace Sherlock diff --git a/engines/sherlock/tattoo/tattoo_map.h b/engines/sherlock/tattoo/tattoo_map.h index b0c1a3fbc0..079aa46b16 100644 --- a/engines/sherlock/tattoo/tattoo_map.h +++ b/engines/sherlock/tattoo/tattoo_map.h @@ -25,6 +25,8 @@ #include "common/scummsys.h" #include "sherlock/map.h" +#include "sherlock/resources.h" +#include "sherlock/surface.h" namespace Sherlock { @@ -32,6 +34,8 @@ class SherlockEngine; namespace Tattoo { +#define CLOSEUP_STEPS 30 + struct MapEntry : Common::Point { int _iconNum; Common::String _description; @@ -44,11 +48,35 @@ struct MapEntry : Common::Point { class TattooMap : public Map { private: Common::Array<MapEntry> _data; + ImageFile *_iconImages; + int _bgFound, _oldBgFound; + Surface *_textBuffer; + Common::Rect _textBounds, _oldTextBounds; /** * Load data needed for the map */ void loadData(); + + /** + * Draws all available location icons onto the back buffer + */ + void drwaMapIcons(); + + /** + * Draws the location names of whatever the mouse moves over on the map + */ + void checkMapNames(bool slamIt); + + /** + * Restores an area of the map background + */ + void restoreArea(const Common::Rect &bounds); + + /** + * This will load a specified close up and zoom it up to the middle of the screen + */ + void showCloseUp(int closeUpNum); public: TattooMap(SherlockEngine *vm); virtual ~TattooMap() {} |