diff --git a/distribution/changelog.txt b/distribution/changelog.txt index a1ba38e2f6..b1330260e8 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,7 @@ 0.4.10 (in development) ------------------------------------------------------------------------ +- Improved: [#21424] Extra viewports can now rotate independently from the main viewport. +- Fix: [#910] Extra viewport does not preserve the location when rotating. 0.4.9 (2024-03-02) ------------------------------------------------------------------------ diff --git a/src/openrct2-ui/WindowManager.cpp b/src/openrct2-ui/WindowManager.cpp index 7e9e73d519..16466cb4a2 100644 --- a/src/openrct2-ui/WindowManager.cpp +++ b/src/openrct2-ui/WindowManager.cpp @@ -587,7 +587,7 @@ public: mainWindow->viewport_target_sprite = EntityId::GetNull(); mainWindow->savedViewPos = viewPos; viewport->zoom = zoom; - gCurrentRotation = rotation; + viewport->rotation = rotation; if (zoomDifference != ZoomLevel{ 0 }) { diff --git a/src/openrct2-ui/input/MouseInput.cpp b/src/openrct2-ui/input/MouseInput.cpp index 80aaa68cbf..2f9eb1915a 100644 --- a/src/openrct2-ui/input/MouseInput.cpp +++ b/src/openrct2-ui/input/MouseInput.cpp @@ -1688,8 +1688,8 @@ void InputScrollViewport(const ScreenCoordsXY& scrollScreenCoords) int32_t y = mainWindow->savedViewPos.y + viewport->view_height / 2; int32_t y_dy = mainWindow->savedViewPos.y + viewport->view_height / 2 + dy; - auto mapCoord = ViewportPosToMapPos({ x, y }, 0); - auto mapCoord_dy = ViewportPosToMapPos({ x, y_dy }, 0); + auto mapCoord = ViewportPosToMapPos({ x, y }, 0, viewport->rotation); + auto mapCoord_dy = ViewportPosToMapPos({ x, y_dy }, 0, viewport->rotation); // Check if we're crossing the boundary // Clamp to the map minimum value diff --git a/src/openrct2-ui/input/Shortcuts.cpp b/src/openrct2-ui/input/Shortcuts.cpp index daef77393d..8081c03527 100644 --- a/src/openrct2-ui/input/Shortcuts.cpp +++ b/src/openrct2-ui/input/Shortcuts.cpp @@ -62,11 +62,7 @@ static void RotateCamera(int32_t direction) { if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO)) { - auto window = WindowGetMain(); - if (window != nullptr) - { - WindowRotateCamera(*window, direction); - } + ViewportRotateAll(direction); } } diff --git a/src/openrct2-ui/interface/ViewportInteraction.cpp b/src/openrct2-ui/interface/ViewportInteraction.cpp index 7d3acc3c3d..b73668644b 100644 --- a/src/openrct2-ui/interface/ViewportInteraction.cpp +++ b/src/openrct2-ui/interface/ViewportInteraction.cpp @@ -718,16 +718,21 @@ struct PeepDistance }; template -PeepDistance GetClosestPeep(const ScreenCoordsXY& viewportCoords, const int32_t maxDistance, PeepDistance goal) +static PeepDistance GetClosestPeep( + const ScreenCoordsXY& viewportCoords, uint8_t rotation, const int32_t maxDistance, PeepDistance goal) { for (auto peep : EntityList()) { if (peep->x == LOCATION_NULL) continue; - auto distance = abs(((peep->SpriteData.SpriteRect.GetLeft() + peep->SpriteData.SpriteRect.GetRight()) / 2) - - viewportCoords.x) - + abs(((peep->SpriteData.SpriteRect.GetTop() + peep->SpriteData.SpriteRect.GetBottom()) / 2) - viewportCoords.y); + auto screenCoords = Translate3DTo2DWithZ(rotation, peep->GetLocation()); + auto spriteRect = ScreenRect( + screenCoords - ScreenCoordsXY{ peep->SpriteData.Width, peep->SpriteData.HeightMin }, + screenCoords + ScreenCoordsXY{ peep->SpriteData.Width, peep->SpriteData.HeightMax }); + + auto distance = abs(((spriteRect.GetLeft() + spriteRect.GetRight()) / 2) - viewportCoords.x) + + abs(((spriteRect.GetTop() + spriteRect.GetBottom()) / 2) - viewportCoords.y); if (distance > maxDistance) continue; @@ -754,9 +759,9 @@ static Peep* ViewportInteractionGetClosestPeep(ScreenCoordsXY screenCoords, int3 PeepDistance goal; if (!(viewport->flags & VIEWPORT_FLAG_HIDE_GUESTS)) - goal = GetClosestPeep(viewportCoords, maxDistance, goal); + goal = GetClosestPeep(viewportCoords, viewport->rotation, maxDistance, goal); if (!(viewport->flags & VIEWPORT_FLAG_HIDE_STAFF)) - goal = GetClosestPeep(viewportCoords, maxDistance, goal); + goal = GetClosestPeep(viewportCoords, viewport->rotation, maxDistance, goal); return goal.peep; } @@ -800,7 +805,7 @@ CoordsXY ViewportInteractionGetTileStartAtCursor(const ScreenCoordsXY& screenCoo { z = TileElementHeight(mapPos); } - mapPos = ViewportPosToMapPos(initialVPPos, z); + mapPos = ViewportPosToMapPos(initialVPPos, z, viewport->rotation); mapPos.x = std::clamp(mapPos.x, initialPos.x, initialPos.x + 31); mapPos.y = std::clamp(mapPos.y, initialPos.y, initialPos.y + 31); } diff --git a/src/openrct2-ui/scripting/ScViewport.hpp b/src/openrct2-ui/scripting/ScViewport.hpp index 6781c16e96..828e9639fe 100644 --- a/src/openrct2-ui/scripting/ScViewport.hpp +++ b/src/openrct2-ui/scripting/ScViewport.hpp @@ -111,7 +111,12 @@ namespace OpenRCT2::Scripting int32_t rotation_get() const { - return GetCurrentRotation(); + auto viewport = GetViewport(); + if (viewport != nullptr) + { + return viewport->rotation; + } + return 0; } void rotation_set(int32_t value) { @@ -120,9 +125,9 @@ namespace OpenRCT2::Scripting auto w = GetWindow(); if (w != nullptr) { - while (GetCurrentRotation() != value) + while (w->viewport->rotation != value) { - WindowRotateCamera(*w, 1); + ViewportRotateSingle(w, 1); } } } @@ -179,7 +184,7 @@ namespace OpenRCT2::Scripting if (viewport != nullptr) { auto centre = viewport->viewPos + ScreenCoordsXY{ viewport->view_width / 2, viewport->view_height / 2 }; - auto coords = ViewportPosToMapPos(centre, 24); + auto coords = ViewportPosToMapPos(centre, 24, viewport->rotation); auto ctx = GetContext()->GetScriptEngine().GetContext(); auto obj = duk_push_object(ctx); @@ -203,7 +208,7 @@ namespace OpenRCT2::Scripting auto coords = GetCoordsFromObject(position); if (coords) { - auto screenCoords = Translate3DTo2DWithZ(GetCurrentRotation(), *coords); + auto screenCoords = Translate3DTo2DWithZ(viewport->rotation, *coords); auto left = screenCoords.x - (viewport->view_width / 2); auto top = screenCoords.y - (viewport->view_height / 2); SetViewLeftTop(left, top); diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index b6d9a70dc7..bb4b06f602 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -85,7 +85,7 @@ private: (viewportWidget->width()) - 1, (viewportWidget->height()) - 1, Focus(_bannerViewPos)); if (viewport != nullptr) - viewport->flags = gConfigGeneral.AlwaysShowGridlines ? VIEWPORT_FLAG_GRIDLINES : 0; + viewport->flags = gConfigGeneral.AlwaysShowGridlines ? VIEWPORT_FLAG_GRIDLINES : VIEWPORT_FLAG_NONE; Invalidate(); } diff --git a/src/openrct2-ui/windows/Main.cpp b/src/openrct2-ui/windows/Main.cpp index 6b3d414c17..3484275922 100644 --- a/src/openrct2-ui/windows/Main.cpp +++ b/src/openrct2-ui/windows/Main.cpp @@ -35,8 +35,8 @@ public: if (viewport != nullptr) { SetViewportFlags(); + viewport->rotation = 0; } - gCurrentRotation = 0; gShowGridLinesRefCount = 0; gShowLandRightsRefCount = 0; gShowConstructionRightsRefCount = 0; diff --git a/src/openrct2-ui/windows/Park.cpp b/src/openrct2-ui/windows/Park.cpp index c900be1989..c7312ad288 100644 --- a/src/openrct2-ui/windows/Park.cpp +++ b/src/openrct2-ui/windows/Park.cpp @@ -628,7 +628,7 @@ private: int32_t viewportFlags{}; if (viewport == nullptr) { - viewportFlags = gConfigGeneral.AlwaysShowGridlines ? VIEWPORT_FLAG_GRIDLINES : 0; + viewportFlags = gConfigGeneral.AlwaysShowGridlines ? VIEWPORT_FLAG_GRIDLINES : VIEWPORT_FLAG_NONE; } else { diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index ec8a007811..446055c5a4 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -2584,7 +2584,7 @@ private: TileElement tempSideTrackTileElement{ 0x80, 0x8F, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; TileElement tempTrackTileElement{}; TileElement* backupTileElementArrays[5]{}; - PaintSession* session = PaintSessionAlloc(dpi, 0); + PaintSession* session = PaintSessionAlloc(dpi, 0, GetCurrentRotation()); trackDirection &= 3; auto currentRide = GetRide(rideIndex); diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index 0d16eeeaca..79926b55b3 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -137,7 +137,7 @@ public: this, windowPos + ScreenCoordsXY{ viewportWidget.left + 1, viewportWidget.top + 1 }, viewportWidget.width() - 1, viewportWidget.height() - 1, Focus(CoordsXYZ{ signViewPosition, viewZ })); - viewport->flags = gConfigGeneral.AlwaysShowGridlines ? VIEWPORT_FLAG_GRIDLINES : 0; + viewport->flags = gConfigGeneral.AlwaysShowGridlines ? VIEWPORT_FLAG_GRIDLINES : VIEWPORT_FLAG_NONE; Invalidate(); return true; @@ -315,7 +315,7 @@ public: this, windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, viewportWidget->width() - 1, viewportWidget->height() - 1, Focus(CoordsXYZ{ signViewPos })); if (viewport != nullptr) - viewport->flags = gConfigGeneral.AlwaysShowGridlines ? VIEWPORT_FLAG_GRIDLINES : 0; + viewport->flags = gConfigGeneral.AlwaysShowGridlines ? VIEWPORT_FLAG_GRIDLINES : VIEWPORT_FLAG_NONE; Invalidate(); } diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 2cc73bac57..0abd720470 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -3689,19 +3689,13 @@ void TopToolbar::InitRotateMenu(Widget& widget) void TopToolbar::RotateMenuDropdown(int16_t dropdownIndex) { - auto* w = WindowGetMain(); - if (w != nullptr) + if (dropdownIndex == 0) { - if (dropdownIndex == 0) - { - WindowRotateCamera(*w, 1); - w->Invalidate(); - } - else if (dropdownIndex == 1) - { - WindowRotateCamera(*w, -1); - w->Invalidate(); - } + ViewportRotateAll(1); + } + else if (dropdownIndex == 1) + { + ViewportRotateAll(-1); } } diff --git a/src/openrct2-ui/windows/Viewport.cpp b/src/openrct2-ui/windows/Viewport.cpp index 09a29e24ad..6a5599c45b 100644 --- a/src/openrct2-ui/windows/Viewport.cpp +++ b/src/openrct2-ui/windows/Viewport.cpp @@ -28,6 +28,7 @@ enum WindowViewportWidgetIdx WIDX_ZOOM_IN, WIDX_ZOOM_OUT, WIDX_LOCATE, + WIDX_ROTATE, }; #pragma region MEASUREMENTS @@ -48,6 +49,7 @@ static Widget _viewportWidgets[] = MakeWidget({WW - 25, 17}, VIEWPORT_BUTTON, WindowWidgetType::FlatBtn, WindowColour::Primary , ImageId(SPR_G2_ZOOM_IN), STR_ZOOM_IN_TIP ), // zoom in MakeWidget({WW - 25, 41}, VIEWPORT_BUTTON, WindowWidgetType::FlatBtn, WindowColour::Primary , ImageId(SPR_G2_ZOOM_OUT), STR_ZOOM_OUT_TIP ), // zoom out MakeWidget({WW - 25, 65}, VIEWPORT_BUTTON, WindowWidgetType::FlatBtn, WindowColour::Primary , ImageId(SPR_LOCATE), STR_LOCATE_SUBJECT_TIP), // locate + MakeWidget({WW - 25, 89}, VIEWPORT_BUTTON, WindowWidgetType::FlatBtn, WindowColour::Primary , ImageId(SPR_ROTATE_ARROW),STR_LOCATE_SUBJECT_TIP), // rotate WIDGETS_END, }; @@ -93,7 +95,7 @@ public: savedViewPos = { x - (viewport->view_width / 2), y - (viewport->view_height / 2) }; } - viewport->flags |= VIEWPORT_FLAG_SOUND_ON; + viewport->flags |= VIEWPORT_FLAG_SOUND_ON | VIEWPORT_FLAG_INDEPEDENT_ROTATION; min_width = WW; min_height = WH; @@ -109,7 +111,7 @@ public: if (viewport != nullptr && viewport->flags != mainWindow->viewport->flags) { - viewport->flags = mainWindow->viewport->flags; + viewport->flags = mainWindow->viewport->flags | VIEWPORT_FLAG_INDEPEDENT_ROTATION; Invalidate(); } @@ -125,20 +127,25 @@ public: Close(); break; case WIDX_ZOOM_IN: + { if (viewport != nullptr && viewport->zoom > ZoomLevel::min()) { viewport->zoom--; Invalidate(); } break; + } case WIDX_ZOOM_OUT: + { if (viewport != nullptr && viewport->zoom < ZoomLevel::max()) { viewport->zoom++; Invalidate(); } break; + } case WIDX_LOCATE: + { auto* mainWindow = WindowGetMain(); if (mainWindow != nullptr) { @@ -147,6 +154,13 @@ public: WindowScrollToLocation(*mainWindow, { info.Loc, TileElementHeight(info.Loc) }); } break; + } + case WIDX_ROTATE: + { + ViewportRotateSingle(this, 1); + Invalidate(); + break; + } } } @@ -184,6 +198,8 @@ public: widgets[WIDX_ZOOM_OUT].right = width - 2; widgets[WIDX_LOCATE].left = width - 27; widgets[WIDX_LOCATE].right = width - 2; + widgets[WIDX_ROTATE].left = width - 27; + widgets[WIDX_ROTATE].right = width - 2; widgets[WIDX_VIEWPORT].right = widgets[WIDX_ZOOM_IN].left - 1; widgets[WIDX_VIEWPORT].bottom = widgets[WIDX_BACKGROUND].bottom - 3; diff --git a/src/openrct2/drawing/LightFX.cpp b/src/openrct2/drawing/LightFX.cpp index c1ebd2ec05..73b8b3e58a 100644 --- a/src/openrct2/drawing/LightFX.cpp +++ b/src/openrct2/drawing/LightFX.cpp @@ -305,7 +305,7 @@ void LightFXPrepareLightList() dpi.zoom_level = _current_view_zoom_front; dpi.width = 1; - PaintSession* session = PaintSessionAlloc(dpi, w->viewport->flags); + PaintSession* session = PaintSessionAlloc(dpi, w->viewport->flags, w->viewport->rotation); PaintSessionGenerate(*session); PaintSessionArrange(*session); auto info = SetInteractionInfoFromPaintSession(session, w->viewport->flags, ViewportInteractionItemAll); @@ -437,7 +437,7 @@ void LightFXUpdateViewportSettings() Viewport* viewport = WindowGetViewport(mainWindow); _current_view_x_back = viewport->viewPos.x; _current_view_y_back = viewport->viewPos.y; - _current_view_rotation_back = GetCurrentRotation(); + _current_view_rotation_back = viewport->rotation; _current_view_zoom_back = viewport->zoom; } } diff --git a/src/openrct2/entity/EntityBase.cpp b/src/openrct2/entity/EntityBase.cpp index 75e9a07bfa..ac71e56e36 100644 --- a/src/openrct2/entity/EntityBase.cpp +++ b/src/openrct2/entity/EntityBase.cpp @@ -64,7 +64,7 @@ void EntityBase::Invalidate() break; } - ViewportsInvalidate(SpriteData.SpriteRect, maxZoom); + ViewportsInvalidate(GetLocation(), SpriteData.Width, SpriteData.HeightMin, SpriteData.HeightMax, maxZoom); } void EntityBase::Serialise(DataSerialiser& stream) diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index ef92c1c711..23f0d0e29e 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1165,15 +1165,14 @@ static int32_t ConsoleCommandSet(InteractiveConsole& console, const arguments_t& else if (argv[0] == "current_rotation" && InvalidArguments(&invalidArgs, int_valid[0])) { uint8_t currentRotation = GetCurrentRotation(); - WindowBase* mainWindow = WindowGetMain(); int32_t newRotation = int_val[0]; if (newRotation < 0 || newRotation > 3) { console.WriteLineError("Invalid argument. Valid rotations are 0-3."); } - else if (newRotation != currentRotation && mainWindow != nullptr) + else if (newRotation != currentRotation) { - WindowRotateCamera(*mainWindow, newRotation - currentRotation); + ViewportRotateAll(newRotation - currentRotation); } console.Execute("get current_rotation"); } diff --git a/src/openrct2/interface/Screenshot.cpp b/src/openrct2/interface/Screenshot.cpp index 56e27dcc61..3d6f2227b1 100644 --- a/src/openrct2/interface/Screenshot.cpp +++ b/src/openrct2/interface/Screenshot.cpp @@ -498,7 +498,7 @@ int32_t CommandLineForScreenshot(const char** argv, int32_t argc, ScreenshotOpti auto zoom = ZoomLevel{ customZoom }; auto rotation = std::atoi(argv[4]) & 3; viewport = GetGiantViewport(rotation, zoom); - gCurrentRotation = rotation; + viewport.rotation = rotation; } else { @@ -554,7 +554,7 @@ int32_t CommandLineForScreenshot(const char** argv, int32_t argc, ScreenshotOpti viewport.viewPos = { coords2d.x - ((viewport.view_width << customZoom) / 2), coords2d.y - ((viewport.view_height << customZoom) / 2) }; viewport.zoom = ZoomLevel{ static_cast(customZoom) }; - gCurrentRotation = customRotation; + viewport.rotation = customRotation; } else { @@ -562,7 +562,7 @@ int32_t CommandLineForScreenshot(const char** argv, int32_t argc, ScreenshotOpti viewport.viewPos = { gameState.SavedView - ScreenCoordsXY{ (viewport.view_width / 2), (viewport.view_height / 2) } }; viewport.zoom = gameState.SavedViewZoom; - gCurrentRotation = gameState.SavedViewRotation; + viewport.rotation = gameState.SavedViewRotation; } } @@ -656,8 +656,7 @@ void CaptureImage(const CaptureOptions& options) viewport = GetGiantViewport(options.Rotation, options.Zoom); } - auto backupRotation = gCurrentRotation; - gCurrentRotation = options.Rotation; + viewport.rotation = options.Rotation; if (options.Transparent) { @@ -669,6 +668,4 @@ void CaptureImage(const CaptureOptions& options) RenderViewport(nullptr, viewport, dpi); WriteDpiToFile(outputPath, dpi, gPalette); ReleaseDPI(dpi); - - gCurrentRotation = backupRotation; } diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 026cb67a09..65eb269a9a 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -65,8 +65,6 @@ Viewport* g_music_tracking_viewport; static std::unique_ptr _paintJobs; static std::vector _paintColumns; -uint8_t gCurrentRotation; - static uint32_t _currentImageType; InteractionInfo::InteractionInfo(const PaintStruct* ps) : Loc(ps->MapPos) @@ -75,7 +73,9 @@ InteractionInfo::InteractionInfo(const PaintStruct* ps) , SpriteType(ps->InteractionItem) { } + static void ViewportPaintWeatherGloom(DrawPixelInfo& dpi); +static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect); /** * This is not a viewport function. It is used to setup many variables for @@ -122,7 +122,7 @@ std::optional centre_2d_coordinates(const CoordsXYZ& loc, Viewpo return std::nullopt; } - auto screenCoord = Translate3DTo2DWithZ(GetCurrentRotation(), loc); + auto screenCoord = Translate3DTo2DWithZ(viewport->rotation, loc); screenCoord.x -= viewport->view_width / 2; screenCoord.y -= viewport->view_height / 2; return { screenCoord }; @@ -190,6 +190,7 @@ void ViewportCreate(WindowBase* w, const ScreenCoordsXY& screenCoords, int32_t w viewport->view_height = zoom.ApplyTo(height); viewport->zoom = zoom; viewport->flags = 0; + viewport->rotation = GetCurrentRotation(); if (gConfigGeneral.AlwaysShowGridlines) viewport->flags |= VIEWPORT_FLAG_GRIDLINES; @@ -227,6 +228,53 @@ void ViewportRemove(Viewport* viewport) _viewports.erase(it); } +Viewport* ViewportGetMain() +{ + auto mainWindow = WindowGetMain(); + if (mainWindow == nullptr) + { + return nullptr; + } + return mainWindow->viewport; +} + +void ViewportsInvalidate(int32_t x, int32_t y, int32_t z0, int32_t z1, ZoomLevel maxZoom) +{ + for (auto& vp : _viewports) + { + if (maxZoom == ZoomLevel{ -1 } || vp.zoom <= ZoomLevel{ maxZoom }) + { + int32_t x1, y1, x2, y2; + + x += 16; + y += 16; + auto screenCoord = Translate3DTo2DWithZ(vp.rotation, CoordsXYZ{ x, y, 0 }); + + x1 = screenCoord.x - 32; + y1 = screenCoord.y - 32 - z1; + x2 = screenCoord.x + 32; + y2 = screenCoord.y + 32 - z0; + + ViewportInvalidate(&vp, ScreenRect{ { x1, y1 }, { x2, y2 } }); + } + } +} + +void ViewportsInvalidate(const CoordsXYZ& pos, int32_t width, int32_t minHeight, int32_t maxHeight, ZoomLevel maxZoom) +{ + for (auto& vp : _viewports) + { + if (maxZoom == ZoomLevel{ -1 } || vp.zoom <= ZoomLevel{ maxZoom }) + { + auto screenCoords = Translate3DTo2DWithZ(vp.rotation, pos); + auto screenPos = ScreenRect( + screenCoords - ScreenCoordsXY{ width, minHeight }, screenCoords + ScreenCoordsXY{ width, maxHeight }); + + ViewportInvalidate(&vp, screenPos); + } + } +} + void ViewportsInvalidate(const ScreenRect& screenRect, ZoomLevel maxZoom) { for (auto& vp : _viewports) @@ -244,15 +292,14 @@ void ViewportsInvalidate(const ScreenRect& screenRect, ZoomLevel maxZoom) * edx is assumed to be (and always is) the current rotation, so it is not * needed as parameter. */ -CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords) +CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords, uint8_t rotation) { int32_t height = 0; - uint32_t rotation = GetCurrentRotation(); CoordsXY pos{}; for (int32_t i = 0; i < 6; i++) { - pos = ViewportPosToMapPos(startCoords, height); + pos = ViewportPosToMapPos(startCoords, height, rotation); height = TileElementHeight(pos); // HACK: This is to prevent the x and y values being set to values outside @@ -587,7 +634,7 @@ void ViewportUpdatePosition(WindowBase* window) auto viewportMidPoint = ScreenCoordsXY{ window->savedViewPos.x + viewport->view_width / 2, window->savedViewPos.y + viewport->view_height / 2 }; - auto mapCoord = ViewportPosToMapPos(viewportMidPoint, 0); + auto mapCoord = ViewportPosToMapPos(viewportMidPoint, 0, viewport->rotation); // Clamp to the map minimum value int32_t at_map_edge = 0; @@ -793,6 +840,65 @@ void ViewportUpdateSmartFollowVehicle(WindowBase* window) window->viewport_target_sprite = window->viewport_smart_follow_sprite; } +static void ViewportRotateSingleInternal(WindowBase& w, int32_t direction) +{ + auto* viewport = w.viewport; + if (viewport == nullptr) + return; + + auto windowPos = ScreenCoordsXY{ (viewport->width >> 1), (viewport->height >> 1) } + viewport->pos; + + // has something to do with checking if middle of the viewport is obstructed + Viewport* other; + auto mapXYCoords = ScreenGetMapXY(windowPos, &other); + CoordsXYZ coords{}; + + // other != viewport probably triggers on viewports in ride or guest window? + // naoXYCoords is nullopt if middle of viewport is obstructed by another window? + if (!mapXYCoords.has_value() || other != viewport) + { + auto viewPos = ScreenCoordsXY{ (viewport->view_width >> 1), (viewport->view_height >> 1) } + viewport->viewPos; + + coords = ViewportAdjustForMapHeight(viewPos, viewport->rotation); + } + else + { + coords.x = mapXYCoords->x; + coords.y = mapXYCoords->y; + coords.z = TileElementHeight(coords); + } + + viewport->rotation = (viewport->rotation + direction) & 3; + + auto centreLoc = centre_2d_coordinates(coords, viewport); + + if (centreLoc.has_value()) + { + w.savedViewPos = centreLoc.value(); + viewport->viewPos = *centreLoc; + } + + w.Invalidate(); + w.OnViewportRotate(); +} + +void ViewportRotateSingle(WindowBase* window, int32_t direction) +{ + ViewportRotateSingleInternal(*window, direction); +} + +void ViewportRotateAll(int32_t direction) +{ + WindowVisitEach([direction](WindowBase* w) { + auto* viewport = w->viewport; + if (viewport == nullptr) + return; + if (viewport->flags & VIEWPORT_FLAG_INDEPEDENT_ROTATION) + return; + ViewportRotateSingleInternal(*w, direction); + }); +} + /** * * rct2: 0x00685C02 @@ -891,7 +997,7 @@ static void ViewportPaintColumn(PaintSession& session) * edi: dpi * ebp: bottom */ -void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect) +static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect) { PROFILED_FUNCTION(); @@ -952,7 +1058,7 @@ void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRec // Generate and sort columns. for (x = alignedX; x < rightBorder; x += 32) { - PaintSession* session = PaintSessionAlloc(dpi1, viewFlags); + PaintSession* session = PaintSessionAlloc(dpi1, viewFlags, viewport->rotation); _paintColumns.push_back(session); DrawPixelInfo& dpi2 = session->DPI; @@ -1091,11 +1197,11 @@ void Viewport::Invalidate() const ViewportInvalidate(this, { viewPos, viewPos + ScreenCoordsXY{ view_width, view_height } }); } -CoordsXY ViewportPosToMapPos(const ScreenCoordsXY& coords, int32_t z) +CoordsXY ViewportPosToMapPos(const ScreenCoordsXY& coords, int32_t z, uint8_t rotation) { // Reverse of Translate3DTo2DWithZ CoordsXY ret = { coords.y - coords.x / 2 + z, coords.y + coords.x / 2 + z }; - auto inverseRotation = DirectionFlipXAxis(GetCurrentRotation()); + auto inverseRotation = DirectionFlipXAxis(rotation); return ret.Rotate(inverseRotation); } @@ -1819,31 +1925,31 @@ InteractionInfo GetMapCoordinatesFromPosWindow(WindowBase* window, const ScreenC return info; } - Viewport* myviewport = window->viewport; + Viewport* viewport = window->viewport; auto viewLoc = screenCoords; - viewLoc -= myviewport->pos; - if (viewLoc.x >= 0 && viewLoc.x < static_cast(myviewport->width) && viewLoc.y >= 0 - && viewLoc.y < static_cast(myviewport->height)) + viewLoc -= viewport->pos; + if (viewLoc.x >= 0 && viewLoc.x < static_cast(viewport->width) && viewLoc.y >= 0 + && viewLoc.y < static_cast(viewport->height)) { - viewLoc.x = myviewport->zoom.ApplyTo(viewLoc.x); - viewLoc.y = myviewport->zoom.ApplyTo(viewLoc.y); - viewLoc += myviewport->viewPos; - if (myviewport->zoom > ZoomLevel{ 0 }) + viewLoc.x = viewport->zoom.ApplyTo(viewLoc.x); + viewLoc.y = viewport->zoom.ApplyTo(viewLoc.y); + viewLoc += viewport->viewPos; + if (viewport->zoom > ZoomLevel{ 0 }) { - viewLoc.x &= myviewport->zoom.ApplyTo(0xFFFFFFFF) & 0xFFFFFFFF; - viewLoc.y &= myviewport->zoom.ApplyTo(0xFFFFFFFF) & 0xFFFFFFFF; + viewLoc.x &= viewport->zoom.ApplyTo(0xFFFFFFFF) & 0xFFFFFFFF; + viewLoc.y &= viewport->zoom.ApplyTo(0xFFFFFFFF) & 0xFFFFFFFF; } DrawPixelInfo dpi; dpi.x = viewLoc.x; dpi.y = viewLoc.y; dpi.height = 1; - dpi.zoom_level = myviewport->zoom; + dpi.zoom_level = viewport->zoom; dpi.width = 1; - PaintSession* session = PaintSessionAlloc(dpi, myviewport->flags); + PaintSession* session = PaintSessionAlloc(dpi, viewport->flags, viewport->rotation); PaintSessionGenerate(*session); PaintSessionArrange(*session); - info = SetInteractionInfoFromPaintSession(session, myviewport->flags, flags & 0xFFFF); + info = SetInteractionInfoFromPaintSession(session, viewport->flags, flags & 0xFFFF); PaintSessionFree(session); } return info; @@ -1944,7 +2050,7 @@ std::optional ScreenGetMapXY(const ScreenCoordsXY& screenCoords, Viewp for (int32_t i = 0; i < 5; i++) { int32_t z = TileElementHeight(cursorMapPos); - cursorMapPos = ViewportPosToMapPos(start_vp_pos, z); + cursorMapPos = ViewportPosToMapPos(start_vp_pos, z, myViewport->rotation); cursorMapPos.x = std::clamp(cursorMapPos.x, info.Loc.x, info.Loc.x + 31); cursorMapPos.y = std::clamp(cursorMapPos.y, info.Loc.y, info.Loc.y + 31); } @@ -1968,7 +2074,7 @@ std::optional ScreenGetMapXYWithZ(const ScreenCoordsXY& screenCoords, } auto vpCoords = viewport->ScreenToViewportCoord(screenCoords); - auto mapPosition = ViewportPosToMapPos(vpCoords, z); + auto mapPosition = ViewportPosToMapPos(vpCoords, z, viewport->rotation); if (!MapIsLocationValid(mapPosition)) { return std::nullopt; @@ -2043,7 +2149,13 @@ std::optional ScreenGetMapXYSideWithZ(const ScreenCoordsXY& screenCoor */ uint8_t GetCurrentRotation() { - uint8_t rotation = gCurrentRotation; + auto* viewport = ViewportGetMain(); + if (viewport == nullptr) + { + LOG_VERBOSE("No viewport found! Will return 0."); + return 0; + } + uint8_t rotation = viewport->rotation; uint8_t rotation_masked = rotation & 3; #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (rotation != rotation_masked) @@ -2081,7 +2193,7 @@ void ViewportSetSavedView() gameState.SavedView = ScreenCoordsXY{ viewport->view_width / 2, viewport->view_height / 2 } + viewport->viewPos; gameState.SavedViewZoom = viewport->zoom; - gameState.SavedViewRotation = GetCurrentRotation(); + gameState.SavedViewRotation = viewport->rotation; } } diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index d206a672a8..904ab8ddf9 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -28,40 +28,44 @@ struct PaintEntry; // Flags must currenly retain their values to avoid breaking plugins. // Values can be changed when plugins move to using named constants. -enum +enum : uint32_t { - VIEWPORT_FLAG_GRIDLINES = (1 << 7), - VIEWPORT_FLAG_UNDERGROUND_INSIDE = (1 << 0), - VIEWPORT_FLAG_HIDE_BASE = (1 << 12), - VIEWPORT_FLAG_HIDE_VERTICAL = (1 << 13), + VIEWPORT_FLAG_NONE = 0U, - VIEWPORT_FLAG_SOUND_ON = (1 << 10), - VIEWPORT_FLAG_LAND_OWNERSHIP = (1 << 8), - VIEWPORT_FLAG_CONSTRUCTION_RIGHTS = (1 << 9), - VIEWPORT_FLAG_HIDE_ENTITIES = (1 << 14), - VIEWPORT_FLAG_CLIP_VIEW = (1 << 17), - VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES = (1 << 18), - VIEWPORT_FLAG_TRANSPARENT_BACKGROUND = (1 << 19), + VIEWPORT_FLAG_GRIDLINES = (1U << 7), + VIEWPORT_FLAG_UNDERGROUND_INSIDE = (1U << 0), + VIEWPORT_FLAG_HIDE_BASE = (1U << 12), + VIEWPORT_FLAG_HIDE_VERTICAL = (1U << 13), - VIEWPORT_FLAG_LAND_HEIGHTS = (1 << 4), - VIEWPORT_FLAG_TRACK_HEIGHTS = (1 << 5), - VIEWPORT_FLAG_PATH_HEIGHTS = (1 << 6), + VIEWPORT_FLAG_SOUND_ON = (1U << 10), + VIEWPORT_FLAG_LAND_OWNERSHIP = (1U << 8), + VIEWPORT_FLAG_CONSTRUCTION_RIGHTS = (1U << 9), + VIEWPORT_FLAG_HIDE_ENTITIES = (1U << 14), + VIEWPORT_FLAG_CLIP_VIEW = (1U << 17), + VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES = (1U << 18), + VIEWPORT_FLAG_TRANSPARENT_BACKGROUND = (1U << 19), - VIEWPORT_FLAG_HIDE_RIDES = (1 << 1), - VIEWPORT_FLAG_HIDE_VEHICLES = (1 << 20), - VIEWPORT_FLAG_HIDE_VEGETATION = (1 << 21), - VIEWPORT_FLAG_HIDE_SCENERY = (1 << 2), - VIEWPORT_FLAG_HIDE_PATHS = (1 << 16), - VIEWPORT_FLAG_HIDE_SUPPORTS = (1 << 3), - VIEWPORT_FLAG_HIDE_GUESTS = (1 << 11), - VIEWPORT_FLAG_HIDE_STAFF = (1 << 23), + VIEWPORT_FLAG_LAND_HEIGHTS = (1U << 4), + VIEWPORT_FLAG_TRACK_HEIGHTS = (1U << 5), + VIEWPORT_FLAG_PATH_HEIGHTS = (1U << 6), - VIEWPORT_FLAG_INVISIBLE_RIDES = (1 << 24), - VIEWPORT_FLAG_INVISIBLE_VEHICLES = (1 << 25), - VIEWPORT_FLAG_INVISIBLE_VEGETATION = (1 << 26), - VIEWPORT_FLAG_INVISIBLE_SCENERY = (1 << 27), - VIEWPORT_FLAG_INVISIBLE_PATHS = (1 << 28), - VIEWPORT_FLAG_INVISIBLE_SUPPORTS = (1 << 29), + VIEWPORT_FLAG_HIDE_RIDES = (1U << 1), + VIEWPORT_FLAG_HIDE_VEHICLES = (1U << 20), + VIEWPORT_FLAG_HIDE_VEGETATION = (1U << 21), + VIEWPORT_FLAG_HIDE_SCENERY = (1U << 2), + VIEWPORT_FLAG_HIDE_PATHS = (1U << 16), + VIEWPORT_FLAG_HIDE_SUPPORTS = (1U << 3), + VIEWPORT_FLAG_HIDE_GUESTS = (1U << 11), + VIEWPORT_FLAG_HIDE_STAFF = (1U << 23), + + VIEWPORT_FLAG_INVISIBLE_RIDES = (1U << 24), + VIEWPORT_FLAG_INVISIBLE_VEHICLES = (1U << 25), + VIEWPORT_FLAG_INVISIBLE_VEGETATION = (1U << 26), + VIEWPORT_FLAG_INVISIBLE_SCENERY = (1U << 27), + VIEWPORT_FLAG_INVISIBLE_PATHS = (1U << 28), + VIEWPORT_FLAG_INVISIBLE_SUPPORTS = (1U << 29), + + VIEWPORT_FLAG_INDEPEDENT_ROTATION = (1U << 30), }; enum class VisibilityKind @@ -123,12 +127,13 @@ extern uint8_t gShowConstructionRightsRefCount; // rct2: 0x014234BC extern Viewport* g_music_tracking_viewport; -extern uint8_t gCurrentRotation; - void ViewportInitAll(); std::optional centre_2d_coordinates(const CoordsXYZ& loc, Viewport* viewport); void ViewportCreate(WindowBase* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus); void ViewportRemove(Viewport* viewport); +Viewport* ViewportGetMain(); +void ViewportsInvalidate(int32_t x, int32_t y, int32_t z0, int32_t z1, ZoomLevel maxZoom); +void ViewportsInvalidate(const CoordsXYZ& pos, int32_t width, int32_t minHeight, int32_t maxHeight, ZoomLevel maxZoom); void ViewportsInvalidate(const ScreenRect& screenRect, ZoomLevel maxZoom = ZoomLevel{ -1 }); void ViewportUpdatePosition(WindowBase* window); void ViewportUpdateFollowSprite(WindowBase* window); @@ -136,12 +141,13 @@ void ViewportUpdateSmartFollowEntity(WindowBase* window); void ViewportUpdateSmartFollowGuest(WindowBase* window, const Guest* peep); void ViewportUpdateSmartFollowStaff(WindowBase* window, const Staff* peep); void ViewportUpdateSmartFollowVehicle(WindowBase* window); +void ViewportRotateSingle(WindowBase* window, int32_t direction); +void ViewportRotateAll(int32_t direction); void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport, const ScreenRect& screenRect); -void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect); -CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords); +CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords, uint8_t rotation); -CoordsXY ViewportPosToMapPos(const ScreenCoordsXY& coords, int32_t z); +CoordsXY ViewportPosToMapPos(const ScreenCoordsXY& coords, int32_t z, uint8_t rotation); std::optional ScreenPosToMapPos(const ScreenCoordsXY& screenCoords, int32_t* direction); void ShowGridlines(); diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index 52dac802eb..4d7b2898a1 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -836,7 +836,7 @@ void WindowScrollToLocation(WindowBase& w, const CoordsXYZ& coords) } } - auto screenCoords = Translate3DTo2DWithZ(GetCurrentRotation(), coords); + auto screenCoords = Translate3DTo2DWithZ(w.viewport->rotation, coords); int32_t i = 0; if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO)) @@ -889,66 +889,6 @@ void WindowScrollToLocation(WindowBase& w, const CoordsXYZ& coords) } } -/** - * - * rct2: 0x00688956 - */ -static void call_event_viewport_rotate_on_all_windows() -{ - WindowVisitEach([](WindowBase* w) { w->OnViewportRotate(); }); -} - -/** - * - * rct2: 0x0068881A - * direction can be used to alter the camera rotation: - * 1: clockwise - * -1: anti-clockwise - */ -void WindowRotateCamera(WindowBase& w, int32_t direction) -{ - Viewport* viewport = w.viewport; - if (viewport == nullptr) - return; - - auto windowPos = ScreenCoordsXY{ (viewport->width >> 1), (viewport->height >> 1) } + viewport->pos; - - // has something to do with checking if middle of the viewport is obstructed - Viewport* other; - auto mapXYCoords = ScreenGetMapXY(windowPos, &other); - CoordsXYZ coords{}; - - // other != viewport probably triggers on viewports in ride or guest window? - // naoXYCoords is nullopt if middle of viewport is obstructed by another window? - if (!mapXYCoords.has_value() || other != viewport) - { - auto viewPos = ScreenCoordsXY{ (viewport->view_width >> 1), (viewport->view_height >> 1) } + viewport->viewPos; - - coords = ViewportAdjustForMapHeight(viewPos); - } - else - { - coords.x = mapXYCoords->x; - coords.y = mapXYCoords->y; - coords.z = TileElementHeight(coords); - } - - gCurrentRotation = (GetCurrentRotation() + direction) & 3; - - auto centreLoc = centre_2d_coordinates(coords, viewport); - - if (centreLoc.has_value()) - { - w.savedViewPos = centreLoc.value(); - viewport->viewPos = *centreLoc; - } - - w.Invalidate(); - - call_event_viewport_rotate_on_all_windows(); - ResetAllSpriteQuadrantPlacements(); -} - void WindowViewportGetMapCoordsByCursor( const WindowBase& w, int32_t* map_x, int32_t* map_y, int32_t* offset_x, int32_t* offset_y) { @@ -957,8 +897,8 @@ void WindowViewportGetMapCoordsByCursor( // Compute map coordinate by mouse position. auto viewportPos = w.viewport->ScreenToViewportCoord(mouseCoords); - auto coordsXYZ = ViewportAdjustForMapHeight(viewportPos); - auto mapCoords = ViewportPosToMapPos(viewportPos, coordsXYZ.z); + auto coordsXYZ = ViewportAdjustForMapHeight(viewportPos, w.viewport->rotation); + auto mapCoords = ViewportPosToMapPos(viewportPos, coordsXYZ.z, w.viewport->rotation); *map_x = mapCoords.x; *map_y = mapCoords.y; diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index 556292be1b..f671194564 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -148,16 +148,16 @@ struct Widget */ struct Viewport { - int32_t width; - int32_t height; - ScreenCoordsXY pos; - ScreenCoordsXY viewPos; - int32_t view_width; - int32_t view_height; - uint32_t flags; - ZoomLevel zoom; - uint8_t var_11; - VisibilityCache visibility; + int32_t width{}; + int32_t height{}; + ScreenCoordsXY pos{}; + ScreenCoordsXY viewPos{}; + int32_t view_width{}; + int32_t view_height{}; + uint32_t flags{}; + ZoomLevel zoom{}; + uint8_t rotation{}; + VisibilityCache visibility{}; // Use this function on coordinates that are relative to the viewport zoom i.e. a peeps x, y position after transforming // from its x, y, z @@ -579,7 +579,6 @@ void WindowPushOthersBelow(WindowBase& w1); WindowBase* WindowGetMain(); void WindowScrollToLocation(WindowBase& w, const CoordsXYZ& coords); -void WindowRotateCamera(WindowBase& w, int32_t direction); void WindowViewportGetMapCoordsByCursor( const WindowBase& w, int32_t* map_x, int32_t* map_y, int32_t* offset_x, int32_t* offset_y); void WindowViewportCentreTileAroundCursor(WindowBase& w, int32_t map_x, int32_t map_y, int32_t offset_x, int32_t offset_y); diff --git a/src/openrct2/paint/Paint.Entity.cpp b/src/openrct2/paint/Paint.Entity.cpp index be86e4e3a5..3e1e074dc6 100644 --- a/src/openrct2/paint/Paint.Entity.cpp +++ b/src/openrct2/paint/Paint.Entity.cpp @@ -94,10 +94,13 @@ void EntityPaintSetup(PaintSession& session, const CoordsXY& pos) } } - if (session.DPI.y + session.DPI.height <= spr->SpriteData.SpriteRect.GetTop() - || spr->SpriteData.SpriteRect.GetBottom() <= session.DPI.y - || session.DPI.x + session.DPI.width <= spr->SpriteData.SpriteRect.GetLeft() - || spr->SpriteData.SpriteRect.GetRight() <= session.DPI.x) + auto screenCoords = Translate3DTo2DWithZ(session.CurrentRotation, spr->GetLocation()); + auto spriteRect = ScreenRect( + 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) { continue; } diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index 714f203fea..3a99d2117f 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -55,7 +55,7 @@ bool gPaintBoundingBoxes; bool gPaintBlockedTiles; static void PaintAttachedPS(DrawPixelInfo& dpi, PaintStruct* ps, uint32_t viewFlags); -static void PaintPSImageWithBoundingBoxes(DrawPixelInfo& dpi, PaintStruct* ps, ImageId imageId, int32_t x, int32_t y); +static void PaintPSImageWithBoundingBoxes(PaintSession& session, PaintStruct* ps, ImageId imageId, int32_t x, int32_t y); static ImageId PaintPSColourifyImage(const PaintStruct* ps, ImageId imageId, uint32_t viewFlags); static int32_t RemapPositionToQuadrant(const PaintStruct& ps, uint8_t rotation) @@ -243,7 +243,6 @@ template void PaintSessionGenerateRotate(PaintSession& sessio */ void PaintSessionGenerate(PaintSession& session) { - session.CurrentRotation = GetCurrentRotation(); switch (DirectionFlipXAxis(session.CurrentRotation)) { case 0: @@ -533,7 +532,7 @@ static void PaintDrawStruct(PaintSession& session, PaintStruct* ps) auto imageId = PaintPSColourifyImage(ps, ps->image_id, session.ViewFlags); if (gPaintBoundingBoxes && session.DPI.zoom_level == ZoomLevel{ 0 }) { - PaintPSImageWithBoundingBoxes(session.DPI, ps, imageId, screenPos.x, screenPos.y); + PaintPSImageWithBoundingBoxes(session, ps, imageId, screenPos.x, screenPos.y); } else { @@ -588,10 +587,12 @@ static void PaintAttachedPS(DrawPixelInfo& dpi, PaintStruct* ps, uint32_t viewFl } } -static void PaintPSImageWithBoundingBoxes(DrawPixelInfo& dpi, PaintStruct* ps, ImageId imageId, int32_t x, int32_t y) +static void PaintPSImageWithBoundingBoxes(PaintSession& session, PaintStruct* ps, ImageId imageId, int32_t x, int32_t y) { + auto& dpi = session.DPI; + const uint8_t colour = BoundBoxDebugColours[EnumValue(ps->InteractionItem)]; - const uint8_t rotation = GetCurrentRotation(); + const uint8_t rotation = session.CurrentRotation; const CoordsXYZ frontTop = { ps->Bounds.x_end, @@ -688,9 +689,9 @@ static ImageId PaintPSColourifyImage(const PaintStruct* ps, ImageId imageId, uin } } -PaintSession* PaintSessionAlloc(DrawPixelInfo& dpi, uint32_t viewFlags) +PaintSession* PaintSessionAlloc(DrawPixelInfo& dpi, uint32_t viewFlags, uint8_t rotation) { - return GetContext()->GetPainter()->CreateSession(dpi, viewFlags); + return GetContext()->GetPainter()->CreateSession(dpi, viewFlags, rotation); } void PaintSessionFree(PaintSession* session) diff --git a/src/openrct2/paint/Paint.h b/src/openrct2/paint/Paint.h index 7248fe134c..3bd4dc19e8 100644 --- a/src/openrct2/paint/Paint.h +++ b/src/openrct2/paint/Paint.h @@ -338,7 +338,7 @@ void PaintFloatingMoneyEffect( PaintSession& session, money64 amount, StringId string_id, int32_t y, int32_t z, int8_t y_offsets[], int32_t offset_x, uint32_t rotation); -PaintSession* PaintSessionAlloc(DrawPixelInfo& dpi, uint32_t viewFlags); +PaintSession* PaintSessionAlloc(DrawPixelInfo& dpi, uint32_t viewFlags, uint8_t rotation); void PaintSessionFree(PaintSession* session); void PaintSessionGenerate(PaintSession& session); void PaintSessionArrange(PaintSessionCore& session); diff --git a/src/openrct2/paint/Painter.cpp b/src/openrct2/paint/Painter.cpp index 1240a9270b..d91d24d94a 100644 --- a/src/openrct2/paint/Painter.cpp +++ b/src/openrct2/paint/Painter.cpp @@ -133,7 +133,7 @@ void Painter::MeasureFPS() _lastSecond = currentTime; } -PaintSession* Painter::CreateSession(DrawPixelInfo& dpi, uint32_t viewFlags) +PaintSession* Painter::CreateSession(DrawPixelInfo& dpi, uint32_t viewFlags, uint8_t rotation) { PROFILED_FUNCTION(); @@ -160,6 +160,7 @@ PaintSession* Painter::CreateSession(DrawPixelInfo& dpi, uint32_t viewFlags) session->QuadrantFrontIndex = 0; session->PaintEntryChain = _paintStructPool.Create(); session->Flags = 0; + session->CurrentRotation = rotation; std::fill(std::begin(session->Quadrants), std::end(session->Quadrants), nullptr); session->PaintHead = nullptr; diff --git a/src/openrct2/paint/Painter.h b/src/openrct2/paint/Painter.h index 7f51f6558e..54a119fd0c 100644 --- a/src/openrct2/paint/Painter.h +++ b/src/openrct2/paint/Painter.h @@ -47,7 +47,7 @@ namespace OpenRCT2 explicit Painter(const std::shared_ptr& uiContext); void Paint(Drawing::IDrawingEngine& de); - PaintSession* CreateSession(DrawPixelInfo& dpi, uint32_t viewFlags); + PaintSession* CreateSession(DrawPixelInfo& dpi, uint32_t viewFlags, uint8_t rotation); void ReleaseSession(PaintSession* session); ~Painter(); diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index acba501d46..df37b689a5 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -2081,10 +2081,9 @@ void TrackDesignDrawPreview(TrackDesign* td6, uint8_t* pixels) const ScreenCoordsXY offset = { size_x / 2, size_y / 2 }; for (uint8_t i = 0; i < 4; i++) { - gCurrentRotation = i; - view.viewPos = Translate3DTo2DWithZ(i, centre) - offset; - ViewportPaint(&view, dpi, { view.viewPos, view.viewPos + ScreenCoordsXY{ size_x, size_y } }); + view.rotation = i; + ViewportRender(dpi, &view, { {}, ScreenCoordsXY{ size_x, size_y } }); dpi.bits += TRACK_PREVIEW_IMAGE_SIZE; } diff --git a/src/openrct2/title/Command/RotateView.cpp b/src/openrct2/title/Command/RotateView.cpp index a4e6ac7263..b49cf5b313 100644 --- a/src/openrct2/title/Command/RotateView.cpp +++ b/src/openrct2/title/Command/RotateView.cpp @@ -9,19 +9,16 @@ #include "RotateView.h" +#include "../../interface/Viewport.h" #include "../../interface/Window.h" namespace OpenRCT2::Title { int16_t RotateViewCommand::operator()(int16_t timer) { - WindowBase* w = WindowGetMain(); - if (w != nullptr) + for (uint_fast8_t i = 0; i < Rotations; i++) { - for (uint_fast8_t i = 0; i < Rotations; i++) - { - WindowRotateCamera(*w, 1); - } + ViewportRotateAll(1); } return 0; diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 9902003726..c54adceb7f 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -289,7 +289,7 @@ CoordsXY FootpathGetCoordinatesFromPos(const ScreenCoordsXY& screenCoords, int32 { z = TileElementHeight(position); } - position = ViewportPosToMapPos(start_vp_pos, z); + position = ViewportPosToMapPos(start_vp_pos, z, viewport->rotation); position.x = std::clamp(position.x, minPosition.x, maxPosition.x); position.y = std::clamp(position.y, minPosition.y, maxPosition.y); } diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index cf0cff8579..d1b5e81d3e 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -111,7 +111,6 @@ static std::vector _tileElementsStash; static size_t _tileElementsInUse; static size_t _tileElementsInUseStash; static TileCoordsXY _mapSizeStash; -static int32_t _currentRotationStash; void StashMap() { @@ -119,7 +118,6 @@ void StashMap() _tileIndexStash = std::move(_tileIndex); _tileElementsStash = std::move(gameState.TileElements); _mapSizeStash = GetGameState().MapSize; - _currentRotationStash = gCurrentRotation; _tileElementsInUseStash = _tileElementsInUse; } @@ -129,7 +127,6 @@ void UnstashMap() _tileIndex = std::move(_tileIndexStash); gameState.TileElements = std::move(_tileElementsStash); GetGameState().MapSize = _mapSizeStash; - gCurrentRotation = _currentRotationStash; _tileElementsInUse = _tileElementsInUseStash; } @@ -1797,18 +1794,7 @@ static void MapInvalidateTileUnderZoom(int32_t x, int32_t y, int32_t z0, int32_t if (gOpenRCT2Headless) return; - int32_t x1, y1, x2, y2; - - x += 16; - y += 16; - auto screenCoord = Translate3DTo2D(GetCurrentRotation(), { x, y }); - - x1 = screenCoord.x - 32; - y1 = screenCoord.y - 32 - z1; - x2 = screenCoord.x + 32; - y2 = screenCoord.y + 32 - z0; - - ViewportsInvalidate({ { x1, y1 }, { x2, y2 } }, maxZoom); + ViewportsInvalidate(x, y, z0, z1, maxZoom); } /**