diff options
author | Marisa-Chan | 2014-01-07 18:39:16 +0700 |
---|---|---|
committer | Marisa-Chan | 2014-01-07 18:39:16 +0700 |
commit | 1428cb8950e5bdcfad9d15d0fb2e32ff1dbc0bae (patch) | |
tree | 5baeb94cd7e5249f5416c9af9a0e5e59443bfafa /engines | |
parent | 48156debaf148b50acd3eb6e3de7020498016a5f (diff) | |
download | scummvm-rg350-1428cb8950e5bdcfad9d15d0fb2e32ff1dbc0bae.tar.gz scummvm-rg350-1428cb8950e5bdcfad9d15d0fb2e32ff1dbc0bae.tar.bz2 scummvm-rg350-1428cb8950e5bdcfad9d15d0fb2e32ff1dbc0bae.zip |
ZVISION: Refactoring of renderManager.
Diffstat (limited to 'engines')
-rw-r--r-- | engines/zvision/animation_node.cpp | 8 | ||||
-rw-r--r-- | engines/zvision/console.cpp | 16 | ||||
-rw-r--r-- | engines/zvision/events.cpp | 48 | ||||
-rw-r--r-- | engines/zvision/input_control.cpp | 4 | ||||
-rw-r--r-- | engines/zvision/lever_control.cpp | 14 | ||||
-rw-r--r-- | engines/zvision/render_manager.cpp | 863 | ||||
-rw-r--r-- | engines/zvision/render_manager.h | 320 | ||||
-rw-r--r-- | engines/zvision/render_table.cpp | 22 | ||||
-rw-r--r-- | engines/zvision/render_table.h | 2 | ||||
-rw-r--r-- | engines/zvision/script_manager.cpp | 4 | ||||
-rw-r--r-- | engines/zvision/zvision.cpp | 50 | ||||
-rw-r--r-- | engines/zvision/zvision.h | 2 |
12 files changed, 577 insertions, 776 deletions
diff --git a/engines/zvision/animation_node.cpp b/engines/zvision/animation_node.cpp index 967dee2c4a..74b532b2ef 100644 --- a/engines/zvision/animation_node.cpp +++ b/engines/zvision/animation_node.cpp @@ -165,15 +165,15 @@ bool AnimationNode::process(uint32 deltaTimeInMillis) { if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) { Graphics::Surface *transposed = RenderManager::tranposeSurface(frame); if (_mask > 0) - _engine->getRenderManager()->renderImageToBackground(*transposed, nod->pos.left, nod->pos.top, _mask); + _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask); else - _engine->getRenderManager()->renderImageToBackground(*transposed, nod->pos.left, nod->pos.top); + _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top); delete transposed; } else { if (_mask > 0) - _engine->getRenderManager()->renderImageToBackground(*frame, nod->pos.left, nod->pos.top, _mask); + _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask); else - _engine->getRenderManager()->renderImageToBackground(*frame, nod->pos.left, nod->pos.top); + _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top); } } } diff --git a/engines/zvision/console.cpp b/engines/zvision/console.cpp index 400dcb3f39..252a4b75ef 100644 --- a/engines/zvision/console.cpp +++ b/engines/zvision/console.cpp @@ -60,12 +60,12 @@ Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) { } bool Console::cmdLoadImage(int argc, const char **argv) { - if (argc == 4) - _engine->getRenderManager()->renderImageToScreen(argv[1], atoi(argv[2]), atoi(argv[3])); - else { - DebugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n"); - return true; - } +// if (argc == 4) +// _engine->getRenderManager()->renderImageToScreen(argv[1], atoi(argv[2]), atoi(argv[3])); +// else { +// DebugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n"); +// return true; +// } return true; } @@ -208,8 +208,8 @@ bool Console::cmdRenderText(int argc, const char **argv) { return true; } - StringManager::TextStyle style = _engine->getStringManager()->getTextStyle(atoi(argv[2])); - _engine->getRenderManager()->renderTextToWorkingWindow(333, Common::String(argv[1]), style.font, atoi(argv[3]), atoi(argv[4]), style.color, atoi(argv[5]), -1, Graphics::kTextAlignLeft, atoi(argv[6]) == 0 ? false : true); + //StringManager::TextStyle style = _engine->getStringManager()->getTextStyle(atoi(argv[2])); + //_engine->getRenderManager()->renderTextToWorkingWindow(333, Common::String(argv[1]), style.font, atoi(argv[3]), atoi(argv[4]), style.color, atoi(argv[5]), -1, Graphics::kTextAlignLeft, atoi(argv[6]) == 0 ? false : true); return true; } diff --git a/engines/zvision/events.cpp b/engines/zvision/events.cpp index 69f5ffec24..d8828867b0 100644 --- a/engines/zvision/events.cpp +++ b/engines/zvision/events.cpp @@ -146,43 +146,53 @@ void ZVision::onMouseMove(const Common::Point &pos) { RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); if (renderState == RenderTable::PANORAMA) { if (pos.x >= _workingWindow.left && pos.x < _workingWindow.left + ROTATION_SCREEN_EDGE_OFFSET) { - // Linear function of distance to the left edge (y = -mx + b) - // We use fixed point math to get better accuracy - Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.left)) - MAX_ROTATION_SPEED; - _renderManager->setBackgroundVelocity(velocity.toInt()); + + int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; + if (mspeed <= 0) + mspeed = 400 >> 4; + _velocity = (((pos.x - (ROTATION_SCREEN_EDGE_OFFSET + _workingWindow.left)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + _cursorManager->changeCursor(CursorIndex_Left); cursorWasChanged = true; } else if (pos.x <= _workingWindow.right && pos.x > _workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET) { - // Linear function of distance to the right edge (y = mx) - // We use fixed point math to get better accuracy - Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.x - _workingWindow.right + ROTATION_SCREEN_EDGE_OFFSET); - _renderManager->setBackgroundVelocity(velocity.toInt()); + + int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; + if (mspeed <= 0) + mspeed = 400 >> 4; + _velocity = (((pos.x - (_workingWindow.right - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + _cursorManager->changeCursor(CursorIndex_Right); cursorWasChanged = true; } else { - _renderManager->setBackgroundVelocity(0); + _velocity = 0; } } else if (renderState == RenderTable::TILT) { if (pos.y >= _workingWindow.top && pos.y < _workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET) { - // Linear function of distance to top edge - // We use fixed point math to get better accuracy - Common::Rational velocity = (Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.top)) - MAX_ROTATION_SPEED; - _renderManager->setBackgroundVelocity(velocity.toInt()); + + int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; + if (mspeed <= 0) + mspeed = 400 >> 4; + _velocity = (((pos.y - (_workingWindow.top + ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + _cursorManager->changeCursor(CursorIndex_UpArr); cursorWasChanged = true; } else if (pos.y <= _workingWindow.bottom && pos.y > _workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET) { - // Linear function of distance to the bottom edge (y = mx) - // We use fixed point math to get better accuracy - Common::Rational velocity = Common::Rational(MAX_ROTATION_SPEED, ROTATION_SCREEN_EDGE_OFFSET) * (pos.y - _workingWindow.bottom + ROTATION_SCREEN_EDGE_OFFSET); - _renderManager->setBackgroundVelocity(velocity.toInt()); + + int16 mspeed = _scriptManager->getStateValue(StateKey_RotateSpeed) >> 4; + if (mspeed <= 0) + mspeed = 400 >> 4; + _velocity = (((pos.y - (_workingWindow.bottom - ROTATION_SCREEN_EDGE_OFFSET)) << 7) / ROTATION_SCREEN_EDGE_OFFSET * mspeed) >> 7; + _cursorManager->changeCursor(CursorIndex_DownArr); cursorWasChanged = true; } else { - _renderManager->setBackgroundVelocity(0); + _velocity = 0; } + } else { + _velocity = 0; } } else { - _renderManager->setBackgroundVelocity(0); + _velocity = 0; } if (!cursorWasChanged) { diff --git a/engines/zvision/input_control.cpp b/engines/zvision/input_control.cpp index 8d9d79ba09..a366e06923 100644 --- a/engines/zvision/input_control.cpp +++ b/engines/zvision/input_control.cpp @@ -129,9 +129,9 @@ bool InputControl::process(uint32 deltaTimeInMillis) { // First see if we need to render the text if (_textChanged) { // Blit the text using the RenderManager - Common::Rect destRect = _engine->getRenderManager()->renderTextToWorkingWindow(_key, _currentInputText, _textStyle.font, _textRectangle.left, _textRectangle.top, _textStyle.color, _textRectangle.width()); + //Common::Rect destRect = _engine->getRenderManager()->renderTextToWorkingWindow(_key, _currentInputText, _textStyle.font, _textRectangle.left, _textRectangle.top, _textStyle.color, _textRectangle.width()); - _cursorOffset = destRect.left - _textRectangle.left; + //_cursorOffset = destRect.left - _textRectangle.left; } // Render the next frame of the animation diff --git a/engines/zvision/lever_control.cpp b/engines/zvision/lever_control.cpp index fa8475f457..9cd36cf653 100644 --- a/engines/zvision/lever_control.cpp +++ b/engines/zvision/lever_control.cpp @@ -375,26 +375,20 @@ void LeverControl::renderFrame(uint frameNumber) { _lastRenderedFrame = frameNumber; } - const uint16 *frameData; + const Graphics::Surface *frameData; int x = _animationCoords.left; int y = _animationCoords.top; - int width; - int height; if (_fileType == RLF) { // getFrameData() will automatically optimize to getNextFrame() / getPreviousFrame() if it can - frameData = (const uint16 *)_animation.rlf->getFrameData(frameNumber)->getPixels(); - width = _animation.rlf->width(); // Use the animation width instead of _animationCoords.width() - height = _animation.rlf->height(); // Use the animation height instead of _animationCoords.height() + frameData = _animation.rlf->getFrameData(frameNumber); } else if (_fileType == AVI) { _animation.avi->seekToFrame(frameNumber); const Graphics::Surface *surface = _animation.avi->decodeNextFrame(); - frameData = (const uint16 *)surface->getPixels(); - width = surface->w; - height = surface->h; + frameData = surface; } - _engine->getRenderManager()->copyRectToWorkingWindow(frameData, x, y, width, width, height); + _engine->getRenderManager()->blitSurfaceToBkg(*frameData, x, y); } } // End of namespace ZVision diff --git a/engines/zvision/render_manager.cpp b/engines/zvision/render_manager.cpp index 6578c850f6..bc4d169569 100644 --- a/engines/zvision/render_manager.cpp +++ b/engines/zvision/render_manager.cpp @@ -39,356 +39,75 @@ namespace ZVision { RenderManager::RenderManager(OSystem *system, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat) : _system(system), - _workingWidth(workingWindow.width()), - _workingHeight(workingWindow.height()), - _screenCenterX(_workingWidth / 2), - _screenCenterY(_workingHeight / 2), + _wrkWidth(workingWindow.width()), + _wrkHeight(workingWindow.height()), + _screenCenterX(_wrkWidth / 2), + _screenCenterY(_wrkHeight / 2), _workingWindow(workingWindow), _pixelFormat(pixelFormat), - _backgroundWidth(0), - _backgroundHeight(0), - _backgroundInverseVelocity(0), - _backgroundOffset(0, 0), - _accumulatedVelocityMilliseconds(0), - _renderTable(_workingWidth, _workingHeight) { + _bkgWidth(0), + _bkgHeight(0), + _bkgOff(0), + _renderTable(_wrkWidth, _wrkHeight) { - _workingWindowBuffer.create(_workingWidth, _workingHeight, _pixelFormat); - _backBuffer.create(windowWidth, windowHeight, pixelFormat); -} + _wrkWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); + _outWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); + _menuWnd.create(windowWidth, workingWindow.top, _pixelFormat); + _subWnd.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); -RenderManager::~RenderManager() { - _workingWindowBuffer.free(); - _currentBackground.free(); - _backBuffer.free(); + _menuWndRect = Common::Rect(0, 0, windowWidth, workingWindow.top); + _subWndRect = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight); - for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) { - iter->_value.data->free(); - delete iter->_value.data; - } + _subid = 0; } -void RenderManager::update(uint deltaTimeInMillis) { - // An inverse velocity of 0 would be infinitely fast, so we'll let 0 mean no velocity. - if (_backgroundInverseVelocity != 0) { - _accumulatedVelocityMilliseconds += deltaTimeInMillis; - - uint absVelocity = uint(abs(_backgroundInverseVelocity)); - - int numberOfSteps = 0; - while (_accumulatedVelocityMilliseconds >= absVelocity) { - _accumulatedVelocityMilliseconds -= absVelocity; - numberOfSteps++; - } - - // Choose the direction of movement using the sign of the velocity - moveBackground(_backgroundInverseVelocity < 0 ? -numberOfSteps : numberOfSteps); - } +RenderManager::~RenderManager() { + _curBkg.free(); + _wrkWnd.free(); + _outWnd.free(); } void RenderManager::renderBackbufferToScreen() { - if (!_workingWindowDirtyRect.isEmpty()) { - RenderTable::RenderState state = _renderTable.getRenderState(); - if (state == RenderTable::PANORAMA || state == RenderTable::TILT) { - _renderTable.mutateImage((uint16 *)_workingWindowBuffer.getPixels(), (uint16 *)_backBuffer.getBasePtr(_workingWindow.left + _workingWindowDirtyRect.left, _workingWindow.top + _workingWindowDirtyRect.top), _backBuffer.w, _workingWindowDirtyRect); - } else { - _backBuffer.copyRectToSurface(_workingWindowBuffer.getBasePtr(_workingWindowDirtyRect.left, _workingWindowDirtyRect.top), _workingWindowBuffer.pitch, _workingWindow.left + _workingWindowDirtyRect.left, _workingWindow.top + _workingWindowDirtyRect.top, _workingWindowDirtyRect.width(), _workingWindowDirtyRect.height()); - } - - // Translate the working window dirty rect to screen coords - _workingWindowDirtyRect.translate(_workingWindow.left, _workingWindow.top); - // Then extend the backbuffer dirty rect to contain it - if (_backBufferDirtyRect.isEmpty()) { - _backBufferDirtyRect = _workingWindowDirtyRect; - } else { - _backBufferDirtyRect.extend(_workingWindowDirtyRect); - } - - // Clear the dirty rect - _workingWindowDirtyRect = Common::Rect(); - } - - // TODO: Add menu rendering - - // Render alpha entries - processAlphaEntries(); - - if (!_backBufferDirtyRect.isEmpty()) { - _system->copyRectToScreen(_backBuffer.getBasePtr(_backBufferDirtyRect.left, _backBufferDirtyRect.top), _backBuffer.pitch, _backBufferDirtyRect.left, _backBufferDirtyRect.top, _backBufferDirtyRect.width(), _backBufferDirtyRect.height()); - _backBufferDirtyRect = Common::Rect(); - } -} - -void RenderManager::processAlphaEntries() { - // TODO: Add dirty rectangling support. AKA only draw an entry if the _backbufferDirtyRect intersects/contains the entry Rect + Graphics::Surface *out = &_outWnd; - for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) { - uint32 destOffset = 0; - uint32 sourceOffset = 0; - uint16 *backbufferPtr = (uint16 *)_backBuffer.getBasePtr(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top); - uint16 *entryPtr = (uint16 *)iter->_value.data->getPixels(); - - for (int32 y = 0; y < iter->_value.height; ++y) { - for (int32 x = 0; x < iter->_value.width; ++x) { - uint16 color = entryPtr[sourceOffset + x]; - if (color != iter->_value.alphaColor) { - backbufferPtr[destOffset + x] = color; - } - } - - destOffset += _backBuffer.w; - sourceOffset += iter->_value.width; - } - - if (_backBufferDirtyRect.isEmpty()) { - _backBufferDirtyRect = Common::Rect(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top, iter->_value.destX + _workingWindow.left + iter->_value.width, iter->_value.destY + _workingWindow.top + iter->_value.height); - } else { - _backBufferDirtyRect.extend(Common::Rect(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top, iter->_value.destX + _workingWindow.left + iter->_value.width, iter->_value.destY + _workingWindow.top + iter->_value.height)); + RenderTable::RenderState state = _renderTable.getRenderState(); + if (state == RenderTable::PANORAMA || state == RenderTable::TILT) { + if (!_wrkWndDirtyRect.isEmpty()) { + _renderTable.mutateImage(&_outWnd, &_wrkWnd); + out = &_outWnd; + _outWndDirtyRect = Common::Rect(_wrkWidth, _wrkHeight); } + } else { + out = &_wrkWnd; + _outWndDirtyRect = _wrkWndDirtyRect; } -} - -void RenderManager::clearWorkingWindowTo555Color(uint16 color) { - uint32 workingWindowSize = _workingWidth * _workingHeight; - byte r, g, b; - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(color, r, g, b); - uint16 colorIn565 = _pixelFormat.RGBToColor(r, g, b); - uint16 *bufferPtr = (uint16 *)_workingWindowBuffer.getPixels(); - - for (uint32 i = 0; i < workingWindowSize; ++i) { - bufferPtr[i] = colorIn565; - } -} - -void RenderManager::copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &_srcRect, const Common::Rect &_dstRect) { - if (src.format != dst.format) - return; - - Common::Rect dstRect = _dstRect; - if (dstRect.isEmpty()) - dstRect = Common::Rect(dst.w, dst.h); - dstRect.clip(dst.w, dst.h); - - Common::Rect srcRect = _srcRect; - if (srcRect.isEmpty()) - srcRect = Common::Rect(src.w, src.h); - srcRect.clip(src.w, src.h); - - if (!srcRect.isValidRect() || !dstRect.isValidRect()) - return; - - Common::Rect rendRect = srcRect; - rendRect.clip(dstRect.width(), dstRect.height()); - - if (rendRect.isEmpty() || !rendRect.isValidRect()) - return; - // Copy rendRect from src surface to dst surface - const byte *src_buf = (const byte *)src.getBasePtr(rendRect.left, rendRect.top); - byte *dst_buf = (byte *)dst.getBasePtr(dstRect.left, dstRect.top); - int32 w = rendRect.width(); - int32 h = rendRect.height(); + if (!_outWndDirtyRect.isEmpty()) { + _system->copyRectToScreen(out->getBasePtr(_outWndDirtyRect.left, _outWndDirtyRect.top), out->pitch, + _outWndDirtyRect.left + _workingWindow.left, + _outWndDirtyRect.top + _workingWindow.top, + _outWndDirtyRect.width(), + _outWndDirtyRect.height()); - for (int32 y = 0; y < h; y++) { - memcpy(dst_buf, src_buf, w * src.format.bytesPerPixel); - src_buf += src.pitch; - dst_buf += dst.pitch; + _outWndDirtyRect = Common::Rect(); } } -void RenderManager::copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &_srcRect, const Common::Rect &_dstRect, uint32 keycolor) { - if (src.format != dst.format) - return; - - Common::Rect dstRect = _dstRect; - if (dstRect.isEmpty()) - dstRect = Common::Rect(dst.w, dst.h); - dstRect.clip(dst.w, dst.h); - - Common::Rect srcRect = _srcRect; - if (srcRect.isEmpty()) - srcRect = Common::Rect(src.w, src.h); - srcRect.clip(src.w, src.h); - - if (!srcRect.isValidRect() || !dstRect.isValidRect()) - return; - - Common::Rect rendRect = srcRect; - rendRect.clip(dstRect.width(), dstRect.height()); - - if (rendRect.isEmpty() || !rendRect.isValidRect()) - return; - - uint32 _keycolor = keycolor & ((1 << (src.format.bytesPerPixel << 3)) - 1); - - // Copy rendRect from src surface to dst surface - const byte *src_buf = (const byte *)src.getBasePtr(rendRect.left, rendRect.top); - byte *dst_buf = (byte *)dst.getBasePtr(dstRect.left, dstRect.top); - - int32 w = rendRect.width(); - int32 h = rendRect.height(); - - for (int32 y = 0; y < h; y++) { - switch (src.format.bytesPerPixel) { - case 1: { - const uint *src_tmp = (const uint *)src_buf; - uint *dst_tmp = (uint *)dst_buf; - for (int32 x = 0; x < w; x++) { - if (*src_tmp != _keycolor) - *dst_tmp = *src_tmp; - src_tmp++; - dst_tmp++; - } - } - break; - - case 2: { - const uint16 *src_tmp = (const uint16 *)src_buf; - uint16 *dst_tmp = (uint16 *)dst_buf; - for (int32 x = 0; x < w; x++) { - if (*src_tmp != _keycolor) - *dst_tmp = *src_tmp; - src_tmp++; - dst_tmp++; - } - } - break; - - case 4: { - const uint32 *src_tmp = (const uint32 *)src_buf; - uint32 *dst_tmp = (uint32 *)dst_buf; - for (int32 x = 0; x < w; x++) { - if (*src_tmp != _keycolor) - *dst_tmp = *src_tmp; - src_tmp++; - dst_tmp++; - } - } - break; - - default: - break; - } - src_buf += src.pitch; - dst_buf += dst.pitch; - } -} - -void RenderManager::copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &srcRect, const Common::Point &dstPt) { - if (!Common::Rect(dst.w, dst.h).contains(dstPt)) - return; - Common::Rect dstRect(dstPt.x, dstPt.y, dst.w, dst.h); - copyRectToSurface(src, dst, srcRect, dstRect); -} - -void RenderManager::copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &srcRect, const Common::Point &dstPt, uint32 keycolor) { - if (!Common::Rect(dst.w, dst.h).contains(dstPt)) - return; - Common::Rect dstRect(dstPt.x, dstPt.y, dst.w, dst.h); - copyRectToSurface(src, dst, srcRect, dstRect, keycolor); -} - void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY) { Graphics::Surface surface; readImageToSurface(fileName, surface); - Common::Rect srcRect(surface.w, surface.h); - Common::Point dstPt(destX, destY); - - copyRectToSurface(surface, _currentBackground, srcRect, dstPt); - moveBackground(0); -} - -void RenderManager::renderImageToBackground(const Graphics::Surface &surface, int16 destX, int16 destY) { - Common::Rect srcRect(surface.w, surface.h); - Common::Point dstPt(destX, destY); - - copyRectToSurface(surface, _currentBackground, srcRect, dstPt); - moveBackground(0); + blitSurfaceToBkg(surface, destX, destY); + surface.free(); } void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, uint32 keycolor) { Graphics::Surface surface; readImageToSurface(fileName, surface); - Common::Rect srcRect(surface.w, surface.h); - Common::Point dstPt(destX, destY); - - copyRectToSurface(surface, _currentBackground, srcRect, dstPt, keycolor); - moveBackground(0); -} - -void RenderManager::renderImageToBackground(const Graphics::Surface &surface, int16 destX, int16 destY, uint32 keycolor) { - Common::Rect srcRect(surface.w, surface.h); - Common::Point dstPt(destX, destY); - - copyRectToSurface(surface, _currentBackground, srcRect, dstPt, keycolor); - moveBackground(0); -} - -void RenderManager::renderSubRectToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) { - int16 subRectX = 0; - int16 subRectY = 0; - - // Take care of negative destinations - if (destinationX < 0) { - subRectX = -destinationX; - destinationX = 0; - } else if (destinationX >= surface.w) { - // Take care of extreme positive destinations - destinationX -= surface.w; - } - - // Take care of negative destinations - if (destinationY < 0) { - subRectY = -destinationY; - destinationY = 0; - } else if (destinationY >= surface.h) { - // Take care of extreme positive destinations - destinationY -= surface.h; - } - - if (wrap) { - _backgroundWidth = surface.w; - _backgroundHeight = surface.h; - - if (destinationX > 0) { - // Move destinationX to 0 - subRectX = surface.w - destinationX; - destinationX = 0; - } - - if (destinationY > 0) { - // Move destinationY to 0 - subRectY = surface.h - destinationY; - destinationY = 0; - } - } - - // Clip subRect to working window bounds - Common::Rect subRect(subRectX, subRectY, subRectX + _workingWidth, subRectY + _workingHeight); - - if (!wrap) { - // Clip to image bounds - subRect.clip(surface.w, surface.h); - } - - // Check destRect for validity - if (!subRect.isValidRect() || subRect.isEmpty()) - return; - - copyRectToWorkingWindow((const uint16 *)surface.getBasePtr(subRect.left, subRect.top), destinationX, destinationY, surface.w, subRect.width(), subRect.height()); -} - -void RenderManager::renderImageToScreen(const Common::String &fileName, int16 destinationX, int16 destinationY, bool wrap) { - Graphics::Surface surface; - readImageToSurface(fileName, surface); - - renderSubRectToScreen(surface, destinationX, destinationY, wrap); -} - -void RenderManager::renderImageToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) { - renderSubRectToScreen(surface, destinationX, destinationY, wrap); + blitSurfaceToBkg(surface, destX, destY, keycolor); + surface.free(); } void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) { @@ -485,72 +204,6 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics: destination.convertToInPlace(_pixelFormat); } -void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height) { - uint32 destOffset = 0; - uint32 sourceOffset = 0; - uint16 *workingWindowBufferPtr = (uint16 *)_workingWindowBuffer.getBasePtr(destX, destY); - - for (int32 y = 0; y < height; ++y) { - for (int32 x = 0; x < width; ++x) { - workingWindowBufferPtr[destOffset + x] = buffer[sourceOffset + x]; - } - - destOffset += _workingWidth; - sourceOffset += imageWidth; - } - - if (_workingWindowDirtyRect.isEmpty()) { - _workingWindowDirtyRect = Common::Rect(destX, destY, destX + width, destY + height); - } else { - _workingWindowDirtyRect.extend(Common::Rect(destX, destY, destX + width, destY + height)); - } - - // TODO: Remove this from release. It's here to make sure code that uses this function clips their destinations correctly - assert(_workingWindowDirtyRect.width() <= _workingWidth && _workingWindowDirtyRect.height() <= _workingHeight); -} - -void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor, uint32 idNumber) { - AlphaDataEntry entry; - entry.alphaColor = alphaColor; - entry.data = new Graphics::Surface(); - entry.data->create(width, height, _pixelFormat); - entry.destX = destX; - entry.destY = destY; - entry.width = width; - entry.height = height; - - uint32 sourceOffset = 0; - uint32 destOffset = 0; - uint16 *surfacePtr = (uint16 *)entry.data->getPixels(); - - for (int32 y = 0; y < height; ++y) { - for (int32 x = 0; x < width; ++x) { - surfacePtr[destOffset + x] = buffer[sourceOffset + x]; - } - - destOffset += width; - sourceOffset += imageWidth; - } - - _alphaDataEntries[idNumber] = entry; -} - -Common::Rect RenderManager::renderTextToWorkingWindow(uint32 idNumber, const Common::String &text, TruetypeFont *font, int destX, int destY, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap) { - AlphaDataEntry entry; - entry.alphaColor = 0; - entry.destX = destX; - entry.destY = destY; - - // Draw the text to the working window - entry.data = font->drawTextToSurface(text, textColor, maxWidth, maxHeight, align, wrap); - entry.width = entry.data->w; - entry.height = entry.data->h; - - _alphaDataEntries[idNumber] = entry; - - return Common::Rect(destX, destY, destX + entry.width, destY + entry.height); -} - const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) { if (_workingWindow.contains(point)) { // Convert from screen space to working window space @@ -562,19 +215,20 @@ const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point & } if (state == RenderTable::PANORAMA) { - newPoint -= (Common::Point(_screenCenterX, 0) - _backgroundOffset); + newPoint += (Common::Point(_bkgOff - _screenCenterX, 0)); } else if (state == RenderTable::TILT) { - newPoint -= (Common::Point(0, _screenCenterY) - _backgroundOffset); + newPoint += (Common::Point(0, _bkgOff - _screenCenterY)); } + if (_bkgWidth) + newPoint.x %= _bkgWidth; + if (_bkgHeight) + newPoint.y %= _bkgHeight; + if (newPoint.x < 0) - newPoint.x += _backgroundWidth; - else if (newPoint.x >= _backgroundWidth) - newPoint.x -= _backgroundWidth; + newPoint.x += _bkgWidth; if (newPoint.y < 0) - newPoint.y += _backgroundHeight; - else if (newPoint.y >= _backgroundHeight) - newPoint.y -= _backgroundHeight; + newPoint.y += _bkgHeight; return newPoint; } else { @@ -582,95 +236,32 @@ const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point & } } -const Common::Point RenderManager::imageSpaceToWorkingWindowSpace(const Common::Point &point) { - Common::Point newPoint(point); - - RenderTable::RenderState state = _renderTable.getRenderState(); - if (state == RenderTable::PANORAMA) { - newPoint += (Common::Point(_screenCenterX, 0) - _backgroundOffset); - } else if (state == RenderTable::TILT) { - newPoint += (Common::Point(0, _screenCenterY) - _backgroundOffset); - } - - return newPoint; -} - -bool RenderManager::clipRectToWorkingWindow(Common::Rect &rect) { - if (!_workingWindow.contains(rect)) { - return false; - } - - // We can't clip against the actual working window rect because it's in screen space - // But rect is in working window space - rect.clip(_workingWidth, _workingHeight); - return true; -} - RenderTable *RenderManager::getRenderTable() { return &_renderTable; } void RenderManager::setBackgroundImage(const Common::String &fileName) { - readImageToSurface(fileName, _currentBackground); - - moveBackground(0); + readImageToSurface(fileName, _curBkg); + _bkgWidth = _curBkg.w; + _bkgHeight = _curBkg.h; + _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); } void RenderManager::setBackgroundPosition(int offset) { RenderTable::RenderState state = _renderTable.getRenderState(); - if (state == RenderTable::TILT) { - _backgroundOffset.x = 0; - _backgroundOffset.y = offset; - } else if (state == RenderTable::PANORAMA) { - _backgroundOffset.x = offset; - _backgroundOffset.y = 0; - } else { - _backgroundOffset.x = 0; - _backgroundOffset.y = 0; - } -} - -void RenderManager::setBackgroundVelocity(int velocity) { - // setBackgroundVelocity(0) will be called quite often, so make sure - // _backgroundInverseVelocity isn't already 0 to prevent an extraneous assignment - if (velocity == 0) { - if (_backgroundInverseVelocity != 0) { - _backgroundInverseVelocity = 0; - } - } else { - _backgroundInverseVelocity = 1000 / velocity; - } -} - -void RenderManager::moveBackground(int offset) { - RenderTable::RenderState state = _renderTable.getRenderState(); - if (state == RenderTable::TILT) { - _backgroundOffset += Common::Point(0, offset); - - _backgroundOffset.y = CLIP<int16>(_backgroundOffset.y, _screenCenterY, (int16)_backgroundHeight - _screenCenterY); - - renderImageToScreen(_currentBackground, 0, _screenCenterY - _backgroundOffset.y, true); - } else if (state == RenderTable::PANORAMA) { - _backgroundOffset += Common::Point(offset, 0); - - if (_backgroundOffset.x <= -_backgroundWidth) - _backgroundOffset.x += _backgroundWidth; - else if (_backgroundOffset.x >= _backgroundWidth) - _backgroundOffset.x -= _backgroundWidth; - - renderImageToScreen(_currentBackground, _screenCenterX - _backgroundOffset.x, 0, true); - } else { - renderImageToScreen(_currentBackground, 0, 0); - } + if (state == RenderTable::TILT || state == RenderTable::PANORAMA) + if (_bkgOff != offset) + _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); + _bkgOff = offset; } uint32 RenderManager::getCurrentBackgroundOffset() { RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA) { - return _backgroundOffset.x; + return _bkgOff; } else if (state == RenderTable::TILT) { - return _backgroundOffset.y; + return _bkgOff; } else { return 0; } @@ -721,47 +312,196 @@ void RenderManager::scaleBuffer(const void *src, void *dst, uint32 srcWidth, uin } } -void RenderManager::blitSurfaceToSurface(Graphics::Surface &src, Graphics::Surface &dst, int x, int y) { - Common::Rect pos(x, y, x + src.w, y + src.h); - pos.clip(dst.w, dst.h); - copyRectToSurface(src, dst, Common::Rect(), pos); +void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y) { + + if (src.format != dst.format) + return; + + Common::Rect srcRect = _srcRect; + if (srcRect.isEmpty()) + srcRect = Common::Rect(src.w, src.h); + srcRect.clip(src.w, src.h); + Common::Rect dstRect = Common::Rect(-_x + srcRect.left , -_y + srcRect.top, -_x + srcRect.left + dst.w, -_y + srcRect.top + dst.h); + srcRect.clip(dstRect); + + if (srcRect.isEmpty() || !srcRect.isValidRect()) + return; + + // Copy srcRect from src surface to dst surface + const byte *src_buf = (const byte *)src.getBasePtr(srcRect.left, srcRect.top); + + int xx = _x; + int yy = _y; + + if (xx < 0) + xx = 0; + if (yy < 0) + yy = 0; + + if (_x >= dst.w || _y >= dst.h) + return; + + byte *dst_buf = (byte *)dst.getBasePtr(xx, yy); + + int32 w = srcRect.width(); + int32 h = srcRect.height(); + + for (int32 y = 0; y < h; y++) { + memcpy(dst_buf, src_buf, w * src.format.bytesPerPixel); + src_buf += src.pitch; + dst_buf += dst.pitch; + } } -void RenderManager::blitSurfaceToSurface(Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey) { - Common::Rect pos(x, y, x + src.w, y + src.h); - pos.clip(dst.w, dst.h); - copyRectToSurface(src, dst, Common::Rect(), pos, colorkey); +void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey) { + + if (src.format != dst.format) + return; + + Common::Rect srcRect = _srcRect; + if (srcRect.isEmpty()) + srcRect = Common::Rect(src.w, src.h); + srcRect.clip(src.w, src.h); + Common::Rect dstRect = Common::Rect(-_x + srcRect.left , -_y + srcRect.top, -_x + srcRect.left + dst.w, -_y + srcRect.top + dst.h); + srcRect.clip(dstRect); + + if (srcRect.isEmpty() || !srcRect.isValidRect()) + return; + + + + uint32 _keycolor = colorkey & ((1 << (src.format.bytesPerPixel << 3)) - 1); + + // Copy srcRect from src surface to dst surface + const byte *src_buf = (const byte *)src.getBasePtr(srcRect.left, srcRect.top); + + int xx = _x; + int yy = _y; + + if (xx < 0) + xx = 0; + if (yy < 0) + yy = 0; + + if (_x >= dst.w || _y >= dst.h) + return; + + byte *dst_buf = (byte *)dst.getBasePtr(xx, yy); + + int32 w = srcRect.width(); + int32 h = srcRect.height(); + + for (int32 y = 0; y < h; y++) { + switch (src.format.bytesPerPixel) { + case 1: { + const uint *src_tmp = (const uint *)src_buf; + uint *dst_tmp = (uint *)dst_buf; + for (int32 x = 0; x < w; x++) { + if (*src_tmp != _keycolor) + *dst_tmp = *src_tmp; + src_tmp++; + dst_tmp++; + } + } + break; + + case 2: { + const uint16 *src_tmp = (const uint16 *)src_buf; + uint16 *dst_tmp = (uint16 *)dst_buf; + for (int32 x = 0; x < w; x++) { + if (*src_tmp != _keycolor) + *dst_tmp = *src_tmp; + src_tmp++; + dst_tmp++; + } + } + break; + + case 4: { + const uint32 *src_tmp = (const uint32 *)src_buf; + uint32 *dst_tmp = (uint32 *)dst_buf; + for (int32 x = 0; x < w; x++) { + if (*src_tmp != _keycolor) + *dst_tmp = *src_tmp; + src_tmp++; + dst_tmp++; + } + } + break; + + default: + break; + } + src_buf += src.pitch; + dst_buf += dst.pitch; + } +} + +void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y) { + Common::Rect empt; + blitSurfaceToSurface(src, empt, dst, x, y); +} + +void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey) { + Common::Rect empt; + blitSurfaceToSurface(src, empt, dst, x, y, colorkey); } -void RenderManager::blitSurfaceToBkg(Graphics::Surface &src, int x, int y) { - blitSurfaceToSurface(src, _currentBackground, x, y); - moveBackground(0); // Temporary workaround +void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y) { + Common::Rect empt; + blitSurfaceToSurface(src, empt, _curBkg, x, y); + Common::Rect dirty(src.w, src.h); + dirty.translate(x, y); + if (_bkgDirtyRect.isEmpty()) + _bkgDirtyRect = dirty; + else + _bkgDirtyRect.extend(dirty); } -void RenderManager::blitSurfaceToBkg(Graphics::Surface &src, int x, int y, uint32 colorkey) { - blitSurfaceToSurface(src, _currentBackground, x, y, colorkey); - moveBackground(0); // Temporary workaround +void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey) { + Common::Rect empt; + blitSurfaceToSurface(src, empt, _curBkg, x, y, colorkey); + Common::Rect dirty(src.w, src.h); + dirty.translate(x, y); + if (_bkgDirtyRect.isEmpty()) + _bkgDirtyRect = dirty; + else + _bkgDirtyRect.extend(dirty); } -void RenderManager::blitSurfaceUpBkg(Graphics::Surface &src, int x, int y) { - blitSurfaceToSurface(src, _workingWindowBuffer, x, y); +void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y) { + Common::Rect empt; + blitSurfaceToSurface(src, empt, _menuWnd, x, y); + Common::Rect dirty(src.w, src.h); + dirty.translate(x, y); + if (_menuWndDirtyRect.isEmpty()) + _menuWndDirtyRect = dirty; + else + _menuWndDirtyRect.extend(dirty); } -void RenderManager::blitSurfaceUpBkg(Graphics::Surface &src, int x, int y, uint32 colorkey) { - blitSurfaceToSurface(src, _workingWindowBuffer, x, y, colorkey); +void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey) { + Common::Rect empt; + blitSurfaceToSurface(src, empt, _menuWnd, x, y, colorkey); + Common::Rect dirty(src.w, src.h); + dirty.translate(x, y); + if (_menuWndDirtyRect.isEmpty()) + _menuWndDirtyRect = dirty; + else + _menuWndDirtyRect.extend(dirty); } Graphics::Surface *RenderManager::getBkgRect(Common::Rect &rect) { Common::Rect dst = rect; - dst.clip(_currentBackground.w, _currentBackground.h); + dst.clip(_bkgWidth, _bkgHeight); if (dst.isEmpty() || !dst.isValidRect()) return NULL; Graphics::Surface *srf = new Graphics::Surface; - srf->create(dst.width(), dst.height(), _currentBackground.format); + srf->create(dst.width(), dst.height(), _curBkg.format); - srf->copyRectToSurface(_currentBackground, 0, 0, Common::Rect(dst)); + srf->copyRectToSurface(_curBkg, 0, 0, Common::Rect(dst)); return srf; } @@ -777,4 +517,149 @@ Graphics::Surface *RenderManager::loadImage(const char *file) { return loadImage(str); } +void RenderManager::prepareBkg() { + _bkgDirtyRect.clip(_bkgWidth, _bkgHeight); + RenderTable::RenderState state = _renderTable.getRenderState(); + + if (state == RenderTable::PANORAMA) { + Common::Rect viewPort(_wrkWidth, _wrkHeight); + viewPort.translate(-(_screenCenterX - _bkgOff), 0); + Common::Rect drawRect = _bkgDirtyRect; + drawRect.clip(viewPort); + + if (!drawRect.isEmpty()) + blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - _bkgOff + drawRect.left, drawRect.top); + + _wrkWndDirtyRect = _bkgDirtyRect; + _wrkWndDirtyRect.translate(_screenCenterX - _bkgOff, 0); + + if (_bkgOff < _screenCenterX) { + viewPort.moveTo(-(_screenCenterX - (_bkgOff + _bkgWidth)), 0); + drawRect = _bkgDirtyRect; + drawRect.clip(viewPort); + + if (!drawRect.isEmpty()) + blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - (_bkgOff + _bkgWidth) + drawRect.left, drawRect.top); + + Common::Rect tmp = _bkgDirtyRect; + tmp.translate(_screenCenterX - (_bkgOff + _bkgWidth), 0); + if (!tmp.isEmpty()) + _wrkWndDirtyRect.extend(tmp); + + } else if (_bkgWidth - _bkgOff < _screenCenterX) { + viewPort.moveTo(-(_screenCenterX + _bkgWidth - _bkgOff), 0); + drawRect = _bkgDirtyRect; + drawRect.clip(viewPort); + + if (!drawRect.isEmpty()) + blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX + _bkgWidth - _bkgOff + drawRect.left, drawRect.top); + + Common::Rect tmp = _bkgDirtyRect; + tmp.translate(_screenCenterX + _bkgWidth - _bkgOff, 0); + if (!tmp.isEmpty()) + _wrkWndDirtyRect.extend(tmp); + + } + } else if (state == RenderTable::TILT) { + Common::Rect viewPort(_wrkWidth, _wrkHeight); + viewPort.translate(0, -(_screenCenterY - _bkgOff)); + Common::Rect drawRect = _bkgDirtyRect; + drawRect.clip(viewPort); + if (!drawRect.isEmpty()) + blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, drawRect.left, _screenCenterY - _bkgOff + drawRect.top); + + _wrkWndDirtyRect = _bkgDirtyRect; + _wrkWndDirtyRect.translate(0, _screenCenterY - _bkgOff); + + } else { + if (!_bkgDirtyRect.isEmpty()) + blitSurfaceToSurface(_curBkg, _bkgDirtyRect, _wrkWnd, _bkgDirtyRect.left, _bkgDirtyRect.top); + _wrkWndDirtyRect = _bkgDirtyRect; + } + + _bkgDirtyRect = Common::Rect(); + + _wrkWndDirtyRect.clip(_wrkWidth, _wrkHeight); +} + +void RenderManager::clearMenuSurface() { + _menuWndDirtyRect = Common::Rect(0, 0, _menuWnd.w, _menuWnd.h); + _menuWnd.fillRect(_menuWndDirtyRect, 0); +} + +void RenderManager::renderMenuToScreen() { + if (!_menuWndDirtyRect.isEmpty()) { + _menuWndDirtyRect.clip(Common::Rect(_menuWnd.w, _menuWnd.h)); + + _system->copyRectToScreen(_menuWnd.getBasePtr(_menuWndDirtyRect.left, _menuWndDirtyRect.top), _menuWnd.pitch, + _menuWndDirtyRect.left + _menuWndRect.left, + _menuWndDirtyRect.top + _menuWndRect.top, + _menuWndDirtyRect.width(), + _menuWndDirtyRect.height()); + _menuWndDirtyRect = Common::Rect(); + } +} + +uint16 RenderManager::createSubArea(const Common::Rect &area) { + _subid++; + + oneSub sub; + sub.redraw = false; + sub.timer = -1; + sub.todelete = false; + sub._r = area; + + _subsList[_subid] = sub; + + return _subid; +} + +void RenderManager::deleteSubArea(uint16 id) { + if (_subsList.contains(id)) + _subsList[id].todelete = true; +} + +void RenderManager::deleteSubArea(uint16 id, int16 delay) { + if (_subsList.contains(id)) + _subsList[id].timer = delay; +} + +void RenderManager::updateSubArea(uint16 id, const Common::String &txt) { + if (_subsList.contains(id)) { + oneSub *sub = &_subsList[id]; + sub->_txt = txt; + sub->redraw = true; + } +} + +void RenderManager::renderSubsToScreen() { + bool redraw = false; + for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { + if (it->_value.todelete) { + _subsList.erase(it); + redraw = true; + } else if (it->_value.redraw) { + redraw = true; + } + } + + if (redraw) { + _subWnd.fillRect(Common::Rect(_subWnd.w, _subWnd.h), 0); + + for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { + //draw subs + } + + _system->copyRectToScreen(_subWnd.getPixels(), _subWnd.pitch, + _subWndRect.left, + _subWndRect.top, + _subWnd.w, + _subWnd.h); + } +} + +Common::Point RenderManager::getBkgSize() { + return Common::Point(_bkgWidth, _bkgHeight); +} + } // End of namespace ZVision diff --git a/engines/zvision/render_manager.h b/engines/zvision/render_manager.h index e16d3562dc..de53481be0 100644 --- a/engines/zvision/render_manager.h +++ b/engines/zvision/render_manager.h @@ -51,39 +51,66 @@ public: ~RenderManager(); private: - struct AlphaDataEntry { - Graphics::Surface *data; - uint16 alphaColor; - uint16 destX; - uint16 destY; - uint16 width; - uint16 height; + struct oneSub { + Common::Rect _r; + Common::String _txt; + int16 timer; + bool todelete; + bool redraw; }; - - typedef Common::HashMap<uint32, AlphaDataEntry> AlphaEntryMap; +// struct AlphaDataEntry { +// Graphics::Surface *data; +// uint16 alphaColor; +// uint16 destX; +// uint16 destY; +// uint16 width; +// uint16 height; +// }; +// + typedef Common::HashMap<uint16, oneSub> subMap; private: OSystem *_system; const Graphics::PixelFormat _pixelFormat; + // A buffer for blitting background image to working window + Graphics::Surface _wrkWnd; + + Common::Rect _wrkWndDirtyRect; + + Graphics::Surface _outWnd; + + Common::Rect _outWndDirtyRect; + + Common::Rect _bkgDirtyRect; + + Graphics::Surface _subWnd; + + Common::Rect _subWndDirtyRect; + + Graphics::Surface _menuWnd; + + Common::Rect _menuWndDirtyRect; + + // A buffer the exact same size as the workingWindow // This buffer stores everything un-warped, then does a warp at the end of the frame - Graphics::Surface _workingWindowBuffer; + //Graphics::Surface _workingWindowBuffer; // A buffer representing the entire screen. Any graphical updates are first done with this buffer // before actually being blitted to the screen - Graphics::Surface _backBuffer; + //Graphics::Surface _backBuffer; // A list of Alpha Entries that need to be blitted to the backbuffer - AlphaEntryMap _alphaDataEntries; + //AlphaEntryMap _alphaDataEntries; // A rectangle representing the portion of the working window where the pixels have been changed since last frame - Common::Rect _workingWindowDirtyRect; + //Common::Rect _workingWindowDirtyRect; // A rectangle representing the portion of the backbuffer where the pixels have been changed since last frame - Common::Rect _backBufferDirtyRect; + //Common::Rect _backBufferDirtyRect; /** Width of the working window. Saved to prevent extraneous calls to _workingWindow.width() */ - const int _workingWidth; + const int _wrkWidth; /** Height of the working window. Saved to prevent extraneous calls to _workingWindow.height() */ - const int _workingHeight; + const int _wrkHeight; /** Center of the screen in the x direction */ const int _screenCenterX; /** Center of the screen in the y direction */ @@ -95,33 +122,36 @@ private: * edges of this Rectangle */ const Common::Rect _workingWindow; + + Common::Rect _subWndRect; + + Common::Rect _menuWndRect; + /** Used to warp the background image */ RenderTable _renderTable; - Graphics::Surface _currentBackground; + Graphics::Surface _curBkg; /** The (x1,y1) coordinates of the subRectangle of the background that is currently displayed on the screen */ - Common::Point _backgroundOffset; + int16 _bkgOff; /** The width of the current background image */ - uint16 _backgroundWidth; + uint16 _bkgWidth; /** The height of the current background image */ - uint16 _backgroundHeight; + uint16 _bkgHeight; + + uint16 _subid; + + subMap _subsList; /** * The "velocity" at which the background image is panning. We actually store the inverse of velocity (ms/pixel instead of pixels/ms) * because it allows you to accumulate whole pixels 'steps' instead of rounding pixels every frame */ - int _backgroundInverseVelocity; + //int _backgroundInverseVelocity; /** Holds any 'leftover' milliseconds between frames */ - uint _accumulatedVelocityMilliseconds; + //uint _accumulatedVelocityMilliseconds; public: void initialize(); - /** - * Rotates the background image in accordance to the current _backgroundInverseVelocity - * - * @param deltaTimeInMillis The amount of time that has passed since the last frame - */ - void update(uint deltaTimeInMillis); /** * Renders the current state of the backbuffer to the screen @@ -129,137 +159,6 @@ public: void renderBackbufferToScreen(); /** - * Renders all AlphaEntries to the backbuffer - */ - void processAlphaEntries(); - /** - * Clears the AlphaEntry list - */ - void clearAlphaEntries() { - _alphaDataEntries.clear(); - } - /** - * Removes a specific AlphaEntry from the list - * - * @param idNumber The id number identifing the AlphaEntry - */ - void removeAlphaEntry(uint32 idNumber) { - _alphaDataEntries.erase(idNumber); - } - - /** - * Copies a sub-rectangle of a buffer to the working window - * - * @param buffer The pixel data to copy to the working window - * @param destX The X destination in the working window where the subRect of data should be put - * @param destY The Y destination in the working window where the subRect of data should be put - * @param imageWidth The width of the source image - * @param width The width of the sub rectangle - * @param height The height of the sub rectangle - */ - void copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height); - /** - * Copies a sub-rectangle of a buffer to the working window with binary alpha support. - * - * @param buffer The pixel data to copy to the working window - * @param destX The X destination in the working window where the subRect of data should be put - * @param destY The Y destination in the working window where the subRect of data should be put - * @param imageWidth The width of the source image - * @param width The width of the sub rectangle - * @param height The height of the sub rectangle - * @param alphaColor The color to interpret as meaning 'transparent' - * @param idNumber A unique identifier for the data being copied over. - */ - void copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor, uint32 idNumber); - - /** - * Renders the supplied text to the working window - * - * @param idNumber A unique identifier for the text - * @param text The text to be rendered - * @param font The font to use to render the text - * @param destX The X destination in the working window where the text should be rendered - * @param destY The Y destination in the working window where the text should be rendered - * @param textColor The color to render the text with (in RBG 565) - * @param maxWidth The max width the text should take up. - * @param maxHeight The max height the text should take up. - * @param align The alignment of the text within the bounds of maxWidth - * @param wrap If true, any words extending past maxWidth will wrap to a new line. If false, ellipses will be rendered to show that the text didn't fit - * @return A rectangle representing where the text was drawn in the working window - */ - Common::Rect renderTextToWorkingWindow(uint32 idNumber, const Common::String &text, TruetypeFont *font, int destX, int destY, uint16 textColor, int maxWidth, int maxHeight = -1, Graphics::TextAlign align = Graphics::kTextAlignLeft, bool wrap = true); - - /** - * Fills the entire workingWindow with the specified color. Internally, the color - * will be converted to RGB 565 and then blitted. - * - * @param color The color to fill the working window with. (In RGB 555) - */ - void clearWorkingWindowTo555Color(uint16 color); - - /** - * Blits the image or a portion of the image to the backbuffer. Actual screen updates won't happen until the end of the frame. - * The image will be clipped to fit inside the working window. Coords are in working window space, not screen space! - * - * @param fileName Name of the image file - * @param destinationX X position where the image should be put. Coords are in working window space, not screen space! - * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space! - */ - void renderImageToScreen(const Common::String &fileName, int16 destinationX, int16 destinationY, bool wrap = false); - - /** - * Blits the image or a portion of the image to the backbuffer. Actual screen updates won't happen until the end of the frame. - * The image will be clipped to fit inside the working window. Coords are in working window space, not screen space! - * - * @param stream Surface to read the image data from - * @param destinationX X position where the image should be put. Coords are in working window space, not screen space! - * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space! - */ - void renderImageToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap = false); - - /** - * Copies a rectangla of source surface and copy to destination rect. - * - * @param src Source surface - * @param dst Destenation surface - * @param srcRect Rect of source surface - * @param dstRect Rect for destenation surface - */ - void copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &srcRect, const Common::Rect &dstRect); - - /** - * Copies a rectangla of source surface and copy to destination rect. - * - * @param src Source surface - * @param dst Destenation surface - * @param srcRect Rect of source surface - * @param dstRect Rect for destenation surface - * @param colorkey Transparent color - */ - void copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &srcRect, const Common::Rect &dstRect, uint32 colorkey); - - /** - * Copies a rectangla of source surface and copy to destination rect. - * - * @param src Source surface - * @param dst Destenation surface - * @param srcRect Rect of source surface - * @param dstPt Point for destenation surface - */ - void copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &srcRect, const Common::Point &dstPt); - - /** - * Copies a rectangla of source surface and copy to destination rect. - * - * @param src Source surface - * @param dst Destenation surface - * @param srcRect Rect of source surface - * @param dstPt Point for destenation surface - * @param colorkey Transparent color - */ - void copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &srcRect, const Common::Point &dstPt, uint32 colorkey); - - /** * Blits the image or a portion of the image to the background. * * @param fileName Name of the image file @@ -271,15 +170,6 @@ public: /** * Blits the image or a portion of the image to the background. * - * @param surface Surface to read the image data from - * @param destinationX X position where the image should be put. Coords are in working window space, not screen space! - * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space! - */ - void renderImageToBackground(const Graphics::Surface &surface, int16 destinationX, int16 destinationY); - - /** - * Blits the image or a portion of the image to the background. - * * @param fileName Name of the image file * @param destinationX X position where the image should be put. Coords are in working window space, not screen space! * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space! @@ -288,16 +178,6 @@ public: void renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, uint32 colorkey); /** - * Blits the image or a portion of the image to the background. - * - * @param surface Surface to read the image data from - * @param destinationX X position where the image should be put. Coords are in working window space, not screen space! - * @param destinationY Y position where the image should be put. Coords are in working window space, not screen space! - * @param colorkey Transparent color - */ - void renderImageToBackground(const Graphics::Surface &surface, int16 destX, int16 destY, uint32 colorkey); - - /** * Sets the current background image to be used by the RenderManager and immediately * blits it to the screen. (It won't show up until the end of the frame) * @@ -318,43 +198,15 @@ public: void setBackgroundPosition(int offset); /** - * Set the background scroll velocity. Negative velocities correspond to left / up scrolling and - * positive velocities correspond to right / down scrolling - * - * @param velocity Velocity - */ - void setBackgroundVelocity(int velocity); - - /** * Converts a point in screen coordinate space to image coordinate space * * @param point Point in screen coordinate space * @return Point in image coordinate space */ const Common::Point screenSpaceToImageSpace(const Common::Point &point); - /** - * Converts a point in image coordinate space to ***PRE-WARP*** - * working window coordinate space - * - * @param point Point in image coordinate space - * @return Point in PRE-WARP working window coordinate space - */ - const Common::Point imageSpaceToWorkingWindowSpace(const Common::Point &point); - - /** - * Clip a rectangle to the working window. If it returns false, the original rect - * is not inside the working window. - * - * @param rect The rectangle to clip against the working window - * @return Is rect at least partially inside the working window (true) or completely outside (false) - */ - bool clipRectToWorkingWindow(Common::Rect &rect); RenderTable *getRenderTable(); uint32 getCurrentBackgroundOffset(); - const Graphics::Surface *getBackBuffer() { - return &_backBuffer; - } /** * Creates a copy of surface and transposes the data. @@ -369,31 +221,32 @@ public: void scaleBuffer(const void *src, void *dst, uint32 srcWidth, uint32 srcHeight, byte bytesPerPixel, uint32 dstWidth, uint32 dstHeight); - void blitSurfaceToSurface(Graphics::Surface &src, Graphics::Surface &dst, int x, int y); - void blitSurfaceToSurface(Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey); - void blitSurfaceToBkg(Graphics::Surface &src, int x, int y); - void blitSurfaceToBkg(Graphics::Surface &src, int x, int y, uint32 colorkey); - void blitSurfaceUpBkg(Graphics::Surface &src, int x, int y); - void blitSurfaceUpBkg(Graphics::Surface &src, int x, int y, uint32 colorkey); + + void blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int x, int y); + void blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey); + void blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y); + void blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey); + void blitSurfaceToBkg(const Graphics::Surface &src, int x, int y); + void blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey); + void blitSurfaceToMenu(const Graphics::Surface &src, int x, int y); + void blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey); + + uint16 createSubArea(const Common::Rect &area); + void deleteSubArea(uint16 id); + void deleteSubArea(uint16 id, int16 delay); + void updateSubArea(uint16 id, const Common::String &txt); + void renderSubsToScreen(); + + Common::Point getBkgSize(); + Graphics::Surface *getBkgRect(Common::Rect &rect); Graphics::Surface *loadImage(const char *file); Graphics::Surface *loadImage(Common::String &file); -private: - /** - * Renders a subRectangle of an image to the backbuffer. The destinationRect and SubRect - * will be clipped to image bound and to working window bounds - * - * @param buffer Pointer to (0, 0) of the image data - * @param imageWidth The width of the original image (not of the subRectangle) - * @param imageHeight The width of the original image (not of the subRectangle) - * @param horizontalPitch The horizontal pitch of the original image - * @param destinationX The x coordinate (in working window space) of where to put the final image - * @param destinationY The y coordinate (in working window space) of where to put the final image - * @param subRectangle A rectangle representing the part of the image that should be rendered - * @param wrap Should the image wrap (tile) if it doesn't completely fill the screen? - */ - void renderSubRectToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap); + void clearMenuSurface(); + void renderMenuToScreen(); + + void prepareBkg(); /** * Reads an image file pixel data into a Surface buffer. In the process @@ -406,19 +259,6 @@ private: * @param destination A reference to the Surface to store the pixel data in */ void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination); - - /** - * Move the background image by an offset. If we are currently in Panorama mode, - * the offset will correspond to a horizontal motion. If we are currently in Tilt mode, - * the offset will correspond to a vertical motion. This function should not be called - * if we are in Flat mode. - * - * The RenderManager will take care of wrapping the image. - * Ex: If the image has width 1400px, it is legal to offset 1500px. - * - * @param offset The amount to move the background - */ - void moveBackground(int offset); }; } // End of namespace ZVision diff --git a/engines/zvision/render_table.cpp b/engines/zvision/render_table.cpp index 5a0bae7c22..210c4fc1fb 100644 --- a/engines/zvision/render_table.cpp +++ b/engines/zvision/render_table.cpp @@ -123,6 +123,28 @@ void RenderTable::mutateImage(uint16 *sourceBuffer, uint16 *destBuffer, uint32 d } } +void RenderTable::mutateImage(Graphics::Surface *dstBuf, Graphics::Surface *srcBuf) { + uint32 destOffset = 0; + + uint16 *sourceBuffer = (uint16 *)srcBuf->getPixels(); + uint16 *destBuffer = (uint16 *)dstBuf->getPixels(); + + for (int16 y = 0; y < srcBuf->h; ++y) { + uint32 sourceOffset = y * _numColumns; + + for (int16 x = 0; x < srcBuf->w; ++x) { + uint32 index = sourceOffset + x; + + // RenderTable only stores offsets from the original coordinates + uint32 sourceYIndex = y + _internalBuffer[index].y; + uint32 sourceXIndex = x + _internalBuffer[index].x; + + destBuffer[destOffset] = sourceBuffer[sourceYIndex * _numColumns + sourceXIndex]; + destOffset++; + } + } +} + void RenderTable::generateRenderTable() { switch (_renderState) { case ZVision::RenderTable::PANORAMA: diff --git a/engines/zvision/render_table.h b/engines/zvision/render_table.h index 401e627747..db9ab08f7c 100644 --- a/engines/zvision/render_table.h +++ b/engines/zvision/render_table.h @@ -24,6 +24,7 @@ #define ZVISION_RENDER_TABLE_H #include "common/rect.h" +#include "graphics/surface.h" namespace ZVision { @@ -67,6 +68,7 @@ public: const Common::Point convertWarpedCoordToFlatCoord(const Common::Point &point); void mutateImage(uint16 *sourceBuffer, uint16 *destBuffer, uint32 destWidth, const Common::Rect &subRect); + void mutateImage(Graphics::Surface *dstBuf, Graphics::Surface *srcBuf); void generateRenderTable(); void setPanoramaFoV(float fov); diff --git a/engines/zvision/script_manager.cpp b/engines/zvision/script_manager.cpp index e30861aa98..ddb57c80da 100644 --- a/engines/zvision/script_manager.cpp +++ b/engines/zvision/script_manager.cpp @@ -516,10 +516,10 @@ void ScriptManager::do_changeLocation() { _engine->getCursorManager()->changeCursor(CursorIndex_Idle); // Reset the background velocity - _engine->getRenderManager()->setBackgroundVelocity(0); + //_engine->getRenderManager()->setBackgroundVelocity(0); // Remove any alphaEntries - _engine->getRenderManager()->clearAlphaEntries(); + //_engine->getRenderManager()->clearAlphaEntries(); // Change the background position _engine->getRenderManager()->setBackgroundPosition(_nextLocation.offset); diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index 65064d8a66..787b3ee3da 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -63,7 +63,8 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) _stringManager(nullptr), _cursorManager(nullptr), _aud_id(0), - _rendDelay(2) { + _rendDelay(2), + _velocity(0) { debug(1, "ZVision::ZVision"); } @@ -147,13 +148,16 @@ Common::Error ZVision::run() { _cursorManager->setItemID(_scriptManager->getStateValue(StateKey_InventoryItem)); processEvents(); + updateRotation(); // Call _renderManager->update() first so the background renders // before anything that puzzles/controls will render - _renderManager->update(deltaTime); _scriptManager->update(deltaTime); // Render the backBuffer to the screen + _renderManager->prepareBkg(); + _renderManager->renderMenuToScreen(); + _renderManager->renderSubsToScreen(); _renderManager->renderBackbufferToScreen(); // Update the screen @@ -205,4 +209,46 @@ bool ZVision::canRender() { return _rendDelay <= 0; } +void ZVision::updateRotation() { + if (_velocity) { + RenderTable::RenderState renderState = _renderManager->getRenderTable()->getRenderState(); + if (renderState == RenderTable::PANORAMA) { + int16 st_pos = _scriptManager->getStateValue(StateKey_ViewPos); + + int16 new_pos = st_pos + _velocity * (1 - 2 * 0); + + int16 zero_point = 0; + if (st_pos >= zero_point && new_pos < zero_point) + _scriptManager->setStateValue(StateKey_Rounds, _scriptManager->getStateValue(StateKey_Rounds) - 1); + if (st_pos <= zero_point && new_pos > zero_point) + _scriptManager->setStateValue(StateKey_Rounds, _scriptManager->getStateValue(StateKey_Rounds) + 1); + + int16 scr_width = _renderManager->getBkgSize().x; + if (scr_width) + new_pos %= scr_width; + + if (new_pos < 0) + new_pos += scr_width; + + _scriptManager->setStateValue(StateKey_ViewPos, new_pos); + _renderManager->setBackgroundPosition(new_pos); + } else if (renderState == RenderTable::TILT) { + int16 st_pos = _scriptManager->getStateValue(StateKey_ViewPos); + + int16 new_pos = st_pos + _velocity * (1 - 2 * 0); + + int16 scr_height = _renderManager->getBkgSize().y; + int16 tilt_gap = _workingWindow.height() / 2; + + if (new_pos >= (scr_height - tilt_gap)) + new_pos = scr_height - tilt_gap; + if (new_pos <= tilt_gap) + new_pos = tilt_gap; + + _scriptManager->setStateValue(StateKey_ViewPos, new_pos); + _renderManager->setBackgroundPosition(new_pos); + } + } +} + } // End of namespace ZVision diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index 05c5fcd3a4..974384c7ff 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -111,6 +111,7 @@ private: const Common::Rect _workingWindow_ZNM; int _rendDelay; + int16 _velocity; public: uint32 getFeatures() const; Common::Language getLanguage() const; @@ -170,6 +171,7 @@ private: void onMouseDown(const Common::Point &pos); void onMouseUp(const Common::Point &pos); void onMouseMove(const Common::Point &pos); + void updateRotation(); }; } // End of namespace ZVision |