From 4cd5548352757535afe76e1d753bb5715f3c68d7 Mon Sep 17 00:00:00 2001 From: Michael Bernardi Date: Mon, 16 Sep 2024 03:42:54 +1000 Subject: [PATCH] Refactor DPI to distinguish screen and world coords --- src/openrct2-ui/UiContext.cpp | 8 +- .../engines/opengl/OpenGLDrawingEngine.cpp | 80 +++++++------ .../engines/opengl/OpenGLFramebuffer.cpp | 4 +- .../drawing/engines/opengl/TextureCache.cpp | 20 ++-- src/openrct2-ui/interface/Widget.cpp | 24 ++-- src/openrct2-ui/interface/Window.cpp | 10 +- src/openrct2-ui/scripting/CustomImages.cpp | 4 +- src/openrct2-ui/scripting/CustomListView.cpp | 16 +-- .../scripting/ScGraphicsContext.hpp | 4 +- src/openrct2-ui/windows/AssetPacks.cpp | 8 +- src/openrct2-ui/windows/Changelog.cpp | 2 +- .../windows/EditorInventionsList.cpp | 2 +- .../windows/EditorObjectSelection.cpp | 3 +- .../windows/EditorObjectiveOptions.cpp | 8 +- src/openrct2-ui/windows/Guest.cpp | 6 +- src/openrct2-ui/windows/GuestList.cpp | 12 +- src/openrct2-ui/windows/LoadSave.cpp | 8 +- src/openrct2-ui/windows/Main.cpp | 5 +- src/openrct2-ui/windows/Multiplayer.cpp | 12 +- src/openrct2-ui/windows/News.cpp | 4 +- src/openrct2-ui/windows/ObjectLoadError.cpp | 8 +- src/openrct2-ui/windows/Ride.cpp | 37 +++--- src/openrct2-ui/windows/RideConstruction.cpp | 4 +- src/openrct2-ui/windows/RideList.cpp | 4 +- src/openrct2-ui/windows/ScenarioSelect.cpp | 2 +- src/openrct2-ui/windows/ServerList.cpp | 2 +- src/openrct2-ui/windows/ShortcutKeys.cpp | 8 +- src/openrct2-ui/windows/StaffList.cpp | 8 +- src/openrct2-ui/windows/Themes.cpp | 4 +- src/openrct2-ui/windows/TileInspector.cpp | 4 +- src/openrct2-ui/windows/TrackList.cpp | 3 +- src/openrct2/CommandLineSprite.cpp | 16 +-- src/openrct2/drawing/Drawing.Sprite.BMP.cpp | 4 +- src/openrct2/drawing/Drawing.Sprite.RLE.cpp | 4 +- src/openrct2/drawing/Drawing.Sprite.cpp | 38 +++--- src/openrct2/drawing/Drawing.String.cpp | 4 +- src/openrct2/drawing/Drawing.cpp | 50 ++++---- src/openrct2/drawing/Drawing.h | 68 +++++++++-- src/openrct2/drawing/LightFX.cpp | 36 +++--- src/openrct2/drawing/Line.cpp | 15 +-- src/openrct2/drawing/ScrollingText.cpp | 4 +- src/openrct2/drawing/X8DrawingEngine.cpp | 112 +++++++++--------- src/openrct2/interface/Screenshot.cpp | 20 ++-- src/openrct2/interface/Viewport.cpp | 71 ++++++----- src/openrct2/interface/Window.cpp | 31 ++--- src/openrct2/interface/ZoomLevel.h | 4 +- src/openrct2/paint/Paint.Entity.cpp | 7 +- src/openrct2/paint/Paint.cpp | 12 +- .../paint/tile_element/Paint.TileElement.cpp | 10 +- src/openrct2/ride/CarEntry.cpp | 17 ++- src/openrct2/ride/TrackDesign.cpp | 10 +- 51 files changed, 471 insertions(+), 386 deletions(-) diff --git a/src/openrct2-ui/UiContext.cpp b/src/openrct2-ui/UiContext.cpp index 885463cc1f..99ba70d155 100644 --- a/src/openrct2-ui/UiContext.cpp +++ b/src/openrct2-ui/UiContext.cpp @@ -299,10 +299,10 @@ public: void DrawWeatherAnimation(IWeatherDrawer* weatherDrawer, DrawPixelInfo& dpi, DrawWeatherFunc drawFunc) override { - int32_t left = dpi.x; - int32_t right = left + dpi.width; - int32_t top = dpi.y; - int32_t bottom = top + dpi.height; + int32_t left = dpi.ScreenX(); + int32_t right = left + dpi.ScreenWidth(); + int32_t top = dpi.ScreenY(); + int32_t bottom = top + dpi.ScreenHeight(); for (auto& w : g_window_list) { diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index 82784655ed..a9566ec51f 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -151,7 +151,7 @@ public: uint8_t patternStartXOffset = xStart % patternXSpace; uint8_t patternStartYOffset = yStart % patternYSpace; - uint32_t pixelOffset = (dpi.pitch + dpi.width) * y + x; + uint32_t pixelOffset = dpi.LineStride() * y + x; uint8_t patternYPos = patternStartYOffset % patternYSpace; for (; height != 0; height--) @@ -167,14 +167,14 @@ public: auto patternPixel = pattern[patternYPos * 2 + 1]; for (; xPixelOffset < finalPixelOffset; xPixelOffset += patternXSpace) { - int32_t pixelX = xPixelOffset % dpi.width; - int32_t pixelY = (xPixelOffset / dpi.width) % dpi.height; + int32_t pixelX = xPixelOffset % dpi.ScreenWidth(); + int32_t pixelY = (xPixelOffset / dpi.ScreenWidth()) % dpi.ScreenHeight(); _drawingContext->DrawLine(dpi, patternPixel, { { pixelX, pixelY }, { pixelX + 1, pixelY + 1 } }); } } - pixelOffset += dpi.pitch + dpi.width; + pixelOffset += dpi.LineStride(); patternYPos++; patternYPos %= patternYSpace; } @@ -442,10 +442,10 @@ private: DrawPixelInfo* dpi = &_bitsDPI; dpi->bits = _bits.get(); - dpi->x = 0; - dpi->y = 0; - dpi->width = width; - dpi->height = height; + dpi->SetX(0); + dpi->SetY(0); + dpi->SetWidth(width); + dpi->SetHeight(height); dpi->pitch = _pitch - width; } @@ -607,8 +607,9 @@ uint8_t OpenGLDrawingContext::ComputeOutCode( // based on: https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm bool OpenGLDrawingContext::CohenSutherlandLineClip(ScreenLine& line, const DrawPixelInfo& dpi) { - ScreenCoordsXY topLeft = { dpi.x, dpi.y }; - ScreenCoordsXY bottomRight = { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 }; + // TODO (mber) make this work entirely with screen coords. + ScreenCoordsXY topLeft = { dpi.WorldX(), dpi.WorldY() }; + ScreenCoordsXY bottomRight = { dpi.WorldX() + dpi.WorldWidth() - 1, dpi.WorldY() + dpi.WorldHeight() - 1 }; uint8_t outcode1 = ComputeOutCode(line.Point1, topLeft, bottomRight); uint8_t outcode2 = ComputeOutCode(line.Point2, topLeft, bottomRight); @@ -671,6 +672,7 @@ bool OpenGLDrawingContext::CohenSutherlandLineClip(ScreenLine& line, const DrawP void OpenGLDrawingContext::DrawLine(DrawPixelInfo& dpi, uint32_t colour, const ScreenLine& line) { + // TODO (mber) make this work entirely with screen coords. ScreenLine trimmedLine = line; if (!CohenSutherlandLineClip(trimmedLine, dpi)) return; @@ -679,10 +681,10 @@ void OpenGLDrawingContext::DrawLine(DrawPixelInfo& dpi, uint32_t colour, const S DrawLineCommand& command = _commandBuffers.lines.allocate(); - const int32_t x1 = dpi.zoom_level.ApplyInversedTo(trimmedLine.GetX1() - dpi.x) + _clipLeft; - const int32_t y1 = dpi.zoom_level.ApplyInversedTo(trimmedLine.GetY1() - dpi.y) + _clipTop; - const int32_t x2 = dpi.zoom_level.ApplyInversedTo(trimmedLine.GetX2() - dpi.x) + _clipLeft; - const int32_t y2 = dpi.zoom_level.ApplyInversedTo(trimmedLine.GetY2() - dpi.y) + _clipTop; + const int32_t x1 = dpi.zoom_level.ApplyInversedTo(trimmedLine.GetX1() - dpi.WorldX()) + _clipLeft; + const int32_t y1 = dpi.zoom_level.ApplyInversedTo(trimmedLine.GetY1() - dpi.WorldY()) + _clipTop; + const int32_t x2 = dpi.zoom_level.ApplyInversedTo(trimmedLine.GetX2() - dpi.WorldX()) + _clipLeft; + const int32_t y2 = dpi.zoom_level.ApplyInversedTo(trimmedLine.GetY2() - dpi.WorldY()) + _clipTop; command.bounds = { x1, y1, x2, y2 }; command.colour = colour & 0xFF; @@ -705,10 +707,10 @@ void OpenGLDrawingContext::DrawSprite(DrawPixelInfo& dpi, const ImageId imageId, { DrawPixelInfo zoomedDPI; zoomedDPI.bits = dpi.bits; - zoomedDPI.x = dpi.x >> 1; - zoomedDPI.y = dpi.y >> 1; - zoomedDPI.height = dpi.height >> 1; - zoomedDPI.width = dpi.width >> 1; + zoomedDPI.SetX(dpi.zoom_level.ApplyInversedTo(dpi.WorldX()) / 2); + zoomedDPI.SetY(dpi.zoom_level.ApplyInversedTo(dpi.WorldY()) / 2); + zoomedDPI.SetHeight(dpi.zoom_level.ApplyInversedTo(dpi.WorldHeight()) / 2); + zoomedDPI.SetWidth(dpi.zoom_level.ApplyInversedTo(dpi.WorldWidth()) / 2); zoomedDPI.pitch = dpi.pitch; zoomedDPI.zoom_level = dpi.zoom_level - 1; DrawSprite(zoomedDPI, imageId.WithIndex(imageId.GetIndex() - g1Element->zoomed_offset), x >> 1, y >> 1); @@ -758,10 +760,10 @@ void OpenGLDrawingContext::DrawSprite(DrawPixelInfo& dpi, const ImageId imageId, std::swap(top, bottom); } - left -= dpi.x; - top -= dpi.y; - right -= dpi.x; - bottom -= dpi.y; + left -= dpi.WorldX(); + top -= dpi.WorldY(); + right -= dpi.WorldX(); + bottom -= dpi.WorldY(); left = dpi.zoom_level.ApplyInversedTo(left); top = dpi.zoom_level.ApplyInversedTo(top); @@ -873,10 +875,10 @@ void OpenGLDrawingContext::DrawSpriteRawMasked( std::swap(top, bottom); } - left -= dpi.x; - top -= dpi.y; - right -= dpi.x; - bottom -= dpi.y; + left -= dpi.WorldX(); + top -= dpi.WorldY(); + right -= dpi.WorldX(); + bottom -= dpi.WorldY(); left = dpi.zoom_level.ApplyInversedTo(left); top = dpi.zoom_level.ApplyInversedTo(top); @@ -978,10 +980,10 @@ void OpenGLDrawingContext::DrawGlyph(DrawPixelInfo& dpi, const ImageId image, in std::swap(top, bottom); } - left -= dpi.x; - top -= dpi.y; - right -= dpi.x; - bottom -= dpi.y; + left -= dpi.WorldX(); + top -= dpi.WorldY(); + right -= dpi.WorldX(); + bottom -= dpi.WorldY(); left = dpi.zoom_level.ApplyInversedTo(left); top = dpi.zoom_level.ApplyInversedTo(top); @@ -1182,18 +1184,18 @@ void OpenGLDrawingContext::CalculcateClipping(DrawPixelInfo& dpi) auto bytesPerRow = screenDPI->GetBytesPerRow(); auto bitsOffset = static_cast(dpi.bits - screenDPI->bits); # ifndef NDEBUG - auto bitsSize = static_cast(screenDPI->height) * bytesPerRow; + auto bitsSize = static_cast(screenDPI->ScreenHeight()) * bytesPerRow; assert(bitsOffset < bitsSize); # endif - _clipLeft = static_cast(bitsOffset % bytesPerRow) + dpi.remX; - _clipTop = static_cast(bitsOffset / bytesPerRow) + dpi.remY; - _clipRight = _clipLeft + dpi.zoom_level.ApplyInversedTo(dpi.width); - _clipBottom = _clipTop + dpi.zoom_level.ApplyInversedTo(dpi.height); - _offsetX = _clipLeft - dpi.x; - _offsetY = _clipTop - dpi.y; - _spriteOffset.x = _clipLeft - dpi.remX; - _spriteOffset.y = _clipTop - dpi.remY; + _clipLeft = static_cast(bitsOffset % bytesPerRow); + _clipTop = static_cast(bitsOffset / bytesPerRow); + _clipRight = _clipLeft + dpi.zoom_level.ApplyInversedTo(dpi.WorldWidth()); + _clipBottom = _clipTop + dpi.zoom_level.ApplyInversedTo(dpi.WorldHeight()); + _offsetX = _clipLeft - dpi.WorldX(); + _offsetY = _clipTop - dpi.WorldY(); + _spriteOffset.x = _clipLeft; + _spriteOffset.y = _clipTop; } #endif /* DISABLE_OPENGL */ diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLFramebuffer.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLFramebuffer.cpp index f9b458df35..f38980156a 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLFramebuffer.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLFramebuffer.cpp @@ -91,7 +91,7 @@ void OpenGLFramebuffer::BindRead() const void OpenGLFramebuffer::GetPixels(DrawPixelInfo& dpi) const { - assert(dpi.width == _width && dpi.height == _height); + assert(dpi.ScreenWidth() == _width && dpi.ScreenHeight() == _height); auto pixels = std::make_unique(_width * _height); glBindTexture(GL_TEXTURE_2D, _texture); @@ -105,7 +105,7 @@ void OpenGLFramebuffer::GetPixels(DrawPixelInfo& dpi) const { std::copy_n(src, _width, dst); src -= _width; - dst += dpi.width + dpi.pitch; + dst += dpi.LineStride(); } } diff --git a/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp b/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp index 414e39b3b3..dab486f0a9 100644 --- a/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp @@ -289,13 +289,13 @@ AtlasTextureInfo TextureCache::LoadImageTexture(const ImageId imageId) { DrawPixelInfo dpi = GetImageAsDPI(ImageId(imageId.GetIndex())); - auto cacheInfo = AllocateImage(dpi.width, dpi.height); + auto cacheInfo = AllocateImage(dpi.ScreenWidth(), dpi.ScreenHeight()); cacheInfo.image = imageId.GetIndex(); glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture); glTexSubImage3D( - GL_TEXTURE_2D_ARRAY, 0, cacheInfo.bounds.x, cacheInfo.bounds.y, cacheInfo.index, dpi.width, dpi.height, 1, - GL_RED_INTEGER, GL_UNSIGNED_BYTE, dpi.bits); + GL_TEXTURE_2D_ARRAY, 0, cacheInfo.bounds.x, cacheInfo.bounds.y, cacheInfo.index, dpi.ScreenWidth(), dpi.ScreenHeight(), + 1, GL_RED_INTEGER, GL_UNSIGNED_BYTE, dpi.bits); DeleteDPI(dpi); @@ -306,13 +306,13 @@ AtlasTextureInfo TextureCache::LoadGlyphTexture(const ImageId imageId, const Pal { DrawPixelInfo dpi = GetGlyphAsDPI(imageId, paletteMap); - auto cacheInfo = AllocateImage(dpi.width, dpi.height); + auto cacheInfo = AllocateImage(dpi.ScreenWidth(), dpi.ScreenHeight()); cacheInfo.image = imageId.GetIndex(); glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture); glTexSubImage3D( - GL_TEXTURE_2D_ARRAY, 0, cacheInfo.bounds.x, cacheInfo.bounds.y, cacheInfo.index, dpi.width, dpi.height, 1, - GL_RED_INTEGER, GL_UNSIGNED_BYTE, dpi.bits); + GL_TEXTURE_2D_ARRAY, 0, cacheInfo.bounds.x, cacheInfo.bounds.y, cacheInfo.index, dpi.ScreenWidth(), dpi.ScreenHeight(), + 1, GL_RED_INTEGER, GL_UNSIGNED_BYTE, dpi.bits); DeleteDPI(dpi); @@ -407,10 +407,10 @@ DrawPixelInfo TextureCache::CreateDPI(int32_t width, int32_t height) DrawPixelInfo dpi; dpi.bits = pixels8; dpi.pitch = 0; - dpi.x = 0; - dpi.y = 0; - dpi.width = width; - dpi.height = height; + dpi.SetX(0); + dpi.SetY(0); + dpi.SetWidth(width); + dpi.SetHeight(height); dpi.zoom_level = ZoomLevel{ 0 }; return dpi; } diff --git a/src/openrct2-ui/interface/Widget.cpp b/src/openrct2-ui/interface/Widget.cpp index 44ea545127..f75878fae9 100644 --- a/src/openrct2-ui/interface/Widget.cpp +++ b/src/openrct2-ui/interface/Widget.cpp @@ -715,22 +715,22 @@ namespace OpenRCT2::Ui DrawPixelInfo scroll_dpi = dpi; // Clip the scroll dpi against the outer dpi - int32_t cl = std::max(dpi.x, topLeft.x); - int32_t ct = std::max(dpi.y, topLeft.y); - int32_t cr = std::min(dpi.x + dpi.width, bottomRight.x); - int32_t cb = std::min(dpi.y + dpi.height, bottomRight.y); + int32_t cl = std::max(dpi.ScreenX(), topLeft.x); + int32_t ct = std::max(dpi.ScreenY(), topLeft.y); + int32_t cr = std::min(dpi.ScreenX() + dpi.ScreenWidth(), bottomRight.x); + int32_t cb = std::min(dpi.ScreenY() + dpi.ScreenHeight(), bottomRight.y); // Set the respective dpi attributes - scroll_dpi.x = cl - topLeft.x + scroll.contentOffsetX; - scroll_dpi.y = ct - topLeft.y + scroll.contentOffsetY; - scroll_dpi.width = cr - cl; - scroll_dpi.height = cb - ct; - scroll_dpi.bits += cl - dpi.x; - scroll_dpi.bits += (ct - dpi.y) * (dpi.width + dpi.pitch); - scroll_dpi.pitch = (dpi.width + dpi.pitch) - scroll_dpi.width; + scroll_dpi.SetX(cl - topLeft.x + scroll.contentOffsetX); + scroll_dpi.SetY(ct - topLeft.y + scroll.contentOffsetY); + scroll_dpi.SetWidth(cr - cl); + scroll_dpi.SetHeight(cb - ct); + scroll_dpi.bits += cl - dpi.ScreenX(); + scroll_dpi.bits += (ct - dpi.ScreenY()) * dpi.LineStride(); + scroll_dpi.pitch = dpi.LineStride() - scroll_dpi.ScreenWidth(); // Draw the scroll contents - if (scroll_dpi.width > 0 && scroll_dpi.height > 0) + if (scroll_dpi.ScreenWidth() > 0 && scroll_dpi.ScreenHeight() > 0) w.OnScrollDraw(scrollIndex, scroll_dpi); } diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index 2103a71dce..9d7d6df784 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -1299,7 +1299,9 @@ namespace OpenRCT2::Ui::Windows */ void WindowDrawViewport(DrawPixelInfo& dpi, WindowBase& w) { - ViewportRender(dpi, w.viewport, { { dpi.x, dpi.y }, { dpi.x + dpi.width, dpi.y + dpi.height } }); + ViewportRender( + dpi, w.viewport, + { { dpi.ScreenX(), dpi.ScreenY() }, { dpi.ScreenX() + dpi.ScreenWidth(), dpi.ScreenY() + dpi.ScreenHeight() } }); } /** @@ -1323,9 +1325,11 @@ namespace OpenRCT2::Ui::Windows if (widget->IsVisible()) { // Check if widget is outside the draw region - if (w.windowPos.x + widget->left < dpi.x + dpi.width && w.windowPos.x + widget->right >= dpi.x) + if (w.windowPos.x + widget->left < dpi.ScreenX() + dpi.ScreenWidth() + && w.windowPos.x + widget->right >= dpi.ScreenX()) { - if (w.windowPos.y + widget->top < dpi.y + dpi.height && w.windowPos.y + widget->bottom >= dpi.y) + if (w.windowPos.y + widget->top < dpi.ScreenY() + dpi.ScreenHeight() + && w.windowPos.y + widget->bottom >= dpi.ScreenY()) { w.OnDrawWidget(widgetIndex, dpi); } diff --git a/src/openrct2-ui/scripting/CustomImages.cpp b/src/openrct2-ui/scripting/CustomImages.cpp index 93d2854890..ca77885928 100644 --- a/src/openrct2-ui/scripting/CustomImages.cpp +++ b/src/openrct2-ui/scripting/CustomImages.cpp @@ -434,8 +434,8 @@ namespace OpenRCT2::Scripting auto drawingEngine = std::make_unique(GetContext()->GetUiContext()); DrawPixelInfo dpi; dpi.DrawingEngine = drawingEngine.get(); - dpi.width = size.width; - dpi.height = size.height; + dpi.SetWidth(size.width); + dpi.SetHeight(size.height); auto createNewImage = false; auto g1 = GfxGetG1Element(id); diff --git a/src/openrct2-ui/scripting/CustomListView.cpp b/src/openrct2-ui/scripting/CustomListView.cpp index e9486c434c..e911ac87ee 100644 --- a/src/openrct2-ui/scripting/CustomListView.cpp +++ b/src/openrct2-ui/scripting/CustomListView.cpp @@ -552,18 +552,20 @@ void CustomListView::MouseUp(const ScreenCoordsXY& pos) void CustomListView::Paint(WindowBase* w, DrawPixelInfo& dpi, const ScrollArea* scroll) const { auto paletteIndex = ColourMapA[w->colours[1].colour].mid_light; - GfxFillRect(dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width, dpi.y + dpi.height } }, paletteIndex); + GfxFillRect( + dpi, { { dpi.ScreenX(), dpi.ScreenY() }, { dpi.ScreenX() + dpi.ScreenWidth(), dpi.ScreenY() + dpi.ScreenHeight() } }, + paletteIndex); int32_t y = ShowColumnHeaders ? COLUMN_HEADER_HEIGHT : 0; for (size_t i = 0; i < Items.size(); i++) { - if (y > dpi.y + dpi.height) + if (y > dpi.ScreenY() + dpi.ScreenHeight()) { // Past the scroll view area break; } - if (y + kListRowHeight >= dpi.y) + if (y + kListRowHeight >= dpi.ScreenY()) { const auto& itemIndex = static_cast(SortedItems[i]); const auto& item = Items[itemIndex]; @@ -583,19 +585,19 @@ void CustomListView::Paint(WindowBase* w, DrawPixelInfo& dpi, const ScrollArea* if (isSelected) { GfxFilterRect( - dpi, { { dpi.x, y }, { dpi.x + dpi.width, y + (kListRowHeight - 1) } }, + dpi, { { dpi.ScreenX(), y }, { dpi.ScreenX() + dpi.ScreenWidth(), y + (kListRowHeight - 1) } }, FilterPaletteID::PaletteDarken2); } else if (isHighlighted) { GfxFilterRect( - dpi, { { dpi.x, y }, { dpi.x + dpi.width, y + (kListRowHeight - 1) } }, + dpi, { { dpi.ScreenX(), y }, { dpi.ScreenX() + dpi.ScreenWidth(), y + (kListRowHeight - 1) } }, FilterPaletteID::PaletteDarken2); } else if (isStriped) { GfxFillRect( - dpi, { { dpi.x, y }, { dpi.x + dpi.width, y + (kListRowHeight - 1) } }, + dpi, { { dpi.ScreenX(), y }, { dpi.ScreenX() + dpi.ScreenWidth(), y + (kListRowHeight - 1) } }, ColourMapA[w->colours[1].colour].lighter | 0x1000000); } @@ -641,7 +643,7 @@ void CustomListView::Paint(WindowBase* w, DrawPixelInfo& dpi, const ScrollArea* y = scroll->contentOffsetY; auto bgColour = ColourMapA[w->colours[1].colour].mid_light; - GfxFillRect(dpi, { { dpi.x, y }, { dpi.x + dpi.width, y + 12 } }, bgColour); + GfxFillRect(dpi, { { dpi.ScreenX(), y }, { dpi.ScreenX() + dpi.ScreenWidth(), y + 12 } }, bgColour); int32_t x = 0; for (int32_t j = 0; j < static_cast(Columns.size()); j++) diff --git a/src/openrct2-ui/scripting/ScGraphicsContext.hpp b/src/openrct2-ui/scripting/ScGraphicsContext.hpp index ad1ec00091..f69408e1cf 100644 --- a/src/openrct2-ui/scripting/ScGraphicsContext.hpp +++ b/src/openrct2-ui/scripting/ScGraphicsContext.hpp @@ -141,12 +141,12 @@ namespace OpenRCT2::Scripting int32_t width_get() const { - return _dpi.width; + return _dpi.ScreenWidth(); } int32_t height_get() const { - return _dpi.height; + return _dpi.ScreenHeight(); } DukValue getImage(uint32_t id) diff --git a/src/openrct2-ui/windows/AssetPacks.cpp b/src/openrct2-ui/windows/AssetPacks.cpp index 01029985c8..4b1c6efbe3 100644 --- a/src/openrct2-ui/windows/AssetPacks.cpp +++ b/src/openrct2-ui/windows/AssetPacks.cpp @@ -194,9 +194,9 @@ namespace OpenRCT2::Ui::Windows void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override { - auto dpiCoords = ScreenCoordsXY{ dpi.x, dpi.y }; + auto dpiCoords = ScreenCoordsXY{ dpi.ScreenX(), dpi.ScreenY() }; GfxFillRect( - dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.width - 1, dpi.height - 1 } }, + dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.ScreenWidth() - 1, dpi.ScreenHeight() - 1 } }, ColourMapA[colours[1].colour].mid_light); auto assetPackManager = GetContext()->GetAssetPackManager(); @@ -207,9 +207,9 @@ namespace OpenRCT2::Ui::Windows auto y = 0; for (size_t i = 0; i <= numAssetPacks; i++) { - if (y > dpi.y + dpi.height) + if (y > dpi.ScreenY() + dpi.ScreenHeight()) break; - if (y + 11 < dpi.y) + if (y + 11 < dpi.ScreenY()) continue; auto isSelected = i == _selectedIndex; diff --git a/src/openrct2-ui/windows/Changelog.cpp b/src/openrct2-ui/windows/Changelog.cpp index 8c1e08bcb2..4c647607df 100644 --- a/src/openrct2-ui/windows/Changelog.cpp +++ b/src/openrct2-ui/windows/Changelog.cpp @@ -199,7 +199,7 @@ namespace OpenRCT2::Ui::Windows for (const auto& line : _changelogLines) { screenCoords.y += lineHeight; - if (screenCoords.y + lineHeight < dpi.y || screenCoords.y >= dpi.y + dpi.height) + if (screenCoords.y + lineHeight < dpi.ScreenY() || screenCoords.y >= dpi.ScreenY() + dpi.ScreenHeight()) continue; DrawText(dpi, screenCoords, { colours[0] }, line.c_str()); diff --git a/src/openrct2-ui/windows/EditorInventionsList.cpp b/src/openrct2-ui/windows/EditorInventionsList.cpp index abdd21b50c..989738b165 100644 --- a/src/openrct2-ui/windows/EditorInventionsList.cpp +++ b/src/openrct2-ui/windows/EditorInventionsList.cpp @@ -287,7 +287,7 @@ namespace OpenRCT2::Ui::Windows for (const auto& researchItem : researchList) { itemY += kScrollableRowHeight; - if (itemY + kScrollableRowHeight < dpi.y || itemY >= dpi.y + dpi.height) + if (itemY + kScrollableRowHeight < dpi.ScreenY() || itemY >= dpi.ScreenY() + dpi.ScreenHeight()) continue; if (_selectedResearchItem == &researchItem) diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index 31734e4414..af54a96e8b 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -725,7 +725,8 @@ namespace OpenRCT2::Ui::Windows for (size_t i = 0; i < _listItems.size(); i++) { const auto& listItem = _listItems[i]; - if (screenCoords.y + kScrollableRowHeight >= dpi.y && screenCoords.y <= dpi.y + dpi.height) + if (screenCoords.y + kScrollableRowHeight >= dpi.ScreenY() + && screenCoords.y <= dpi.ScreenY() + dpi.ScreenHeight()) { // Draw checkbox if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && !(*listItem.flags & 0x20)) diff --git a/src/openrct2-ui/windows/EditorObjectiveOptions.cpp b/src/openrct2-ui/windows/EditorObjectiveOptions.cpp index 96e99a21f1..a6aa62f894 100644 --- a/src/openrct2-ui/windows/EditorObjectiveOptions.cpp +++ b/src/openrct2-ui/windows/EditorObjectiveOptions.cpp @@ -1145,13 +1145,17 @@ namespace OpenRCT2::Ui::Windows void OnScrollDrawRides(DrawPixelInfo& dpi, int32_t scrollIndex) { int32_t colour = ColourMapA[colours[1].colour].mid_light; - GfxFillRect(dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, colour); + GfxFillRect( + dpi, + { { dpi.ScreenX(), dpi.ScreenY() }, + { dpi.ScreenX() + dpi.ScreenWidth() - 1, dpi.ScreenY() + dpi.ScreenHeight() - 1 } }, + colour); for (int32_t i = 0; i < static_cast(_rideableRides.size()); i++) { int32_t y = i * 12; - if (y + 12 < dpi.y || y >= dpi.y + dpi.height) + if (y + 12 < dpi.ScreenY() || y >= dpi.ScreenY() + dpi.ScreenHeight()) continue; // Checkbox diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index a3f9bcf874..abee03be76 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -1333,7 +1333,11 @@ namespace OpenRCT2::Ui::Windows void OnScrollDrawRides(int32_t scrollIndex, DrawPixelInfo& dpi) { auto colour = ColourMapA[colours[1].colour].mid_light; - GfxFillRect(dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, colour); + GfxFillRect( + dpi, + { { dpi.ScreenX(), dpi.ScreenY() }, + { dpi.ScreenX() + dpi.ScreenWidth() - 1, dpi.ScreenY() + dpi.ScreenHeight() - 1 } }, + colour); for (int32_t listIndex = 0; listIndex < static_cast(_riddenRides.size()); listIndex++) { diff --git a/src/openrct2-ui/windows/GuestList.cpp b/src/openrct2-ui/windows/GuestList.cpp index 8b46fbf4ce..82b63aeaab 100644 --- a/src/openrct2-ui/windows/GuestList.cpp +++ b/src/openrct2-ui/windows/GuestList.cpp @@ -595,7 +595,9 @@ namespace OpenRCT2::Ui::Windows void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override { GfxFillRect( - dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, + dpi, + { { dpi.ScreenX(), dpi.ScreenY() }, + { dpi.ScreenX() + dpi.ScreenWidth() - 1, dpi.ScreenY() + dpi.ScreenHeight() - 1 } }, ColourMapA[colours[1].colour].mid_light); switch (_selectedTab) { @@ -669,8 +671,8 @@ namespace OpenRCT2::Ui::Windows for (const auto& guestItem : _guestList) { // Check if y is beyond the scroll control - if (y + kScrollableRowHeight + 1 >= -0x7FFF && y + kScrollableRowHeight + 1 > dpi.y && y < 0x7FFF - && y < dpi.y + dpi.height) + if (y + kScrollableRowHeight + 1 >= -0x7FFF && y + kScrollableRowHeight + 1 > dpi.ScreenY() && y < 0x7FFF + && y < dpi.ScreenY() + dpi.ScreenHeight()) { // Highlight backcolour and text colour (format) StringId format = STR_BLACK_STRING; @@ -736,10 +738,10 @@ namespace OpenRCT2::Ui::Windows for (auto& group : _groups) { // Check if y is beyond the scroll control - if (y + SUMMARISED_GUEST_ROW_HEIGHT + 1 >= dpi.y) + if (y + SUMMARISED_GUEST_ROW_HEIGHT + 1 >= dpi.ScreenY()) { // Check if y is beyond the scroll control - if (y >= dpi.y + dpi.height) + if (y >= dpi.ScreenY() + dpi.ScreenHeight()) break; // Highlight backcolour and text colour (format) diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 58b7ec134c..a7cabbc8fb 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -977,7 +977,9 @@ namespace OpenRCT2::Ui::Windows void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override { GfxFillRect( - dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, + dpi, + { { dpi.ScreenX(), dpi.ScreenY() }, + { dpi.ScreenX() + dpi.ScreenWidth() - 1, dpi.ScreenY() + dpi.ScreenHeight() - 1 } }, ColourMapA[colours[1].colour].mid_light); const int32_t listWidth = widgets[WIDX_SCROLL].width(); const int32_t dateAnchor = widgets[WIDX_SORT_DATE].left + maxDateWidth + DATE_TIME_GAP; @@ -985,10 +987,10 @@ namespace OpenRCT2::Ui::Windows for (int32_t i = 0; i < no_list_items; i++) { int32_t y = i * kScrollableRowHeight; - if (y > dpi.y + dpi.height) + if (y > dpi.ScreenY() + dpi.ScreenHeight()) break; - if (y + kScrollableRowHeight < dpi.y) + if (y + kScrollableRowHeight < dpi.ScreenY()) continue; StringId stringId = STR_BLACK_STRING; diff --git a/src/openrct2-ui/windows/Main.cpp b/src/openrct2-ui/windows/Main.cpp index f1fe9d57b3..6cc1df8395 100644 --- a/src/openrct2-ui/windows/Main.cpp +++ b/src/openrct2-ui/windows/Main.cpp @@ -48,7 +48,10 @@ namespace OpenRCT2::Ui::Windows void OnDraw(DrawPixelInfo& dpi) override { - ViewportRender(dpi, viewport, { { dpi.x, dpi.y }, { dpi.x + dpi.width, dpi.y + dpi.height } }); + ViewportRender( + dpi, viewport, + { { dpi.ScreenX(), dpi.ScreenY() }, + { dpi.ScreenX() + dpi.ScreenWidth(), dpi.ScreenY() + dpi.ScreenHeight() } }); } private: diff --git a/src/openrct2-ui/windows/Multiplayer.cpp b/src/openrct2-ui/windows/Multiplayer.cpp index d92b4d6844..0e6afbcb32 100644 --- a/src/openrct2-ui/windows/Multiplayer.cpp +++ b/src/openrct2-ui/windows/Multiplayer.cpp @@ -749,12 +749,12 @@ namespace OpenRCT2::Ui::Windows for (int32_t player = firstPlayerInList; player < NetworkGetNumPlayers(); player++) { - if (screenCoords.y > dpi.y + dpi.height) + if (screenCoords.y > dpi.ScreenY() + dpi.ScreenHeight()) { break; } - if (screenCoords.y + kScrollableRowHeight + 1 >= dpi.y) + if (screenCoords.y + kScrollableRowHeight + 1 >= dpi.ScreenY()) { thread_local std::string _buffer; _buffer.reserve(512); @@ -887,9 +887,9 @@ namespace OpenRCT2::Ui::Windows { auto screenCoords = ScreenCoordsXY{ 0, 0 }; - auto dpiCoords = ScreenCoordsXY{ dpi.x, dpi.y }; + auto dpiCoords = ScreenCoordsXY{ dpi.ScreenX(), dpi.ScreenY() }; GfxFillRect( - dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.width - 1, dpi.height - 1 } }, + dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.ScreenWidth() - 1, dpi.ScreenHeight() - 1 } }, ColourMapA[colours[1].colour].mid_light); for (int32_t i = 0; i < NetworkGetNumActions(); i++) @@ -900,12 +900,12 @@ namespace OpenRCT2::Ui::Windows dpi, { 0, screenCoords.y, 800, screenCoords.y + kScrollableRowHeight - 1 }, FilterPaletteID::PaletteDarken1); } - if (screenCoords.y > dpi.y + dpi.height) + if (screenCoords.y > dpi.ScreenY() + dpi.ScreenHeight()) { break; } - if (screenCoords.y + kScrollableRowHeight + 1 >= dpi.y) + if (screenCoords.y + kScrollableRowHeight + 1 >= dpi.ScreenY()) { int32_t groupindex = NetworkGetGroupIndex(_selectedGroup); if (groupindex != -1) diff --git a/src/openrct2-ui/windows/News.cpp b/src/openrct2-ui/windows/News.cpp index e07083b641..6608965556 100644 --- a/src/openrct2-ui/windows/News.cpp +++ b/src/openrct2-ui/windows/News.cpp @@ -182,9 +182,9 @@ namespace OpenRCT2::Ui::Windows for (const auto& newsItem : GetGameState().NewsItems.GetArchived()) { - if (y >= dpi.y + dpi.height) + if (y >= dpi.ScreenY() + dpi.ScreenHeight()) break; - if (y + itemHeight < dpi.y) + if (y + itemHeight < dpi.ScreenY()) { y += itemHeight; i++; diff --git a/src/openrct2-ui/windows/ObjectLoadError.cpp b/src/openrct2-ui/windows/ObjectLoadError.cpp index 27ccc76fa7..2a2c24bc12 100644 --- a/src/openrct2-ui/windows/ObjectLoadError.cpp +++ b/src/openrct2-ui/windows/ObjectLoadError.cpp @@ -508,9 +508,9 @@ namespace OpenRCT2::Ui::Windows void OnScrollDraw(const int32_t scrollIndex, DrawPixelInfo& dpi) override { - auto dpiCoords = ScreenCoordsXY{ dpi.x, dpi.y }; + auto dpiCoords = ScreenCoordsXY{ dpi.ScreenX(), dpi.ScreenY() }; GfxFillRect( - dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.width - 1, dpi.height - 1 } }, + dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.ScreenWidth() - 1, dpi.ScreenHeight() - 1 } }, ColourMapA[colours[1].colour].mid_light); const int32_t listWidth = widgets[WIDX_SCROLL].width(); @@ -518,10 +518,10 @@ namespace OpenRCT2::Ui::Windows { ScreenCoordsXY screenCoords; screenCoords.y = i * kScrollableRowHeight; - if (screenCoords.y > dpi.y + dpi.height) + if (screenCoords.y > dpi.ScreenY() + dpi.ScreenHeight()) break; - if (screenCoords.y + kScrollableRowHeight < dpi.y) + if (screenCoords.y + kScrollableRowHeight < dpi.ScreenY()) continue; const auto screenRect = ScreenRect{ { 0, screenCoords.y }, diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 3851705d3a..6d3293eb48 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -1283,12 +1283,10 @@ namespace OpenRCT2::Ui::Windows if (rideEntry->flags & RIDE_ENTRY_FLAG_VEHICLE_TAB_SCALE_HALF) { clipDPI.zoom_level = ZoomLevel{ 1 }; - clipDPI.width *= 2; - clipDPI.height *= 2; screenCoords.x *= 2; screenCoords.y *= 2; - clipDPI.x *= 2; - clipDPI.y *= 2; + clipDPI.SetX(clipDPI.ScreenX() * 2); + clipDPI.SetY(clipDPI.ScreenY() * 2); } // For any suspended rides, move image higher in the vehicle tab on the rides window @@ -2978,7 +2976,10 @@ namespace OpenRCT2::Ui::Windows const auto* rideEntry = ride->GetRideEntry(); // Background - GfxFillRect(dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width, dpi.y + dpi.height } }, PALETTE_INDEX_12); + GfxFillRect( + dpi, + { { dpi.ScreenX(), dpi.ScreenY() }, { dpi.ScreenX() + dpi.ScreenWidth(), dpi.ScreenY() + dpi.ScreenHeight() } }, + PALETTE_INDEX_12); Widget* widget = &widgets[WIDX_VEHICLE_TRAINS_PREVIEW]; int32_t startX = std::max(2, (widget->width() - ((ride->NumTrains - 1) * 36)) / 2 - 25); @@ -4972,7 +4973,11 @@ namespace OpenRCT2::Ui::Windows auto vehicleColour = RideGetVehicleColour(*ride, _vehicleIndex); // Background colour - GfxFillRect(dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, PALETTE_INDEX_12); + GfxFillRect( + dpi, + { { dpi.ScreenX(), dpi.ScreenY() }, + { dpi.ScreenX() + dpi.ScreenWidth() - 1, dpi.ScreenY() + dpi.ScreenHeight() - 1 } }, + PALETTE_INDEX_12); // ? auto screenCoords = ScreenCoordsXY{ vehiclePreviewWidget->width() / 2, vehiclePreviewWidget->height() - 15 }; @@ -5328,7 +5333,7 @@ namespace OpenRCT2::Ui::Windows for (size_t i = 0; i < musicObj->GetTrackCount(); i++) { // Skip invisible items - if (y + kScrollableRowHeight < dpi.y || y > dpi.y + dpi.height) + if (y + kScrollableRowHeight < dpi.ScreenY() || y > dpi.ScreenY() + dpi.ScreenHeight()) { y += kScrollableRowHeight; continue; @@ -6133,12 +6138,12 @@ namespace OpenRCT2::Ui::Windows const uint8_t darkColour = ColourMapA[COLOUR_SATURATED_GREEN].mid_dark; int32_t time = 0; - for (int32_t x = 0; x < dpi.x + dpi.width; x += 80) + for (int32_t x = 0; x < dpi.ScreenX() + dpi.ScreenWidth(); x += 80) { - if (x + 80 >= dpi.x) + if (x + 80 >= dpi.ScreenX()) { - auto coord1 = ScreenCoordsXY{ x, dpi.y }; - auto coord2 = ScreenCoordsXY{ x, dpi.y + dpi.height - 1 }; + auto coord1 = ScreenCoordsXY{ x, dpi.ScreenY() }; + auto coord2 = ScreenCoordsXY{ x, dpi.ScreenY() + dpi.ScreenHeight() - 1 }; GfxFillRect(dpi, { coord1, coord2 }, lightColour); GfxFillRect(dpi, { coord1 + ScreenCoordsXY{ 16, 0 }, coord2 + ScreenCoordsXY{ 16, 0 } }, darkColour); GfxFillRect(dpi, { coord1 + ScreenCoordsXY{ 32, 0 }, coord2 + ScreenCoordsXY{ 32, 0 } }, darkColour); @@ -6165,7 +6170,7 @@ namespace OpenRCT2::Ui::Windows { // Minor / major line int32_t colour = yUnit == 0 ? lightColour : darkColour; - GfxFillRect(dpi, { { dpi.x, y }, { dpi.x + dpi.width - 1, y } }, colour); + GfxFillRect(dpi, { { dpi.ScreenX(), y }, { dpi.ScreenX() + dpi.ScreenWidth() - 1, y } }, colour); int16_t scaled_yUnit = yUnit; // Scale modifier @@ -6180,23 +6185,23 @@ namespace OpenRCT2::Ui::Windows // Time marks time = 0; - for (int32_t x = 0; x < dpi.x + dpi.width; x += 80) + for (int32_t x = 0; x < dpi.ScreenX() + dpi.ScreenWidth(); x += 80) { auto ft = Formatter(); ft.Add(time); - if (x + 80 >= dpi.x) + if (x + 80 >= dpi.ScreenX()) DrawTextBasic(dpi, { x + 2, 1 }, STR_RIDE_STATS_TIME, ft, { FontStyle::Small }); time += 5; } // Plot - int32_t x = dpi.x; + int32_t x = dpi.ScreenX(); int32_t firstPoint, secondPoint; // Uses the force limits (used to draw extreme G's in red on measurement tab) to determine if line should be drawn // red. int32_t intensityThresholdPositive = 0; int32_t intensityThresholdNegative = 0; - for (int32_t graphWidth = 0; graphWidth < dpi.width; graphWidth++, x++) + for (int32_t graphWidth = 0; graphWidth < dpi.ScreenWidth(); graphWidth++, x++) { if (x < 0 || x >= measurement->num_items - 1) continue; diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 549fc37e22..ccc420cc0c 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -2616,8 +2616,8 @@ namespace OpenRCT2::Ui::Windows const ScreenCoordsXY rotatedScreenCoords = Translate3DTo2DWithZ(GetCurrentRotation(), mapCoords); - dpi.x += rotatedScreenCoords.x - widgetWidth / 2; - dpi.y += rotatedScreenCoords.y - widgetHeight / 2 - 16; + dpi.SetX(dpi.ScreenX() + rotatedScreenCoords.x - widgetWidth / 2); + dpi.SetY(dpi.ScreenY() + rotatedScreenCoords.y - widgetHeight / 2 - 16); DrawTrackPieceHelper(dpi, rideIndex, trackType, trackDirection, liftHillAndInvertedState, { 4096, 4096 }, 1024); } diff --git a/src/openrct2-ui/windows/RideList.cpp b/src/openrct2-ui/windows/RideList.cpp index 7ebd900152..4a3bdd98c8 100644 --- a/src/openrct2-ui/windows/RideList.cpp +++ b/src/openrct2-ui/windows/RideList.cpp @@ -540,9 +540,9 @@ namespace OpenRCT2::Ui::Windows */ void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override { - auto dpiCoords = ScreenCoordsXY{ dpi.x, dpi.y }; + auto dpiCoords = ScreenCoordsXY{ dpi.ScreenX(), dpi.ScreenY() }; GfxFillRect( - dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.width, dpi.height } }, + dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.ScreenWidth(), dpi.ScreenHeight() } }, ColourMapA[colours[1].colour].mid_light); auto y = 0; diff --git a/src/openrct2-ui/windows/ScenarioSelect.cpp b/src/openrct2-ui/windows/ScenarioSelect.cpp index bdfda4915f..a903943569 100644 --- a/src/openrct2-ui/windows/ScenarioSelect.cpp +++ b/src/openrct2-ui/windows/ScenarioSelect.cpp @@ -415,7 +415,7 @@ namespace OpenRCT2::Ui::Windows int32_t y = 0; for (const auto& listItem : _listItems) { - if (y > dpi.y + dpi.height) + if (y > dpi.ScreenY() + dpi.ScreenHeight()) { continue; } diff --git a/src/openrct2-ui/windows/ServerList.cpp b/src/openrct2-ui/windows/ServerList.cpp index 3b7e3e9c4d..509574b21e 100644 --- a/src/openrct2-ui/windows/ServerList.cpp +++ b/src/openrct2-ui/windows/ServerList.cpp @@ -347,7 +347,7 @@ namespace OpenRCT2::Ui::Windows screenCoords.y = 0; for (int32_t i = 0; i < no_list_items; i++) { - if (screenCoords.y >= dpi.y + dpi.height) + if (screenCoords.y >= dpi.ScreenY() + dpi.ScreenHeight()) continue; const auto& serverDetails = _serverList.GetServer(i); diff --git a/src/openrct2-ui/windows/ShortcutKeys.cpp b/src/openrct2-ui/windows/ShortcutKeys.cpp index 6c22e68c61..3458bfe84e 100644 --- a/src/openrct2-ui/windows/ShortcutKeys.cpp +++ b/src/openrct2-ui/windows/ShortcutKeys.cpp @@ -305,9 +305,9 @@ namespace OpenRCT2::Ui::Windows void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override { - auto dpiCoords = ScreenCoordsXY{ dpi.x, dpi.y }; + auto dpiCoords = ScreenCoordsXY{ dpi.ScreenX(), dpi.ScreenY() }; GfxFillRect( - dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.width - 1, dpi.height - 1 } }, + dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.ScreenWidth() - 1, dpi.ScreenHeight() - 1 } }, ColourMapA[colours[1].colour].mid_light); // TODO: the line below is a workaround for what is presumably a bug with dpi->width @@ -317,12 +317,12 @@ namespace OpenRCT2::Ui::Windows for (size_t i = 0; i < _list.size(); ++i) { auto y = static_cast(1 + i * kScrollableRowHeight); - if (y > dpi.y + dpi.height) + if (y > dpi.ScreenY() + dpi.ScreenHeight()) { break; } - if (y + kScrollableRowHeight < dpi.y) + if (y + kScrollableRowHeight < dpi.ScreenY()) { continue; } diff --git a/src/openrct2-ui/windows/StaffList.cpp b/src/openrct2-ui/windows/StaffList.cpp index 26bac9eb69..573e6baf04 100644 --- a/src/openrct2-ui/windows/StaffList.cpp +++ b/src/openrct2-ui/windows/StaffList.cpp @@ -381,9 +381,9 @@ namespace OpenRCT2::Ui::Windows void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override { - auto dpiCoords = ScreenCoordsXY{ dpi.x, dpi.y }; + auto dpiCoords = ScreenCoordsXY{ dpi.ScreenX(), dpi.ScreenY() }; GfxFillRect( - dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.width - 1, dpi.height - 1 } }, + dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.ScreenWidth() - 1, dpi.ScreenHeight() - 1 } }, ColourMapA[colours[1].colour].mid_light); // How much space do we have for the name and action columns? (Discount scroll area and icons.) @@ -396,12 +396,12 @@ namespace OpenRCT2::Ui::Windows size_t i = 0; for (const auto& entry : _staffList) { - if (y > dpi.y + dpi.height) + if (y > dpi.ScreenY() + dpi.ScreenHeight()) { break; } - if (y + 11 >= dpi.y) + if (y + 11 >= dpi.ScreenY()) { const auto* peep = GetEntity(entry.Id); if (peep == nullptr) diff --git a/src/openrct2-ui/windows/Themes.cpp b/src/openrct2-ui/windows/Themes.cpp index b8ec8e72fa..9e22e19af1 100644 --- a/src/openrct2-ui/windows/Themes.cpp +++ b/src/openrct2-ui/windows/Themes.cpp @@ -761,11 +761,11 @@ namespace OpenRCT2::Ui::Windows screenCoords.y = 0; for (int32_t i = 0; i < GetColourSchemeTabCount(); i++) { - if (screenCoords.y > dpi.y + dpi.height) + if (screenCoords.y > dpi.ScreenY() + dpi.ScreenHeight()) { break; } - if (screenCoords.y + _row_height >= dpi.y) + if (screenCoords.y + _row_height >= dpi.ScreenY()) { if (i + 1 < GetColourSchemeTabCount()) { diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index cf84cf44a7..50e386a717 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -1575,7 +1575,9 @@ static uint64_t PageDisabledWidgets[] = { { const int32_t listWidth = widgets[WIDX_LIST].width(); GfxFillRect( - dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, + dpi, + { { dpi.ScreenX(), dpi.ScreenY() }, + { dpi.ScreenX() + dpi.ScreenWidth() - 1, dpi.ScreenY() + dpi.ScreenHeight() - 1 } }, ColourMapA[colours[1].colour].mid_light); // Show usage hint when nothing is selected diff --git a/src/openrct2-ui/windows/TrackList.cpp b/src/openrct2-ui/windows/TrackList.cpp index 5abb15d3f1..e63e5e403f 100644 --- a/src/openrct2-ui/windows/TrackList.cpp +++ b/src/openrct2-ui/windows/TrackList.cpp @@ -710,7 +710,8 @@ namespace OpenRCT2::Ui::Windows for (auto i : _filteredTrackIds) { - if (screenCoords.y + kScrollableRowHeight >= dpi.y && screenCoords.y < dpi.y + dpi.height) + if (screenCoords.y + kScrollableRowHeight >= dpi.ScreenY() + && screenCoords.y < dpi.ScreenY() + dpi.ScreenHeight()) { StringId stringId; if (listIndex == static_cast(selected_list_item)) diff --git a/src/openrct2/CommandLineSprite.cpp b/src/openrct2/CommandLineSprite.cpp index d31c0435a3..2431aa7fa6 100644 --- a/src/openrct2/CommandLineSprite.cpp +++ b/src/openrct2/CommandLineSprite.cpp @@ -195,10 +195,10 @@ static bool SpriteImageExport(const G1Element& spriteElement, u8string_view outP DrawPixelInfo dpi; dpi.bits = pixels; - dpi.x = 0; - dpi.y = 0; - dpi.width = spriteElement.width; - dpi.height = spriteElement.height; + dpi.SetX(0); + dpi.SetY(0); + dpi.SetWidth(spriteElement.width); + dpi.SetHeight(spriteElement.height); dpi.pitch = 0; dpi.zoom_level = ZoomLevel{ 0 }; @@ -207,14 +207,14 @@ static bool SpriteImageExport(const G1Element& spriteElement, u8string_view outP GfxSpriteToBuffer(dpi, args); auto const pixels8 = dpi.bits; - auto const pixelsLen = (dpi.width + dpi.pitch) * dpi.height; + auto const pixelsLen = dpi.LineStride() * dpi.WorldHeight(); try { Image image; - image.Width = dpi.width; - image.Height = dpi.height; + image.Width = dpi.ScreenWidth(); + image.Height = dpi.ScreenHeight(); image.Depth = 8; - image.Stride = dpi.width + dpi.pitch; + image.Stride = dpi.LineStride(); image.Palette = std::make_unique(StandardPalette); image.Pixels = std::vector(pixels8, pixels8 + pixelsLen); Imaging::WriteToFile(outPath, image, IMAGE_FORMAT::PNG); diff --git a/src/openrct2/drawing/Drawing.Sprite.BMP.cpp b/src/openrct2/drawing/Drawing.Sprite.BMP.cpp index d742c842db..c1e9bd91cb 100644 --- a/src/openrct2/drawing/Drawing.Sprite.BMP.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.BMP.cpp @@ -17,7 +17,7 @@ template static void FASTCALL DrawBMPSpriteMagnify(DrawPix auto& paletteMap = args.PalMap; auto zoomLevel = dpi.zoom_level; size_t srcLineWidth = g1.width; - size_t dstLineWidth = zoomLevel.ApplyInversedTo(dpi.width) + dpi.pitch; + size_t dstLineWidth = dpi.LineStride(); uint8_t zoom = zoomLevel.ApplyInversedTo(1); auto width = zoomLevel.ApplyInversedTo(args.Width); auto height = zoomLevel.ApplyInversedTo(args.Height); @@ -45,7 +45,7 @@ template static void FASTCALL DrawBMPSpriteMinify(DrawPixe auto height = args.Height; auto zoomLevel = dpi.zoom_level; size_t srcLineWidth = zoomLevel.ApplyTo(g1.width); - size_t dstLineWidth = zoomLevel.ApplyInversedTo(static_cast(dpi.width)) + dpi.pitch; + size_t dstLineWidth = dpi.LineStride(); uint8_t zoom = zoomLevel.ApplyTo(1); for (; height > 0; height -= zoom) { diff --git a/src/openrct2/drawing/Drawing.Sprite.RLE.cpp b/src/openrct2/drawing/Drawing.Sprite.RLE.cpp index 59f862811e..46db4bd11e 100644 --- a/src/openrct2/drawing/Drawing.Sprite.RLE.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.RLE.cpp @@ -23,7 +23,7 @@ static void FASTCALL DrawRLESpriteMagnify(DrawPixelInfo& dpi, const DrawSpriteAr auto height = args.Height; auto& paletteMap = args.PalMap; auto zoom = 1 << TZoom; - auto dstLineWidth = (static_cast(dpi.width) << TZoom) + dpi.pitch; + auto dstLineWidth = static_cast(dpi.LineStride()); // Move up to the first line of the image if source_y_start is negative. Why does this even occur? if (srcY < 0) @@ -93,7 +93,7 @@ static void FASTCALL DrawRLESpriteMinify(DrawPixelInfo& dpi, const DrawSpriteArg auto width = args.Width; auto height = args.Height; auto zoom = 1 << TZoom; - auto dstLineWidth = (static_cast(dpi.width) >> TZoom) + dpi.pitch; + auto dstLineWidth = static_cast(dpi.LineStride()); // Move up to the first line of the image if source_y_start is negative. Why does this even occur? if (srcY < 0) diff --git a/src/openrct2/drawing/Drawing.Sprite.cpp b/src/openrct2/drawing/Drawing.Sprite.cpp index 5921bc5e85..014008cb70 100644 --- a/src/openrct2/drawing/Drawing.Sprite.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.cpp @@ -526,10 +526,10 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( { DrawPixelInfo zoomed_dpi = dpi; zoomed_dpi.bits = dpi.bits; - zoomed_dpi.x = dpi.x >> 1; - zoomed_dpi.y = dpi.y >> 1; - zoomed_dpi.height = dpi.height >> 1; - zoomed_dpi.width = dpi.width >> 1; + zoomed_dpi.SetX(dpi.ScreenX()); + zoomed_dpi.SetY(dpi.ScreenY()); + zoomed_dpi.SetHeight(dpi.ScreenHeight()); + zoomed_dpi.SetWidth(dpi.ScreenWidth()); zoomed_dpi.pitch = dpi.pitch; zoomed_dpi.zoom_level = dpi.zoom_level - 1; @@ -564,11 +564,11 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( // the zoom mask on the y coordinate but does on x. if (g1->flags & G1_FLAG_RLE_COMPRESSION) { - dest_start_y -= dpi.y; + dest_start_y -= dpi.WorldY(); } else { - dest_start_y = (dest_start_y & zoom_mask) - dpi.y; + dest_start_y = (dest_start_y & zoom_mask) - dpi.WorldY(); } // This is the start y coordinate on the source int32_t source_start_y = 0; @@ -599,11 +599,11 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( int32_t dest_end_y = dest_start_y + height; - if (dest_end_y > dpi.height) + if (dest_end_y > dpi.WorldHeight()) { // If the destination y is outside of the drawing // image reduce the height of the image - height -= dest_end_y - dpi.height; + height -= dest_end_y - dpi.WorldHeight(); } // If the image no longer has anything to draw if (height <= 0) @@ -617,7 +617,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( // This is the source start x coordinate int32_t source_start_x = 0; // This is the destination start x coordinate - int16_t dest_start_x = ((x + g1->x_offset + ~zoom_mask) & zoom_mask) - dpi.x; + int16_t dest_start_x = ((x + g1->x_offset + ~zoom_mask) & zoom_mask) - dpi.WorldX(); if (dest_start_x < 0) { @@ -644,11 +644,11 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( int32_t dest_end_x = dest_start_x + width; - if (dest_end_x > dpi.width) + if (dest_end_x > dpi.WorldWidth()) { // If the destination x is outside of the drawing area // reduce the image width. - width -= dest_end_x - dpi.width; + width -= dest_end_x - dpi.WorldWidth(); // If there is no image to draw. if (width <= 0) return; @@ -658,7 +658,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( uint8_t* dest_pointer = dpi.bits; // Move the pointer to the start point of the destination - dest_pointer += (zoom_level.ApplyInversedTo(dpi.width) + dpi.pitch) * dest_start_y + dest_start_x; + dest_pointer += (zoom_level.ApplyInversedTo(dpi.WorldWidth()) + dpi.pitch) * dest_start_y + dest_start_x; DrawSpriteArgs args(imageId, paletteMap, *g1, source_start_x, source_start_y, width, height, dest_pointer); GfxSpriteToBuffer(dpi, args); @@ -703,7 +703,7 @@ void FASTCALL GfxDrawSpriteRawMaskedSoftware( if (dpi.zoom_level != ZoomLevel{ 0 }) { // TODO: Implement other zoom levels (probably not used though) - //assert(false); // TODO complete work for sofware zooming or revert change. + // assert(false); // TODO (mber) complete work for sofware zooming or revert change. return; } @@ -712,10 +712,10 @@ void FASTCALL GfxDrawSpriteRawMaskedSoftware( auto offsetCoords = scrCoords + ScreenCoordsXY{ imgMask->x_offset, imgMask->y_offset }; - left = std::max(dpi.x, offsetCoords.x); - top = std::max(dpi.y, offsetCoords.y); - right = std::min(dpi.x + dpi.width, offsetCoords.x + width); - bottom = std::min(dpi.y + dpi.height, offsetCoords.y + height); + left = std::max(dpi.ScreenX(), offsetCoords.x); + top = std::max(dpi.ScreenY(), offsetCoords.y); + right = std::min(dpi.ScreenX() + dpi.ScreenWidth(), offsetCoords.x + width); + bottom = std::min(dpi.ScreenY() + dpi.ScreenHeight(), offsetCoords.y + height); width = right - left; height = bottom - top; @@ -727,11 +727,11 @@ void FASTCALL GfxDrawSpriteRawMaskedSoftware( uint8_t const* maskSrc = imgMask->offset + (skipY * imgMask->width) + skipX; uint8_t const* colourSrc = imgColour->offset + (skipY * imgColour->width) + skipX; - uint8_t* dst = dpi.bits + (left - dpi.x) + ((top - dpi.y) * (dpi.width + dpi.pitch)); + uint8_t* dst = dpi.bits + (left - dpi.ScreenX()) + ((top - dpi.ScreenY()) * dpi.LineStride()); int32_t maskWrap = imgMask->width - width; int32_t colourWrap = imgColour->width - width; - int32_t dstWrap = ((dpi.width + dpi.pitch) - width); + int32_t dstWrap = dpi.LineStride() - width; MaskFn(width, height, maskSrc, colourSrc, dst, maskWrap, colourWrap, dstWrap); } diff --git a/src/openrct2/drawing/Drawing.String.cpp b/src/openrct2/drawing/Drawing.String.cpp index 4ad0215b06..a3cbec1d41 100644 --- a/src/openrct2/drawing/Drawing.String.cpp +++ b/src/openrct2/drawing/Drawing.String.cpp @@ -325,7 +325,7 @@ static void ColourCharacterWindow(colour_t colour, const uint16_t* current_font_ void DrawStringCentredRaw( DrawPixelInfo& dpi, const ScreenCoordsXY& coords, int32_t numLines, const utf8* text, FontStyle fontStyle) { - ScreenCoordsXY screenCoords(dpi.x, dpi.y); + ScreenCoordsXY screenCoords(dpi.ScreenX(), dpi.ScreenY()); DrawText(dpi, screenCoords, { COLOUR_BLACK, fontStyle }, ""); screenCoords = coords; @@ -422,7 +422,7 @@ void DrawNewsTicker( int32_t ticks) { int32_t numLines, lineHeight, lineY; - ScreenCoordsXY screenCoords(dpi.x, dpi.y); + ScreenCoordsXY screenCoords(dpi.ScreenX(), dpi.ScreenY()); DrawText(dpi, screenCoords, { colour }, ""); diff --git a/src/openrct2/drawing/Drawing.cpp b/src/openrct2/drawing/Drawing.cpp index 6d701b29a3..c74f13dd67 100644 --- a/src/openrct2/drawing/Drawing.cpp +++ b/src/openrct2/drawing/Drawing.cpp @@ -787,47 +787,48 @@ void GfxInvalidateScreen() */ bool ClipDrawPixelInfo(DrawPixelInfo& dst, DrawPixelInfo& src, const ScreenCoordsXY& coords, int32_t width, int32_t height) { + assert(src.zoom_level == ZoomLevel{ 0 }); int32_t right = coords.x + width; int32_t bottom = coords.y + height; dst = src; dst.zoom_level = ZoomLevel{ 0 }; - if (coords.x > dst.x) + if (coords.x > dst.ScreenX()) { - uint16_t clippedFromLeft = coords.x - dst.x; - dst.width -= clippedFromLeft; - dst.x = coords.x; + uint16_t clippedFromLeft = coords.x - dst.ScreenX(); + dst.SetWidth(dst.ScreenWidth() - clippedFromLeft); + dst.SetX(coords.x); dst.pitch += clippedFromLeft; dst.bits += clippedFromLeft; } - int32_t stickOutWidth = dst.x + dst.width - right; + int32_t stickOutWidth = dst.ScreenX() + dst.ScreenWidth() - right; if (stickOutWidth > 0) { - dst.width -= stickOutWidth; + dst.SetWidth(dst.ScreenWidth() - stickOutWidth); dst.pitch += stickOutWidth; } - if (coords.y > dst.y) + if (coords.y > dst.ScreenY()) { - uint16_t clippedFromTop = coords.y - dst.y; - dst.height -= clippedFromTop; - dst.y = coords.y; - uint32_t bitsPlus = (dst.pitch + dst.width) * clippedFromTop; + uint16_t clippedFromTop = coords.y - dst.ScreenY(); + dst.SetHeight(dst.ScreenHeight() - clippedFromTop); + dst.SetY(coords.y); + uint32_t bitsPlus = dst.LineStride() * clippedFromTop; dst.bits += bitsPlus; } - int32_t bp = dst.y + dst.height - bottom; + int32_t bp = dst.ScreenY() + dst.ScreenHeight() - bottom; if (bp > 0) { - dst.height -= bp; + dst.SetHeight(dst.ScreenHeight() - bp); } - if (dst.width > 0 && dst.height > 0) + if (dst.ScreenWidth() > 0 && dst.ScreenHeight() > 0) { - dst.x -= coords.x; - dst.y -= coords.y; + dst.SetX(dst.ScreenX() - coords.x); + dst.SetY(dst.ScreenY() - coords.y); return true; } @@ -1143,15 +1144,16 @@ void DebugDPI(DrawPixelInfo& dpi) { DrawPixelInfo unzoomed = dpi; unzoomed.zoom_level = ZoomLevel{ 0 }; - unzoomed.x = dpi.zoom_level.ApplyInversedTo(dpi.x); - unzoomed.y = dpi.zoom_level.ApplyInversedTo(dpi.y); - unzoomed.width = dpi.zoom_level.ApplyInversedTo(dpi.width); - unzoomed.height = dpi.zoom_level.ApplyInversedTo(dpi.height); + unzoomed.SetX(dpi.ScreenX()); + unzoomed.SetY(dpi.ScreenY()); + unzoomed.SetWidth(dpi.ScreenWidth()); + unzoomed.SetHeight(dpi.ScreenHeight()); - ScreenCoordsXY topLeft = { unzoomed.x, unzoomed.y }; - ScreenCoordsXY topRight = { unzoomed.x + unzoomed.width - 1, unzoomed.y }; - ScreenCoordsXY bottomLeft = { unzoomed.x, unzoomed.y + unzoomed.height - 1 }; - ScreenCoordsXY bottomRight = { unzoomed.x + unzoomed.width - 1, unzoomed.y + unzoomed.height - 1 }; + ScreenCoordsXY topLeft = { unzoomed.ScreenX(), unzoomed.ScreenY() }; + ScreenCoordsXY topRight = { unzoomed.ScreenX() + unzoomed.ScreenWidth() - 1, unzoomed.ScreenY() }; + ScreenCoordsXY bottomLeft = { unzoomed.ScreenX(), unzoomed.ScreenY() + unzoomed.ScreenHeight() - 1 }; + ScreenCoordsXY bottomRight = { unzoomed.ScreenX() + unzoomed.ScreenWidth() - 1, + unzoomed.ScreenY() + unzoomed.ScreenHeight() - 1 }; GfxDrawLine(unzoomed, { topLeft, bottomRight }, PALETTE_INDEX_129); GfxDrawLine(unzoomed, { topLeft, topRight }, PALETTE_INDEX_129); GfxDrawLine(unzoomed, { topRight, bottomRight }, PALETTE_INDEX_129); diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index 69f5adde0b..4fa4a14fa0 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -108,21 +108,17 @@ struct Gx struct DrawPixelInfo { uint8_t* bits{}; + +private: int32_t x{}; int32_t y{}; int32_t width{}; int32_t height{}; + +public: int32_t pitch{}; // note: this is actually (pitch - width) ZoomLevel zoom_level{}; - /** - * As x and y are based on 1:1 units, zooming in will cause a reduction in precision when mapping zoomed-in - * pixels to 1:1 pixels. When x, y are not a multiple of the zoom level, the remainder will be non-zero. - * The drawing of sprites will need to be offset by this amount. - */ - uint8_t remX{}; - uint8_t remY{}; - // Last position of drawn text. ScreenCoordsXY lastStringPos{}; @@ -131,6 +127,62 @@ struct DrawPixelInfo size_t GetBytesPerRow() const; uint8_t* GetBitsOffset(const ScreenCoordsXY& pos) const; DrawPixelInfo Crop(const ScreenCoordsXY& pos, const ScreenSize& size) const; + + constexpr int32_t WorldX() const + { + return zoom_level.ApplyTo(x); + } + constexpr int32_t WorldY() const + { + return zoom_level.ApplyTo(y); + } + constexpr int32_t WorldWidth() const + { + return zoom_level.ApplyTo(width); + } + constexpr int32_t WorldHeight() const + { + return zoom_level.ApplyTo(height); + } + + constexpr int32_t ScreenX() const + { + return x; + } + constexpr int32_t ScreenY() const + { + return y; + } + constexpr int32_t ScreenWidth() const + { + return width; + } + constexpr int32_t ScreenHeight() const + { + return height; + } + + constexpr int32_t LineStride() const + { + return width + pitch; + } + + void SetX(const int32_t value) + { + x = value; + } + void SetY(const int32_t value) + { + y = value; + } + void SetWidth(const int32_t value) + { + width = value; + } + void SetHeight(const int32_t value) + { + height = value; + } }; struct TextDrawInfo diff --git a/src/openrct2/drawing/LightFX.cpp b/src/openrct2/drawing/LightFX.cpp index 8c87d4082f..f5c22b3166 100644 --- a/src/openrct2/drawing/LightFX.cpp +++ b/src/openrct2/drawing/LightFX.cpp @@ -182,8 +182,8 @@ void LightFXInit() void LightFXUpdateBuffers(DrawPixelInfo& info) { - _light_rendered_buffer_front = realloc(_light_rendered_buffer_front, info.width * info.height); - _light_rendered_buffer_back = realloc(_light_rendered_buffer_back, info.width * info.height); + _light_rendered_buffer_front = realloc(_light_rendered_buffer_front, info.ScreenWidth() * info.ScreenHeight()); + _light_rendered_buffer_back = realloc(_light_rendered_buffer_back, info.ScreenWidth() * info.ScreenHeight()); _pixelInfo = info; } @@ -205,8 +205,8 @@ void LightFXPrepareLightList() posOnScreenX = _current_view_zoom_front.ApplyInversedTo(posOnScreenX); posOnScreenY = _current_view_zoom_front.ApplyInversedTo(posOnScreenY); - if ((posOnScreenX < -128) || (posOnScreenY < -128) || (posOnScreenX > _pixelInfo.width + 128) - || (posOnScreenY > _pixelInfo.height + 128)) + if ((posOnScreenX < -128) || (posOnScreenY < -128) || (posOnScreenX > _pixelInfo.ScreenWidth() + 128) + || (posOnScreenY > _pixelInfo.ScreenHeight() + 128)) { entry->Type = LightType::None; continue; @@ -299,11 +299,13 @@ void LightFXPrepareLightList() { // based on GetMapCoordinatesFromPosWindow DrawPixelInfo dpi; - dpi.x = entry->ViewCoords.x + offsetPattern[0 + pat * 2] / mapFrontDiv; - dpi.y = entry->ViewCoords.y + offsetPattern[1 + pat * 2] / mapFrontDiv; - dpi.height = 1; dpi.zoom_level = _current_view_zoom_front; - dpi.width = 1; + dpi.SetX(_current_view_zoom_front.ApplyInversedTo( + entry->ViewCoords.x + offsetPattern[0 + pat * 2] / mapFrontDiv)); + dpi.SetY(_current_view_zoom_front.ApplyInversedTo( + entry->ViewCoords.y + offsetPattern[1 + pat * 2] / mapFrontDiv)); + dpi.SetHeight(1); + dpi.SetWidth(1); PaintSession* session = PaintSessionAlloc(dpi, w->viewport->flags, w->viewport->rotation); PaintSessionGenerate(*session); @@ -449,7 +451,7 @@ void LightFXRenderLightsToFrontBuffer() return; } - std::memset(_light_rendered_buffer_front, 0, _pixelInfo.width * _pixelInfo.height); + std::memset(_light_rendered_buffer_front, 0, _pixelInfo.ScreenWidth() * _pixelInfo.ScreenHeight()); _lightPolution_back = 0; @@ -524,8 +526,8 @@ void LightFXRenderLightsToFrontBuffer() } // Clamp the reads to be no larger than the buffer size - bufReadHeight = std::min(_pixelInfo.height, bufReadHeight); - bufReadWidth = std::min(_pixelInfo.width, bufReadWidth); + bufReadHeight = std::min(_pixelInfo.ScreenHeight(), bufReadHeight); + bufReadWidth = std::min(_pixelInfo.ScreenWidth(), bufReadWidth); bufWriteX = inRectCentreX - bufReadWidth / 2; bufWriteY = inRectCentreY - bufReadHeight / 2; @@ -553,7 +555,7 @@ void LightFXRenderLightsToFrontBuffer() } else { - bufWriteBase += bufWriteY * _pixelInfo.width; + bufWriteBase += bufWriteY * _pixelInfo.ScreenWidth(); } if (bufWriteHeight <= 0) @@ -562,13 +564,13 @@ void LightFXRenderLightsToFrontBuffer() int32_t rightEdge = bufWriteX + bufWriteWidth; int32_t bottomEdge = bufWriteY + bufWriteHeight; - if (rightEdge > _pixelInfo.width) + if (rightEdge > _pixelInfo.ScreenWidth()) { - bufWriteWidth -= rightEdge - _pixelInfo.width; + bufWriteWidth -= rightEdge - _pixelInfo.ScreenWidth(); } - if (bottomEdge > _pixelInfo.height) + if (bottomEdge > _pixelInfo.ScreenHeight()) { - bufWriteHeight -= bottomEdge - _pixelInfo.height; + bufWriteHeight -= bottomEdge - _pixelInfo.ScreenHeight(); } if (bufWriteWidth <= 0) @@ -579,7 +581,7 @@ void LightFXRenderLightsToFrontBuffer() _lightPolution_back += (bufWriteWidth * bufWriteHeight) / 256; bufReadSkip = bufReadWidth - bufWriteWidth; - bufWriteSkip = _pixelInfo.width - bufWriteWidth; + bufWriteSkip = _pixelInfo.ScreenWidth() - bufWriteWidth; if (entry->LightIntensity == 0xFF) { diff --git a/src/openrct2/drawing/Line.cpp b/src/openrct2/drawing/Line.cpp index d21c289d22..a7a183880e 100644 --- a/src/openrct2/drawing/Line.cpp +++ b/src/openrct2/drawing/Line.cpp @@ -18,13 +18,13 @@ */ static void GfxDrawLineOnBuffer(DrawPixelInfo& dpi, char colour, const ScreenCoordsXY& coords, int32_t no_pixels) { - ScreenCoordsXY offset{ coords.x - dpi.x, coords.y - dpi.y }; + ScreenCoordsXY offset{ coords.x - dpi.WorldX(), coords.y - dpi.WorldY() }; offset.x = dpi.zoom_level.ApplyInversedTo(offset.x); offset.y = dpi.zoom_level.ApplyInversedTo(offset.y); no_pixels = dpi.zoom_level.ApplyInversedTo(no_pixels); - const int32_t width = dpi.zoom_level.ApplyInversedTo(dpi.width); - const int32_t height = dpi.zoom_level.ApplyInversedTo(dpi.height); + const int32_t width = dpi.zoom_level.ApplyInversedTo(dpi.WorldWidth()); + const int32_t height = dpi.zoom_level.ApplyInversedTo(dpi.WorldHeight()); // Check to make sure point is in the y range if (offset.y < 0) @@ -79,27 +79,28 @@ static void GfxDrawLineOnBuffer(DrawPixelInfo& dpi, char colour, const ScreenCoo void GfxDrawLineSoftware(DrawPixelInfo& dpi, const ScreenLine& line, int32_t colour) { + // TODO: (mber) Rewrite to work with screen DPI coordinates rather than world. int32_t x1 = line.GetX1(); int32_t x2 = line.GetX2(); int32_t y1 = line.GetY1(); int32_t y2 = line.GetY2(); // Check to make sure the line is within the drawing area - if ((x1 < dpi.x) && (x2 < dpi.x)) + if ((x1 < dpi.WorldX()) && (x2 < dpi.WorldX())) { return; } - if ((y1 < dpi.y) && (y2 < dpi.y)) + if ((y1 < dpi.WorldY()) && (y2 < dpi.WorldY())) { return; } - if ((x1 > (dpi.x + dpi.width)) && (x2 > (dpi.x + dpi.width))) + if ((x1 > (dpi.WorldX() + dpi.WorldWidth())) && (x2 > (dpi.WorldX() + dpi.WorldWidth()))) { return; } - if ((y1 > (dpi.y + dpi.height)) && (y2 > (dpi.y + dpi.height))) + if ((y1 > (dpi.WorldY() + dpi.WorldHeight())) && (y2 > (dpi.WorldY() + dpi.WorldHeight()))) { return; } diff --git a/src/openrct2/drawing/ScrollingText.cpp b/src/openrct2/drawing/ScrollingText.cpp index b1552f3f69..9d4a5602fb 100644 --- a/src/openrct2/drawing/ScrollingText.cpp +++ b/src/openrct2/drawing/ScrollingText.cpp @@ -52,8 +52,8 @@ static void ScrollingTextInitialiseCharacterBitmaps(uint32_t glyphStart, uint16_ uint8_t drawingSurface[64]; DrawPixelInfo dpi; dpi.bits = reinterpret_cast(&drawingSurface); - dpi.width = 8; - dpi.height = 8; + dpi.SetWidth(8); + dpi.SetHeight(8); for (int32_t i = 0; i < count; i++) { diff --git a/src/openrct2/drawing/X8DrawingEngine.cpp b/src/openrct2/drawing/X8DrawingEngine.cpp index 0d2836e1fb..1829da8c2c 100644 --- a/src/openrct2/drawing/X8DrawingEngine.cpp +++ b/src/openrct2/drawing/X8DrawingEngine.cpp @@ -52,7 +52,7 @@ void X8WeatherDrawer::Draw( uint8_t patternStartXOffset = xStart % patternXSpace; uint8_t patternStartYOffset = yStart % patternYSpace; - uint32_t pixelOffset = (dpi.pitch + dpi.width) * y + x; + uint32_t pixelOffset = dpi.LineStride() * y + x; uint8_t patternYPos = patternStartYOffset % patternYSpace; uint8_t* screenBits = dpi.bits; @@ -84,7 +84,7 @@ void X8WeatherDrawer::Draw( } } - pixelOffset += dpi.pitch + dpi.width; + pixelOffset += dpi.LineStride(); patternYPos++; patternYPos %= patternYSpace; } @@ -94,7 +94,7 @@ void X8WeatherDrawer::Restore(DrawPixelInfo& dpi) { if (_weatherPixelsCount > 0) { - uint32_t numPixels = (dpi.width + dpi.pitch) * dpi.height; + uint32_t numPixels = dpi.LineStride() * dpi.ScreenHeight(); uint8_t* bits = dpi.bits; for (uint32_t i = 0; i < _weatherPixelsCount; i++) { @@ -237,7 +237,7 @@ void X8DrawingEngine::CopyRect(int32_t x, int32_t y, int32_t width, int32_t heig width += lmargin + rmargin; height += tmargin + bmargin; - int32_t stride = _bitsDPI.width + _bitsDPI.pitch; + int32_t stride = _bitsDPI.LineStride(); uint8_t* to = _bitsDPI.bits + y * stride + x; uint8_t* from = _bitsDPI.bits + (y - dy) * stride + x - dx; @@ -331,10 +331,10 @@ void X8DrawingEngine::ConfigureBits(uint32_t width, uint32_t height, uint32_t pi DrawPixelInfo* dpi = &_bitsDPI; dpi->bits = _bits; - dpi->x = 0; - dpi->y = 0; - dpi->width = width; - dpi->height = height; + dpi->SetX(0); + dpi->SetY(0); + dpi->SetWidth(width); + dpi->SetHeight(height); dpi->pitch = _pitch - width; ConfigureDirtyGrid(); @@ -463,8 +463,8 @@ X8DrawingContext::X8DrawingContext(X8DrawingEngine* engine) void X8DrawingContext::Clear(DrawPixelInfo& dpi, uint8_t paletteIndex) { - int32_t w = dpi.zoom_level.ApplyInversedTo(dpi.width); - int32_t h = dpi.zoom_level.ApplyInversedTo(dpi.height); + int32_t w = dpi.ScreenWidth(); + int32_t h = dpi.ScreenHeight(); uint8_t* ptr = dpi.bits; for (int32_t y = 0; y < h; y++) @@ -524,45 +524,46 @@ static constexpr const uint16_t* Patterns[] = { void X8DrawingContext::FillRect(DrawPixelInfo& dpi, uint32_t colour, int32_t left, int32_t top, int32_t right, int32_t bottom) { + assert(dpi.zoom_level == ZoomLevel{ 0 }); if (left > right) return; if (top > bottom) return; - if (dpi.x > right) + if (dpi.ScreenX() > right) return; - if (left >= dpi.x + dpi.width) + if (left >= dpi.ScreenX() + dpi.ScreenWidth()) return; - if (bottom < dpi.y) + if (bottom < dpi.ScreenY()) return; - if (top >= dpi.y + dpi.height) + if (top >= dpi.ScreenY() + dpi.ScreenHeight()) return; uint16_t crossPattern = 0; - int32_t startX = left - dpi.x; + int32_t startX = left - dpi.ScreenX(); if (startX < 0) { crossPattern ^= startX; startX = 0; } - int32_t endX = right - dpi.x + 1; - if (endX > dpi.width) + int32_t endX = right - dpi.ScreenX() + 1; + if (endX > dpi.ScreenWidth()) { - endX = dpi.width; + endX = dpi.ScreenWidth(); } - int32_t startY = top - dpi.y; + int32_t startY = top - dpi.ScreenY(); if (startY < 0) { crossPattern ^= startY; startY = 0; } - int32_t endY = bottom - dpi.y + 1; - if (endY > dpi.height) + int32_t endY = bottom - dpi.ScreenY() + 1; + if (endY > dpi.ScreenHeight()) { - endY = dpi.height; + endY = dpi.ScreenHeight(); } int32_t width = endX - startX; @@ -571,10 +572,10 @@ void X8DrawingContext::FillRect(DrawPixelInfo& dpi, uint32_t colour, int32_t lef if (colour & 0x1000000) { // Cross hatching - uint8_t* dst = (startY * (dpi.width + dpi.pitch)) + startX + dpi.bits; + uint8_t* dst = startY * dpi.LineStride() + startX + dpi.bits; for (int32_t i = 0; i < height; i++) { - uint8_t* nextdst = dst + dpi.width + dpi.pitch; + uint8_t* nextdst = dst + dpi.LineStride(); uint32_t p = Numerics::ror32(crossPattern, 1); p = (p & 0xFFFF0000) | width; @@ -598,22 +599,22 @@ void X8DrawingContext::FillRect(DrawPixelInfo& dpi, uint32_t colour, int32_t lef } else if (colour & 0x4000000) { - uint8_t* dst = startY * (dpi.width + dpi.pitch) + startX + dpi.bits; + uint8_t* dst = startY * dpi.LineStride() + startX + dpi.bits; // The pattern loops every 15 lines this is which // part the pattern is on. - int32_t patternY = (startY + dpi.y) % 16; + int32_t patternY = (startY + dpi.ScreenY()) % 16; // The pattern loops every 15 pixels this is which // part the pattern is on. - int32_t startPatternX = (startX + dpi.x) % 16; + int32_t startPatternX = (startX + dpi.ScreenX()) % 16; int32_t patternX = startPatternX; const uint16_t* patternsrc = Patterns[colour >> 28]; // or possibly uint8_t)[esi*4] ? for (int32_t numLines = height; numLines > 0; numLines--) { - uint8_t* nextdst = dst + dpi.width + dpi.pitch; + uint8_t* nextdst = dst + dpi.LineStride(); uint16_t pattern = patternsrc[patternY]; for (int32_t numPixels = width; numPixels > 0; numPixels--) @@ -632,11 +633,11 @@ void X8DrawingContext::FillRect(DrawPixelInfo& dpi, uint32_t colour, int32_t lef } else { - uint8_t* dst = startY * (dpi.width + dpi.pitch) + startX + dpi.bits; + uint8_t* dst = startY * dpi.LineStride() + startX + dpi.bits; for (int32_t i = 0; i < height; i++) { std::fill_n(dst, width, colour & 0xFF); - dst += dpi.width + dpi.pitch; + dst += dpi.LineStride(); } } } @@ -648,60 +649,54 @@ void X8DrawingContext::FilterRect( return; if (top > bottom) return; - if (dpi.x > right) + if (dpi.ScreenX() > right) return; - if (left >= dpi.x + dpi.width) + if (left >= dpi.ScreenX() + dpi.ScreenWidth()) return; - if (bottom < dpi.y) + if (bottom < dpi.ScreenY()) return; - if (top >= dpi.y + dpi.height) + if (top >= dpi.ScreenY() + dpi.ScreenHeight()) return; - int32_t startX = left - dpi.x; + int32_t startX = left - dpi.ScreenX(); if (startX < 0) { startX = 0; } - int32_t endX = right - dpi.x + 1; - if (endX > dpi.width) + int32_t endX = right - dpi.ScreenX() + 1; + if (endX > dpi.ScreenWidth()) { - endX = dpi.width; + endX = dpi.ScreenWidth(); } - int32_t startY = top - dpi.y; + int32_t startY = top - dpi.ScreenY(); if (startY < 0) { startY = 0; } - int32_t endY = bottom - dpi.y + 1; - if (endY > dpi.height) + int32_t endY = bottom - dpi.ScreenY() + 1; + if (endY > dpi.ScreenHeight()) { - endY = dpi.height; + endY = dpi.ScreenHeight(); } int32_t width = endX - startX; int32_t height = endY - startY; - // 0x2000000 - // 00678B7E 00678C83 - // Location in screen buffer? - uint8_t* dst = dpi.bits - + static_cast( - dpi.zoom_level.ApplyInversedTo(startY) * (dpi.zoom_level.ApplyInversedTo(dpi.width) + dpi.pitch) - + dpi.zoom_level.ApplyInversedTo(startX)); + uint8_t* dst = dpi.bits + (startY * dpi.LineStride() + startX); // Find colour in colour table? auto paletteMap = GetPaletteMapForColour(EnumValue(palette)); if (paletteMap.has_value()) { const auto& paletteEntries = paletteMap.value(); - const int32_t scaled_width = dpi.zoom_level.ApplyInversedTo(width); - const int32_t step = dpi.zoom_level.ApplyInversedTo(dpi.width) + dpi.pitch; + const int32_t scaled_width = width; + const int32_t step = dpi.LineStride(); // Fill the rectangle with the colours from the colour table - auto c = dpi.zoom_level.ApplyInversedTo(height); + auto c = height; for (int32_t i = 0; i < c; i++) { uint8_t* nextdst = dst + step * i; @@ -750,18 +745,19 @@ template static void DrawTTFBitmapInternal( DrawPixelInfo& dpi, uint8_t colour, TTFSurface* surface, int32_t x, int32_t y, uint8_t hintingThreshold) { + assert(dpi.zoom_level == ZoomLevel{ 0 }); const int32_t surfaceWidth = surface->w; int32_t width = surfaceWidth; int32_t height = surface->h; - const int32_t overflowX = (dpi.x + dpi.width) - (x + width); - const int32_t overflowY = (dpi.y + dpi.height) - (y + height); + const int32_t overflowX = (dpi.ScreenX() + dpi.ScreenWidth()) - (x + width); + const int32_t overflowY = (dpi.ScreenY() + dpi.ScreenHeight()) - (y + height); if (overflowX < 0) width += overflowX; if (overflowY < 0) height += overflowY; - int32_t skipX = x - dpi.x; - int32_t skipY = y - dpi.y; + int32_t skipX = x - dpi.ScreenX(); + int32_t skipY = y - dpi.ScreenY(); auto src = static_cast(surface->pixels); uint8_t* dst = dpi.bits; @@ -780,10 +776,10 @@ static void DrawTTFBitmapInternal( } dst += skipX; - dst += skipY * (dpi.width + dpi.pitch); + dst += skipY * dpi.LineStride(); const int32_t srcScanSkip = surfaceWidth - width; - const int32_t dstScanSkip = dpi.width + dpi.pitch - width; + const int32_t dstScanSkip = dpi.LineStride() - width; for (int32_t yy = 0; yy < height; yy++) { for (int32_t xx = 0; xx < width; xx++) diff --git a/src/openrct2/interface/Screenshot.cpp b/src/openrct2/interface/Screenshot.cpp index 7befc09abb..44f334e426 100644 --- a/src/openrct2/interface/Screenshot.cpp +++ b/src/openrct2/interface/Screenshot.cpp @@ -55,14 +55,14 @@ uint8_t gScreenshotCountdown = 0; static bool WriteDpiToFile(std::string_view path, const DrawPixelInfo& dpi, const GamePalette& palette) { auto const pixels8 = dpi.bits; - auto const pixelsLen = (dpi.width + dpi.pitch) * dpi.height; + auto const pixelsLen = dpi.LineStride() * dpi.ScreenHeight(); try { Image image; - image.Width = dpi.width; - image.Height = dpi.height; + image.Width = dpi.ScreenWidth(); + image.Height = dpi.ScreenHeight(); image.Depth = 8; - image.Stride = dpi.width + dpi.pitch; + image.Stride = dpi.LineStride(); image.Palette = std::make_unique(palette); image.Pixels = std::vector(pixels8, pixels8 + pixelsLen); Imaging::WriteToFile(path, image, IMAGE_FORMAT::PNG); @@ -230,9 +230,9 @@ static int32_t GetTallestVisibleTileTop( static DrawPixelInfo CreateDPI(const Viewport& viewport) { DrawPixelInfo dpi; - dpi.width = viewport.width; - dpi.height = viewport.height; - dpi.bits = new (std::nothrow) uint8_t[dpi.width * dpi.height]; + dpi.SetWidth(viewport.width); + dpi.SetHeight(viewport.height); + dpi.bits = new (std::nothrow) uint8_t[dpi.ScreenWidth() * dpi.ScreenHeight()]; if (dpi.bits == nullptr) { throw std::runtime_error("Giant screenshot failed, unable to allocate memory for image."); @@ -240,7 +240,7 @@ static DrawPixelInfo CreateDPI(const Viewport& viewport) if (viewport.flags & VIEWPORT_FLAG_TRANSPARENT_BACKGROUND) { - std::memset(dpi.bits, PALETTE_INDEX_0, static_cast(dpi.width) * dpi.height); + std::memset(dpi.bits, PALETTE_INDEX_0, static_cast(dpi.ScreenWidth()) * dpi.ScreenHeight()); } return dpi; @@ -251,8 +251,8 @@ static void ReleaseDPI(DrawPixelInfo& dpi) if (dpi.bits != nullptr) delete[] dpi.bits; dpi.bits = nullptr; - dpi.width = 0; - dpi.height = 0; + dpi.SetWidth(0); + dpi.SetHeight(0); } static Viewport GetGiantViewport(int32_t rotation, ZoomLevel zoom) diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 91dfa45c96..1a07d0678f 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -1026,6 +1026,7 @@ static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const Sc uint32_t width = screenRect.GetWidth(); uint32_t height = screenRect.GetHeight(); + // TODO: (mber) remove this masking code. const uint32_t bitmask = viewport->zoom >= ZoomLevel{ 0 } ? 0xFFFFFFFF & (viewport->zoom.ApplyTo(0xFFFFFFFF)) : 0xFFFFFFFF; ScreenCoordsXY topLeft = screenRect.Point1; @@ -1044,20 +1045,18 @@ static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const Sc DrawPixelInfo dpi1; dpi1.DrawingEngine = dpi.DrawingEngine; - dpi1.bits = dpi.bits + (x - dpi.x) + ((y - dpi.y) * (dpi.width + dpi.pitch)); - dpi1.x = topLeft.x; - dpi1.y = topLeft.y; - dpi1.width = width; - dpi1.height = height; - dpi1.pitch = (dpi.width + dpi.pitch) - viewport->zoom.ApplyInversedTo(width); + dpi1.bits = dpi.bits + (x - dpi.ScreenX()) + ((y - dpi.ScreenY()) * dpi.LineStride()); + dpi1.SetX(viewport->zoom.ApplyInversedTo(topLeft.x)); + dpi1.SetY(viewport->zoom.ApplyInversedTo(topLeft.y)); + dpi1.SetWidth(viewport->zoom.ApplyInversedTo(width)); + dpi1.SetHeight(viewport->zoom.ApplyInversedTo(height)); + dpi1.pitch = dpi.LineStride() - viewport->zoom.ApplyInversedTo(width); dpi1.zoom_level = viewport->zoom; - dpi1.remX = std::max(0, dpi.x - x); - dpi1.remY = std::max(0, dpi.y - y); // make sure, the compare operation is done in int32_t to avoid the loop becoming an infinite loop. // this as well as the [x += 32] in the loop causes signed integer overflow -> undefined behaviour. - auto rightBorder = dpi1.x + dpi1.width; - auto alignedX = Floor2(dpi1.x, 32); + auto rightBorder = dpi1.WorldX() + dpi1.WorldWidth(); + auto alignedX = Floor2(dpi1.WorldX(), 32); _paintColumns.clear(); @@ -1084,23 +1083,23 @@ static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const Sc _paintColumns.push_back(session); DrawPixelInfo& dpi2 = session->DPI; - if (x >= dpi2.x) + if (x >= dpi2.WorldX()) { - auto leftPitch = x - dpi2.x; - dpi2.width -= leftPitch; + auto leftPitch = x - dpi2.WorldX(); + dpi2.SetWidth(dpi2.ScreenWidth() - dpi2.zoom_level.ApplyInversedTo(leftPitch)); dpi2.bits += dpi2.zoom_level.ApplyInversedTo(leftPitch); dpi2.pitch += dpi2.zoom_level.ApplyInversedTo(leftPitch); - dpi2.x = x; + dpi2.SetX(dpi2.zoom_level.ApplyInversedTo(x)); } - auto paintRight = dpi2.x + dpi2.width; + auto paintRight = dpi2.WorldX() + dpi2.WorldWidth(); if (paintRight >= x + 32) { auto rightPitch = paintRight - x - 32; paintRight -= rightPitch; dpi2.pitch += dpi2.zoom_level.ApplyInversedTo(rightPitch); } - dpi2.width = paintRight - dpi2.x; + dpi2.SetWidth(dpi2.zoom_level.ApplyInversedTo(paintRight - dpi2.WorldX())); if (useMultithreading) { @@ -1127,7 +1126,7 @@ static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const Sc else { ViewportPaintColumn(*session); - DebugDPI(session->DPI); // TODO. Debug change. Revert. + DebugDPI(session->DPI); // TODO. Debug change. Revert. (mber) } } if (useParallelDrawing) @@ -1147,12 +1146,10 @@ static void ViewportPaintWeatherGloom(DrawPixelInfo& dpi) auto paletteId = ClimateGetWeatherGloomPaletteId(GetGameState().ClimateCurrent); if (paletteId != FilterPaletteID::PaletteNull) { - // Only scale width if zoomed in more than 1:1 - auto zoomLevel = dpi.zoom_level < ZoomLevel{ 0 } ? dpi.zoom_level : ZoomLevel{ 0 }; - auto x = dpi.x; - auto y = dpi.y; - auto w = zoomLevel.ApplyInversedTo(dpi.width) - 1; - auto h = zoomLevel.ApplyInversedTo(dpi.height) - 1; + auto x = dpi.ScreenX(); + auto y = dpi.ScreenX(); + auto w = dpi.ScreenWidth() - 1; + auto h = dpi.ScreenHeight() - 1; GfxFilterRect(dpi, ScreenRect(x, y, x + w, y + h), paletteId); } } @@ -1642,7 +1639,7 @@ static bool IsSpriteInteractedWithPaletteSet( } ZoomLevel zoomLevel = dpi.zoom_level; - ScreenCoordsXY interactionPoint{ dpi.x, dpi.y }; + ScreenCoordsXY interactionPoint{ dpi.WorldX(), dpi.WorldY() }; ScreenCoordsXY origin = coords; if (dpi.zoom_level > ZoomLevel{ 0 }) @@ -1816,11 +1813,11 @@ InteractionInfo GetMapCoordinatesFromPosWindow(WindowBase* window, const ScreenC viewLoc.y &= viewport->zoom.ApplyTo(0xFFFFFFFF) & 0xFFFFFFFF; } DrawPixelInfo dpi; - dpi.x = viewLoc.x; - dpi.y = viewLoc.y; - dpi.height = 1; dpi.zoom_level = viewport->zoom; - dpi.width = 1; + dpi.SetX(viewport->zoom.ApplyInversedTo(viewLoc.x)); + dpi.SetY(viewport->zoom.ApplyInversedTo(viewLoc.y)); + dpi.SetHeight(1); + dpi.SetWidth(1); PaintSession* session = PaintSessionAlloc(dpi, viewport->flags, viewport->rotation); PaintSessionGenerate(*session); @@ -2082,14 +2079,14 @@ void ViewportSetSavedView() ZoomLevel ZoomLevel::min() { - // TODO complete work for sofware zooming or revert change. + // TODO (mber) complete work for sofware zooming or revert change. return ZoomLevel{ -2 }; -// #ifndef DISABLE_OPENGL -// if (drawing_engine_get_type() == DrawingEngine::OpenGL) -// { -// return ZoomLevel{ -2 }; -// } -// #endif -// -// return ZoomLevel{ 0 }; + // #ifndef DISABLE_OPENGL + // if (drawing_engine_get_type() == DrawingEngine::OpenGL) + // { + // return ZoomLevel{ -2 }; + // } + // #endif + // + // return ZoomLevel{ 0 }; } diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index 009eb229b8..1abcfe53ef 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -1048,48 +1048,49 @@ static void WindowDrawCore(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int3 static void WindowDrawSingle(DrawPixelInfo& dpi, WindowBase& w, int32_t left, int32_t top, int32_t right, int32_t bottom) { + assert(dpi.zoom_level == ZoomLevel{ 0 }); // Copy dpi so we can crop it DrawPixelInfo copy = dpi; // Clamp left to 0 - int32_t overflow = left - copy.x; + int32_t overflow = left - copy.ScreenX(); if (overflow > 0) { - copy.x += overflow; - copy.width -= overflow; - if (copy.width <= 0) + copy.SetX(copy.ScreenX() + overflow); + copy.SetWidth(copy.ScreenWidth() - overflow); + if (copy.ScreenWidth() <= 0) return; copy.pitch += overflow; copy.bits += overflow; } // Clamp width to right - overflow = copy.x + copy.width - right; + overflow = copy.ScreenX() + copy.ScreenWidth() - right; if (overflow > 0) { - copy.width -= overflow; - if (copy.width <= 0) + copy.SetWidth(copy.ScreenWidth() - overflow); + if (copy.ScreenWidth() <= 0) return; copy.pitch += overflow; } // Clamp top to 0 - overflow = top - copy.y; + overflow = top - copy.ScreenY(); if (overflow > 0) { - copy.y += overflow; - copy.height -= overflow; - if (copy.height <= 0) + copy.SetY(copy.ScreenY() + overflow); + copy.SetHeight(copy.ScreenHeight() - overflow); + if (copy.ScreenHeight() <= 0) return; - copy.bits += (copy.width + copy.pitch) * overflow; + copy.bits += copy.LineStride() * overflow; } // Clamp height to bottom - overflow = copy.y + copy.height - bottom; + overflow = copy.ScreenY() + copy.ScreenHeight() - bottom; if (overflow > 0) { - copy.height -= overflow; - if (copy.height <= 0) + copy.SetHeight(copy.ScreenHeight() - overflow); + if (copy.ScreenHeight() <= 0) return; } diff --git a/src/openrct2/interface/ZoomLevel.h b/src/openrct2/interface/ZoomLevel.h index d680523681..bed59b820d 100644 --- a/src/openrct2/interface/ZoomLevel.h +++ b/src/openrct2/interface/ZoomLevel.h @@ -53,7 +53,7 @@ public: friend constexpr bool operator>(const ZoomLevel& lhs, const ZoomLevel& rhs); friend constexpr bool operator<(const ZoomLevel& lhs, const ZoomLevel& rhs); - template T ApplyTo(const T& lhs) const + template constexpr T ApplyTo(const T& lhs) const { if (_level < 0) return lhs >> -_level; @@ -61,7 +61,7 @@ public: return lhs << _level; } - template T ApplyInversedTo(const T& lhs) const + template constexpr T ApplyInversedTo(const T& lhs) const { if (_level < 0) return lhs << -_level; diff --git a/src/openrct2/paint/Paint.Entity.cpp b/src/openrct2/paint/Paint.Entity.cpp index 0e1d46a54d..654dfb02a7 100644 --- a/src/openrct2/paint/Paint.Entity.cpp +++ b/src/openrct2/paint/Paint.Entity.cpp @@ -101,8 +101,11 @@ void EntityPaintSetup(PaintSession& session, const CoordsXY& pos) screenCoords - ScreenCoordsXY{ spr->SpriteData.Width, spr->SpriteData.HeightMin }, screenCoords + ScreenCoordsXY{ spr->SpriteData.Width, spr->SpriteData.HeightMax }); - if (session.DPI.y + session.DPI.height <= spriteRect.GetTop() || spriteRect.GetBottom() <= session.DPI.y - || session.DPI.x + session.DPI.width <= spriteRect.GetLeft() || spriteRect.GetRight() <= session.DPI.x) + // We must compare with world DPI coordinates as spriteRect is not adjusted for the DPI zoom. + if (session.DPI.WorldY() + session.DPI.WorldHeight() <= spriteRect.GetTop() + || spriteRect.GetBottom() <= session.DPI.WorldY() + || session.DPI.WorldX() + session.DPI.WorldWidth() <= spriteRect.GetLeft() + || spriteRect.GetRight() <= session.DPI.WorldX()) { continue; } diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index aa9e969d2a..fa2306c8be 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -109,13 +109,13 @@ static constexpr bool ImageWithinDPI(const ScreenCoordsXY& imagePos, const G1Ele int32_t right = left + g1.width; int32_t top = bottom + g1.height; - if (right <= dpi.x) + if (right <= dpi.WorldX()) return false; - if (top <= dpi.y) + if (top <= dpi.WorldY()) return false; - if (left >= dpi.x + dpi.width) + if (left >= dpi.WorldX() + dpi.WorldWidth()) return false; - if (bottom >= dpi.y + dpi.height) + if (bottom >= dpi.WorldY() + dpi.WorldHeight()) return false; return true; } @@ -200,7 +200,7 @@ static PaintStruct* CreateNormalPaintStruct( template void PaintSessionGenerateRotate(PaintSession& session) { // Optimised modified version of ViewportPosToMapPos - ScreenCoordsXY screenCoord = { Floor2(session.DPI.x, 32), Floor2((session.DPI.y - 16), 32) }; + ScreenCoordsXY screenCoord = { Floor2(session.DPI.WorldX(), 32), Floor2((session.DPI.WorldY() - 16), 32) }; CoordsXY mapTile = { screenCoord.y - screenCoord.x / 2, screenCoord.y + screenCoord.x / 2 }; mapTile = mapTile.Rotate(direction); @@ -210,7 +210,7 @@ template void PaintSessionGenerateRotate(PaintSession& sessio } mapTile = mapTile.ToTileStart(); - uint16_t numVerticalTiles = (session.DPI.height + 2128) >> 5; + uint16_t numVerticalTiles = (session.DPI.WorldHeight() + 2128) >> 5; // Adjacent tiles to also check due to overlapping of sprites constexpr CoordsXY adjacentTiles[] = { diff --git a/src/openrct2/paint/tile_element/Paint.TileElement.cpp b/src/openrct2/paint/tile_element/Paint.TileElement.cpp index aa6386c00c..34691e8d0d 100644 --- a/src/openrct2/paint/tile_element/Paint.TileElement.cpp +++ b/src/openrct2/paint/tile_element/Paint.TileElement.cpp @@ -91,11 +91,11 @@ static void BlankTilesPaint(PaintSession& session, int32_t x, int32_t y) dx -= 16; int32_t bx = dx + 32; - if (bx <= session.DPI.y) + if (bx <= session.DPI.WorldY()) return; dx -= 20; - dx -= session.DPI.height; - if (dx >= session.DPI.y) + dx -= session.DPI.WorldHeight(); + if (dx >= session.DPI.WorldY()) return; session.SpritePosition.x = x; @@ -179,7 +179,7 @@ static void PaintTileElementBase(PaintSession& session, const CoordsXY& origCoor PaintAddImageAsParent(session, imageId, { 0, 0, arrowZ }, { { 0, 0, arrowZ + 18 }, { 32, 32, -1 } }); } - if (screenMinY + 52 <= session.DPI.y) + if (screenMinY + 52 <= session.DPI.WorldY()) return; const TileElement* element = tile_element; // push tile_element @@ -203,7 +203,7 @@ static void PaintTileElementBase(PaintSession& session, const CoordsXY& origCoor max_height = std::max(max_height, VirtualFloorGetHeight()); } - if (screenMinY - (max_height + 32) >= session.DPI.y + session.DPI.height) + if (screenMinY - (max_height + 32) >= session.DPI.WorldY() + session.DPI.WorldHeight()) return; session.SpritePosition.x = coords.x; diff --git a/src/openrct2/ride/CarEntry.cpp b/src/openrct2/ride/CarEntry.cpp index 460c385491..6e6952d8c9 100644 --- a/src/openrct2/ride/CarEntry.cpp +++ b/src/openrct2/ride/CarEntry.cpp @@ -48,15 +48,14 @@ void CarEntrySetImageMaxSizes(CarEntry& carEntry, int32_t numImages) { uint8_t bitmap[200][200] = { 0 }; - DrawPixelInfo dpi = { - /*.bits = */ reinterpret_cast(bitmap), - /*.x = */ -100, - /*.y = */ -100, - /*.width = */ 200, - /*.height = */ 200, - /*.pitch = */ 0, - /*.zoom_level = */ ZoomLevel{ 0 }, - }; + DrawPixelInfo dpi; + dpi.zoom_level = ZoomLevel{ 0 }; + dpi.bits = reinterpret_cast(bitmap); + dpi.pitch = 0; + dpi.SetX(-100); + dpi.SetY(-100); + dpi.SetWidth(200); + dpi.SetHeight(200); for (int32_t i = 0; i < numImages; ++i) { diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index dc71c37fb7..09af8ec60e 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -2119,11 +2119,11 @@ void TrackDesignDrawPreview(TrackDesign& td, uint8_t* pixels) view.flags = VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_ENTITIES; DrawPixelInfo dpi; - dpi.zoom_level = zoom_level; - dpi.x = 0; - dpi.y = 0; - dpi.width = 370; - dpi.height = 217; + // dpi.zoom_level = zoom_level; // TODO (mber) this can be removed I think + dpi.SetX(0); + dpi.SetY(0); + dpi.SetWidth(370); + dpi.SetHeight(217); dpi.pitch = 0; dpi.bits = pixels;