aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2015-06-10 20:54:05 -0400
committerPaul Gilbert2015-06-10 20:54:05 -0400
commit6780c63e538d28c13a5fc1db8c282d00a95bcaaa (patch)
treee32e766468349d1bd3830281635cfb2fa86c8e44
parentdd1781a3f29fdcaad7b3551872e5246e4f694389 (diff)
downloadscummvm-rg350-6780c63e538d28c13a5fc1db8c282d00a95bcaaa.tar.gz
scummvm-rg350-6780c63e538d28c13a5fc1db8c282d00a95bcaaa.tar.bz2
scummvm-rg350-6780c63e538d28c13a5fc1db8c282d00a95bcaaa.zip
SHERLOCK: Implemented more support methods for RT map
-rw-r--r--engines/sherlock/fonts.h2
-rw-r--r--engines/sherlock/screen.h17
-rw-r--r--engines/sherlock/surface.h10
-rw-r--r--engines/sherlock/tattoo/tattoo_map.cpp262
-rw-r--r--engines/sherlock/tattoo/tattoo_map.h28
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() {}