From 8a5145678cd143b11444cc2484828efdf44f6dd8 Mon Sep 17 00:00:00 2001 From: mix Date: Sat, 24 May 2025 05:01:36 +0100 Subject: [PATCH] Pass viewport through map animation invalidation functions --- src/openrct2/interface/Viewport.cpp | 25 ++++--- src/openrct2/interface/Viewport.h | 2 + src/openrct2/world/MapAnimation.cpp | 101 +++++++++++++++++----------- 3 files changed, 82 insertions(+), 46 deletions(-) diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index e93fff2603..2bcd00fcb8 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -249,16 +249,11 @@ namespace OpenRCT2 void ViewportsInvalidate(const int32_t x, const int32_t y, const int32_t z0, const int32_t z1, const ZoomLevel maxZoom) { - for (auto& vp : _viewports) + for (const auto& viewport : _viewports) { - if (vp.isVisible && (maxZoom == ZoomLevel{ -1 } || vp.zoom <= ZoomLevel{ maxZoom })) + if (viewport.isVisible) { - const auto screenCoord = Translate3DTo2DWithZ(vp.rotation, CoordsXYZ{ x + 16, y + 16, 0 }); - - const auto topLeft = screenCoord - ScreenCoordsXY(32, 32 + z1); - const auto bottomRight = screenCoord + ScreenCoordsXY(32, 32 - z0); - - ViewportInvalidate(&vp, ScreenRect{ topLeft, bottomRight }); + viewport.Invalidate(x, y, z0, z1, maxZoom); } } } @@ -1191,6 +1186,20 @@ namespace OpenRCT2 ViewportInvalidate(this, { viewPos, viewPos + ScreenCoordsXY{ ViewWidth(), ViewHeight() } }); } + void Viewport::Invalidate( + const int32_t x, const int32_t y, const int32_t z0, const int32_t z1, const ZoomLevel maxZoom) const + { + if ((maxZoom == ZoomLevel{ -1 } || zoom <= ZoomLevel{ maxZoom })) + { + const auto screenCoord = Translate3DTo2DWithZ(rotation, CoordsXYZ{ x + 16, y + 16, 0 }); + + const auto topLeft = screenCoord - ScreenCoordsXY(32, 32 + z1); + const auto bottomRight = screenCoord + ScreenCoordsXY(32, 32 - z0); + + ViewportInvalidate(this, ScreenRect{ topLeft, bottomRight }); + } + } + CoordsXY ViewportPosToMapPos(const ScreenCoordsXY& coords, int32_t z, uint8_t rotation) { // Reverse of Translate3DTo2DWithZ diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index d6e23b012b..f775f43d8a 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -71,6 +71,8 @@ namespace OpenRCT2 [[nodiscard]] ScreenCoordsXY ScreenToViewportCoord(const ScreenCoordsXY& screenCoord) const; void Invalidate() const; + + void Invalidate(const int32_t x, const int32_t y, const int32_t z0, const int32_t z1, const ZoomLevel maxZoom) const; }; struct Focus; diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index 01f21e83a7..157930b4aa 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -75,8 +75,22 @@ static std::set _mapAnimationsUpdate; static std::set _temporaryMapAnimations; -template -static bool UpdateEntranceAnimation(const EntranceElement& entrance, const CoordsXYZ& loc, const int32_t baseZ) +template +static void Invalidate(const Viewport& viewport, const int32_t x, const int32_t y, const int32_t z0, const int32_t z1) +{ + if constexpr (invalidateAllViewports) + { + ViewportsInvalidate(x, y, z0, z1, kMaxZoom); + } + else + { + viewport.Invalidate(x, y, z0, z1, kMaxZoom); + } +} + +template +static bool UpdateEntranceAnimation( + const EntranceElement& entrance, const CoordsXYZ& loc, const int32_t baseZ, const Viewport& viewport) { if (entrance.GetEntranceType() == ENTRANCE_TYPE_RIDE_ENTRANCE) { @@ -88,8 +102,8 @@ static bool UpdateEntranceAnimation(const EntranceElement& entrance, const Coord { if constexpr (invalidate) { - ViewportsInvalidate( - loc.x, loc.y, baseZ + stationObj->Height + 8, baseZ + stationObj->Height + 24, kMaxZoom); + Invalidate( + viewport, loc.x, loc.y, baseZ + stationObj->Height + 8, baseZ + stationObj->Height + 24); } return true; } @@ -102,7 +116,7 @@ static bool UpdateEntranceAnimation(const EntranceElement& entrance, const Coord const int32_t direction = (entrance.GetDirection() + GetCurrentRotation()) & 3; if (direction == TILE_ELEMENT_DIRECTION_SOUTH || direction == TILE_ELEMENT_DIRECTION_WEST) { - ViewportsInvalidate(loc.x, loc.y, baseZ + 32, baseZ + 64, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ + 32, baseZ + 64); } } return true; @@ -111,8 +125,8 @@ static bool UpdateEntranceAnimation(const EntranceElement& entrance, const Coord return false; } -template -static bool UpdatePathAnimation(const PathElement& path, const CoordsXYZ& loc, const int32_t baseZ) +template +static bool UpdatePathAnimation(const PathElement& path, const CoordsXYZ& loc, const int32_t baseZ, const Viewport& viewport) { if (path.IsQueue() && path.HasQueueBanner()) { @@ -121,7 +135,7 @@ static bool UpdatePathAnimation(const PathElement& path, const CoordsXYZ& loc, c const int32_t direction = (path.GetQueueBannerDirection() + GetCurrentRotation()) & 3; if (direction == TILE_ELEMENT_DIRECTION_NORTH || direction == TILE_ELEMENT_DIRECTION_EAST) { - ViewportsInvalidate(loc.x, loc.y, baseZ + 16, baseZ + 30, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ + 16, baseZ + 30); } } return true; @@ -129,9 +143,9 @@ static bool UpdatePathAnimation(const PathElement& path, const CoordsXYZ& loc, c return false; } -template +template static std::optional UpdateSmallSceneryAnimation( - const SmallSceneryElement& scenery, const CoordsXYZ& loc, const int32_t baseZ) + const SmallSceneryElement& scenery, const CoordsXYZ& loc, const int32_t baseZ, const Viewport& viewport) { const auto entry = scenery.GetEntry(); if (entry == nullptr) @@ -169,13 +183,13 @@ static std::optional UpdateSmallSceneryAnimation( } if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ, scenery.GetClearanceZ(), kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ, scenery.GetClearanceZ()); } } } else if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ, scenery.GetClearanceZ(), kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ, scenery.GetClearanceZ()); } return std::optional(animationType); } @@ -183,28 +197,28 @@ static std::optional UpdateSmallSceneryAnimation( return std::nullopt; } -template -static bool UpdateTrackAnimation(TrackElement& track, const CoordsXYZ& loc, const int32_t baseZ) +template +static bool UpdateTrackAnimation(TrackElement& track, const CoordsXYZ& loc, const int32_t baseZ, const Viewport& viewport) { switch (track.GetTrackType()) { case TrackElemType::Waterfall: if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ + 14, baseZ + 46, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ + 14, baseZ + 46); } return true; case TrackElemType::Rapids: case TrackElemType::Whirlpool: if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ + 14, baseZ + 18, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ + 14, baseZ + 18); } return true; case TrackElemType::SpinningTunnel: if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ + 14, baseZ + 32, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ + 14, baseZ + 32); } return true; default: @@ -214,15 +228,16 @@ static bool UpdateTrackAnimation(TrackElement& track, const CoordsXYZ& loc, cons return false; } -template -static bool UpdateLargeSceneryAnimation(const LargeSceneryElement& scenery, const CoordsXYZ& loc, const int32_t baseZ) +template +static bool UpdateLargeSceneryAnimation( + const LargeSceneryElement& scenery, const CoordsXYZ& loc, const int32_t baseZ, const Viewport& viewport) { const auto entry = scenery.GetEntry(); if (entry != nullptr && (entry->flags & LARGE_SCENERY_FLAG_ANIMATED)) { if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ, baseZ + 16, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ, baseZ + 16); } return true; } @@ -230,8 +245,9 @@ static bool UpdateLargeSceneryAnimation(const LargeSceneryElement& scenery, cons return false; } -template -static std::optional UpdateWallAnimation(WallElement& wall, const CoordsXYZ& loc, const int32_t baseZ) +template +static std::optional UpdateWallAnimation( + WallElement& wall, const CoordsXYZ& loc, const int32_t baseZ, const Viewport& viewport) { const auto entry = wall.GetEntry(); if (entry == nullptr) @@ -274,7 +290,7 @@ static std::optional UpdateWallAnimation(WallElement& wall, const Co wall.SetAnimationFrame(newFrame); if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ, baseZ + 32, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ, baseZ + 32); } } } @@ -285,7 +301,7 @@ static std::optional UpdateWallAnimation(WallElement& wall, const Co { if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ, baseZ + 16, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ, baseZ + 16); } return std::optional(UpdateType::invalidate); } @@ -293,18 +309,19 @@ static std::optional UpdateWallAnimation(WallElement& wall, const Co return std::nullopt; } -template -static bool UpdateBannerAnimation([[maybe_unused]] const BannerElement& banner, const CoordsXYZ& loc, const int32_t baseZ) +template +static bool UpdateBannerAnimation( + [[maybe_unused]] const BannerElement& banner, const CoordsXYZ& loc, const int32_t baseZ, const Viewport& viewport) { if constexpr (invalidate) { - ViewportsInvalidate(loc.x, loc.y, baseZ, baseZ + 16, kMaxZoom); + Invalidate(viewport, loc.x, loc.y, baseZ, baseZ + 16); } return true; } -template -static std::optional UpdateTile(const TileCoordsXY& coords) +template +static std::optional UpdateTile(const TileCoordsXY& coords, const Viewport& viewport) { auto tileElement = MapGetFirstElementAt(coords); if (tileElement == nullptr) @@ -322,14 +339,17 @@ static std::optional UpdateTile(const TileCoordsXY& coords) switch (tileElement->GetType()) { case TileElementType::Entrance: - hasAnimations |= UpdateEntranceAnimation(*tileElement->AsEntrance(), loc, baseZ); + hasAnimations |= UpdateEntranceAnimation( + *tileElement->AsEntrance(), loc, baseZ, viewport); break; case TileElementType::Path: - hasAnimations |= UpdatePathAnimation(*tileElement->AsPath(), loc, baseZ); + hasAnimations |= UpdatePathAnimation( + *tileElement->AsPath(), loc, baseZ, viewport); break; case TileElementType::SmallScenery: { - const auto result = UpdateSmallSceneryAnimation(*tileElement->AsSmallScenery(), loc, baseZ); + const auto result = UpdateSmallSceneryAnimation( + *tileElement->AsSmallScenery(), loc, baseZ, viewport); if (result) { hasAnimations |= true; @@ -341,17 +361,21 @@ static std::optional UpdateTile(const TileCoordsXY& coords) break; } case TileElementType::Track: - hasAnimations |= UpdateTrackAnimation(*tileElement->AsTrack(), loc, baseZ); + hasAnimations |= UpdateTrackAnimation( + *tileElement->AsTrack(), loc, baseZ, viewport); break; case TileElementType::Banner: - hasAnimations |= UpdateBannerAnimation(*tileElement->AsBanner(), loc, baseZ); + hasAnimations |= UpdateBannerAnimation( + *tileElement->AsBanner(), loc, baseZ, viewport); break; case TileElementType::LargeScenery: - hasAnimations |= UpdateLargeSceneryAnimation(*tileElement->AsLargeScenery(), loc, baseZ); + hasAnimations |= UpdateLargeSceneryAnimation( + *tileElement->AsLargeScenery(), loc, baseZ, viewport); break; case TileElementType::Wall: { - const auto result = UpdateWallAnimation(*tileElement->AsWall(), loc, baseZ); + const auto result = UpdateWallAnimation( + *tileElement->AsWall(), loc, baseZ, viewport); if (result) { hasAnimations |= true; @@ -626,7 +650,7 @@ static void InvalidateAll(const ViewportList& viewports) { if (_mapAnimationsInvalidate.contains(tileCoords)) { - if (!UpdateTile(tileCoords)) + if (!UpdateTile(tileCoords, *viewport)) { _mapAnimationsInvalidate.erase(tileCoords); } @@ -655,7 +679,8 @@ static void UpdateAll(const ViewportList& viewports) while (it != _mapAnimationsUpdate.end()) { const bool isVisible = IsTileVisible(viewports, *it); - const auto result = isVisible ? UpdateTile(*it) : UpdateTile(*it); + const auto result = isVisible ? UpdateTile(*it, *viewports.front()) + : UpdateTile(*it, *viewports.front()); if (result) { if (result.value() == UpdateType::invalidate)