diff --git a/contributors.md b/contributors.md index 25c4082a91..34c3d18bde 100644 --- a/contributors.md +++ b/contributors.md @@ -178,6 +178,7 @@ The following people are not part of the development team, but have been contrib * (ocalhoun6) * Sean Payne (seanmajorpayne) * Soham Roy (sohamroy19) +* Gaven Rendell (Rendello) ## Toolchain * (Balletie) - macOS diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 432cd2d76f..744d2249c1 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -28,12 +28,14 @@ - Fix: [#15255] Tile Inspector shows banner information on walls that do not contain one. - Fix: [#15257] Chat icon shows in scenario/track editor. Other icons don't disable when deactivated in options menu. - Fix: [#15289] Unexpected behavior with duplicated banners which also caused desyncs in multiplayer. +- Fix: [#15451] Guest list name filter remains after group selection. - Fix: [#15476] Crash when placing/clearing small scenery. - Fix: [#15487] Map animations do not work correctly when loading an exported SV6 file in vanilla RCT2. - Fix: [#15496] Crash in paint_swinging_inverter_ship_structure(). - Fix: [#15503] Freeze when doing specific coaster merges with block brakes. - Fix: [#15514] Two different “quit to menu” menu items are available in track designer and track design manager. - Improved: [#3417] Crash dumps are now placed in their own folder. +- Improved: [#15538] Software rendering can now draw in parallel when Multithreading is enabled. - Change: [#8601] Revert ToonTower base block fix to re-enable support blocking. - Change: [#15174] [Plugin] Deprecate the type "peep" and add support to target a specific scripting api version. diff --git a/src/openrct2-ui/UiContext.cpp b/src/openrct2-ui/UiContext.cpp index 9031f447a1..1410aa0cdc 100644 --- a/src/openrct2-ui/UiContext.cpp +++ b/src/openrct2-ui/UiContext.cpp @@ -296,7 +296,7 @@ public: for (auto& w : g_window_list) { - DrawWeatherWindow(weatherDrawer, w.get(), left, right, top, bottom, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, w.get(), left, right, top, bottom, drawFunc); } } @@ -523,6 +523,15 @@ public: #endif case SDL_KEYDOWN: { +#ifndef __MACOSX__ + // Ignore winkey keydowns. Handles edge case where tiling + // window managers don't eat the keypresses when changing + // workspaces. + if (SDL_GetModState() & KMOD_GUI) + { + break; + } +#endif _textComposition.HandleMessage(&e); auto ie = GetInputEventFromSDLEvent(e); ie.State = InputEventState::Down; @@ -860,8 +869,8 @@ private: } static void DrawWeatherWindow( - IWeatherDrawer* weatherDrawer, rct_window* original_w, int16_t left, int16_t right, int16_t top, int16_t bottom, - DrawWeatherFunc drawFunc) + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, rct_window* original_w, int16_t left, int16_t right, int16_t top, + int16_t bottom, DrawWeatherFunc drawFunc) { rct_window* w{}; auto itStart = window_get_iterator(original_w); @@ -881,7 +890,7 @@ private: { auto width = right - left; auto height = bottom - top; - drawFunc(weatherDrawer, left, top, width, height); + drawFunc(dpi, weatherDrawer, left, top, width, height); } } return; @@ -903,39 +912,39 @@ private: break; } - DrawWeatherWindow(weatherDrawer, original_w, left, w->windowPos.x, top, bottom, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, original_w, left, w->windowPos.x, top, bottom, drawFunc); left = w->windowPos.x; - DrawWeatherWindow(weatherDrawer, original_w, left, right, top, bottom, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, original_w, left, right, top, bottom, drawFunc); return; } int16_t w_right = RCT_WINDOW_RIGHT(w); if (right > w_right) { - DrawWeatherWindow(weatherDrawer, original_w, left, w_right, top, bottom, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, original_w, left, w_right, top, bottom, drawFunc); left = w_right; - DrawWeatherWindow(weatherDrawer, original_w, left, right, top, bottom, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, original_w, left, right, top, bottom, drawFunc); return; } if (top < w->windowPos.y) { - DrawWeatherWindow(weatherDrawer, original_w, left, right, top, w->windowPos.y, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, original_w, left, right, top, w->windowPos.y, drawFunc); top = w->windowPos.y; - DrawWeatherWindow(weatherDrawer, original_w, left, right, top, bottom, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, original_w, left, right, top, bottom, drawFunc); return; } int16_t w_bottom = RCT_WINDOW_BOTTOM(w); if (bottom > w_bottom) { - DrawWeatherWindow(weatherDrawer, original_w, left, right, top, w_bottom, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, original_w, left, right, top, w_bottom, drawFunc); top = w_bottom; - DrawWeatherWindow(weatherDrawer, original_w, left, right, top, bottom, drawFunc); + DrawWeatherWindow(dpi, weatherDrawer, original_w, left, right, top, bottom, drawFunc); return; } } diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index ad808f966f..9216d261d8 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -57,7 +57,6 @@ class OpenGLDrawingContext final : public IDrawingContext { private: OpenGLDrawingEngine* _engine = nullptr; - rct_drawpixelinfo* _dpi = nullptr; ApplyTransparencyShader* _applyTransparencyShader = nullptr; DrawLineShader* _drawLineShader = nullptr; DrawRectShader* _drawRectShader = nullptr; @@ -101,27 +100,25 @@ public: void ResetPalette(); void StartNewDraw(); - void Clear(uint8_t paletteIndex) override; - void FillRect(uint32_t colour, int32_t x, int32_t y, int32_t w, int32_t h) override; - void FilterRect(FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) override; - void DrawLine(uint32_t colour, const ScreenLine& line) override; - void DrawSprite(uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) override; - void DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) override; - void DrawSpriteSolid(uint32_t image, int32_t x, int32_t y, uint8_t colour) override; - void DrawGlyph(uint32_t image, int32_t x, int32_t y, const PaletteMap& palette) override; - void DrawBitmap(uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, int32_t y) override; + void Clear(rct_drawpixelinfo* dpi, uint8_t paletteIndex) override; + void FillRect(rct_drawpixelinfo* dpi, uint32_t colour, int32_t x, int32_t y, int32_t w, int32_t h) override; + void FilterRect( + rct_drawpixelinfo* dpi, FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) override; + void DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const ScreenLine& line) override; + void DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) override; + void DrawSpriteRawMasked(rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) override; + void DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint8_t colour) override; + void DrawGlyph(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, const PaletteMap& palette) override; + void DrawBitmap( + rct_drawpixelinfo* dpi, uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, + int32_t y) override; void FlushCommandBuffers(); void FlushLines(); void FlushRectangles(); void HandleTransparency(); - - void SetDPI(rct_drawpixelinfo* dpi); - rct_drawpixelinfo* GetDPI() const - { - return _dpi; - } + void CalculcateClipping(rct_drawpixelinfo* dpi); }; class OpenGLWeatherDrawer final : public IWeatherDrawer @@ -135,7 +132,7 @@ public: } virtual void Draw( - int32_t x, int32_t y, int32_t width, int32_t height, int32_t xStart, int32_t yStart, + rct_drawpixelinfo* dpi, int32_t x, int32_t y, int32_t width, int32_t height, int32_t xStart, int32_t yStart, const uint8_t* weatherpattern) override { const uint8_t* pattern = weatherpattern; @@ -145,8 +142,6 @@ public: uint8_t patternStartXOffset = xStart % patternXSpace; uint8_t patternStartYOffset = yStart % patternYSpace; - const auto* dpi = _drawingContext->GetDPI(); - uint32_t pixelOffset = (dpi->pitch + dpi->width) * y + x; uint8_t patternYPos = patternStartYOffset % patternYSpace; @@ -166,7 +161,7 @@ public: int32_t pixelX = xPixelOffset % dpi->width; int32_t pixelY = (xPixelOffset / dpi->width) % dpi->height; - _drawingContext->DrawLine(patternPixel, { { pixelX, pixelY }, { pixelX + 1, pixelY + 1 } }); + _drawingContext->DrawLine(dpi, patternPixel, { { pixelX, pixelY }, { pixelX + 1, pixelY + 1 } }); } } @@ -298,6 +293,7 @@ public: assert(_screenFramebuffer != nullptr); _drawingContext->StartNewDraw(); + _drawingContext->CalculcateClipping(&_bitsDPI); } void EndDraw() override @@ -335,13 +331,16 @@ public: void PaintWindows() override { + _drawingContext->CalculcateClipping(&_bitsDPI); + window_update_all_viewports(); window_draw_all(&_bitsDPI, 0, 0, _width, _height); } void PaintWeather() override { - _drawingContext->SetDPI(&_bitsDPI); + _drawingContext->CalculcateClipping(&_bitsDPI); + DrawWeather(&_bitsDPI, &_weatherDrawer); } @@ -359,9 +358,8 @@ public: // Not applicable for this engine } - IDrawingContext* GetDrawingContext(rct_drawpixelinfo* dpi) override + IDrawingContext* GetDrawingContext() override { - _drawingContext->SetDPI(dpi); return _drawingContext; } @@ -541,13 +539,18 @@ void OpenGLDrawingContext::StartNewDraw() _swapFramebuffer->Clear(); } -void OpenGLDrawingContext::Clear(uint8_t paletteIndex) +void OpenGLDrawingContext::Clear(rct_drawpixelinfo* dpi, uint8_t paletteIndex) { - FillRect(paletteIndex, _clipLeft - _offsetX, _clipTop - _offsetY, _clipRight - _offsetX, _clipBottom - _offsetY); + CalculcateClipping(dpi); + + FillRect(dpi, paletteIndex, _clipLeft - _offsetX, _clipTop - _offsetY, _clipRight - _offsetX, _clipBottom - _offsetY); } -void OpenGLDrawingContext::FillRect(uint32_t colour, int32_t left, int32_t top, int32_t right, int32_t bottom) +void OpenGLDrawingContext::FillRect( + rct_drawpixelinfo* dpi, uint32_t colour, int32_t left, int32_t top, int32_t right, int32_t bottom) { + CalculcateClipping(dpi); + left += _offsetX; top += _offsetY; right += _offsetX; @@ -578,8 +581,11 @@ void OpenGLDrawingContext::FillRect(uint32_t colour, int32_t left, int32_t top, } } -void OpenGLDrawingContext::FilterRect(FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) +void OpenGLDrawingContext::FilterRect( + rct_drawpixelinfo* dpi, FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) { + CalculcateClipping(dpi); + left += _offsetX; top += _offsetY; right += _offsetX; @@ -599,8 +605,10 @@ void OpenGLDrawingContext::FilterRect(FilterPaletteID palette, int32_t left, int command.depth = _drawCount++; } -void OpenGLDrawingContext::DrawLine(uint32_t colour, const ScreenLine& line) +void OpenGLDrawingContext::DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const ScreenLine& line) { + CalculcateClipping(dpi); + DrawLineCommand& command = _commandBuffers.lines.allocate(); command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom }; @@ -609,8 +617,10 @@ void OpenGLDrawingContext::DrawLine(uint32_t colour, const ScreenLine& line) command.depth = _drawCount++; } -void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) +void OpenGLDrawingContext::DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) { + CalculcateClipping(dpi); + int32_t g1Id = image & 0x7FFFF; auto g1Element = gfx_get_g1_element(g1Id); if (g1Element == nullptr) @@ -618,20 +628,19 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint return; } - if (_dpi->zoom_level > 0) + if (dpi->zoom_level > 0) { if (g1Element->flags & G1_FLAG_HAS_ZOOM_SPRITE) { rct_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.pitch = _dpi->pitch; - zoomedDPI.zoom_level = _dpi->zoom_level - 1; - SetDPI(&zoomedDPI); - DrawSprite((image & 0xFFF80000) | (g1Id - g1Element->zoomed_offset), x >> 1, y >> 1, tertiaryColour); + 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.pitch = dpi->pitch; + zoomedDPI.zoom_level = dpi->zoom_level - 1; + DrawSprite(&zoomedDPI, (image & 0xFFF80000) | (g1Id - g1Element->zoomed_offset), x >> 1, y >> 1, tertiaryColour); return; } if (g1Element->flags & G1_FLAG_NO_ZOOM_DRAW) @@ -644,11 +653,11 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint int32_t top = y + g1Element->y_offset; int32_t zoom_mask; - if (_dpi->zoom_level >= 0) - zoom_mask = 0xFFFFFFFF * _dpi->zoom_level; + if (dpi->zoom_level >= 0) + zoom_mask = 0xFFFFFFFF * dpi->zoom_level; else zoom_mask = 0xFFFFFFFF; - if (_dpi->zoom_level != 0 && (g1Element->flags & G1_FLAG_RLE_COMPRESSION)) + if (dpi->zoom_level != 0 && (g1Element->flags & G1_FLAG_RLE_COMPRESSION)) { top -= ~zoom_mask; } @@ -664,7 +673,7 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint int32_t right = left + g1Element->width; int32_t bottom = top + g1Element->height; - if (_dpi->zoom_level != 0 && (g1Element->flags & G1_FLAG_RLE_COMPRESSION)) + if (dpi->zoom_level != 0 && (g1Element->flags & G1_FLAG_RLE_COMPRESSION)) { bottom += top & ~zoom_mask; } @@ -678,15 +687,15 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint std::swap(top, bottom); } - left -= _dpi->x; - top -= _dpi->y; - right -= _dpi->x; - bottom -= _dpi->y; + left -= dpi->x; + top -= dpi->y; + right -= dpi->x; + bottom -= dpi->y; - left = left / _dpi->zoom_level; - top = top / _dpi->zoom_level; - right = right / _dpi->zoom_level; - bottom = bottom / _dpi->zoom_level; + left = left / dpi->zoom_level; + top = top / dpi->zoom_level; + right = right / dpi->zoom_level; + bottom = bottom / dpi->zoom_level; left += _spriteOffset.x; top += _spriteOffset.y; @@ -759,8 +768,11 @@ void OpenGLDrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint } } -void OpenGLDrawingContext::DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) +void OpenGLDrawingContext::DrawSpriteRawMasked( + rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) { + CalculcateClipping(dpi); + auto g1ElementMask = gfx_get_g1_element(maskImage & 0x7FFFF); auto g1ElementColour = gfx_get_g1_element(colourImage & 0x7FFFF); if (g1ElementMask == nullptr || g1ElementColour == nullptr) @@ -790,15 +802,15 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t ma std::swap(top, bottom); } - left -= _dpi->x; - top -= _dpi->y; - right -= _dpi->x; - bottom -= _dpi->y; + left -= dpi->x; + top -= dpi->y; + right -= dpi->x; + bottom -= dpi->y; - left = left / _dpi->zoom_level; - top = top / _dpi->zoom_level; - right = right / _dpi->zoom_level; - bottom = bottom / _dpi->zoom_level; + left = left / dpi->zoom_level; + top = top / dpi->zoom_level; + right = right / dpi->zoom_level; + bottom = bottom / dpi->zoom_level; left += _spriteOffset.x; top += _spriteOffset.y; @@ -819,8 +831,10 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t ma command.depth = _drawCount++; } -void OpenGLDrawingContext::DrawSpriteSolid(uint32_t image, int32_t x, int32_t y, uint8_t colour) +void OpenGLDrawingContext::DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint8_t colour) { + CalculcateClipping(dpi); + assert((colour & 0xFF) > 0u); int32_t g1Id = image & 0x7FFFF; @@ -870,8 +884,10 @@ void OpenGLDrawingContext::DrawSpriteSolid(uint32_t image, int32_t x, int32_t y, command.depth = _drawCount++; } -void OpenGLDrawingContext::DrawGlyph(uint32_t image, int32_t x, int32_t y, const PaletteMap& palette) +void OpenGLDrawingContext::DrawGlyph(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, const PaletteMap& palette) { + CalculcateClipping(dpi); + auto g1Element = gfx_get_g1_element(image & 0x7FFFF); if (g1Element == nullptr) { @@ -894,15 +910,15 @@ void OpenGLDrawingContext::DrawGlyph(uint32_t image, int32_t x, int32_t y, const std::swap(top, bottom); } - left -= _dpi->x; - top -= _dpi->y; - right -= _dpi->x; - bottom -= _dpi->y; + left -= dpi->x; + top -= dpi->y; + right -= dpi->x; + bottom -= dpi->y; - left = left / _dpi->zoom_level; - top = top / _dpi->zoom_level; - right = right / _dpi->zoom_level; - bottom = bottom / _dpi->zoom_level; + left = left / dpi->zoom_level; + top = top / dpi->zoom_level; + right = right / dpi->zoom_level; + bottom = bottom / dpi->zoom_level; left += _spriteOffset.x; top += _spriteOffset.y; @@ -923,8 +939,11 @@ void OpenGLDrawingContext::DrawGlyph(uint32_t image, int32_t x, int32_t y, const command.depth = _drawCount++; } -void OpenGLDrawingContext::DrawBitmap(uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, int32_t y) +void OpenGLDrawingContext::DrawBitmap( + rct_drawpixelinfo* dpi, uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, int32_t y) { + CalculcateClipping(dpi); + const auto texture = _textureCache->GetOrLoadBitmapTexture(image, pixels, width, height); int32_t drawOffsetX = 0; @@ -1041,7 +1060,7 @@ void OpenGLDrawingContext::HandleTransparency() _commandBuffers.transparent.clear(); } -void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo* dpi) +void OpenGLDrawingContext::CalculcateClipping(rct_drawpixelinfo* dpi) { auto screenDPI = _engine->GetDPI(); auto bytesPerRow = screenDPI->GetBytesPerRow(); @@ -1059,8 +1078,6 @@ void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo* dpi) _offsetY = _clipTop - dpi->y; _spriteOffset.x = _clipLeft - dpi->remX; _spriteOffset.y = _clipTop - dpi->remY; - - _dpi = dpi; } #endif /* DISABLE_OPENGL */ diff --git a/src/openrct2-ui/windows/GuestList.cpp b/src/openrct2-ui/windows/GuestList.cpp index 9909718c7a..e70c7c4f83 100644 --- a/src/openrct2-ui/windows/GuestList.cpp +++ b/src/openrct2-ui/windows/GuestList.cpp @@ -321,8 +321,13 @@ public: _selectedPage = 0; _numPages = 1; widgets[WIDX_TRACKING].type = WindowWidgetType::Empty; - widgets[WIDX_FILTER_BY_NAME].type = WindowWidgetType::Empty; - if (_selectedTab == TabId::Individual) + if (_selectedTab == TabId::Summarised) + { + widgets[WIDX_FILTER_BY_NAME].type = WindowWidgetType::Empty; + SetWidgetPressed(WIDX_FILTER_BY_NAME, false); + _filterName.clear(); + } + else if (_selectedTab == TabId::Individual) { widgets[WIDX_TRACKING].type = WindowWidgetType::FlatBtn; widgets[WIDX_FILTER_BY_NAME].type = WindowWidgetType::FlatBtn; @@ -576,6 +581,7 @@ public: _selectedTab = TabId::Individual; widgets[WIDX_TRACKING].type = WindowWidgetType::FlatBtn; Invalidate(); + widgets[WIDX_FILTER_BY_NAME].type = WindowWidgetType::FlatBtn; scrolls[0].v_top = 0; RefreshList(); } diff --git a/src/openrct2-ui/windows/ViewClipping.cpp b/src/openrct2-ui/windows/ViewClipping.cpp index e4c897d335..296dc786ac 100644 --- a/src/openrct2-ui/windows/ViewClipping.cpp +++ b/src/openrct2-ui/windows/ViewClipping.cpp @@ -41,8 +41,6 @@ enum class DISPLAY_TYPE { DISPLAY_UNITS }; -static DISPLAY_TYPE gClipHeightDisplayType = DISPLAY_TYPE::DISPLAY_UNITS; - #pragma region Widgets static constexpr const rct_string_id WINDOW_TITLE = STR_VIEW_CLIPPING_TITLE; @@ -64,373 +62,348 @@ static rct_widget window_view_clipping_widgets[] = { #pragma endregion -#pragma region Members - -static CoordsXY _selectionStart; -static CoordsXY _previousClipSelectionA; -static CoordsXY _previousClipSelectionB; -static bool _toolActive; -static bool _dragging; - -#pragma endregion - -#pragma region Events - -static void window_view_clipping_close_button(rct_window* w); -static void window_view_clipping_mouseup(rct_window* w, rct_widgetindex widgetIndex); -static void window_view_clipping_mousedown(rct_window*w, rct_widgetindex widgetIndex, rct_widget *widget); -static void window_view_clipping_update(rct_window* w); -static void window_view_clipping_tool_update(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords); -static void window_view_clipping_tool_down(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords); -static void window_view_clipping_tool_drag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords); -static void window_view_clipping_tool_up(rct_window* w, rct_widgetindex, const ScreenCoordsXY&); -static void window_view_clipping_invalidate(rct_window* w); -static void window_view_clipping_paint(rct_window* w, rct_drawpixelinfo* dpi); -static void window_view_clipping_scrollgetsize(rct_window* w, int scrollIndex, int* width, int* height); -static void window_view_clipping_close(); - -static rct_window_event_list window_view_clipping_events([](auto& events) -{ - events.close = &window_view_clipping_close_button; - events.mouse_up = &window_view_clipping_mouseup; - events.mouse_down = &window_view_clipping_mousedown; - events.update = &window_view_clipping_update; - events.tool_update = &window_view_clipping_tool_update; - events.tool_down = &window_view_clipping_tool_down; - events.tool_drag = &window_view_clipping_tool_drag; - events.tool_up = &window_view_clipping_tool_up; - events.get_scroll_size = &window_view_clipping_scrollgetsize; - events.invalidate = &window_view_clipping_invalidate; - events.paint = &window_view_clipping_paint; -}); // clang-format on - -#pragma endregion - -static void window_view_clipping_set_clipheight(rct_window* w, const uint8_t clipheight) +class ViewClippingWindow final : public Window { - gClipHeight = clipheight; - rct_widget* widget = &window_view_clipping_widgets[WIDX_CLIP_HEIGHT_SLIDER]; - const float clip_height_ratio = static_cast(gClipHeight) / 255; - w->scrolls[0].h_left = static_cast(std::ceil(clip_height_ratio * (w->scrolls[0].h_right - (widget->width() - 1)))); -} +private: + CoordsXY _selectionStart; + CoordsXY _previousClipSelectionA; + CoordsXY _previousClipSelectionB; + bool _toolActive{ false }; + bool _dragging{ false }; + static inline DISPLAY_TYPE _clipHeightDisplayType; -rct_window* window_view_clipping_open() -{ - rct_window* window; - - // Get the main viewport to set the view clipping flag. - rct_window* mainWindow = window_get_main(); - - // Check if window is already open - window = window_find_by_class(WC_VIEW_CLIPPING); - if (window != nullptr) +public: + void OnCloseButton() { - return window; + OnClose(); } - // Window is not open - create it. - window = WindowCreate(ScreenCoordsXY(32, 32), WW, WH, &window_view_clipping_events, WC_VIEW_CLIPPING, 0); - window->widgets = window_view_clipping_widgets; - window->enabled_widgets = (1ULL << WIDX_CLOSE) | (1ULL << WIDX_CLIP_CHECKBOX_ENABLE) | (1ULL << WIDX_CLIP_HEIGHT_VALUE) - | (1ULL << WIDX_CLIP_HEIGHT_INCREASE) | (1ULL << WIDX_CLIP_HEIGHT_DECREASE) | (1ULL << WIDX_CLIP_HEIGHT_SLIDER) - | (1ULL << WIDX_CLIP_SELECTOR) | (1ULL << WIDX_CLIP_CLEAR); - window->hold_down_widgets = (1ULL << WIDX_CLIP_HEIGHT_INCREASE) | (1UL << WIDX_CLIP_HEIGHT_DECREASE); - - WindowInitScrollWidgets(window); - - // Initialise the clip height slider from the current clip height value. - window_view_clipping_set_clipheight(window, gClipHeight); - - window_push_others_below(window); - - // Turn on view clipping when the window is opened. - if (mainWindow != nullptr) + void OnMouseUp(rct_widgetindex widgetIndex) override { - mainWindow->viewport->flags |= VIEWPORT_FLAG_CLIP_VIEW; - mainWindow->Invalidate(); + // mouseup appears to be used for buttons, checkboxes + switch (widgetIndex) + { + case WIDX_CLOSE: + window_close(this); + break; + case WIDX_CLIP_CHECKBOX_ENABLE: + { + // Toggle height clipping. + rct_window* mainWindow = window_get_main(); + if (mainWindow != nullptr) + { + mainWindow->viewport->flags ^= VIEWPORT_FLAG_CLIP_VIEW; + mainWindow->Invalidate(); + } + this->Invalidate(); + break; + } + case WIDX_CLIP_HEIGHT_VALUE: + // Toggle display of the cut height value in RAW vs UNITS + if (_clipHeightDisplayType == DISPLAY_TYPE::DISPLAY_RAW) + { + _clipHeightDisplayType = DISPLAY_TYPE::DISPLAY_UNITS; + } + else + { + _clipHeightDisplayType = DISPLAY_TYPE::DISPLAY_RAW; + } + this->Invalidate(); + break; + case WIDX_CLIP_SELECTOR: + // Activate the selection tool + tool_set(this, WIDX_BACKGROUND, Tool::Crosshair); + _toolActive = true; + _dragging = false; + + // Reset clip selection to show all tiles + _previousClipSelectionA = gClipSelectionA; + _previousClipSelectionB = gClipSelectionB; + gClipSelectionA = { 0, 0 }; + gClipSelectionB = { MAXIMUM_MAP_SIZE_BIG - 1, MAXIMUM_MAP_SIZE_BIG - 1 }; + gfx_invalidate_screen(); + break; + case WIDX_CLIP_CLEAR: + if (IsActive()) + { + _toolActive = false; + tool_cancel(); + } + gClipSelectionA = { 0, 0 }; + gClipSelectionB = { MAXIMUM_MAP_SIZE_BIG - 1, MAXIMUM_MAP_SIZE_BIG - 1 }; + gfx_invalidate_screen(); + break; + } } - _toolActive = false; - _dragging = false; - - return window; -} - -static void window_view_clipping_close() -{ - // Turn off view clipping when the window is closed. - rct_window* mainWindow = window_get_main(); - if (mainWindow != nullptr) + void OnMouseDown(rct_widgetindex widgetIndex) override { - mainWindow->viewport->flags &= ~VIEWPORT_FLAG_CLIP_VIEW; - mainWindow->Invalidate(); + rct_window* mainWindow; + + switch (widgetIndex) + { + case WIDX_CLIP_HEIGHT_INCREASE: + if (gClipHeight < 255) + SetClipHeight(gClipHeight + 1); + mainWindow = window_get_main(); + if (mainWindow != nullptr) + mainWindow->Invalidate(); + break; + case WIDX_CLIP_HEIGHT_DECREASE: + if (gClipHeight > 0) + SetClipHeight(gClipHeight - 1); + mainWindow = window_get_main(); + if (mainWindow != nullptr) + mainWindow->Invalidate(); + break; + } } -} -static void window_view_clipping_close_button(rct_window* w) -{ - window_view_clipping_close(); -} - -// Returns true when the tool is active -static bool window_view_clipping_tool_is_active() -{ - if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE))) - return false; - if (gCurrentToolWidget.window_classification != WC_VIEW_CLIPPING) - return false; - return _toolActive; -} - -static void window_view_clipping_mouseup(rct_window* w, rct_widgetindex widgetIndex) -{ - rct_window* mainWindow; - - // mouseup appears to be used for buttons, checkboxes - switch (widgetIndex) + void OnUpdate() override { - case WIDX_CLOSE: - window_close(w); - break; - case WIDX_CLIP_CHECKBOX_ENABLE: - // Toggle height clipping. - mainWindow = window_get_main(); + const auto& widget = widgets[WIDX_CLIP_HEIGHT_SLIDER]; + const rct_scroll* const scroll = &this->scrolls[0]; + const int16_t scroll_width = widget.width() - 1; + const uint8_t clip_height = static_cast( + (static_cast(scroll->h_left) / (scroll->h_right - scroll_width)) * 255); + if (clip_height != gClipHeight) + { + gClipHeight = clip_height; + + // Update the main window accordingly. + rct_window* mainWindow = window_get_main(); if (mainWindow != nullptr) { - mainWindow->viewport->flags ^= VIEWPORT_FLAG_CLIP_VIEW; mainWindow->Invalidate(); } - w->Invalidate(); - break; - case WIDX_CLIP_HEIGHT_VALUE: - // Toggle display of the cut height value in RAW vs UNITS - if (gClipHeightDisplayType == DISPLAY_TYPE::DISPLAY_RAW) - { - gClipHeightDisplayType = DISPLAY_TYPE::DISPLAY_UNITS; - } - else - { - gClipHeightDisplayType = DISPLAY_TYPE::DISPLAY_RAW; - } - w->Invalidate(); - break; - case WIDX_CLIP_SELECTOR: - // Activate the selection tool - tool_set(w, WIDX_BACKGROUND, Tool::Crosshair); - _toolActive = true; - _dragging = false; + } - // Reset clip selection to show all tiles - _previousClipSelectionA = gClipSelectionA; - _previousClipSelectionB = gClipSelectionB; - gClipSelectionA = { 0, 0 }; - gClipSelectionB = { MAXIMUM_MAP_SIZE_BIG - 1, MAXIMUM_MAP_SIZE_BIG - 1 }; - gfx_invalidate_screen(); - break; - case WIDX_CLIP_CLEAR: - if (window_view_clipping_tool_is_active()) - { - _toolActive = false; - tool_cancel(); - } - gClipSelectionA = { 0, 0 }; - gClipSelectionB = { MAXIMUM_MAP_SIZE_BIG - 1, MAXIMUM_MAP_SIZE_BIG - 1 }; - gfx_invalidate_screen(); - break; + // Restore previous selection if the tool has been interrupted + if (_toolActive && !IsActive()) + { + _toolActive = false; + gClipSelectionA = _previousClipSelectionA; + gClipSelectionB = _previousClipSelectionB; + } + + widget_invalidate(this, WIDX_CLIP_HEIGHT_SLIDER); } -} -static void window_view_clipping_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget) -{ - rct_window* mainWindow = window_get_main(); - - switch (widgetIndex) + void OnToolUpdate(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override { - case WIDX_CLIP_HEIGHT_INCREASE: - if (gClipHeight < 255) - window_view_clipping_set_clipheight(w, gClipHeight + 1); - if (mainWindow != nullptr) - mainWindow->Invalidate(); - break; - case WIDX_CLIP_HEIGHT_DECREASE: - if (gClipHeight > 0) - window_view_clipping_set_clipheight(w, gClipHeight - 1); - if (mainWindow != nullptr) - mainWindow->Invalidate(); - break; + if (_dragging) + { + return; + } + + int32_t direction; + auto mapCoords = screen_pos_to_map_pos(screenCoords, &direction); + if (mapCoords.has_value()) + { + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; + map_invalidate_tile_full(gMapSelectPositionA); + gMapSelectPositionA = gMapSelectPositionB = mapCoords.value(); + map_invalidate_tile_full(mapCoords.value()); + gMapSelectType = MAP_SELECT_TYPE_FULL; + } } -} -static void window_view_clipping_update(rct_window* w) -{ - const rct_widget* const widget = &window_view_clipping_widgets[WIDX_CLIP_HEIGHT_SLIDER]; - const rct_scroll* const scroll = &w->scrolls[0]; - const int16_t scroll_width = widget->width() - 1; - const uint8_t clip_height = static_cast( - (static_cast(scroll->h_left) / (scroll->h_right - scroll_width)) * 255); - if (clip_height != gClipHeight) + void OnToolDown(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override { - gClipHeight = clip_height; + int32_t direction; + auto mapCoords = screen_pos_to_map_pos(screenCoords, &direction); + if (mapCoords.has_value()) + { + _dragging = true; + _selectionStart = mapCoords.value(); + } + } + + void OnToolDrag(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override + { + if (!_dragging) + { + return; + } + + int32_t direction; + auto mapCoords = screen_pos_to_map_pos(screenCoords, &direction); + if (mapCoords) + { + map_invalidate_selection_rect(); + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; + gMapSelectPositionA.x = std::min(_selectionStart.x, mapCoords->x); + gMapSelectPositionB.x = std::max(_selectionStart.x, mapCoords->x); + gMapSelectPositionA.y = std::min(_selectionStart.y, mapCoords->y); + gMapSelectPositionB.y = std::max(_selectionStart.y, mapCoords->y); + gMapSelectType = MAP_SELECT_TYPE_FULL; + map_invalidate_selection_rect(); + } + } + + void OnToolUp(rct_widgetindex, const ScreenCoordsXY&) override + { + gClipSelectionA = gMapSelectPositionA; + gClipSelectionB = gMapSelectPositionB; + _toolActive = false; + tool_cancel(); + gfx_invalidate_screen(); + } + + void OnPrepareDraw() override + { + WidgetScrollUpdateThumbs(this, WIDX_CLIP_HEIGHT_SLIDER); - // Update the main window accordingly. rct_window* mainWindow = window_get_main(); if (mainWindow != nullptr) { + WidgetSetCheckboxValue(this, WIDX_CLIP_CHECKBOX_ENABLE, mainWindow->viewport->flags & VIEWPORT_FLAG_CLIP_VIEW); + } + + if (IsActive()) + { + this->pressed_widgets |= 1ULL << WIDX_CLIP_SELECTOR; + } + else + { + this->pressed_widgets &= ~(1ULL << WIDX_CLIP_SELECTOR); + } + } + + void OnDraw(rct_drawpixelinfo& dpi) override + { + WindowDrawWidgets(this, &dpi); + + // Clip height value + auto screenCoords = this->windowPos + ScreenCoordsXY{ 8, this->widgets[WIDX_CLIP_HEIGHT_VALUE].top }; + DrawTextBasic(&dpi, screenCoords, STR_VIEW_CLIPPING_HEIGHT_VALUE, {}, { this->colours[0] }); + + screenCoords = this->windowPos + + ScreenCoordsXY{ this->widgets[WIDX_CLIP_HEIGHT_VALUE].left + 1, this->widgets[WIDX_CLIP_HEIGHT_VALUE].top }; + + switch (_clipHeightDisplayType) + { + case DISPLAY_TYPE::DISPLAY_RAW: + default: + { + auto ft = Formatter(); + ft.Add(static_cast(gClipHeight)); + + // Printing the raw value. + DrawTextBasic(&dpi, screenCoords, STR_FORMAT_INTEGER, ft, { this->colours[0] }); + break; + } + case DISPLAY_TYPE::DISPLAY_UNITS: + { + // Print the value in the configured height label type: + if (gConfigGeneral.show_height_as_units) + { + // Height label is Units. + auto ft = Formatter(); + ft.Add(static_cast(FIXED_1DP(gClipHeight, 0) / 2 - FIXED_1DP(7, 0))); + DrawTextBasic( + &dpi, screenCoords, STR_UNIT1DP_NO_SUFFIX, ft, + { this->colours[0] }); // Printing the value in Height Units. + } + else + { + // Height label is Real Values. + // Print the value in the configured measurement units. + switch (gConfigGeneral.measurement_format) + { + case MeasurementFormat::Metric: + case MeasurementFormat::SI: + { + auto ft = Formatter(); + ft.Add( + static_cast(FIXED_2DP(gClipHeight, 0) / 2 * 1.5f - FIXED_2DP(10, 50))); + DrawTextBasic(&dpi, screenCoords, STR_UNIT2DP_SUFFIX_METRES, ft, { this->colours[0] }); + break; + } + case MeasurementFormat::Imperial: + { + auto ft = Formatter(); + ft.Add( + static_cast(FIXED_1DP(gClipHeight, 0) / 2.0f * 5 - FIXED_1DP(35, 0))); + DrawTextBasic(&dpi, screenCoords, STR_UNIT1DP_SUFFIX_FEET, ft, { this->colours[0] }); + break; + } + } + } + } + } + } + + ScreenSize OnScrollGetSize(int32_t scrollIndex) override + { + return { 1000, 0 }; + } + + void OnOpen() override + { + this->widgets = window_view_clipping_widgets; + this->enabled_widgets = (1ULL << WIDX_CLOSE) | (1ULL << WIDX_CLIP_CHECKBOX_ENABLE) | (1ULL << WIDX_CLIP_HEIGHT_VALUE) + | (1ULL << WIDX_CLIP_HEIGHT_INCREASE) | (1ULL << WIDX_CLIP_HEIGHT_DECREASE) | (1ULL << WIDX_CLIP_HEIGHT_SLIDER) + | (1ULL << WIDX_CLIP_SELECTOR) | (1ULL << WIDX_CLIP_CLEAR); + this->hold_down_widgets = (1ULL << WIDX_CLIP_HEIGHT_INCREASE) | (1UL << WIDX_CLIP_HEIGHT_DECREASE); + WindowInitScrollWidgets(this); + + _clipHeightDisplayType = DISPLAY_TYPE::DISPLAY_UNITS; + + // Initialise the clip height slider from the current clip height value. + this->SetClipHeight(gClipHeight); + + window_push_others_below(this); + + // Get the main viewport to set the view clipping flag. + rct_window* mainWindow = window_get_main(); + + // Turn on view clipping when the window is opened. + if (mainWindow != nullptr) + { + mainWindow->viewport->flags |= VIEWPORT_FLAG_CLIP_VIEW; mainWindow->Invalidate(); } } - // Restore previous selection if the tool has been interrupted - if (_toolActive && !window_view_clipping_tool_is_active()) +private: + void OnClose() override { - _toolActive = false; - gClipSelectionA = _previousClipSelectionA; - gClipSelectionB = _previousClipSelectionB; - } - - widget_invalidate(w, WIDX_CLIP_HEIGHT_SLIDER); -} - -static void window_view_clipping_tool_update(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) -{ - if (_dragging) - { - return; - } - - int32_t direction; - auto mapCoords = screen_pos_to_map_pos(screenCoords, &direction); - if (mapCoords.has_value()) - { - gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; - map_invalidate_tile_full(gMapSelectPositionA); - gMapSelectPositionA = gMapSelectPositionB = mapCoords.value(); - map_invalidate_tile_full(mapCoords.value()); - gMapSelectType = MAP_SELECT_TYPE_FULL; - } -} - -static void window_view_clipping_tool_down(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) -{ - int32_t direction; - auto mapCoords = screen_pos_to_map_pos(screenCoords, &direction); - if (mapCoords.has_value()) - { - _dragging = true; - _selectionStart = mapCoords.value(); - } -} - -static void window_view_clipping_tool_drag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) -{ - if (!_dragging) - { - return; - } - - int32_t direction; - auto mapCoords = screen_pos_to_map_pos(screenCoords, &direction); - if (mapCoords) - { - map_invalidate_selection_rect(); - gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; - gMapSelectPositionA.x = std::min(_selectionStart.x, mapCoords->x); - gMapSelectPositionB.x = std::max(_selectionStart.x, mapCoords->x); - gMapSelectPositionA.y = std::min(_selectionStart.y, mapCoords->y); - gMapSelectPositionB.y = std::max(_selectionStart.y, mapCoords->y); - gMapSelectType = MAP_SELECT_TYPE_FULL; - map_invalidate_selection_rect(); - } -} - -static void window_view_clipping_tool_up(struct rct_window*, rct_widgetindex, const ScreenCoordsXY&) -{ - gClipSelectionA = gMapSelectPositionA; - gClipSelectionB = gMapSelectPositionB; - _toolActive = false; - tool_cancel(); - gfx_invalidate_screen(); -} - -static void window_view_clipping_invalidate(rct_window* w) -{ - WidgetScrollUpdateThumbs(w, WIDX_CLIP_HEIGHT_SLIDER); - - rct_window* mainWindow = window_get_main(); - if (mainWindow != nullptr) - { - WidgetSetCheckboxValue(w, WIDX_CLIP_CHECKBOX_ENABLE, mainWindow->viewport->flags & VIEWPORT_FLAG_CLIP_VIEW); - } - - if (window_view_clipping_tool_is_active()) - { - w->pressed_widgets |= 1ULL << WIDX_CLIP_SELECTOR; - } - else - { - w->pressed_widgets &= ~(1ULL << WIDX_CLIP_SELECTOR); - } -} - -static void window_view_clipping_paint(rct_window* w, rct_drawpixelinfo* dpi) -{ - WindowDrawWidgets(w, dpi); - - // Clip height value - auto screenCoords = w->windowPos + ScreenCoordsXY{ 8, w->widgets[WIDX_CLIP_HEIGHT_VALUE].top }; - DrawTextBasic(dpi, screenCoords, STR_VIEW_CLIPPING_HEIGHT_VALUE, {}, { w->colours[0] }); - - screenCoords = w->windowPos - + ScreenCoordsXY{ w->widgets[WIDX_CLIP_HEIGHT_VALUE].left + 1, w->widgets[WIDX_CLIP_HEIGHT_VALUE].top }; - - switch (gClipHeightDisplayType) - { - case DISPLAY_TYPE::DISPLAY_RAW: - default: + // Turn off view clipping when the window is closed. + rct_window* mainWindow = window_get_main(); + if (mainWindow != nullptr) { - auto ft = Formatter(); - ft.Add(static_cast(gClipHeight)); - DrawTextBasic(dpi, screenCoords, STR_FORMAT_INTEGER, ft, { w->colours[0] }); // Printing the raw value. - break; + mainWindow->viewport->flags &= ~VIEWPORT_FLAG_CLIP_VIEW; + mainWindow->Invalidate(); } - case DISPLAY_TYPE::DISPLAY_UNITS: - // Print the value in the configured height label type: - if (gConfigGeneral.show_height_as_units == 1) - { - // Height label is Units. - auto ft = Formatter(); - ft.Add(static_cast(FIXED_1DP(gClipHeight, 0) / 2 - FIXED_1DP(7, 0))); - DrawTextBasic( - dpi, screenCoords, STR_UNIT1DP_NO_SUFFIX, ft, { w->colours[0] }); // Printing the value in Height Units. - } - else - { - // Height label is Real Values. - // Print the value in the configured measurement units. - switch (gConfigGeneral.measurement_format) - { - case MeasurementFormat::Metric: - case MeasurementFormat::SI: - { - auto ft = Formatter(); - ft.Add(static_cast(FIXED_2DP(gClipHeight, 0) / 2 * 1.5f - FIXED_2DP(10, 50))); - DrawTextBasic(dpi, screenCoords, STR_UNIT2DP_SUFFIX_METRES, ft, { w->colours[0] }); - break; - } - case MeasurementFormat::Imperial: - { - auto ft = Formatter(); - ft.Add(static_cast(FIXED_1DP(gClipHeight, 0) / 2.0f * 5 - FIXED_1DP(35, 0))); - DrawTextBasic(dpi, screenCoords, STR_UNIT1DP_SUFFIX_FEET, ft, { w->colours[0] }); - break; - } - } - } } -} -static void window_view_clipping_scrollgetsize(rct_window* w, int scrollIndex, int* width, int* height) + void SetClipHeight(const uint8_t clipHeight) + { + gClipHeight = clipHeight; + const auto& widget = widgets[WIDX_CLIP_HEIGHT_SLIDER]; + const float clip_height_ratio = static_cast(gClipHeight) / 255; + this->scrolls[0].h_left = static_cast( + std::ceil(clip_height_ratio * (this->scrolls[0].h_right - (widget.width() - 1)))); + } + + bool IsActive() + { + if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE))) + return false; + if (gCurrentToolWidget.window_classification != WC_VIEW_CLIPPING) + return false; + return _toolActive; + } +}; + +rct_window* window_view_clipping_open() { - *width = 1000; + auto* window = window_bring_to_front_by_class(WC_VIEW_CLIPPING); + if (window == nullptr) + { + window = WindowCreate(WC_VIEW_CLIPPING, ScreenCoordsXY(32, 32), WW, WH); + } + return window; } diff --git a/src/openrct2/drawing/Drawing.String.cpp b/src/openrct2/drawing/Drawing.String.cpp index e6f1df2dde..4450706156 100644 --- a/src/openrct2/drawing/Drawing.String.cpp +++ b/src/openrct2/drawing/Drawing.String.cpp @@ -578,9 +578,9 @@ static void ttf_draw_string_raw_ttf(rct_drawpixelinfo* dpi, std::string_view tex auto baseId = uint32_t(0x7FFFF) - 1024; auto imageId = baseId + _ttfGlId; auto drawingEngine = dpi->DrawingEngine; - auto drawingContext = drawingEngine->GetDrawingContext(dpi); + auto drawingContext = drawingEngine->GetDrawingContext(); drawingEngine->InvalidateImage(imageId); - drawingContext->DrawBitmap(imageId, surface->pixels, surface->pitch, surface->h, drawX, drawY); + drawingContext->DrawBitmap(dpi, imageId, surface->pixels, surface->pitch, surface->h, drawX, drawY); _ttfGlId++; if (_ttfGlId >= 1023) diff --git a/src/openrct2/drawing/Drawing.cpp b/src/openrct2/drawing/Drawing.cpp index 520bb6ddb6..c4c9d2f466 100644 --- a/src/openrct2/drawing/Drawing.cpp +++ b/src/openrct2/drawing/Drawing.cpp @@ -94,7 +94,7 @@ int32_t gPickupPeepY; * rct2: 0x0009ABE0C */ // clang-format off -uint8_t gPeepPalette[256] = { +thread_local uint8_t gPeepPalette[256] = { 0x00, 0xF3, 0xF4, 0xF5, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, @@ -114,7 +114,7 @@ uint8_t gPeepPalette[256] = { }; /** rct2: 0x009ABF0C */ -uint8_t gOtherPalette[256] = { +thread_local uint8_t gOtherPalette[256] = { 0x00, 0xF3, 0xF4, 0xF5, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index 47cb785d20..2e66236126 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -657,8 +657,8 @@ extern GamePalette gPalette; extern uint8_t gGamePalette[256 * 4]; extern uint32_t gPaletteEffectFrame; extern const FilterPaletteID GlassPaletteIds[COLOUR_COUNT]; -extern uint8_t gPeepPalette[256]; -extern uint8_t gOtherPalette[256]; +extern thread_local uint8_t gPeepPalette[256]; +extern thread_local uint8_t gOtherPalette[256]; extern uint8_t text_palette[]; extern const translucent_window_palette TranslucentWindowPalettes[COLOUR_COUNT]; diff --git a/src/openrct2/drawing/IDrawingContext.h b/src/openrct2/drawing/IDrawingContext.h index e8fbadc702..adff81a6d6 100644 --- a/src/openrct2/drawing/IDrawingContext.h +++ b/src/openrct2/drawing/IDrawingContext.h @@ -21,15 +21,21 @@ namespace OpenRCT2::Drawing virtual ~IDrawingContext() = default; virtual OpenRCT2::Drawing::IDrawingEngine* GetEngine() abstract; - virtual void Clear(uint8_t paletteIndex) abstract; - virtual void FillRect(uint32_t colour, int32_t left, int32_t top, int32_t right, int32_t bottom) abstract; - virtual void FilterRect(FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) abstract; - virtual void DrawLine(uint32_t colour, const ScreenLine& line) abstract; - virtual void DrawSprite(uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) abstract; - virtual void DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) abstract; - virtual void DrawSpriteSolid(uint32_t image, int32_t x, int32_t y, uint8_t colour) abstract; - virtual void DrawGlyph(uint32_t image, int32_t x, int32_t y, const PaletteMap& palette) abstract; + virtual void Clear(rct_drawpixelinfo* dpi, uint8_t paletteIndex) abstract; + virtual void FillRect( + rct_drawpixelinfo* dpi, uint32_t colour, int32_t left, int32_t top, int32_t right, int32_t bottom) abstract; + virtual void FilterRect( + rct_drawpixelinfo* dpi, FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) abstract; + virtual void DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const ScreenLine& line) abstract; + virtual void DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) abstract; + virtual void DrawSpriteRawMasked( + rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) abstract; + virtual void DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint8_t colour) abstract; + virtual void DrawGlyph( + rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, const PaletteMap& palette) abstract; virtual void DrawBitmap( - uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, int32_t y) abstract; + rct_drawpixelinfo* dpi, uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, + int32_t y) abstract; }; + } // namespace OpenRCT2::Drawing diff --git a/src/openrct2/drawing/IDrawingEngine.h b/src/openrct2/drawing/IDrawingEngine.h index 41c3adb383..76552da80b 100644 --- a/src/openrct2/drawing/IDrawingEngine.h +++ b/src/openrct2/drawing/IDrawingEngine.h @@ -32,6 +32,11 @@ enum DRAWING_ENGINE_FLAGS * Whether or not the engine will only draw changed blocks of the screen each frame. */ DEF_DIRTY_OPTIMISATIONS = 1 << 0, + + /** + * The drawing engine is capable of processing the drawing in parallel. + */ + DEF_PARALLEL_DRAWING = 1 << 1, }; struct rct_drawpixelinfo; @@ -66,7 +71,7 @@ namespace OpenRCT2::Drawing virtual void CopyRect(int32_t x, int32_t y, int32_t width, int32_t height, int32_t dx, int32_t dy) abstract; virtual std::string Screenshot() abstract; - virtual IDrawingContext* GetDrawingContext(rct_drawpixelinfo* dpi) abstract; + virtual IDrawingContext* GetDrawingContext() abstract; virtual rct_drawpixelinfo* GetDrawingPixelInfo() abstract; virtual DRAWING_ENGINE_FLAGS GetFlags() abstract; @@ -85,11 +90,9 @@ namespace OpenRCT2::Drawing struct IWeatherDrawer { - virtual ~IWeatherDrawer() - { - } + virtual ~IWeatherDrawer() = default; virtual void Draw( - int32_t x, int32_t y, int32_t width, int32_t height, int32_t xStart, int32_t yStart, + rct_drawpixelinfo* dpi, int32_t x, int32_t y, int32_t width, int32_t height, int32_t xStart, int32_t yStart, const uint8_t* weatherpattern) abstract; }; } // namespace OpenRCT2::Drawing diff --git a/src/openrct2/drawing/NewDrawing.cpp b/src/openrct2/drawing/NewDrawing.cpp index c1eb196933..ed5f8c4aee 100644 --- a/src/openrct2/drawing/NewDrawing.cpp +++ b/src/openrct2/drawing/NewDrawing.cpp @@ -165,8 +165,8 @@ void gfx_clear(rct_drawpixelinfo* dpi, uint8_t paletteIndex) auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); - dc->Clear(paletteIndex); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); + dc->Clear(dpi, paletteIndex); } } @@ -175,8 +175,8 @@ void gfx_fill_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, int32_t colou auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); - dc->FillRect(colour, rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom()); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); + dc->FillRect(dpi, colour, rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom()); } } @@ -190,8 +190,8 @@ void gfx_filter_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, FilterPalet auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); - dc->FilterRect(palette, rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom()); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); + dc->FilterRect(dpi, palette, rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom()); } } @@ -200,8 +200,8 @@ void gfx_draw_line(rct_drawpixelinfo* dpi, const ScreenLine& line, int32_t colou auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); - dc->DrawLine(colour, line); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); + dc->DrawLine(dpi, colour, line); } } @@ -227,13 +227,13 @@ void gfx_draw_dashed_line( const int32_t lineYDist = std::abs(screenLine.GetY2() - screenLine.GetY1()); const int32_t dxPrecise = precisionFactor * lineXDist / lineSegmentCount / 2; const int32_t dyPrecise = precisionFactor * lineYDist / lineSegmentCount / 2; - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); for (int32_t i = 0, x, y; i < lineSegmentCount; ++i) { x = screenLine.GetX1() + dxPrecise * i * 2 / precisionFactor; y = screenLine.GetY1() + dyPrecise * i * 2 / precisionFactor; - dc->DrawLine(color, { { x, y }, { x + dxPrecise / precisionFactor, y + dyPrecise / precisionFactor } }); + dc->DrawLine(dpi, color, { { x, y }, { x + dxPrecise / precisionFactor, y + dyPrecise / precisionFactor } }); } } } @@ -248,8 +248,8 @@ void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, int32_t image, const Scree auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); - dc->DrawSprite(image, coords.x, coords.y, tertiary_colour); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); + dc->DrawSprite(dpi, image, coords.x, coords.y, tertiary_colour); } } @@ -258,8 +258,8 @@ void FASTCALL gfx_draw_glyph(rct_drawpixelinfo* dpi, int32_t image, const Screen auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); - dc->DrawGlyph(image, coords.x, coords.y, paletteMap); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); + dc->DrawGlyph(dpi, image, coords.x, coords.y, paletteMap); } } @@ -269,8 +269,8 @@ void FASTCALL auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); - dc->DrawSpriteRawMasked(coords.x, coords.y, maskImage, colourImage); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); + dc->DrawSpriteRawMasked(dpi, coords.x, coords.y, maskImage, colourImage); } } @@ -279,8 +279,8 @@ void FASTCALL gfx_draw_sprite_solid(rct_drawpixelinfo* dpi, int32_t image, const auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { - IDrawingContext* dc = drawingEngine->GetDrawingContext(dpi); - dc->DrawSpriteSolid(image, coords.x, coords.y, colour); + IDrawingContext* dc = drawingEngine->GetDrawingContext(); + dc->DrawSpriteSolid(dpi, image, coords.x, coords.y, colour); } } diff --git a/src/openrct2/drawing/Weather.cpp b/src/openrct2/drawing/Weather.cpp index ae9a116ef3..c47794ef00 100644 --- a/src/openrct2/drawing/Weather.cpp +++ b/src/openrct2/drawing/Weather.cpp @@ -22,10 +22,14 @@ using namespace OpenRCT2; using namespace OpenRCT2::Drawing; -static void DrawLightRain(IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); -static void DrawHeavyRain(IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); -static void DrawLightSnow(IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); -static void DrawHeavySnow(IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); +static void DrawLightRain( + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); +static void DrawHeavyRain( + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); +static void DrawLightSnow( + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); +static void DrawHeavySnow( + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); /** * @@ -76,59 +80,62 @@ void DrawWeather(rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer) * * rct2: 0x00684114 */ -static void DrawLightRain(IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height) +static void DrawLightRain( + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height) { int32_t x_start = -static_cast(gCurrentTicks) + 8; int32_t y_start = (gCurrentTicks * 3) + 7; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, RainPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, RainPattern); x_start = -static_cast(gCurrentTicks) + 0x18; y_start = (gCurrentTicks * 4) + 0x0D; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, RainPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, RainPattern); } /** * * rct2: 0x0068416D */ -static void DrawHeavyRain(IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height) +static void DrawHeavyRain( + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height) { int32_t x_start = -static_cast(gCurrentTicks); int32_t y_start = gCurrentTicks * 5; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, RainPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, RainPattern); x_start = -static_cast(gCurrentTicks) + 0x10; y_start = (gCurrentTicks * 6) + 5; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, RainPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, RainPattern); x_start = -static_cast(gCurrentTicks) + 8; y_start = (gCurrentTicks * 3) + 7; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, RainPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, RainPattern); x_start = -static_cast(gCurrentTicks) + 0x18; y_start = (gCurrentTicks * 4) + 0x0D; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, RainPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, RainPattern); } -static void DrawLightSnow(IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height) +static void DrawLightSnow( + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height) { const uint32_t t = gCurrentTicks / 2; const int32_t negT = -static_cast(t); @@ -139,43 +146,44 @@ static void DrawLightSnow(IWeatherDrawer* weatherDrawer, int32_t left, int32_t t y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, SnowPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, SnowPattern); x_start = negT + 16 + (cos(cosTick) * 6); y_start = t + 16; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, SnowPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, SnowPattern); } -static void DrawHeavySnow(IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height) +static void DrawHeavySnow( + rct_drawpixelinfo* dpi, IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height) { int32_t x_start = -static_cast(gCurrentTicks * 3) + 1; int32_t y_start = gCurrentTicks + 23; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, SnowPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, SnowPattern); x_start = -static_cast(gCurrentTicks * 4) + 6; y_start = gCurrentTicks + 5; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, SnowPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, SnowPattern); x_start = -static_cast(gCurrentTicks * 2) + 11; y_start = gCurrentTicks + 18; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, SnowPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, SnowPattern); x_start = -static_cast(gCurrentTicks * 3) + 17; y_start = gCurrentTicks + 11; y_start = -y_start; x_start += left; y_start += top; - weatherDrawer->Draw(left, top, width, height, x_start, y_start, SnowPattern); + weatherDrawer->Draw(dpi, left, top, width, height, x_start, y_start, SnowPattern); } diff --git a/src/openrct2/drawing/X8DrawingEngine.cpp b/src/openrct2/drawing/X8DrawingEngine.cpp index 9cbbcdcf77..cb6581836f 100644 --- a/src/openrct2/drawing/X8DrawingEngine.cpp +++ b/src/openrct2/drawing/X8DrawingEngine.cpp @@ -43,13 +43,9 @@ X8WeatherDrawer::~X8WeatherDrawer() delete[] _weatherPixels; } -void X8WeatherDrawer::SetDPI(rct_drawpixelinfo* dpi) -{ - _screenDPI = dpi; -} - void X8WeatherDrawer::Draw( - int32_t x, int32_t y, int32_t width, int32_t height, int32_t xStart, int32_t yStart, const uint8_t* weatherpattern) + rct_drawpixelinfo* dpi, int32_t x, int32_t y, int32_t width, int32_t height, int32_t xStart, int32_t yStart, + const uint8_t* weatherpattern) { const uint8_t* pattern = weatherpattern; auto patternXSpace = *pattern++; @@ -58,10 +54,10 @@ void X8WeatherDrawer::Draw( uint8_t patternStartXOffset = xStart % patternXSpace; uint8_t patternStartYOffset = yStart % patternYSpace; - uint32_t pixelOffset = (_screenDPI->pitch + _screenDPI->width) * y + x; + uint32_t pixelOffset = (dpi->pitch + dpi->width) * y + x; uint8_t patternYPos = patternStartYOffset % patternYSpace; - uint8_t* screenBits = _screenDPI->bits; + uint8_t* screenBits = dpi->bits; // Stores the colours of changed pixels WeatherPixel* newPixels = &_weatherPixels[_weatherPixelsCount]; @@ -90,18 +86,18 @@ void X8WeatherDrawer::Draw( } } - pixelOffset += _screenDPI->pitch + _screenDPI->width; + pixelOffset += dpi->pitch + dpi->width; patternYPos++; patternYPos %= patternYSpace; } } -void X8WeatherDrawer::Restore() +void X8WeatherDrawer::Restore(rct_drawpixelinfo* dpi) { if (_weatherPixelsCount > 0) { - uint32_t numPixels = (_screenDPI->width + _screenDPI->pitch) * _screenDPI->height; - uint8_t* bits = _screenDPI->bits; + uint32_t numPixels = (dpi->width + dpi->pitch) * dpi->height; + uint8_t* bits = dpi->bits; for (uint32_t i = 0; i < _weatherPixelsCount; i++) { WeatherPixel weatherPixel = _weatherPixels[i]; @@ -201,8 +197,7 @@ void X8DrawingEngine::BeginDraw() Resize(_width, _height); } #endif - _weatherDrawer.SetDPI(&_bitsDPI); - _weatherDrawer.Restore(); + _weatherDrawer.Restore(&_bitsDPI); } } @@ -271,9 +266,8 @@ std::string X8DrawingEngine::Screenshot() return screenshot_dump_png(&_bitsDPI); } -IDrawingContext* X8DrawingEngine::GetDrawingContext(rct_drawpixelinfo* dpi) +IDrawingContext* X8DrawingEngine::GetDrawingContext() { - _drawingContext->SetDPI(dpi); return _drawingContext; } @@ -284,7 +278,7 @@ rct_drawpixelinfo* X8DrawingEngine::GetDrawingPixelInfo() DRAWING_ENGINE_FLAGS X8DrawingEngine::GetFlags() { - return DEF_DIRTY_OPTIMISATIONS; + return static_cast(DEF_DIRTY_OPTIMISATIONS | DEF_PARALLEL_DRAWING); } void X8DrawingEngine::InvalidateImage([[maybe_unused]] uint32_t image) @@ -466,10 +460,8 @@ IDrawingEngine* X8DrawingContext::GetEngine() return _engine; } -void X8DrawingContext::Clear(uint8_t paletteIndex) +void X8DrawingContext::Clear(rct_drawpixelinfo* dpi, uint8_t paletteIndex) { - rct_drawpixelinfo* dpi = _dpi; - int32_t w = dpi->width / dpi->zoom_level; int32_t h = dpi->height / dpi->zoom_level; uint8_t* ptr = dpi->bits; @@ -529,10 +521,9 @@ static constexpr const uint16_t * Patterns[] = { }; // clang-format on -void X8DrawingContext::FillRect(uint32_t colour, int32_t left, int32_t top, int32_t right, int32_t bottom) +void X8DrawingContext::FillRect( + rct_drawpixelinfo* dpi, uint32_t colour, int32_t left, int32_t top, int32_t right, int32_t bottom) { - rct_drawpixelinfo* dpi = _dpi; - if (left > right) return; if (top > bottom) @@ -650,10 +641,9 @@ void X8DrawingContext::FillRect(uint32_t colour, int32_t left, int32_t top, int3 } } -void X8DrawingContext::FilterRect(FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) +void X8DrawingContext::FilterRect( + rct_drawpixelinfo* dpi, FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) { - rct_drawpixelinfo* dpi = _dpi; - if (left > right) return; if (top > bottom) @@ -723,22 +713,23 @@ void X8DrawingContext::FilterRect(FilterPaletteID palette, int32_t left, int32_t } } -void X8DrawingContext::DrawLine(uint32_t colour, const ScreenLine& line) +void X8DrawingContext::DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const ScreenLine& line) { - gfx_draw_line_software(_dpi, line, colour); + gfx_draw_line_software(dpi, line, colour); } -void X8DrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) +void X8DrawingContext::DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) { - gfx_draw_sprite_software(_dpi, ImageId::FromUInt32(image, tertiaryColour), { x, y }); + gfx_draw_sprite_software(dpi, ImageId::FromUInt32(image, tertiaryColour), { x, y }); } -void X8DrawingContext::DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) +void X8DrawingContext::DrawSpriteRawMasked( + rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) { - gfx_draw_sprite_raw_masked_software(_dpi, { x, y }, maskImage, colourImage); + gfx_draw_sprite_raw_masked_software(dpi, { x, y }, maskImage, colourImage); } -void X8DrawingContext::DrawSpriteSolid(uint32_t image, int32_t x, int32_t y, uint8_t colour) +void X8DrawingContext::DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint8_t colour) { uint8_t palette[256]; std::fill_n(palette, sizeof(palette), colour); @@ -746,15 +737,10 @@ void X8DrawingContext::DrawSpriteSolid(uint32_t image, int32_t x, int32_t y, uin const auto spriteCoords = ScreenCoordsXY{ x, y }; gfx_draw_sprite_palette_set_software( - _dpi, ImageId::FromUInt32((image & 0x7FFFF) | IMAGE_TYPE_REMAP), spriteCoords, PaletteMap(palette)); + dpi, ImageId::FromUInt32((image & 0x7FFFF) | IMAGE_TYPE_REMAP), spriteCoords, PaletteMap(palette)); } -void X8DrawingContext::DrawGlyph(uint32_t image, int32_t x, int32_t y, const PaletteMap& paletteMap) +void X8DrawingContext::DrawGlyph(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, const PaletteMap& paletteMap) { - gfx_draw_sprite_palette_set_software(_dpi, ImageId::FromUInt32(image), { x, y }, paletteMap); -} - -void X8DrawingContext::SetDPI(rct_drawpixelinfo* dpi) -{ - _dpi = dpi; + gfx_draw_sprite_palette_set_software(dpi, ImageId::FromUInt32(image), { x, y }, paletteMap); } diff --git a/src/openrct2/drawing/X8DrawingEngine.h b/src/openrct2/drawing/X8DrawingEngine.h index b655cac749..d97f1a34ec 100644 --- a/src/openrct2/drawing/X8DrawingEngine.h +++ b/src/openrct2/drawing/X8DrawingEngine.h @@ -49,16 +49,14 @@ namespace OpenRCT2 size_t _weatherPixelsCapacity = MaxWeatherPixels; uint32_t _weatherPixelsCount = 0; WeatherPixel* _weatherPixels = nullptr; - rct_drawpixelinfo* _screenDPI = nullptr; public: X8WeatherDrawer(); ~X8WeatherDrawer(); - void SetDPI(rct_drawpixelinfo* dpi); void Draw( - int32_t x, int32_t y, int32_t width, int32_t height, int32_t xStart, int32_t yStart, + rct_drawpixelinfo* dpi, int32_t x, int32_t y, int32_t width, int32_t height, int32_t xStart, int32_t yStart, const uint8_t* weatherpattern) override; - void Restore(); + void Restore(rct_drawpixelinfo* dpi); }; #ifdef __WARN_SUGGEST_FINAL_TYPES__ @@ -109,7 +107,7 @@ namespace OpenRCT2 void PaintWeather() override; void CopyRect(int32_t x, int32_t y, int32_t width, int32_t height, int32_t dx, int32_t dy) override; std::string Screenshot() override; - IDrawingContext* GetDrawingContext(rct_drawpixelinfo* dpi) override; + IDrawingContext* GetDrawingContext() override; rct_drawpixelinfo* GetDrawingPixelInfo() override; DRAWING_ENGINE_FLAGS GetFlags() override; void InvalidateImage(uint32_t image) override; @@ -135,26 +133,28 @@ namespace OpenRCT2 { private: X8DrawingEngine* _engine = nullptr; - rct_drawpixelinfo* _dpi = nullptr; public: explicit X8DrawingContext(X8DrawingEngine* engine); IDrawingEngine* GetEngine() override; - void Clear(uint8_t paletteIndex) override; - void FillRect(uint32_t colour, int32_t x, int32_t y, int32_t w, int32_t h) override; - void FilterRect(FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) override; - void DrawLine(uint32_t colour, const ScreenLine& line) override; - void DrawSprite(uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) override; - void DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) override; - void DrawSpriteSolid(uint32_t image, int32_t x, int32_t y, uint8_t colour) override; - void DrawGlyph(uint32_t image, int32_t x, int32_t y, const PaletteMap& paletteMap) override; - void DrawBitmap(uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, int32_t y) override + void Clear(rct_drawpixelinfo* dpi, uint8_t paletteIndex) override; + void FillRect(rct_drawpixelinfo* dpi, uint32_t colour, int32_t x, int32_t y, int32_t w, int32_t h) override; + void FilterRect( + rct_drawpixelinfo* dpi, FilterPaletteID palette, int32_t left, int32_t top, int32_t right, + int32_t bottom) override; + void DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const ScreenLine& line) override; + void DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) override; + void DrawSpriteRawMasked( + rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) override; + void DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint8_t colour) override; + void DrawGlyph(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, const PaletteMap& paletteMap) override; + void DrawBitmap( + rct_drawpixelinfo* dpi, uint32_t image, const void* pixels, int32_t width, int32_t height, int32_t x, + int32_t y) override { } - - void SetDPI(rct_drawpixelinfo* dpi); }; } // namespace Drawing } // namespace OpenRCT2 diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 53200d366d..73450b4978 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -931,8 +931,6 @@ static void viewport_paint_column(paint_session* session) { PaintDrawMoneyStructs(&session->DPI, session->PSStringHead); } - - PaintSessionFree(session); } /** @@ -996,6 +994,12 @@ void viewport_paint( _paintJobs.reset(); } + bool useParallelDrawing = false; + if (useMultithreading && (dpi->DrawingEngine->GetFlags() & DEF_PARALLEL_DRAWING)) + { + useParallelDrawing = true; + } + // Create space to record sessions and keep track which index is being drawn size_t index = 0; if (recorded_sessions != nullptr) @@ -1005,7 +1009,7 @@ void viewport_paint( recorded_sessions->resize(columnCount); } - // Splits the area into 32 pixel columns and renders them + // Generate and sort columns. for (x = alignedX; x < rightBorder; x += 32, index++) { paint_session* session = PaintSessionAlloc(&dpi1, viewFlags); @@ -1046,9 +1050,27 @@ void viewport_paint( _paintJobs->Join(); } - for (auto column : _paintColumns) + // Paint columns. + for (auto* session : _paintColumns) { - viewport_paint_column(column); + if (useParallelDrawing) + { + _paintJobs->AddTask([session]() -> void { viewport_paint_column(session); }); + } + else + { + viewport_paint_column(session); + } + } + if (useParallelDrawing) + { + _paintJobs->Join(); + } + + // Release resources. + for (auto* session : _paintColumns) + { + PaintSessionFree(session); } } diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index 2b6543ccc9..663fcec783 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -1462,9 +1462,10 @@ void window_event_unknown_08_call(rct_window* w) void window_event_tool_update_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers != nullptr) - if (w->event_handlers->tool_update != nullptr) - w->event_handlers->tool_update(w, widgetIndex, screenCoords); + if (w->event_handlers == nullptr) + w->OnToolUpdate(widgetIndex, screenCoords); + else if (w->event_handlers->tool_update != nullptr) + w->event_handlers->tool_update(w, widgetIndex, screenCoords); } void window_event_tool_down_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) @@ -1477,16 +1478,18 @@ void window_event_tool_down_call(rct_window* w, rct_widgetindex widgetIndex, con void window_event_tool_drag_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers != nullptr) - if (w->event_handlers->tool_drag != nullptr) - w->event_handlers->tool_drag(w, widgetIndex, screenCoords); + if (w->event_handlers == nullptr) + w->OnToolDrag(widgetIndex, screenCoords); + else if (w->event_handlers->tool_drag != nullptr) + w->event_handlers->tool_drag(w, widgetIndex, screenCoords); } void window_event_tool_up_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers != nullptr) - if (w->event_handlers->tool_up != nullptr) - w->event_handlers->tool_up(w, widgetIndex, screenCoords); + if (w->event_handlers == nullptr) + w->OnToolUp(widgetIndex, screenCoords); + else if (w->event_handlers->tool_up != nullptr) + w->event_handlers->tool_up(w, widgetIndex, screenCoords); } void window_event_tool_abort_call(rct_window* w, rct_widgetindex widgetIndex) diff --git a/src/openrct2/interface/Window_internal.h b/src/openrct2/interface/Window_internal.h index 24b2796636..7ed0b20d60 100644 --- a/src/openrct2/interface/Window_internal.h +++ b/src/openrct2/interface/Window_internal.h @@ -174,9 +174,18 @@ struct rct_window virtual void OnScrollDraw(int32_t scrollIndex, rct_drawpixelinfo& dpi) { } + virtual void OnToolUpdate(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) + { + } virtual void OnToolDown(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { } + virtual void OnToolDrag(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) + { + } + virtual void OnToolUp(rct_widgetindex, const ScreenCoordsXY&) + { + } virtual void OnToolAbort(rct_widgetindex widgetIndex) { } diff --git a/src/openrct2/ui/UiContext.h b/src/openrct2/ui/UiContext.h index c2f38d56ac..8135b209aa 100644 --- a/src/openrct2/ui/UiContext.h +++ b/src/openrct2/ui/UiContext.h @@ -29,7 +29,8 @@ namespace OpenRCT2 struct IDrawingEngineFactory; struct IWeatherDrawer; using DrawWeatherFunc = void (*)( - OpenRCT2::Drawing::IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, int32_t height); + rct_drawpixelinfo* dpi, OpenRCT2::Drawing::IWeatherDrawer* weatherDrawer, int32_t left, int32_t top, int32_t width, + int32_t height); } // namespace Drawing namespace Ui