diff options
9 files changed, 107 insertions, 82 deletions
diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h index 42fd593f61..a53748e9aa 100644 --- a/engines/wintermute/base/gfx/base_surface.h +++ b/engines/wintermute/base/gfx/base_surface.h @@ -56,7 +56,7 @@ public: virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; virtual bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) = 0; virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) = 0; + virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) = 0; virtual bool restore(); virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0; virtual bool create(int width, int height); diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp index 37f577d202..b8e35d9724 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -55,7 +55,6 @@ BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) { _lastFrameIter = _renderQueue.end(); _needsFlip = true; _skipThisFrame = false; - _previousTicket = nullptr; _borderLeft = _borderRight = _borderTop = _borderBottom = 0; _ratioX = _ratioY = 1.0f; @@ -265,7 +264,6 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S ticket->_transform._rgbaMod = _colorMod; ticket->_wantsDraw = true; _renderQueue.push_back(ticket); - _previousTicket = ticket; drawFromSurface(ticket); return; } @@ -296,7 +294,6 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S drawFromSurface(compareTicket); } else { drawFromQueuedTicket(it); - _previousTicket = compareTicket; } return; } @@ -305,57 +302,13 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform); if (!_disableDirtyRects) { drawFromTicket(ticket); - _previousTicket = ticket; } else { ticket->_wantsDraw = true; _renderQueue.push_back(ticket); - _previousTicket = ticket; drawFromSurface(ticket); } } -void BaseRenderOSystem::repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY) { - if (_previousTicket && _lastAddedTicket != _renderQueue.end()) { - RenderTicket *origTicket = _previousTicket; - - // Make sure drawSurface WILL start from the correct _lastAddedTicket - if (!_disableDirtyRects && *_lastAddedTicket != origTicket) { - RenderQueueIterator it; - RenderQueueIterator endIterator = _renderQueue.end(); - for (it = _renderQueue.begin(); it != endIterator; ++it) { - if ((*it) == _previousTicket) { - _lastAddedTicket = it; - break; - } - } - } - Common::Rect srcRect(0, 0, 0, 0); - srcRect.setWidth(origTicket->getSrcRect()->width()); - srcRect.setHeight(origTicket->getSrcRect()->height()); - - Common::Rect dstRect = origTicket->_dstRect; - int initLeft = dstRect.left; - int initRight = dstRect.right; - - TransformStruct temp = TransformStruct(kDefaultZoomX, kDefaultZoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, BLEND_NORMAL, kDefaultRgbaMod, false, false, kDefaultOffsetX, kDefaultOffsetY); - - for (int i = 0; i < numTimesY; i++) { - if (i == 0) { - dstRect.translate(offsetX, 0); - } - for (int j = (i == 0 ? 1 : 0); j < numTimesX; j++) { - drawSurface(origTicket->_owner, origTicket->getSurface(), &srcRect, &dstRect, temp); - dstRect.translate(offsetX, 0); - } - dstRect.left = initLeft; - dstRect.right = initRight; - dstRect.translate(0, offsetY); - } - } else { - error("Repeat-draw failed (did you forget to draw something before this?)"); - } -} - void BaseRenderOSystem::invalidateTicket(RenderTicket *renderTicket) { addDirtyRect(renderTicket->_dstRect); renderTicket->_isValid = false; @@ -614,7 +567,6 @@ void BaseRenderOSystem::endSaveLoad() { delete ticket; } _lastAddedTicket = _renderQueue.begin(); - _previousTicket = nullptr; // HACK: After a save the buffer will be drawn before the scripts get to update it, // so just skip this single frame. _skipThisFrame = true; diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h index fd5d33622e..a6634d9acc 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -111,7 +111,6 @@ public: virtual bool endSpriteBatch() override; void endSaveLoad(); void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform); - void repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY); BaseSurface *createSurface() override; private: /** @@ -130,7 +129,6 @@ private: Common::Rect *_dirtyRect; Common::List<RenderTicket *> _renderQueue; RenderQueueIterator _lastAddedTicket; - RenderTicket *_previousTicket; bool _needsFlip; uint32 _drawNum; ///< The global number of the current draw-operation. diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index e04af45dd9..67d8f3f425 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -381,6 +381,14 @@ bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newR } ////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) { + assert(numTimesX > 0 && numTimesY > 0); + TransformStruct transform(numTimesX, numTimesY); + return drawSprite(x, y, &rect, nullptr, transform); +} + + +////////////////////////////////////////////////////////////////////////// bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transform) { BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); @@ -424,8 +432,8 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, position.setWidth(newRect->width()); position.setHeight(newRect->height()); } else { - position.setWidth((int16)((float)srcRect.width() * transform._zoom.x / kDefaultZoomX)); - position.setHeight((int16)((float)srcRect.height() * transform._zoom.y / kDefaultZoomY)); + position.setWidth((int16)((float)srcRect.width() * transform._zoom.x / kDefaultZoomX) * transform._numTimesX); + position.setHeight((int16)((float)srcRect.height() * transform._zoom.y / kDefaultZoomY) * transform._numTimesY); } renderer->modTargetRect(&position); @@ -441,12 +449,6 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, return STATUS_OK; } -bool BaseSurfaceOSystem::repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) { - BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); - renderer->repeatLastDraw(offsetX, offsetY, numTimesX, numTimesY); - return STATUS_OK; -} - bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) { _loaded = true; _surface->free(); diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h index 340a5a5ffc..67f45f66db 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -58,7 +58,7 @@ public: bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = kDefaultRgbaMod, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) override; - bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) override; + virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY); virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) override; /* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle); static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin); diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp index 006dd77e18..11a4921f97 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -50,13 +50,19 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel); } // Then scale it if necessary + // + // NB: The numTimesX/numTimesY properties don't yet mix well with + // scaling and rotation, but there is no need for that functionality at + // the moment. if (_transform._angle != kDefaultAngle) { TransparentSurface src(*_surface, false); Graphics::Surface *temp = src.rotoscale(transform); _surface->free(); delete _surface; _surface = temp; - } else if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) { + } else if ((dstRect->width() != srcRect->width() || + dstRect->height() != srcRect->height()) && + _transform._numTimesX * _transform._numTimesY == 1) { TransparentSurface src(*_surface, false); Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); _surface->free(); @@ -109,7 +115,19 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { src._alphaMode = _owner->getAlphaType(); } } - src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); + + int y = _dstRect.top; + int w = _dstRect.width() / _transform._numTimesX; + int h = _dstRect.height() / _transform._numTimesY; + + for (int ry = 0; ry < _transform._numTimesY; ++ry) { + int x = _dstRect.left; + for (int rx = 0; rx < _transform._numTimesX; ++rx) { + src.blit(*_targetSurface, x, y, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); + x += w; + } + y += h; + } } void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const { @@ -118,8 +136,8 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect if (!clipRect) { doDelete = true; clipRect = new Common::Rect(); - clipRect->setWidth(getSurface()->w); - clipRect->setHeight(getSurface()->h); + clipRect->setWidth(getSurface()->w * _transform._numTimesX); + clipRect->setHeight(getSurface()->h * _transform._numTimesY); } if (_owner) { @@ -129,7 +147,47 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect src._alphaMode = _owner->getAlphaType(); } } - src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height(), _transform._blendMode); + + if (_transform._numTimesX * _transform._numTimesY == 1) { + + src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height(), _transform._blendMode); + + } else { + + // clipRect is a subrect of the full numTimesX*numTimesY rect + Common::Rect subRect; + + int y = 0; + int w = getSurface()->w; + int h = getSurface()->h; + assert(w == _dstRect.width() / _transform._numTimesX); + assert(h == _dstRect.height() / _transform._numTimesY); + + int basex = dstRect->left - clipRect->left; + int basey = dstRect->top - clipRect->top; + + for (int ry = 0; ry < _transform._numTimesY; ++ry) { + int x = 0; + for (int rx = 0; rx < _transform._numTimesX; ++rx) { + + subRect.left = x; + subRect.top = y; + subRect.setWidth(w); + subRect.setHeight(w); + + if (subRect.intersects(*clipRect)) { + subRect.clip(*clipRect); + subRect.translate(-x, -y); + src.blit(*_targetSurface, basex + x + subRect.left, basey + y + subRect.top, _transform._flip, &subRect, _transform._rgbaMod, subRect.width(), subRect.height(), _transform._blendMode); + + } + + x += w; + } + y += h; + } + } + if (doDelete) { delete clipRect; } diff --git a/engines/wintermute/graphics/transform_struct.cpp b/engines/wintermute/graphics/transform_struct.cpp index 643c6b413f..822c06f42f 100644 --- a/engines/wintermute/graphics/transform_struct.cpp +++ b/engines/wintermute/graphics/transform_struct.cpp @@ -35,6 +35,8 @@ void TransformStruct::init(Point32 zoom, uint32 angle, Point32 hotspot, bool alp _flip += TransparentSurface::FLIP_H * mirrorX; _flip += TransparentSurface::FLIP_V * mirrorY; _offset = offset; + _numTimesX = 1; + _numTimesY = 1; } TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { @@ -83,6 +85,19 @@ TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 h Point32(kDefaultOffsetX, kDefaultOffsetY)); } +TransformStruct::TransformStruct(int32 numTimesX, int32 numTimesY) { + init(Point32(kDefaultZoomX, kDefaultZoomY), + kDefaultAngle, + Point32(kDefaultHotspotX, kDefaultHotspotY), + false, + BLEND_NORMAL, + kDefaultRgbaMod, + false, false, + Point32(kDefaultOffsetX, kDefaultOffsetY)); + _numTimesX = numTimesX; + _numTimesY = numTimesY; +} + TransformStruct::TransformStruct() { init(Point32(kDefaultZoomX, kDefaultZoomY), kDefaultAngle, diff --git a/engines/wintermute/graphics/transform_struct.h b/engines/wintermute/graphics/transform_struct.h index 90a4c1f846..d5a03ea331 100644 --- a/engines/wintermute/graphics/transform_struct.h +++ b/engines/wintermute/graphics/transform_struct.h @@ -51,6 +51,7 @@ public: TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false); TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX = 0, int32 hotspotY = 0); + TransformStruct(int32 numTimesX, int32 numTimesY); TransformStruct(); Point32 _zoom; ///< Zoom; 100 = no zoom @@ -61,6 +62,8 @@ public: TSpriteBlendMode _blendMode; uint32 _rgbaMod; ///< RGBa Point32 _offset; + int32 _numTimesX; + int32 _numTimesY; bool getMirrorX() const; bool getMirrorY() const; @@ -72,7 +75,9 @@ public: compare._offset == _offset && compare._alphaDisable == _alphaDisable && compare._rgbaMod == _rgbaMod && - compare._blendMode == _blendMode + compare._blendMode == _blendMode && + compare._numTimesX == _numTimesX && + compare._numTimesY == _numTimesY ); } diff --git a/engines/wintermute/ui/ui_tiled_image.cpp b/engines/wintermute/ui/ui_tiled_image.cpp index de4b86a6dd..7c28c139f4 100644 --- a/engines/wintermute/ui/ui_tiled_image.cpp +++ b/engines/wintermute/ui/ui_tiled_image.cpp @@ -75,8 +75,6 @@ bool UITiledImage::display(int x, int y, int width, int height) { int nuColumns = (width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth; int nuRows = (height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight; - int col, row; - _gameRef->_renderer->startSpriteBatch(); // top left/right @@ -88,27 +86,24 @@ bool UITiledImage::display(int x, int y, int width, int height) { _image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + nuColumns * tileWidth, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downRight); // left/right - int yyy = y + (_upMiddle.bottom - _upMiddle.top); - for (row = 0; row < nuRows; row++) { - _image->_surface->displayTrans(x, yyy, _middleLeft); - _image->_surface->displayTrans(x + (_middleLeft.right - _middleLeft.left) + nuColumns * tileWidth, yyy, _middleRight); - yyy += tileWidth; + if (nuRows > 0) { + int yyy = y + (_upMiddle.bottom - _upMiddle.top); + _image->_surface->displayTiled(x, yyy, _middleLeft, 1, nuRows); + _image->_surface->displayTiled(x + (_middleLeft.right - _middleLeft.left) + nuColumns * tileWidth, yyy, _middleRight, 1, nuRows); } // top/bottom - int xxx = x + (_upLeft.right - _upLeft.left); - for (col = 0; col < nuColumns; col++) { - _image->_surface->displayTrans(xxx, y, _upMiddle); - _image->_surface->displayTrans(xxx, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downMiddle); - xxx += tileWidth; + if (nuColumns > 0) { + int xxx = x + (_upLeft.right - _upLeft.left); + _image->_surface->displayTiled(xxx, y, _upMiddle, nuColumns, 1); + _image->_surface->displayTiled(xxx, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downMiddle, nuColumns, 1); } // tiles if (nuRows > 0 && nuColumns > 0) { - yyy = y + (_upMiddle.bottom - _upMiddle.top); - xxx = x + (_upLeft.right - _upLeft.left); - _image->_surface->displayTrans(xxx, yyy, _middleMiddle); - _image->_surface->repeatLastDisplayOp(tileWidth, tileWidth, nuColumns, nuRows); + int yyy = y + (_upMiddle.bottom - _upMiddle.top); + int xxx = x + (_upLeft.right - _upLeft.left); + _image->_surface->displayTiled(xxx, yyy, _middleMiddle, nuColumns, nuRows); } _gameRef->_renderer->endSpriteBatch(); |