diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/made/pmvplayer.cpp | 5 | ||||
-rw-r--r-- | engines/made/screenfx.cpp | 2 | ||||
-rw-r--r-- | engines/made/sound.cpp | 26 | ||||
-rw-r--r-- | engines/made/sound.h | 17 | ||||
-rw-r--r-- | engines/mohawk/riven_external.cpp | 33 | ||||
-rw-r--r-- | engines/sherlock/events.cpp | 34 | ||||
-rw-r--r-- | engines/sherlock/events.h | 6 | ||||
-rw-r--r-- | engines/sherlock/module.mk | 1 | ||||
-rw-r--r-- | engines/sherlock/objects.cpp | 4 | ||||
-rw-r--r-- | engines/sherlock/scene.cpp | 11 | ||||
-rw-r--r-- | engines/sherlock/surface.cpp | 13 | ||||
-rw-r--r-- | engines/sherlock/tattoo/tattoo_scene.cpp | 3 | ||||
-rw-r--r-- | engines/sherlock/tattoo/tattoo_user_interface.cpp | 16 | ||||
-rw-r--r-- | engines/sherlock/tattoo/tattoo_user_interface.h | 20 | ||||
-rw-r--r-- | engines/sherlock/tattoo/widget_base.cpp | 8 | ||||
-rw-r--r-- | engines/sherlock/tattoo/widget_inventory.cpp | 108 | ||||
-rw-r--r-- | engines/sherlock/tattoo/widget_inventory.h | 15 | ||||
-rw-r--r-- | engines/sherlock/tattoo/widget_lab.cpp | 43 | ||||
-rw-r--r-- | engines/sherlock/tattoo/widget_lab.h | 52 | ||||
-rw-r--r-- | engines/sherlock/user_interface.cpp | 2 |
20 files changed, 314 insertions, 105 deletions
diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 6ea0dc24d0..453e2a4872 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -118,6 +118,8 @@ bool PmvPlayer::play(const char *filename) { // get it to work well? _audioStream = Audio::makeQueuingAudioStream(soundFreq, false); + SoundDecoderData *soundDecoderData = new SoundDecoderData(); + while (!_vm->shouldQuit() && !_aborted && !_fd->eos() && frameNumber < frameCount) { int32 frameTime = _vm->_system->getMillis(); @@ -153,7 +155,7 @@ bool PmvPlayer::play(const char *filename) { soundSize = chunkCount * chunkSize; soundData = (byte *)malloc(soundSize); - decompressSound(audioData + 8, soundData, chunkSize, chunkCount); + decompressSound(audioData + 8, soundData, chunkSize, chunkCount, NULL, soundDecoderData); _audioStream->queueBuffer(soundData, soundSize, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED); } @@ -213,6 +215,7 @@ bool PmvPlayer::play(const char *filename) { } + delete soundDecoderData; delete[] frameData; _audioStream->finish(); diff --git a/engines/made/screenfx.cpp b/engines/made/screenfx.cpp index 3f98cbb9ab..bae59f05cc 100644 --- a/engines/made/screenfx.cpp +++ b/engines/made/screenfx.cpp @@ -201,7 +201,7 @@ void ScreenEffects::startBlendedPalette(byte *palette, byte *newPalette, int col } void ScreenEffects::stepBlendedPalette() { - if (_blendedPaletteStatus._active && _blendedPaletteStatus._value < _blendedPaletteStatus._maxValue) { + if (_blendedPaletteStatus._active && _blendedPaletteStatus._value <= _blendedPaletteStatus._maxValue) { setBlendedPalette(_blendedPaletteStatus._palette, _blendedPaletteStatus._newPalette, _blendedPaletteStatus._colorCount, _blendedPaletteStatus._value, _blendedPaletteStatus._maxValue); if (_blendedPaletteStatus._value == _blendedPaletteStatus._maxValue) diff --git a/engines/made/sound.cpp b/engines/made/sound.cpp index 91e855cbf5..ad49031e7b 100644 --- a/engines/made/sound.cpp +++ b/engines/made/sound.cpp @@ -133,10 +133,10 @@ void ManholeEgaSoundDecompressor::update3() { _sample2 += _sample1; } -void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount, SoundEnergyArray *soundEnergyArray) { +void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount, SoundEnergyArray *soundEnergyArray, SoundDecoderData *soundDecoderData) { - int16 prevSample = 0, workSample = 0; - byte soundBuffer[1025]; + int16 prevSample, workSample; + byte* soundBuffer; byte deltaSoundBuffer[1024]; int16 soundBuffer2[16]; byte deltaType, type; @@ -159,6 +159,15 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou if (soundEnergyArray) soundEnergyArray->clear(); + if (soundDecoderData) { + soundBuffer = soundDecoderData->_soundBuffer; + prevSample = soundDecoderData->_prevSample; + } else { + soundBuffer = new byte[1025]; + memset(soundBuffer, 0x80, 1025); + prevSample = 0; + } + while (chunkCount--) { deltaType = (*source) >> 6; workChunkSize = chunkSize; @@ -233,6 +242,11 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou } if (deltaType > 0) { + // NB: The original did not add this extra value at the end (as far + // as I can tell), and so technically read past the filled part of + // soundBuffer. + soundBuffer[workChunkSize] = soundBuffer[workChunkSize - 1]; + if (deltaType == 1) { for (i = 0; i < chunkSize - 1; i += 2) { l = i / 2; @@ -255,9 +269,13 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou prevSample = workSample; memcpy(dest, soundBuffer, chunkSize); dest += chunkSize; - } + if (soundDecoderData) { + soundDecoderData->_prevSample = prevSample; + } else { + delete[] soundBuffer; + } } } // End of namespace Made diff --git a/engines/made/sound.h b/engines/made/sound.h index 6ffca13aaa..72537322f9 100644 --- a/engines/made/sound.h +++ b/engines/made/sound.h @@ -53,7 +53,22 @@ struct SoundEnergyItem { typedef Common::Array<SoundEnergyItem> SoundEnergyArray; -void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount, SoundEnergyArray *soundEnergyArray = NULL); + +// Persistent data for decompressSound(). When calling decompressSound() +// repeatedly (for the same stream), pass the same SoundDecoderData object to +// ensure decoding properly resumes. +class SoundDecoderData { +public: + SoundDecoderData() { + memset(_soundBuffer, 0x80, sizeof(_soundBuffer)); + _prevSample = 0; + } + + byte _soundBuffer[1025]; + int16 _prevSample; +}; + +void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount, SoundEnergyArray *soundEnergyArray = NULL, SoundDecoderData *decoderData = NULL); } // End of namespace Made diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index c859248055..7ca41e253c 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -2573,26 +2573,47 @@ void RivenExternal::xt7500_checkmarbles(uint16 argc, uint16 *argv) { void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) { // Draw the small marbles when we're a step away from the waffle - uint16 baseBitmapId = _vm->findResourceID(ID_TBMP, "*tsmallred"); + + // Convert from marble X coordinate to screen X coordinate + static const uint16 xPosOffsets[] = { + 246, 245, 244, 243, 243, 241, 240, 240, 239, 238, 237, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 226, 225 + }; + + // Convert from marble Y coordinate to screen Y coordinate + static const uint16 yPosOffsets[] = { + 261, 263, 265, 267, 268, 270, 272, 274, 276, 278, 281, 284, 285, 288, 290, 293, 295, 298, 300, 303, 306, 309, 311, 314, 316 + }; + + // Handle spacing for y coordinates due to the angle + static const double yAdjusts[] = { + 4.56, 4.68, 4.76, 4.84, 4.84, 4.96, 5.04, 5.04, 5.12, 5.2, 5.28, 5.28, 5.36, 5.44, 5.4, 5.6, 5.72, 5.8, 5.88, 5.96, 6.04, 6.12, 6.2, 6.2, 6.28 + }; + + // Waffle state of 0 is up, 1 down bool waffleDown = _vm->_vars["twaffle"] != 0; // Note that each of the small marble images is exactly 4x2 + // The original seems to scale the marble images from extras.mhk, but + // we're using the pre-scaled images in the stack. + uint16 baseBitmapId = _vm->findResourceID(ID_TBMP, "*tsmallred"); for (uint16 i = 0; i < kMarbleCount; i++) { - uint32 &var = _vm->_vars[s_marbleNames[i]]; + uint32 var = _vm->_vars[s_marbleNames[i]]; if (var == 0) { // The marble is still in its initial place // (Note that this is still drawn even if the waffle is down) - int marbleX = 376 + i * 2; - int marbleY = 253 + i * 4; - _vm->_gfx->copyImageToScreen(baseBitmapId + i, marbleX, marbleY, marbleX + kSmallMarbleWidth, marbleY + kSmallMarbleHeight); + static const uint16 defaultX[] = { 375, 377, 379, 381, 383, 385 }; + static const uint16 defaultY[] = { 253, 257, 261, 265, 268, 273 }; + _vm->_gfx->copyImageToScreen(baseBitmapId + i, defaultX[i], defaultY[i], defaultX[i] + kSmallMarbleWidth, defaultY[i] + kSmallMarbleHeight); } else if (waffleDown) { // The marble is on the grid and the waffle is down // (Nothing to draw here) } else { // The marble is on the grid and the waffle is up - // TODO: Draw them onto the grid + int marbleX = (int)round(getMarbleX(var) * yAdjusts[getMarbleY(var)] + xPosOffsets[getMarbleY(var)]); + int marbleY = yPosOffsets[getMarbleY(var)]; + _vm->_gfx->copyImageToScreen(baseBitmapId + i, marbleX, marbleY, marbleX + kSmallMarbleWidth, marbleY + kSmallMarbleHeight); } } } diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 3f49e347ae..a8912f6f1e 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -89,6 +89,8 @@ void Events::setCursor(CursorId cursorId) { void Events::setCursor(const Graphics::Surface &src, int hotspotX, int hotspotY) { _cursorId = INVALID_CURSOR; + _hotspotPos = Common::Point(hotspotX, hotspotY); + if (!IS_3DO) { // PC 8-bit palettized CursorMan.replaceCursor(src.getPixels(), src.w, src.h, hotspotX, hotspotY, 0xff); @@ -99,6 +101,38 @@ void Events::setCursor(const Graphics::Surface &src, int hotspotX, int hotspotY) showCursor(); } +void Events::setCursor(CursorId cursorId, const Graphics::Surface &surface) { + _cursorId = cursorId; + + int hotspotX, hotspotY; + if (cursorId == MAGNIFY) { + hotspotX = 8; + hotspotY = 8; + } else { + hotspotX = 0; + hotspotY = 0; + } + + // Get the standard cursor frame + Graphics::Surface &surface2 = (*_cursorImages)[cursorId]._frame; + + // Form a single surface containing both frames + int maxWidth = MAX(surface.w, surface2.w); + Graphics::Surface s; + s.create(maxWidth, surface.h + surface2.h, Graphics::PixelFormat::createFormatCLUT8()); + s.fillRect(Common::Rect(0, 0, maxWidth, surface.h + surface2.h), TRANSPARENCY); + + s.copyRectToSurface(surface, (maxWidth - surface.w) / 2, 0, Common::Rect(0, 0, surface.w, surface.h)); + s.copyRectToSurface(surface2, (maxWidth - surface2.w) / 2, surface.h, Common::Rect(0, 0, surface2.w, surface2.h)); + + // Adjust hotspot position + hotspotX += (maxWidth - surface2.w) / 2; + hotspotY += surface.h; + + // Set the cursor + setCursor(s, hotspotX, hotspotY); +} + void Events::animateCursorIfNeeded() { if (_cursorId >= WAIT && _cursorId < (WAIT + 3)) { CursorId newId = (_cursorId == WAIT + 2) ? WAIT : (CursorId)((int)_cursorId + 1); diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index ffe6584ae6..93a5e54f81 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -59,6 +59,7 @@ public: bool _oldRightButton; bool _firstPress; Common::Stack<Common::KeyState> _pendingKeys; + Common::Point _hotspotPos; public: Events(SherlockEngine *vm); ~Events(); @@ -79,6 +80,11 @@ public: void setCursor(const Graphics::Surface &src, int hotspotX = 0, int hotspotY = 0); /** + * Set both a standard cursor as well as an inventory item above it + */ + void setCursor(CursorId cursorId, const Graphics::Surface &surface); + + /** * Animates the mouse cursor if the Wait cursor is showing */ void animateCursorIfNeeded(); diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index 73067fdc14..32c5d3acc3 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -34,6 +34,7 @@ MODULE_OBJS = \ tattoo/tattoo_user_interface.o \ tattoo/widget_base.o \ tattoo/widget_inventory.o \ + tattoo/widget_lab.o \ tattoo/widget_talk.o \ tattoo/widget_text.o \ tattoo/widget_tooltip.o \ diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 2d939ce6cf..6ef08c28cc 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -508,6 +508,10 @@ int BaseObject::checkNameForCodes(const Common::String &name, FixedTextActionId break; } + case 'V': + // Do nothing for Verb codes. This is only a flag for Inventory syntax + break; + default: if (ch >= '0' && ch <= '9') { scene._goToScene = atoi(name.c_str() + 1); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index a33574030f..328bf647d4 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -1210,6 +1210,15 @@ void Scene::transitionToScene() { // Standard info, so set it people[HOLMES]._position = hSavedPos; people[HOLMES]._sequenceNumber = hSavedFacing; + + if (saves._justLoaded && IS_ROSE_TATTOO) { + Tattoo::TattooUserInterface &ui = *(Tattoo::TattooUserInterface *)_vm->_ui; + + // For scrolling scenes, make sure the player is on-screen + ui._targetScroll.x = CLIP(people[HOLMES]._position.x / FIXED_INT_MULTIPLIER - + SHERLOCK_SCREEN_WIDTH / 8 - 250, 0, screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH); + screen._currentScroll = ui._targetScroll; + } } else { // It's canimation information cAnimNum = hSavedFacing - 101; @@ -1283,7 +1292,7 @@ void Scene::transitionToScene() { screen.fadeIntoScreen3DO(3); } } else { - screen.blitFrom(screen._backBuffer1); + screen.slamArea(screen._currentScroll.x, screen._currentScroll.y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); } screen.update(); diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp index 729b4e8c44..42194de7a3 100644 --- a/engines/sherlock/surface.cpp +++ b/engines/sherlock/surface.cpp @@ -112,7 +112,7 @@ void Surface::transBlitFrom(const Surface &src, const Common::Point &pt, void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt, bool flipped, int overrideColor, int scaleVal) { - if (scaleVal == 256) { + if (scaleVal == SCALE_THRESHOLD) { transBlitFromUnscaled(src, pt, flipped, overrideColor); return; } @@ -120,8 +120,11 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p int scaleX = SCALE_THRESHOLD * SCALE_THRESHOLD / scaleVal; int scaleY = scaleX; int scaleXCtr = 0, scaleYCtr = 0; + int destX, destY; + int xCtr, yCtr; + int maxX = pt.x; - for (int yCtr = 0, destY = pt.y; yCtr < src.h && destY < this->h(); ++yCtr) { + for (yCtr = 0, destY = pt.y; yCtr < src.h && destY < this->h(); ++yCtr) { // Handle skipping lines if Y scaling scaleYCtr += scaleY; @@ -134,7 +137,7 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p byte *pDest = (byte *)getBasePtr(pt.x, destY); scaleXCtr = 0; - for (int xCtr = 0, destX = pt.x; xCtr < src.w && destX < this->w(); ++xCtr) { + for (xCtr = 0, destX = pt.x; xCtr < src.w && destX < this->w(); ++xCtr) { // Handle horizontal scaling scaleXCtr += scaleX; @@ -149,6 +152,7 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p ++destX; } + maxX = MAX(maxX, destX); pSrc = pSrc + (flipped ? -1 : 1); } } @@ -156,6 +160,9 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p ++destY; } } + + // Mark the affected area + addDirtyRect(Common::Rect(pt.x, pt.y, maxX, destY)); } void Surface::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp index 0f61109c9d..a171da10cc 100644 --- a/engines/sherlock/tattoo/tattoo_scene.cpp +++ b/engines/sherlock/tattoo/tattoo_scene.cpp @@ -101,6 +101,9 @@ bool TattooScene::loadScene(const Common::String &filename) { // Set the menu/ui mode and whether we're in a lab table close-up scene _labTableScene = _currentScene > 91 && _currentScene < 100; ui._menuMode = _labTableScene ? LAB_MODE : STD_MODE; + + if (_labTableScene) + ui._labWidget.summonWindow(); } return result; diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp index bffdb550cf..e846db2701 100644 --- a/engines/sherlock/tattoo/tattoo_user_interface.cpp +++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp @@ -30,7 +30,8 @@ namespace Sherlock { namespace Tattoo { TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm), - _inventoryWidget(vm), _messageWidget(vm), _textWidget(vm), _tooltipWidget(vm), _verbsWidget(vm) { + _inventoryWidget(vm), _messageWidget(vm), _textWidget(vm), _tooltipWidget(vm), _verbsWidget(vm), + _labWidget(vm) { Common::fill(&_lookupTable[0], &_lookupTable[PALETTE_COUNT], 0); Common::fill(&_lookupTable1[0], &_lookupTable1[PALETTE_COUNT], 0); _scrollSize = 0; @@ -222,6 +223,8 @@ void TattooUserInterface::doJournal() { void TattooUserInterface::reset() { UserInterface::reset(); _lookPos = Common::Point(SHERLOCK_SCREEN_WIDTH / 2, SHERLOCK_SCREEN_HEIGHT / 2); + _tooltipWidget.setText(""); + _widgets.clear(); } void TattooUserInterface::handleInput() { @@ -280,9 +283,6 @@ void TattooUserInterface::handleInput() { case FILES_MODE: doFileControl(); break; - case LAB_MODE: - doLabControl(); - break; default: break; } @@ -356,7 +356,6 @@ void TattooUserInterface::doStandardControl() { Events &events = *_vm->_events; People &people = *_vm->_people; TattooScene &scene = *(TattooScene *)_vm->_scene; - Screen &screen = *_vm->_screen; Talk &talk = *_vm->_talk; Common::Point mousePos = events.mousePos(); bool noDesc = false; @@ -477,7 +476,7 @@ void TattooUserInterface::doStandardControl() { events._pressed = events._released = false; } else { // Walk to where the mouse was clicked - people[HOLMES]._walkDest = mousePos + screen._currentScroll; + people[HOLMES]._walkDest = mousePos; people[HOLMES].goAllTheWay(); } } @@ -527,10 +526,6 @@ void TattooUserInterface::doFileControl() { warning("TODO: ui control (file)"); } -void TattooUserInterface::doLabControl() { - warning("TODO: ui control (lab)"); -} - void TattooUserInterface::displayObjectNames() { Events &events = *_vm->_events; Scene &scene = *_vm->_scene; @@ -583,6 +578,7 @@ void TattooUserInterface::putMessage(const char *formatStr, ...) { va_end(args); // Open the message widget + _menuMode = MESSAGE_MODE; _messageWidget.load(str, 25); _messageWidget.summonWindow(); } diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h index 8dcfaddbd2..7f284531de 100644 --- a/engines/sherlock/tattoo/tattoo_user_interface.h +++ b/engines/sherlock/tattoo/tattoo_user_interface.h @@ -29,6 +29,7 @@ #include "sherlock/screen.h" #include "sherlock/user_interface.h" #include "sherlock/tattoo/widget_inventory.h" +#include "sherlock/tattoo/widget_lab.h" #include "sherlock/tattoo/widget_text.h" #include "sherlock/tattoo/widget_tooltip.h" #include "sherlock/tattoo/widget_verbs.h" @@ -77,17 +78,6 @@ private: * Handle input while the verb menu is open */ void doVerbControl(); - - /** - * Handles input when the player is in the Lab Table scene - */ - void doLabControl(); - - /** - * If the mouse cursor is point at the cursor, then display the name of the object on the screen. - * If there is no object being pointed it, clear any previously displayed name - */ - void displayObjectNames(); /** * Set up to display the Files menu @@ -119,7 +109,7 @@ public: int _maskCounter; ImageFile *_interfaceImages; WidgetText _textWidget; - Common::String _action; + WidgetLab _labWidget; public: TattooUserInterface(SherlockEngine *vm); virtual ~TattooUserInterface(); @@ -197,6 +187,12 @@ public: * Draws all the dialog rectangles for any items that need them */ void drawDialogRect(Surface &s, const Common::Rect &r, bool raised); + + /** + * If the mouse cursor is point at the cursor, then display the name of the object on the screen. + * If there is no object being pointed it, clear any previously displayed name + */ + void displayObjectNames(); public: /** * Resets the user interface diff --git a/engines/sherlock/tattoo/widget_base.cpp b/engines/sherlock/tattoo/widget_base.cpp index 5f16e8800d..66ade474c2 100644 --- a/engines/sherlock/tattoo/widget_base.cpp +++ b/engines/sherlock/tattoo/widget_base.cpp @@ -35,6 +35,14 @@ WidgetBase::WidgetBase(SherlockEngine *vm) : _vm(vm) { void WidgetBase::summonWindow() { TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; + + // Double-check that the same widget isn't added twice + for (Common::List<WidgetBase *>::iterator i = ui._widgets.begin(); i != ui._widgets.end(); ++i) { + if ((*i) == this) + error("Tried to add a widget twice"); + } + + // Add widget to the screen ui._widgets.push_back(this); _outsideMenu = false; diff --git a/engines/sherlock/tattoo/widget_inventory.cpp b/engines/sherlock/tattoo/widget_inventory.cpp index 241eaca182..170fb02481 100644 --- a/engines/sherlock/tattoo/widget_inventory.cpp +++ b/engines/sherlock/tattoo/widget_inventory.cpp @@ -122,17 +122,6 @@ void WidgetInventoryTooltip::handleEvents() { Common::String strWith = fixedText.getText(kFixedText_With); Common::String strUse = fixedText.getText(kFixedText_Use); - // If there's a floating graphic for a selected inventory item, update it's bounds - if (_owner->_invVerbMode == 2 || _owner->_invVerbMode == 3) { - _oldInvGraphicBounds = _invGraphicBounds; - - // Set the New position of the graphic - int xp = CLIP(mousePos.x - _invGraphicBounds.width() / 2, 0, SHERLOCK_SCENE_WIDTH - _invGraphicBounds.width()); - int yp = CLIP(mousePos.y - _invGraphicBounds.height() / 2, 0, SHERLOCK_SCREEN_HEIGHT - _invGraphicBounds.height()); - - _invGraphicBounds.moveTo(xp, yp); - } - // If we are using an inventory item on an object in the room, display the appropriate text above the mouse cursor if (_owner->_invVerbMode == 3) { select = ui._bgFound; @@ -147,18 +136,18 @@ void WidgetInventoryTooltip::handleEvents() { if (_vm->getLanguage() == Common::GR_GRE) { if (!_owner->_swapItems) - str = Common::String::format("%s %s %s %s", ui._action.c_str(), obj._description.c_str(), - inv[_owner->_invSelect]._name.c_str(), _owner->_invVerb.c_str()); + str = Common::String::format("%s %s %s %s", _owner->_action.c_str(), obj._description.c_str(), + inv[_owner->_invSelect]._name.c_str(), _owner->_verb.c_str()); else - str = Common::String::format("%s %s %s %s", ui._action.c_str(), inv[_owner->_invSelect]._name.c_str(), - obj._description.c_str(), _owner->_invVerb.c_str()); + str = Common::String::format("%s %s %s %s", _owner->_action.c_str(), inv[_owner->_invSelect]._name.c_str(), + obj._description.c_str(), _owner->_verb.c_str()); } else { if (_owner->_swapItems) - str = Common::String::format("%s %s %s %s", _owner->_invVerb.c_str(), obj._description.c_str(), ui._action.c_str(), + str = Common::String::format("%s %s %s %s", _owner->_verb.c_str(), obj._description.c_str(), _owner->_action.c_str(), inv[_owner->_invSelect]._name.c_str()); else - str = Common::String::format("%s %s %s %s", _owner->_invVerb.c_str(), inv[_owner->_invSelect]._name.c_str(), - ui._action.c_str(), obj._description.c_str()); + str = Common::String::format("%s %s %s %s", _owner->_verb.c_str(), inv[_owner->_invSelect]._name.c_str(), + _owner->_action.c_str(), obj._description.c_str()); } } } else { @@ -167,19 +156,19 @@ void WidgetInventoryTooltip::handleEvents() { if (!person._description.empty() && !person._description.hasPrefix(" ")) { if (_vm->getLanguage() == Common::GR_GRE) { if (!_owner->_swapItems) - str = Common::String::format("%s %s %s %s", ui._action.c_str(), person._description.c_str(), - inv[_owner->_invSelect]._name.c_str(), _owner->_invVerb.c_str()); + str = Common::String::format("%s %s %s %s", _owner->_action.c_str(), person._description.c_str(), + inv[_owner->_invSelect]._name.c_str(), _owner->_verb.c_str()); else - str = Common::String::format("%s %s %s %s", ui._action.c_str(), inv[_owner->_invSelect]._name.c_str(), - person._description.c_str(), _owner->_invVerb.c_str()); + str = Common::String::format("%s %s %s %s", _owner->_action.c_str(), inv[_owner->_invSelect]._name.c_str(), + person._description.c_str(), _owner->_verb.c_str()); } else { if (_owner->_swapItems) - str = Common::String::format("%s %s %s %s", _owner->_invVerb.c_str(), person._description.c_str(), - ui._action.c_str(), inv[_owner->_invSelect]._name.c_str()); + str = Common::String::format("%s %s %s %s", _owner->_verb.c_str(), person._description.c_str(), + _owner->_action.c_str(), inv[_owner->_invSelect]._name.c_str()); else - str = Common::String::format("%s %s %s %s", _owner->_invVerb.c_str(), - inv[_owner->_invSelect]._name.c_str(), ui._action.c_str(), person._description.c_str()); + str = Common::String::format("%s %s %s %s", _owner->_verb.c_str(), + inv[_owner->_invSelect]._name.c_str(), _owner->_action.c_str(), person._description.c_str()); } } } @@ -241,6 +230,10 @@ void WidgetInventoryTooltip::handleEvents() { return; } + if (_owner->_invVerbMode == 3) + // Adjust tooltip to be above the inventory item being shown above the standard cursor + mousePos.y -= events._hotspotPos.y; + // Update the position of the tooltip int xs = CLIP(mousePos.x - _bounds.width() / 2, 0, SHERLOCK_SCENE_WIDTH - _bounds.width()); int ys = CLIP(mousePos.y - _bounds.height(), 0, SHERLOCK_SCREEN_HEIGHT - _bounds.height()); @@ -267,7 +260,7 @@ void WidgetInventoryVerbs::load() { _inventCommands.push_back(FIXED(Look)); // Default the Action word to "with" - _action = _vm->getLanguage() == Common::GR_GRE ? "" : FIXED(With); + _owner->_action = _vm->getLanguage() == Common::GR_GRE ? "" : FIXED(With); // Search all the bgshapes for any matching Target Fields for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) { @@ -275,7 +268,7 @@ void WidgetInventoryVerbs::load() { if (obj._type != INVALID && obj._type != HIDDEN) { for (int useNum = 0; useNum < 6; ++useNum) { - if (obj._use[useNum]._verb.hasPrefix("*") && + if (!obj._use[useNum]._verb.hasPrefix("*") && !obj._use[useNum]._target.compareToIgnoreCase(inv[_owner->_invSelect]._name)) { // Make sure the Verb is not already in the list bool found1 = false; @@ -293,7 +286,7 @@ void WidgetInventoryVerbs::load() { if (!scumm_strnicmp(obj._use[useNum]._names[nameNum].c_str(), "*VSWAP", 6)) _owner->_swapItems = true; else - _action = Common::String(obj._use[useNum]._names[nameNum].c_str() + 2); + _owner->_action = Common::String(obj._use[useNum]._names[nameNum].c_str() + 2); } } } @@ -428,29 +421,19 @@ void WidgetInventoryVerbs::handleEvents() { events.clearEvents(); ui.checkAction(inv[_owner->_invSelect]._verb, 2000); } else { - _owner->_invVerb = _inventCommands[_invVerbSelect]; + _owner->_verb = _inventCommands[_invVerbSelect]; } // If we are still in Inventory Mode, setup the graphic to float in front of the mouse cursor if (ui._menuMode == INV_MODE) { + // Add the inventory item to the cursor ImageFrame &imgFrame = (*inv._invShapes[_owner->_invSelect - inv._invIndex])[0]; - _owner->_invGraphicBounds = Common::Rect(imgFrame._width, imgFrame._height); - _owner->_invGraphicBounds.moveTo(mousePos.x - _owner->_invGraphicBounds.width() / 2, - mousePos.y - _owner->_invGraphicBounds.height() / 2); - - // Constrain it to the screen - if (_owner->_invGraphicBounds.left < 0) - _owner->_invGraphicBounds.moveTo(0, _owner->_invGraphicBounds.top); - if (_owner->_invGraphicBounds.top < 0) - _owner->_invGraphicBounds.moveTo(_owner->_invGraphicBounds.left, 0); - if (_owner->_invGraphicBounds.right > SHERLOCK_SCREEN_WIDTH) - _owner->_invGraphicBounds.moveTo(SHERLOCK_SCREEN_WIDTH - _owner->_invGraphicBounds.width(), _owner->_invGraphicBounds.top); - if (_owner->_invGraphicBounds.bottom > SHERLOCK_SCREEN_HEIGHT) - _owner->_invGraphicBounds.moveTo(_owner->_invGraphicBounds.left, SHERLOCK_SCREEN_HEIGHT - _owner->_invGraphicBounds.height()); - - // Make a copy of the inventory image - _owner->_invGraphic.create(imgFrame._width, imgFrame._height); - _owner->_invGraphic.blitFrom(imgFrame, Common::Point(0, 0)); + events.setCursor(ARROW, imgFrame._frame); + + // Close the inventory dialog without banishing it, so it can keep getting events + // to handle tooltips and actually making the selection of what object to use them item on + inv.freeInv(); + _owner->_surface.free(); } } } @@ -624,11 +607,7 @@ void WidgetInventory::handleEvents() { if (_invVerbMode == 3) { // Selecting object after inventory verb has been selected _tooltipWidget.banishWindow(); - _invGraphic.free(); - inv.freeInv(); - - ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE; - events.clearEvents(); + close(); if (ui._keyState.keycode != Common::KEYCODE_ESCAPE) { // If user pointed at an item, use the selected inventory item with this item @@ -636,7 +615,7 @@ void WidgetInventory::handleEvents() { if (ui._bgFound != -1) { if (ui._personFound) { for (int idx = 0; idx < 2; ++idx) { - if (!people[ui._bgFound - 1000]._use[idx]._verb.compareToIgnoreCase(_invVerb) && + if (!people[ui._bgFound - 1000]._use[idx]._verb.compareToIgnoreCase(_verb) && !people[ui._bgFound - 1000]._use[idx]._target.compareToIgnoreCase(_invTarget)) { ui.checkAction(people[ui._bgFound - 1000]._use[idx], ui._bgFound); found = true; @@ -644,7 +623,7 @@ void WidgetInventory::handleEvents() { } } else { for (int idx = 0; idx < 6; ++idx) { - if (!ui._bgShape->_use[idx]._verb.compareToIgnoreCase(_invVerb) && + if (!ui._bgShape->_use[idx]._verb.compareToIgnoreCase(_verb) && !ui._bgShape->_use[idx]._target.compareToIgnoreCase(_invTarget)) { ui.checkAction(ui._bgShape->_use[idx], ui._bgFound); found = true; @@ -658,13 +637,8 @@ void WidgetInventory::handleEvents() { } } else if ((_outsideMenu && !_bounds.contains(mousePos)) || ui._keyState.keycode == Common::KEYCODE_ESCAPE) { // Want to close the window (clicked outside of it). So close the window and return to Standard - banishWindow(); - inv.freeInv(); + close(); - events.clearEvents(); - events.setCursor(ARROW); - banishWindow(); - ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE; } else if (_bounds.contains(mousePos)) { // Mouse button was released inside the inventory window _outsideMenu = false; @@ -769,6 +743,20 @@ void WidgetInventory::erase() { _tooltipWidget.erase(); } +void WidgetInventory::close() { + Events &events = *_vm->_events; + Inventory &inv = *_vm->_inventory; + TattooScene &scene = *(TattooScene *)_vm->_scene; + TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; + + banishWindow(); + inv.freeInv(); + events.clearEvents(); + + events.setCursor(ARROW); + ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE; +} + } // End of namespace Tattoo } // End of namespace Sherlock diff --git a/engines/sherlock/tattoo/widget_inventory.h b/engines/sherlock/tattoo/widget_inventory.h index bfc1c7f50f..53bc2038e0 100644 --- a/engines/sherlock/tattoo/widget_inventory.h +++ b/engines/sherlock/tattoo/widget_inventory.h @@ -40,7 +40,6 @@ class WidgetInventory; class WidgetInventoryTooltip: public WidgetTooltipBase { private: WidgetInventory *_owner; - Common::Rect _oldInvGraphicBounds, _invGraphicBounds; protected: /** * Overriden from base class, since tooltips have a completely transparent background @@ -65,7 +64,6 @@ class WidgetInventoryVerbs : public WidgetBase { private: WidgetInventory *_owner; Common::StringArray _inventCommands; - Common::String _action; void highlightControls(); public: @@ -92,12 +90,9 @@ private: int _dialogTimer; WidgetInventoryTooltip _tooltipWidget; WidgetInventoryVerbs _verbList; - Common::Rect _invGraphicBounds; - Surface _invGraphic; bool _swapItems; Surface _menuSurface; Common::String _invTarget; - Common::String _invVerb; /** * Draw the bars within the dialog @@ -115,10 +110,15 @@ private: void highlightControls(); public: int _invMode; + Common::String _action; + Common::String _verb; public: WidgetInventory(SherlockEngine *vm); virtual ~WidgetInventory() {} + /** + * Load the inventory window + */ void load(int mode); /** @@ -127,6 +127,11 @@ public: void drawInventory(); /** + * Close the window + */ + void close(); + + /** * Handle events whilst the widget is on-screen */ virtual void handleEvents(); diff --git a/engines/sherlock/tattoo/widget_lab.cpp b/engines/sherlock/tattoo/widget_lab.cpp new file mode 100644 index 0000000000..47955a0d26 --- /dev/null +++ b/engines/sherlock/tattoo/widget_lab.cpp @@ -0,0 +1,43 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sherlock/tattoo/widget_lab.h" +#include "sherlock/tattoo/tattoo_user_interface.h" +#include "sherlock/tattoo/tattoo.h" + +namespace Sherlock { + +namespace Tattoo { + +WidgetLab::WidgetLab(SherlockEngine *vm) : WidgetBase(vm) { +} + +void WidgetLab::handleEvents() { + Events &events = *_vm->_events; + TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; + WidgetBase::handleEvents(); + +} + +} // End of namespace Tattoo + +} // End of namespace Sherlock diff --git a/engines/sherlock/tattoo/widget_lab.h b/engines/sherlock/tattoo/widget_lab.h new file mode 100644 index 0000000000..344dae7934 --- /dev/null +++ b/engines/sherlock/tattoo/widget_lab.h @@ -0,0 +1,52 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SHERLOCK_TATTOO_WIDGET_LAB_H +#define SHERLOCK_TATTOO_WIDGET_LAB_H + +#include "common/scummsys.h" +#include "sherlock/tattoo/widget_base.h" + +namespace Sherlock { + +class SherlockEngine; + +namespace Tattoo { + +class WidgetLab: public WidgetBase { +public: + Common::String _remainingText; +public: + WidgetLab(SherlockEngine *vm); + virtual ~WidgetLab() {} + + /** + * Handle event processing + */ + virtual void handleEvents(); +}; + +} // End of namespace Tattoo + +} // End of namespace Sherlock + +#endif diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 9db29023c8..9df3f1dc24 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -179,7 +179,7 @@ void UserInterface::checkAction(ActionType &action, int objNum, FixedTextActionI } // Unless we're leaving the scene, print a "Done" message unless the printed flag has been set - if (scene._goToScene != 1 && !printed && !talk._talkToAbort) { + if (IS_SERRATED_SCALPEL && scene._goToScene != 1 && !printed && !talk._talkToAbort) { _infoFlag = true; clearInfo(); screen.print(Common::Point(0, INFO_LINE + 1), COL_INFO_FOREGROUND, "Done..."); |