diff options
Diffstat (limited to 'engines/sherlock/scalpel/scalpel_screen.cpp')
-rw-r--r-- | engines/sherlock/scalpel/scalpel_screen.cpp | 345 |
1 files changed, 67 insertions, 278 deletions
diff --git a/engines/sherlock/scalpel/scalpel_screen.cpp b/engines/sherlock/scalpel/scalpel_screen.cpp index 71bcca5dc5..15e8436be6 100644 --- a/engines/sherlock/scalpel/scalpel_screen.cpp +++ b/engines/sherlock/scalpel/scalpel_screen.cpp @@ -28,313 +28,102 @@ namespace Sherlock { namespace Scalpel { ScalpelScreen::ScalpelScreen(SherlockEngine *vm) : Screen(vm) { + _backBuffer1.create(320, 200); + _backBuffer2.create(320, 200); + activateBackBuffer1(); } void ScalpelScreen::makeButton(const Common::Rect &bounds, int textX, - const Common::String &str) { + const Common::String &buttonText, bool textContainsHotkey) { - Surface &bb = *_backBuffer; + Surface &bb = _backBuffer; bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.right, bounds.top + 1), BUTTON_TOP); bb.fillRect(Common::Rect(bounds.left, bounds.top, bounds.left + 1, bounds.bottom), BUTTON_TOP); bb.fillRect(Common::Rect(bounds.right - 1, bounds.top, bounds.right, bounds.bottom), BUTTON_BOTTOM); bb.fillRect(Common::Rect(bounds.left + 1, bounds.bottom - 1, bounds.right, bounds.bottom), BUTTON_BOTTOM); bb.fillRect(Common::Rect(bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1), BUTTON_MIDDLE); - gPrint(Common::Point(textX, bounds.top), COMMAND_HIGHLIGHTED, "%c", str[0]); - gPrint(Common::Point(textX + charWidth(str[0]), bounds.top), - COMMAND_FOREGROUND, "%s", str.c_str() + 1); + buttonPrint(Common::Point(textX, bounds.top), COMMAND_FOREGROUND, false, buttonText, textContainsHotkey); } +// ButtonText is supposed to have its hotkey as a prefix. The hotkey will get highlighted. void ScalpelScreen::buttonPrint(const Common::Point &pt, uint color, bool slamIt, - const Common::String &str) { - int xStart = pt.x - stringWidth(str) / 2; + const Common::String &buttonText, bool textContainsHotkey) { + int xStart = pt.x; + int skipTextOffset = textContainsHotkey ? +1 : 0; // skip first char in case text contains hotkey - if (color == COMMAND_FOREGROUND) { - // First character needs to be highlighted - if (slamIt) { - print(Common::Point(xStart, pt.y + 1), COMMAND_HIGHLIGHTED, "%c", str[0]); - print(Common::Point(xStart + charWidth(str[0]), pt.y + 1), - COMMAND_FOREGROUND, "%s", str.c_str() + 1); - } else { - gPrint(Common::Point(xStart, pt.y), COMMAND_HIGHLIGHTED, "%c", str[0]); - gPrint(Common::Point(xStart + charWidth(str[0]), pt.y), - COMMAND_FOREGROUND, "%s", str.c_str() + 1); - } - } else if (slamIt) { - print(Common::Point(xStart, pt.y + 1), color, "%s", str.c_str()); + // Center text around given x-coordinate + if (textContainsHotkey) { + xStart -= (stringWidth(Common::String(buttonText.c_str() + 1)) / 2); } else { - gPrint(Common::Point(xStart, pt.y), color, "%s", str.c_str()); - } -} - -void ScalpelScreen::makePanel(const Common::Rect &r) { - _backBuffer->fillRect(r, BUTTON_MIDDLE); - _backBuffer->hLine(r.left, r.top, r.right - 2, BUTTON_TOP); - _backBuffer->hLine(r.left + 1, r.top + 1, r.right - 3, BUTTON_TOP); - _backBuffer->vLine(r.left, r.top, r.bottom - 1, BUTTON_TOP); - _backBuffer->vLine(r.left + 1, r.top + 1, r.bottom - 2, BUTTON_TOP); - - _backBuffer->vLine(r.right - 1, r.top, r.bottom - 1, BUTTON_BOTTOM); - _backBuffer->vLine(r.right - 2, r.top + 1, r.bottom - 2, BUTTON_BOTTOM); - _backBuffer->hLine(r.left, r.bottom - 1, r.right - 1, BUTTON_BOTTOM); - _backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM); -} - -void ScalpelScreen::makeField(const Common::Rect &r) { - _backBuffer->fillRect(r, BUTTON_MIDDLE); - _backBuffer->hLine(r.left, r.top, r.right - 1, BUTTON_BOTTOM); - _backBuffer->hLine(r.left + 1, r.bottom - 1, r.right - 1, BUTTON_TOP); - _backBuffer->vLine(r.left, r.top + 1, r.bottom - 1, BUTTON_BOTTOM); - _backBuffer->vLine(r.right - 1, r.top + 1, r.bottom - 2, BUTTON_TOP); -} - -/*----------------------------------------------------------------*/ - -void Scalpel3DOScreen::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) { - if (!_vm->_isScreenDoubled) { - ScalpelScreen::blitFrom(src, pt, srcBounds); - return; - } - - Common::Rect srcRect = srcBounds; - Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height()); - - if (!srcRect.isValidRect() || !clip(srcRect, destRect)) - return; - - // Add dirty area remapped to the 640x200 surface - addDirtyRect(Common::Rect(destRect.left * 2, destRect.top * 2, destRect.right * 2, destRect.bottom * 2)); - - // Transfer the area, doubling each pixel - for (int yp = 0; yp < srcRect.height(); ++yp) { - const uint16 *srcP = (const uint16 *)src.getBasePtr(srcRect.left, srcRect.top + yp); - uint16 *destP = (uint16 *)getBasePtr(destRect.left * 2, (destRect.top + yp) * 2); - - for (int xp = srcRect.left; xp < srcRect.right; ++xp, ++srcP, destP += 2) { - *destP = *srcP; - *(destP + 1) = *srcP; - *(destP + 640) = *srcP; - *(destP + 640 + 1) = *srcP; - } - } -} - -void Scalpel3DOScreen::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, - bool flipped, int overrideColor) { - if (!_vm->_isScreenDoubled) { - ScalpelScreen::transBlitFromUnscaled(src, pt, flipped, overrideColor); - return; - } - - Common::Rect drawRect(0, 0, src.w, src.h); - Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h); - - // Clip the display area to on-screen - if (!clip(drawRect, destRect)) - // It's completely off-screen - return; - - if (flipped) - drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom, - src.w - drawRect.left, src.h - drawRect.top); - - Common::Point destPt(destRect.left, destRect.top); - addDirtyRect(Common::Rect(destPt.x * 2, destPt.y * 2, (destPt.x + drawRect.width()) * 2, - (destPt.y + drawRect.height()) * 2)); - - assert(src.format.bytesPerPixel == 2 && _surface.format.bytesPerPixel == 2); - - for (int yp = 0; yp < drawRect.height(); ++yp) { - const uint16 *srcP = (const uint16 *)src.getBasePtr( - flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp); - uint16 *destP = (uint16 *)getBasePtr(destPt.x * 2, (destPt.y + yp) * 2); - - for (int xp = 0; xp < drawRect.width(); ++xp, destP += 2) { - // RGB 0, 0, 0 -> transparent on 3DO - if (*srcP) { - *destP = *srcP; - *(destP + 1) = *srcP; - *(destP + 640) = *srcP; - *(destP + 640 + 1) = *srcP; - } - - srcP = flipped ? srcP - 1 : srcP + 1; - } + xStart -= (stringWidth(buttonText) / 2); } -} - -void Scalpel3DOScreen::fillRect(const Common::Rect &r, uint color) { - if (_vm->_isScreenDoubled) - ScalpelScreen::fillRect(Common::Rect(r.left * 2, r.top * 2, r.right * 2, r.bottom * 2), color); - else - ScalpelScreen::fillRect(r, color); -} -void Scalpel3DOScreen::fadeIntoScreen3DO(int speed) { - Events &events = *_vm->_events; - uint16 *currentScreenBasePtr = (uint16 *)getPixels(); - uint16 *targetScreenBasePtr = (uint16 *)_backBuffer->getPixels(); - uint16 currentScreenPixel = 0; - uint16 targetScreenPixel = 0; - - uint16 currentScreenPixelRed = 0; - uint16 currentScreenPixelGreen = 0; - uint16 currentScreenPixelBlue = 0; - - uint16 targetScreenPixelRed = 0; - uint16 targetScreenPixelGreen = 0; - uint16 targetScreenPixelBlue = 0; - - uint16 screenWidth = SHERLOCK_SCREEN_WIDTH; - uint16 screenHeight = SHERLOCK_SCREEN_HEIGHT; - uint16 screenX = 0; - uint16 screenY = 0; - uint16 pixelsChanged = 0; - - clearDirtyRects(); - - do { - pixelsChanged = 0; - uint16 *currentScreenPtr = currentScreenBasePtr; - uint16 *targetScreenPtr = targetScreenBasePtr; - - for (screenY = 0; screenY < screenHeight; screenY++) { - for (screenX = 0; screenX < screenWidth; screenX++) { - currentScreenPixel = *currentScreenPtr; - targetScreenPixel = *targetScreenPtr; - - if (currentScreenPixel != targetScreenPixel) { - // pixel doesn't match, adjust accordingly - currentScreenPixelRed = currentScreenPixel & 0xF800; - currentScreenPixelGreen = currentScreenPixel & 0x07E0; - currentScreenPixelBlue = currentScreenPixel & 0x001F; - targetScreenPixelRed = targetScreenPixel & 0xF800; - targetScreenPixelGreen = targetScreenPixel & 0x07E0; - targetScreenPixelBlue = targetScreenPixel & 0x001F; - - if (currentScreenPixelRed != targetScreenPixelRed) { - if (currentScreenPixelRed < targetScreenPixelRed) { - currentScreenPixelRed += 0x0800; - } else { - currentScreenPixelRed -= 0x0800; - } - } - if (currentScreenPixelGreen != targetScreenPixelGreen) { - // Adjust +2/-2 because we are running RGB555 at RGB565 - if (currentScreenPixelGreen < targetScreenPixelGreen) { - currentScreenPixelGreen += 0x0040; - } else { - currentScreenPixelGreen -= 0x0040; - } - } - if (currentScreenPixelBlue != targetScreenPixelBlue) { - if (currentScreenPixelBlue < targetScreenPixelBlue) { - currentScreenPixelBlue += 0x0001; - } else { - currentScreenPixelBlue -= 0x0001; - } - } - - uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue; - *currentScreenPtr = v; - if (_vm->_isScreenDoubled) { - *(currentScreenPtr + 1) = v; - *(currentScreenPtr + 640) = v; - *(currentScreenPtr + 640 + 1) = v; + if (color == COMMAND_FOREGROUND) { + uint16 prefixOffsetX = 0; + byte hotkey = buttonText[0]; + + // Hotkey needs to be highlighted + if (textContainsHotkey) { + Common::String prefixText = Common::String(buttonText.c_str() + 1); + uint16 prefixTextLen = prefixText.size(); + uint16 prefixTextPos = 0; + + // Hotkey was passed additionally, we search for the hotkey inside the button text and + // remove it from there. We then draw the whole text as highlighted and afterward + // the processed text again as regular text (without the hotkey) + while (prefixTextPos < prefixTextLen) { + if (prefixText[prefixTextPos] == hotkey) { + // Hotkey found, remove remaining text + while (prefixTextPos < prefixText.size()) { + prefixText.deleteLastChar(); } - - pixelsChanged++; + break; } - - currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1; - targetScreenPtr++; + prefixTextPos++; } - if (_vm->_isScreenDoubled) - currentScreenPtr += 640; - } - - // Too much considered dirty at the moment - if (_vm->_isScreenDoubled) - addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2)); - else - addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight)); - - events.pollEvents(); - events.delay(10 * speed); - } while ((pixelsChanged) && (!_vm->shouldQuit())); -} - -void Scalpel3DOScreen::blitFrom3DOcolorLimit(uint16 limitColor) { - uint16 *currentScreenPtr = (uint16 *)getPixels(); - uint16 *targetScreenPtr = (uint16 *)_backBuffer->getPixels(); - uint16 currentScreenPixel = 0; - - uint16 screenWidth = SHERLOCK_SCREEN_WIDTH; - uint16 screenHeight = SHERLOCK_SCREEN_HEIGHT; - uint16 screenX = 0; - uint16 screenY = 0; - - uint16 currentScreenPixelRed = 0; - uint16 currentScreenPixelGreen = 0; - uint16 currentScreenPixelBlue = 0; - - uint16 limitPixelRed = limitColor & 0xF800; - uint16 limitPixelGreen = limitColor & 0x07E0; - uint16 limitPixelBlue = limitColor & 0x001F; - - for (screenY = 0; screenY < screenHeight; screenY++) { - for (screenX = 0; screenX < screenWidth; screenX++) { - currentScreenPixel = *targetScreenPtr; - - currentScreenPixelRed = currentScreenPixel & 0xF800; - currentScreenPixelGreen = currentScreenPixel & 0x07E0; - currentScreenPixelBlue = currentScreenPixel & 0x001F; - - if (currentScreenPixelRed < limitPixelRed) - currentScreenPixelRed = limitPixelRed; - if (currentScreenPixelGreen < limitPixelGreen) - currentScreenPixelGreen = limitPixelGreen; - if (currentScreenPixelBlue < limitPixelBlue) - currentScreenPixelBlue = limitPixelBlue; - - uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue; - *currentScreenPtr = v; - if (_vm->_isScreenDoubled) { - *(currentScreenPtr + 1) = v; - *(currentScreenPtr + 640) = v; - *(currentScreenPtr + 640 + 1) = v; + if (prefixTextPos < prefixTextLen) { + // only adjust in case hotkey character was actually found + prefixOffsetX = stringWidth(prefixText); } - - currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1; - targetScreenPtr++; } - if (_vm->_isScreenDoubled) - currentScreenPtr += 640; + if (slamIt) { + print(Common::Point(xStart, pt.y + 1), + COMMAND_FOREGROUND, "%s", buttonText.c_str() + skipTextOffset); + print(Common::Point(xStart + prefixOffsetX, pt.y + 1), COMMAND_HIGHLIGHTED, "%c", hotkey); + } else { + gPrint(Common::Point(xStart, pt.y), + COMMAND_FOREGROUND, "%s", buttonText.c_str() + skipTextOffset); + gPrint(Common::Point(xStart + prefixOffsetX, pt.y), COMMAND_HIGHLIGHTED, "%c", hotkey); + } + } else if (slamIt) { + print(Common::Point(xStart, pt.y + 1), color, "%s", buttonText.c_str() + skipTextOffset); + } else { + gPrint(Common::Point(xStart, pt.y), color, "%s", buttonText.c_str() + skipTextOffset); } - - // Too much considered dirty at the moment - if (_vm->_isScreenDoubled) - addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2)); - else - addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight)); } -uint16 Scalpel3DOScreen::w() const { - return _vm->_isScreenDoubled ? _surface.w / 2 : _surface.w; -} - -uint16 Scalpel3DOScreen::h() const { - return _vm->_isScreenDoubled ? _surface.h / 2 : _surface.h; +void ScalpelScreen::makePanel(const Common::Rect &r) { + _backBuffer.fillRect(r, BUTTON_MIDDLE); + _backBuffer.hLine(r.left, r.top, r.right - 2, BUTTON_TOP); + _backBuffer.hLine(r.left + 1, r.top + 1, r.right - 3, BUTTON_TOP); + _backBuffer.vLine(r.left, r.top, r.bottom - 1, BUTTON_TOP); + _backBuffer.vLine(r.left + 1, r.top + 1, r.bottom - 2, BUTTON_TOP); + + _backBuffer.vLine(r.right - 1, r.top, r.bottom - 1, BUTTON_BOTTOM); + _backBuffer.vLine(r.right - 2, r.top + 1, r.bottom - 2, BUTTON_BOTTOM); + _backBuffer.hLine(r.left, r.bottom - 1, r.right - 1, BUTTON_BOTTOM); + _backBuffer.hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM); } -void Scalpel3DOScreen::rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt) { - Common::Rect srcRect(0, 0, src.w, src.h); - Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h); - - addDirtyRect(destRect); - _surface.copyRectToSurface(src, destRect.left, destRect.top, srcRect); +void ScalpelScreen::makeField(const Common::Rect &r) { + _backBuffer.fillRect(r, BUTTON_MIDDLE); + _backBuffer.hLine(r.left, r.top, r.right - 1, BUTTON_BOTTOM); + _backBuffer.hLine(r.left + 1, r.bottom - 1, r.right - 1, BUTTON_TOP); + _backBuffer.vLine(r.left, r.top + 1, r.bottom - 1, BUTTON_BOTTOM); + _backBuffer.vLine(r.right - 1, r.top + 1, r.bottom - 2, BUTTON_TOP); } } // End of namespace Scalpel |