aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock/tattoo
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sherlock/tattoo')
-rw-r--r--engines/sherlock/tattoo/tattoo_journal.cpp6
-rw-r--r--engines/sherlock/tattoo/tattoo_scene.cpp64
-rw-r--r--engines/sherlock/tattoo/tattoo_scene.h5
-rw-r--r--engines/sherlock/tattoo/tattoo_talk.cpp2
-rw-r--r--engines/sherlock/tattoo/tattoo_user_interface.cpp6
-rw-r--r--engines/sherlock/tattoo/widget_base.cpp23
-rw-r--r--engines/sherlock/tattoo/widget_files.cpp243
-rw-r--r--engines/sherlock/tattoo/widget_files.h5
-rw-r--r--engines/sherlock/tattoo/widget_talk.cpp5
9 files changed, 307 insertions, 52 deletions
diff --git a/engines/sherlock/tattoo/tattoo_journal.cpp b/engines/sherlock/tattoo/tattoo_journal.cpp
index 6df5ee7458..6c33971357 100644
--- a/engines/sherlock/tattoo/tattoo_journal.cpp
+++ b/engines/sherlock/tattoo/tattoo_journal.cpp
@@ -49,6 +49,9 @@ void TattooJournal::show() {
Screen &screen = *_vm->_screen;
TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
byte palette[PALETTE_SIZE];
+
+ Common::Point oldScroll = screen._currentScroll;
+ screen._currentScroll = Common::Point(0, 0);
// Load journal images
_journalImages = new ImageFile("journal.vgs");
@@ -95,6 +98,9 @@ void TattooJournal::show() {
// Free the images
delete _journalImages;
+
+ // Reset back to whatever scroll was active for the screen
+ screen._currentScroll = oldScroll;
}
void TattooJournal::handleKeyboardEvents() {
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index e40b4d6a9c..1ecc997f42 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -292,6 +292,15 @@ void TattooScene::checkBgShapes() {
}
}
+void TattooScene::freeScene() {
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ Scene::freeScene();
+
+ delete ui._mask;
+ delete ui._mask1;
+ ui._mask = ui._mask1 = nullptr;
+}
+
void TattooScene::doBgAnimCheckCursor() {
Events &events = *_vm->_events;
TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
@@ -724,46 +733,47 @@ void TattooScene::setNPCPath(int npc) {
int TattooScene::findBgShape(const Common::Point &pt) {
People &people = *_vm->_people;
+ UserInterface &ui = *_vm->_ui;
if (!_doBgAnimDone)
// New frame hasn't been drawn yet
return -1;
- int result = Scene::findBgShape(pt);
- if (result == -1) {
- if (_labTableScene) {
- // Check for SOLID objects in the lab scene
- for (int idx = (int)_bgShapes.size() - 1; idx >= 0; --idx) {
- Object &o = _bgShapes[idx];
- if (o._type != INVALID && o._type != NO_SHAPE && o._type != HIDDEN && o._aType == SOLID) {
- if (o.getNewBounds().contains(pt))
- return idx;
- }
- }
+
+ for (int idx = (int)_bgShapes.size() - 1; idx >= 0; --idx) {
+ Object &o = _bgShapes[idx];
+
+ if (o._type != INVALID && o._type != NO_SHAPE && o._type != HIDDEN &&
+ (o._aType <= PERSON || (ui._menuMode == LAB_MODE && o._aType == SOLID))) {
+ if (o.getNewBounds().contains(pt))
+ return idx;
+ } else if (o._type == NO_SHAPE) {
+ if (o.getNoShapeBounds().contains(pt))
+ return idx;
}
+ }
- // No shape found, so check whether a character is highlighted
- for (int idx = 1; idx < MAX_CHARACTERS && result == -1; ++idx) {
- Person &person = people[idx];
+ // If no shape found, so check whether a character is highlighted
+ for (int idx = 1; idx < MAX_CHARACTERS; ++idx) {
+ Person &person = people[idx];
- if (person._type == CHARACTER) {
- int scaleVal = getScaleVal(person._position);
- Common::Rect charRect;
+ if (person._type == CHARACTER) {
+ int scaleVal = getScaleVal(person._position);
+ Common::Rect charRect;
- if (scaleVal == SCALE_THRESHOLD)
- charRect = Common::Rect(person.frameWidth(), person.frameHeight());
- else
- charRect = Common::Rect(person._imageFrame->sDrawXSize(scaleVal), person._imageFrame->sDrawYSize(scaleVal));
- charRect.moveTo(person._position.x / FIXED_INT_MULTIPLIER, person._position.y / FIXED_INT_MULTIPLIER
- - charRect.height());
+ if (scaleVal == SCALE_THRESHOLD)
+ charRect = Common::Rect(person.frameWidth(), person.frameHeight());
+ else
+ charRect = Common::Rect(person._imageFrame->sDrawXSize(scaleVal), person._imageFrame->sDrawYSize(scaleVal));
+ charRect.moveTo(person._position.x / FIXED_INT_MULTIPLIER, person._position.y / FIXED_INT_MULTIPLIER
+ - charRect.height());
- if (charRect.contains(pt))
- result = 1000 + idx;
- }
+ if (charRect.contains(pt))
+ return 1000 + idx;
}
}
- return result;
+ return -1;
}
void TattooScene::synchronize(Serializer &s) {
diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h
index b75f7e70eb..ade4b00a38 100644
--- a/engines/sherlock/tattoo/tattoo_scene.h
+++ b/engines/sherlock/tattoo/tattoo_scene.h
@@ -118,6 +118,11 @@ public:
int getScaleVal(const Point32 &pt);
/**
+ * Fres all the graphics and other dynamically allocated data for the scene
+ */
+ virtual void freeScene();
+
+ /**
* Draw all objects and characters.
*/
virtual void doBgAnim();
diff --git a/engines/sherlock/tattoo/tattoo_talk.cpp b/engines/sherlock/tattoo/tattoo_talk.cpp
index dbeeaf8918..8303fd42ad 100644
--- a/engines/sherlock/tattoo/tattoo_talk.cpp
+++ b/engines/sherlock/tattoo/tattoo_talk.cpp
@@ -193,7 +193,7 @@ void TattooTalk::talkInterface(const byte *&str) {
}
// Display the text window
-// ui.banishWindow();
+ ui.banishWindow();
ui._textWidget.load(Common::String((const char *)s, (const char *)str), _speaker);
ui._textWidget.summonWindow();
_wait = true;
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index 6c40323b0d..d8faa3e0ae 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -65,6 +65,8 @@ TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm),
TattooUserInterface::~TattooUserInterface() {
delete _interfaceImages;
+ delete _mask;
+ delete _mask1;
}
void TattooUserInterface::initScrollVars() {
@@ -388,13 +390,13 @@ void TattooUserInterface::doStandardControl() {
switch (_keyState.keycode) {
case Common::KEYCODE_F5:
// Save game
- freeMenu();
+ events.warpMouse();
saveGame();
return;
case Common::KEYCODE_F7:
// Load game
- freeMenu();
+ events.warpMouse();
loadGame();
return;
diff --git a/engines/sherlock/tattoo/widget_base.cpp b/engines/sherlock/tattoo/widget_base.cpp
index e0b903916b..539d4a2f02 100644
--- a/engines/sherlock/tattoo/widget_base.cpp
+++ b/engines/sherlock/tattoo/widget_base.cpp
@@ -59,11 +59,13 @@ void WidgetBase::banishWindow() {
}
void WidgetBase::close() {
+ Events &events = *_vm->_events;
TattooScene &scene = *(TattooScene *)_vm->_scene;
TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
banishWindow();
ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+ events.clearEvents();
}
bool WidgetBase::active() const {
@@ -175,8 +177,8 @@ void WidgetBase::restrictToScreen() {
_bounds.moveTo(screen._currentScroll.x, _bounds.top);
if (_bounds.top < 0)
_bounds.moveTo(_bounds.left, 0);
- if (_bounds.right > screen._backBuffer1.w())
- _bounds.moveTo(screen._backBuffer1.w() - _bounds.width(), _bounds.top);
+ if (_bounds.right > (screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH))
+ _bounds.moveTo(screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH - _bounds.width(), _bounds.top);
if (_bounds.bottom > screen._backBuffer1.h())
_bounds.moveTo(_bounds.left, screen._backBuffer1.h() - _bounds.height());
}
@@ -330,21 +332,8 @@ void WidgetBase::handleScrolling(int &scrollIndex, int pageSize, int max) {
yp = CLIP(yp, r.top + BUTTON_SIZE + 3, r.bottom - BUTTON_SIZE - 3);
// Calculate the line number that corresponds to the position that the mouse is on the scrollbar
- int lineNum = (yp - _bounds.top - BUTTON_SIZE - 3) * 100 / (_bounds.height() - BUTTON_SIZE * 2 - 6)
- * max / 100 - 3;
-
- // If the new position would place part of the text outsidethe text window, adjust it so it doesn't
- if (lineNum < 0)
- lineNum = 0;
- else if (lineNum + pageSize > max) {
- lineNum = max - pageSize;
-
- // Make sure it's not below zero now
- if (lineNum < 0)
- lineNum = 0;
- }
-
- scrollIndex = lineNum;
+ int lineNum = (yp - r.top - BUTTON_SIZE - 3) * (max - pageSize) / (r.height() - BUTTON_SIZE * 2 - 6);
+ scrollIndex = CLIP(lineNum, 0, max - pageSize);
}
// Get the current frame so we can check the scroll timer against it
diff --git a/engines/sherlock/tattoo/widget_files.cpp b/engines/sherlock/tattoo/widget_files.cpp
index 4a0c0495e0..1743bcd09e 100644
--- a/engines/sherlock/tattoo/widget_files.cpp
+++ b/engines/sherlock/tattoo/widget_files.cpp
@@ -150,7 +150,7 @@ void WidgetFiles::render(FilesRenderMode mode) {
color = INFO_TOP;
if (mode == RENDER_NAMES_AND_SCROLLBAR)
- _surface.fillRect(Common::Rect(4, yp, _surface.w() - BUTTON_SIZE - 9, yp + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.fillRect(Common::Rect(4, yp, _surface.w() - BUTTON_SIZE - 9, yp + _surface.fontHeight()), TRANSPARENCY);
Common::String numStr = Common::String::format("%d.", idx + 1);
_surface.writeString(numStr, Common::Point(_surface.widestChar(), yp), color);
@@ -166,8 +166,11 @@ void WidgetFiles::render(FilesRenderMode mode) {
}
void WidgetFiles::handleEvents() {
- //Events &events = *_vm->_events;
+ Events &events = *_vm->_events;
+ TattooScene &scene = *(TattooScene *)_vm->_scene;
TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+ Common::KeyState keyState = ui._keyState;
// Handle scrollbar events
ScrollHighlight oldHighlight = ui._scrollHighlight;
@@ -176,11 +179,243 @@ void WidgetFiles::handleEvents() {
int oldScrollIndex = _savegameIndex;
handleScrolling(_savegameIndex, FILES_LINES_COUNT, _savegames.size());
+ // See if the mouse is pointing at any filenames in the window
+ if (Common::Rect(_bounds.left, _bounds.top + _surface.fontHeight() + 14,
+ _bounds.right - BUTTON_SIZE - 5, _bounds.bottom - 5).contains(mousePos)) {
+ _selector = (mousePos.y - _bounds.top - _surface.fontHeight() - 14) / (_surface.fontHeight() + 1) +
+ _savegameIndex;
+ } else {
+ _selector = -1;
+ }
+
+ // Check for the Tab key
+ if (keyState.keycode == Common::KEYCODE_TAB) {
+ // If the mouse is not over any of the filenames, move the mouse so that it points to the first one
+ if (_selector == -1) {
+ events.warpMouse(Common::Point(_bounds.right - BUTTON_SIZE - 20,
+ _bounds.top + _surface.fontHeight() * 2 + 8));
+ } else {
+ // See if we're doing Tab or Shift Tab
+ if (keyState.flags & Common::KBD_SHIFT) {
+ // We're doing Shift Tab
+ if (_selector == _savegameIndex)
+ _selector = _savegameIndex + 4;
+ else
+ --_selector;
+ } else {
+ // We're doing Tab
+ ++_selector;
+ if (_selector >= _savegameIndex + 5)
+ _selector = _savegameIndex;
+ }
+
+ events.warpMouse(Common::Point(mousePos.x, _bounds.top + _surface.fontHeight() * 2
+ + 8 + (_selector - _savegameIndex) * (_surface.fontHeight() + 1)));
+ }
+ }
+
// Only redraw the window if the the scrollbar position has changed
- if (ui._scrollHighlight != oldHighlight || oldScrollIndex != _savegameIndex)
+ if (ui._scrollHighlight != oldHighlight || oldScrollIndex != _savegameIndex || _selector != _oldSelector)
render(RENDER_NAMES_AND_SCROLLBAR);
+ _oldSelector = _selector;
+
+ if (events._firstPress && !_bounds.contains(mousePos))
+ _outsideMenu = true;
+
+ if (events._released || events._rightReleased || keyState.keycode == Common::KEYCODE_ESCAPE) {
+ ui._scrollHighlight = SH_NONE;
+
+ if (_outsideMenu && !_bounds.contains(mousePos)) {
+ close();
+ } else {
+ _outsideMenu = false;
+
+ if (_selector != -1) {
+ if (_fileMode = SAVEMODE_LOAD) {
+ // We're in Load Mode
+ _vm->loadGameState(_selector);
+ } else if (_fileMode == SAVEMODE_SAVE) {
+ // We're in Save Mode
+ if (getFilename())
+ _vm->saveGameState(_selector, _savegames[_selector]);
+ close();
+ }
+ }
+ }
+ }
+}
+
+bool WidgetFiles::getFilename() {
+ Events &events = *_vm->_events;
+ TattooScene &scene = *(TattooScene *)_vm->_scene;
+ Talk &talk = *_vm->_talk;
+ int index = 0;
+ int done = 0;
+ bool flag = false;
+ int width;
+ int cursorColor = 192;
+ byte color, textColor;
+ bool insert = true;
+
+ assert(_selector != -1);
+ Common::Point pt(_surface.stringWidth("00.") + _surface.widestChar() + 5,
+ _surface.fontHeight() + 14 + (_selector - _savegameIndex) * (_surface.fontHeight() + 1));
+
+ Common::String str = Common::String::format("%d.", _selector + 1);
+ _surface.writeString(str, Common::Point(_surface.widestChar(), pt.y), COMMAND_HIGHLIGHTED);
+
+ Common::String saveFile = _savegames[_selector];
+ Common::String filename = _savegames[_selector];
+ _savegames[_selector] = "";
+
+ if (isSlotEmpty(_selector)) {
+ index = 0;
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.right - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ } else {
+ index = saveFile.size();
+ _surface.writeString(saveFile, pt, COMMAND_HIGHLIGHTED);
+ pt.x = _surface.stringWidth("00.") + _surface.stringWidth(saveFile) + _surface.widestChar() + 5;
+
+ //filename[index] = 32;
+ }
+
+ do {
+ scene.doBgAnim();
+
+ if (talk._talkToAbort)
+ return false;
+
+ if (filename[index]) {
+ str = Common::String::format("%c", filename[index]);
+ width = _surface.charWidth(filename[index]);
+ } else {
+ width = 7;
+ }
+
+ while (!events.kbHit()) {
+ events.pollEventsAndWait();
+ events.setButtonState();
+
+ scene.doBgAnim();
+
+ if (talk._talkToAbort)
+ return false;
+
+ flag = !flag;
+ if (flag) {
+ textColor = 236;
+ color = cursorColor;
+ } else {
+ textColor = COMMAND_HIGHLIGHTED;
+ color = TRANSPARENCY;
+ }
+
+ _surface.fillRect(Common::Rect(pt.x, pt.y, pt.x + width, pt.y + _surface.fontHeight()), color);
+ if (filename[index])
+ _surface.writeString(str, pt, textColor);
+
+ if (_vm->shouldQuit())
+ return false;
+ }
+
+ Common::KeyState keyState = events.getKey();
+ if (keyState.keycode == Common::KEYCODE_BACKSPACE && index > 0) {
+ pt.x -= _surface.charWidth(filename[index - 1]);
+
+ if (insert) {
+ filename.deleteChar(index);
+ } else {
+ filename.setChar(' ', index - 1);
+ }
+
+ --index;
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _surface.w() - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.writeString(filename.c_str() + index, pt, COMMAND_HIGHLIGHTED);
+
+ } else if ((keyState.keycode == Common::KEYCODE_LEFT && index > 0)
+ || (keyState.keycode == Common::KEYCODE_RIGHT && index < 49 && pt.x < (_bounds.right - BUTTON_SIZE - 20))
+ || (keyState.keycode == Common::KEYCODE_HOME && index > 0)
+ || (keyState.keycode == Common::KEYCODE_END)) {
+ _surface.fillRect(Common::Rect(pt.x, pt.y, pt.x + width, pt.y + _surface.fontHeight()), TRANSPARENCY);
+ if (filename[index])
+ _surface.writeString(str, pt, COMMAND_HIGHLIGHTED);
+
+ switch (keyState.keycode) {
+ case Common::KEYCODE_LEFT:
+ pt.x -= _surface.charWidth(filename[index - 1]);
+ --index;
+ break;
+
+ case Common::KEYCODE_RIGHT:
+ pt.x += _surface.charWidth(filename[index]);
+ ++index;
+ break;
+
+ case Common::KEYCODE_HOME:
+ pt.x = _surface.stringWidth("00.") + _surface.widestChar() + 5;
+ index = 0;
+ break;
+
+ case Common::KEYCODE_END:
+ pt.x = _surface.stringWidth("00.") + _surface.stringWidth(filename) + _surface.widestChar() + 5;
+ index = filename.size();
+
+ while (filename[index - 1] == ' ' && index > 0) {
+ pt.x -= _surface.charWidth(filename[index - 1]);
+ --index;
+ }
+ break;
+ }
+ } else if (keyState.keycode == Common::KEYCODE_INSERT) {
+ insert = !insert;
+ if (insert)
+ cursorColor = 192;
+ else
+ cursorColor = 200;
+
+ } else if (keyState.keycode == Common::KEYCODE_DELETE) {
+ filename.deleteChar(index);
+
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.right - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.writeString(filename + index, pt, COMMAND_HIGHLIGHTED);
+
+ } else if (keyState.keycode == Common::KEYCODE_RETURN) {
+ done = 1;
+
+ } else if (keyState.keycode == Common::KEYCODE_ESCAPE) {
+ filename = saveFile;
+ _selector = -1;
+ render(RENDER_NAMES_AND_SCROLLBAR);
+ done = -1;
+ }
+
+ if ((keyState.keycode >= ' ') && ((keyState.keycode <= 168) || (keyState.keycode == 225)) && (index < 50)) {
+ if (pt.x + _surface.charWidth(keyState.keycode) < _surface.w() - BUTTON_SIZE - 20) {
+ if (insert) {
+ int temp = strlen(filename.c_str() + index) - 1;
+ if (temp)
+ filename.deleteChar(index);
+ }
+
+ filename.insertChar(keyState.ascii, index);
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.width() - BUTTON_SIZE - 9,
+ pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.writeString(filename.c_str() + index, pt, COMMAND_HIGHLIGHTED);
+ pt.x += _surface.charWidth(keyState.keycode);
+ ++index;
+ }
+ }
+ } while (!done && !_vm->shouldQuit());
+
+ scene.doBgAnim();
+
+ if (talk._talkToAbort)
+ return false;
+
+ if (done == 1)
+ _savegames[_selector] = saveFile;
- // TODO
+ return done == 1;
}
Common::Rect WidgetFiles::getScrollBarBounds() const {
diff --git a/engines/sherlock/tattoo/widget_files.h b/engines/sherlock/tattoo/widget_files.h
index e861206d4b..94a029d18d 100644
--- a/engines/sherlock/tattoo/widget_files.h
+++ b/engines/sherlock/tattoo/widget_files.h
@@ -57,6 +57,11 @@ private:
void showScummVMRestoreDialog();
/**
+ * Prompt the user for a savegame name in the currently selected slot
+ */
+ bool getFilename();
+
+ /**
* Return the area of a widget that the scrollbar will be drawn in
*/
virtual Common::Rect getScrollBarBounds() const;
diff --git a/engines/sherlock/tattoo/widget_talk.cpp b/engines/sherlock/tattoo/widget_talk.cpp
index bc2f8339d2..d33da658ab 100644
--- a/engines/sherlock/tattoo/widget_talk.cpp
+++ b/engines/sherlock/tattoo/widget_talk.cpp
@@ -128,7 +128,7 @@ void WidgetTalk::handleEvents() {
// Only redraw the window if the the scrollbar position has changed
if (ui._scrollHighlight != oldHighlight || oldScrollIndex != _talkScrollIndex)
- render(HL_SCROLLBAR_ONLY);
+ render(HL_NO_HIGHLIGHTING);
// Flag if they started pressing outside of the window
if (events._firstPress && !_bounds.contains(mousePos))
@@ -385,6 +385,9 @@ void WidgetTalk::render(Highlight highlightMode) {
for (uint idx = _talkScrollIndex; idx < _statementLines.size() && yp < (_bounds.height() - _surface.fontHeight()); ++idx) {
if (highlightMode == HL_NO_HIGHLIGHTING || _statementLines[idx]._num == _selector ||
_statementLines[idx]._num == _oldSelector) {
+ // Erase the line contents
+ _surface.fillRect(Common::Rect(3, yp, _surface.w() - BUTTON_SIZE - 3, yp + _surface.fontHeight()), TRANSPARENCY);
+
// Different coloring based on whether the option has been previously chosen or not
color = (!talk._talkHistory[talk._converseNum][_statementLines[idx]._num]) ?
INFO_TOP : INFO_BOTTOM;