SHERLOCK: RT: Refactored map to use the tooltip widget

This commit is contained in:
Paul Gilbert 2015-06-20 17:29:40 -04:00
parent 4318e0072b
commit 4a88c69b5d
6 changed files with 66 additions and 157 deletions

View File

@ -41,10 +41,9 @@ void MapEntry::clear() {
/*-------------------------------------------------------------------------*/
TattooMap::TattooMap(SherlockEngine *vm) : Map(vm) {
TattooMap::TattooMap(SherlockEngine *vm) : Map(vm), _mapTooltip(vm) {
_iconImages = nullptr;
_bgFound = _oldBgFound = 0;
_textBuffer = nullptr;
loadData();
}
@ -120,9 +119,7 @@ int TattooMap::show() {
// Display the built map to the screen
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
// Set text display positioning and scroll position
_oldTextBounds.left = _oldTextBounds.top = _oldTextBounds.right = _oldTextBounds.bottom = 0;
_textBounds.left = _textBounds.top = _textBounds.right = _textBounds.bottom = 0;
// Set initial scroll position
_targetScroll = _bigPos;
_currentScroll = Common::Point(-1, -1);
@ -197,9 +194,7 @@ int TattooMap::show() {
// Handle any scrolling of the map
if (_currentScroll != _targetScroll) {
// If there is a Text description being displayed, restore the area under it
if (_oldTextBounds.width() > 0)
screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTextBounds.left,
_oldTextBounds.top), _oldTextBounds);
_mapTooltip.erase();
_currentScroll = _targetScroll;
@ -211,11 +206,7 @@ int TattooMap::show() {
// Handling if a location has been clicked on
if (events._released && _bgFound != -1) {
// If there is a Text description being displayed, restore the area under it
if (_oldTextBounds.width() > 0) {
screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTextBounds.left,
_oldTextBounds.top), _oldTextBounds);
screen.slamRect(_oldTextBounds);
}
_mapTooltip.erase();
// Save the current scroll position on the map
_bigPos = _currentScroll;
@ -227,8 +218,7 @@ int TattooMap::show() {
music.stopMusic();
events.clearEvents();
delete _textBuffer;
_textBuffer = nullptr;
_mapTooltip.banishWindow();
// Reset the back buffers back to standard size
screen._backBuffer1.create(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
@ -336,141 +326,21 @@ void TattooMap::checkMapNames(bool slamIt) {
}
}
// 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)) {
// Handle updating the tooltip
if (_bgFound != _oldBgFound) {
if (_bgFound == -1) {
_mapTooltip.setText("");
} else {
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();
int dif = 10000;
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);
_textBuffer->fillRect(Common::Rect(0, 0, width, height), TRANSPARENCY);
if (space == nullptr) {
// The whole text can be drawn on a single line
_textBuffer->writeFancyString(desc, Common::Point(0, 0), BLACK, 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);
// Draw the first line
int xp = (width - screen.stringWidth(desc)) / 2;
_textBuffer->writeFancyString(line1, Common::Point(xp, 0), BLACK, MAP_NAME_COLOR);
int yp = screen.stringHeight(line2);
xp = (width - screen.stringWidth(line2)) / 2;
// CHECKME: Shouldn't we use yp for drawing line2?
_textBuffer->writeFancyString(line2, Common::Point(xp, yp), BLACK, MAP_NAME_COLOR);
}
// Set the text display position
setTextBounds();
} else if (_bgFound == -1 && _oldBgFound != -1) {
// We need to clear a currently displayed name
delete _textBuffer;
_textBuffer = nullptr;
_mapTooltip.setText(desc);
}
_oldBgFound = _bgFound;
} else {
// Set the new text position
setTextBounds();
}
// If the location name was displayed, restore the graphics underneath where it previously was
if (_oldTextBounds.width() > 0)
screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTextBounds.left, _oldTextBounds.top), _oldTextBounds);
// See if we need to draw the currently highlighted location name
if (_textBuffer != nullptr)
screen._backBuffer1.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)
slamRect(_oldTextBounds);
// If there's no text to display, reset the display 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 text to display, then copy the drawn area to the screen
if (_textBuffer != nullptr && slamIt)
slamRect(_textBounds);
}
void TattooMap::setTextBounds() {
Events &events = *_vm->_events;
Common::Point mousePos = events.mousePos();
if (_textBuffer == nullptr) {
_textBounds = Common::Rect(0, 0, 0, 0);
} else {
int xp = (mousePos.x - _textBounds.width() / 2) + _currentScroll.x;
int yp = (mousePos.y - _textBounds.height() / 2) + _currentScroll.y;
if (xp < _currentScroll.x)
xp = _currentScroll.x;
if ((xp + _textBounds.width()) >(_currentScroll.x + SHERLOCK_SCREEN_WIDTH))
xp = _currentScroll.x + SHERLOCK_SCREEN_WIDTH - _textBounds.width();
if (yp < _currentScroll.y)
yp = _currentScroll.y;
if ((yp + _textBounds.height()) >(_currentScroll.y + SHERLOCK_SCREEN_HEIGHT))
yp = _currentScroll.y + SHERLOCK_SCREEN_HEIGHT - _textBounds.height();
_textBounds = Common::Rect(xp, yp, xp + _textBuffer->w(), yp + _textBuffer->h());
}
_mapTooltip.handleEvents();
if (slamIt)
_mapTooltip.draw();
}
void TattooMap::restoreArea(const Common::Rect &bounds) {

View File

@ -27,6 +27,7 @@
#include "sherlock/map.h"
#include "sherlock/resources.h"
#include "sherlock/surface.h"
#include "sherlock/tattoo/widget_tooltip.h"
namespace Sherlock {
@ -48,9 +49,8 @@ private:
Common::Array<MapEntry> _data;
ImageFile *_iconImages;
int _bgFound, _oldBgFound;
Surface *_textBuffer;
Common::Rect _textBounds, _oldTextBounds;
Common::Point _currentScroll, _targetScroll;
WidgetMapTooltip _mapTooltip;
Common::Point _targetScroll;
/**
* Load data needed for the map
@ -77,15 +77,12 @@ private:
*/
void showCloseUp(int closeUpNum);
/**
* Set the display bounds for the textual description of a location
*/
void setTextBounds();
/**
* Copies an area of the map to the screen, taking into account scrolling
*/
void slamRect(const Common::Rect &bounds);
public:
Common::Point _currentScroll;
public:
TattooMap(SherlockEngine *vm);
virtual ~TattooMap() {}

View File

@ -46,27 +46,39 @@ void WidgetBase::banishWindow() {
void WidgetBase::erase() {
Screen &screen = *_vm->_screen;
const Common::Point &currentScroll = getCurrentScroll();
if (_oldBounds.width() > 0) {
screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
screen.slamRect(_oldBounds);
// Get the bounds to copy from the back buffers, adjusted for scroll position
Common::Rect oldBounds = _oldBounds;
oldBounds.translate(currentScroll.x, currentScroll.y);
// Restore the affected area from the secondary back buffer into the first one, and then copy to screen
screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(oldBounds.left, oldBounds.top), oldBounds);
screen.blitFrom(screen._backBuffer1, Common::Point(_oldBounds.left, _oldBounds.top), oldBounds);
// Reset the old bounds so
_oldBounds = Common::Rect(0, 0, 0, 0);
}
}
void WidgetBase::draw() {
Screen &screen = *_vm->_screen;
const Common::Point &currentScroll = getCurrentScroll();
// If there was a previously drawn frame in a different position that hasn't yet been erased, then erase it
if (_oldBounds.width() > 0 && _oldBounds != _bounds)
erase();
if (_bounds.width() > 0 && !_surface.empty()) {
// Get the area to draw, adjusted for scroll position
Common::Rect bounds = _bounds;
bounds.translate(currentScroll.x, currentScroll.y);
// Copy any area to be drawn on from the secondary back buffer, and then draw surface on top
screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_bounds.left, _bounds.top), _bounds);
screen._backBuffer1.transBlitFrom(_surface, Common::Point(_bounds.left, _bounds.top));
screen.slamRect(_bounds);
screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(bounds.left, bounds.top), bounds);
screen._backBuffer1.transBlitFrom(_surface, Common::Point(bounds.left, bounds.top));
screen.blitFrom(screen._backBuffer1, Common::Point(_bounds.left, _bounds.top), bounds);
// Store a copy of the drawn area for later erasing
_oldBounds = _bounds;
@ -151,6 +163,11 @@ void WidgetBase::makeInfoArea() {
_surface.vLine(_bounds.width() - 1, (*_images)[0]._height, _bounds.height()- (*_images)[2]._height, INFO_BOTTOM);
}
const Common::Point &WidgetBase::getCurrentScroll() const {
TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
return ui._currentScroll;
}
} // End of namespace Tattoo
} // End of namespace Sherlock

View File

@ -56,6 +56,11 @@ protected:
void checkMenuPosition();
void makeInfoArea();
/**
* Returns the current scroll position
*/
virtual const Common::Point &getCurrentScroll() const;
public:
WidgetBase(SherlockEngine *vm);
virtual ~WidgetBase() {}

View File

@ -21,6 +21,7 @@
*/
#include "sherlock/tattoo/widget_tooltip.h"
#include "sherlock/tattoo/tattoo_map.h"
#include "sherlock/tattoo/tattoo_user_interface.h"
#include "sherlock/tattoo/tattoo.h"
@ -173,6 +174,15 @@ void WidgetSceneTooltip::handleEvents() {
}
ui._oldArrowZone = ui._arrowZone;
WidgetTooltip::handleEvents();
}
/*----------------------------------------------------------------*/
const Common::Point &WidgetMapTooltip::getCurrentScroll() const {
TattooMap &map = *(TattooMap *)_vm->_map;
return map._currentScroll;
}
} // End of namespace Tattoo

View File

@ -59,6 +59,16 @@ public:
virtual void handleEvents();
};
class WidgetMapTooltip : public WidgetTooltip {
protected:
/**
* Returns the current scroll position
*/
virtual const Common::Point &getCurrentScroll() const;
public:
WidgetMapTooltip(SherlockEngine *vm) : WidgetTooltip(vm) {}
};
} // End of namespace Tattoo
} // End of namespace Sherlock