mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-12 20:17:49 +00:00
SHERLOCK: RT: Refactored map to use the tooltip widget
This commit is contained in:
parent
4318e0072b
commit
4a88c69b5d
@ -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) {
|
||||
|
@ -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() {}
|
||||
|
@ -46,27 +46,39 @@ void WidgetBase::banishWindow() {
|
||||
|
||||
void WidgetBase::erase() {
|
||||
Screen &screen = *_vm->_screen;
|
||||
const Common::Point ¤tScroll = 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 ¤tScroll = 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
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user