From 698409381eadb59357b42c3c52edd7f8cf7b397c Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 21 Jan 2019 20:02:49 +0000 Subject: [PATCH] Cache viewport station/waypoint sign infomation --- src/misc.cpp | 1 + src/openttd.cpp | 1 + src/station.cpp | 1 + src/station_cmd.cpp | 1 + src/viewport.cpp | 68 ++++++++++++++++++++++++++++++++++++++++---- src/viewport_func.h | 1 + src/waypoint_cmd.cpp | 1 + 7 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index a2aabdbcea..a299f46328 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -67,6 +67,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin AllocateMap(size_x, size_y); ViewportMapClearTunnelCache(); + ViewportClearStationSignCache(); ClearCommandLog(); _pause_mode = PM_UNPAUSED; diff --git a/src/openttd.cpp b/src/openttd.cpp index 294d20c584..a74d5b9603 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -373,6 +373,7 @@ static void ShutdownGame() UninitFreeType(); ViewportMapClearTunnelCache(); + ViewportClearStationSignCache(); ClearCommandLog(); } diff --git a/src/station.cpp b/src/station.cpp index f5057a4c93..d978730fa7 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -51,6 +51,7 @@ BaseStation::~BaseStation() DeleteWindowById(WC_DEPARTURES_BOARD, this->index); this->sign.MarkDirty(); + ViewportClearStationSignCache(); } Station::Station(TileIndex tile) : diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index d8c54712a5..29e9490b48 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -425,6 +425,7 @@ void Station::UpdateVirtCoord() this->sign.UpdatePosition(pt.x, pt.y, STR_VIEWPORT_STATION); SetWindowDirty(WC_STATION_VIEW, this->index); + ViewportClearStationSignCache(); } /** Update the virtual coords needed to draw the station sign for all stations. */ diff --git a/src/viewport.cpp b/src/viewport.cpp index 60e227e518..438f69976b 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -264,6 +264,18 @@ std::vector _vp_route_paths_last_mark_dirty; static void MarkRoutePathsDirty(const std::vector &lines); +struct ViewportStationSignCacheEntry { + int32 top; ///< The top of the sign + int32 left; ///< The left bound of the sign + int32 right; ///< The right bound of the sign + StationID id; ///< Station ID +}; + +static byte _viewport_station_sign_cache_display_mode = 0; +static const byte VIEWPORT_STATION_SIGN_CACHE_DISPLAY_MODE_MASK = ((1 << DO_SHOW_STATION_NAMES) | (1 << DO_SHOW_WAYPOINT_NAMES) | (1 << DO_SHOW_COMPETITOR_SIGNS)); +static OwnerByte _viewport_station_sign_cache_local_company { INVALID_OWNER }; +static std::vector _viewport_station_sign_cache; + TileHighlightData _thd; static TileInfo *_cur_ti; bool _draw_bounding_boxes = false; @@ -1391,6 +1403,26 @@ struct ViewportAddStringApproxBoundsChecker { } }; +struct ViewportStationSignCacheApproxBoundsChecker { + int top; + int bottom; + int left; + int right; + + ViewportStationSignCacheApproxBoundsChecker(const DrawPixelInfo *dpi) + { + this->top = dpi->top - ScaleByZoom(VPSM_TOP + FONT_HEIGHT_NORMAL + VPSM_BOTTOM, dpi->zoom); + this->bottom = dpi->top + dpi->height; + this->left = dpi->left; + this->right = dpi->left + dpi->width; + } + + bool IsStationSignCacheEntryMaybeOnScreen(const ViewportStationSignCacheEntry *sign) const + { + return !(this->bottom < sign->top || this->top > sign->top || this->right < sign->left || this->left > sign->right); + } +}; + static void ViewportAddTownNames(DrawPixelInfo *dpi) { if (!HasBit(_display_opt, DO_SHOW_TOWN_NAMES) || _game_mode == GM_MENU) return; @@ -1406,12 +1438,18 @@ static void ViewportAddTownNames(DrawPixelInfo *dpi) } } - -static void ViewportAddStationNames(DrawPixelInfo *dpi) +void ViewportClearStationSignCache() { - if (!(HasBit(_display_opt, DO_SHOW_STATION_NAMES) || HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES)) || _game_mode == GM_MENU) return; + _viewport_station_sign_cache.clear(); + _viewport_station_sign_cache_display_mode = 0; + _viewport_station_sign_cache_local_company = INVALID_OWNER; +} - ViewportAddStringApproxBoundsChecker checker(dpi); +void ViewportFillStationSignCache() +{ + _viewport_station_sign_cache.clear(); + _viewport_station_sign_cache_display_mode = _display_opt & VIEWPORT_STATION_SIGN_CACHE_DISPLAY_MODE_MASK; + _viewport_station_sign_cache_local_company = _local_company; const BaseStation *st; FOR_ALL_BASE_STATIONS(st) { @@ -1424,7 +1462,27 @@ static void ViewportAddStationNames(DrawPixelInfo *dpi) /* Don't draw if station is owned by another company and competitor station names are hidden. Stations owned by none are never ignored. */ if (!HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS) && _local_company != st->owner && st->owner != OWNER_NONE) continue; - if (!checker.IsSignMaybeOnScreen(&st->sign)) continue; + int sign_half_width = max(ScaleByZoom(st->sign.width_normal, ZOOM_LVL_OUT_8X), ScaleByZoom(st->sign.width_small, ZOOM_LVL_DRAW_SPR)) / 2; + _viewport_station_sign_cache.push_back({ st->sign.top, st->sign.center - sign_half_width, st->sign.center + sign_half_width, st->index }); + } +} + +static void ViewportAddStationNames(DrawPixelInfo *dpi) +{ + if (!(HasBit(_display_opt, DO_SHOW_STATION_NAMES) || HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES)) || _game_mode == GM_MENU) return; + + if (_viewport_station_sign_cache_display_mode != (_display_opt & VIEWPORT_STATION_SIGN_CACHE_DISPLAY_MODE_MASK) || _viewport_station_sign_cache_local_company != _local_company) { + ViewportFillStationSignCache(); + } + + ViewportStationSignCacheApproxBoundsChecker checker(dpi); + + for (const ViewportStationSignCacheEntry &entry : _viewport_station_sign_cache) { + + if (!checker.IsStationSignCacheEntryMaybeOnScreen(&entry)) continue; + + const BaseStation *st = BaseStation::Get(entry.id); + bool is_station = Station::IsExpected(st); ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &st->sign, is_station ? STR_VIEWPORT_STATION : STR_VIEWPORT_WAYPOINT, diff --git a/src/viewport_func.h b/src/viewport_func.h index 161aa9ebee..610cf43b8d 100644 --- a/src/viewport_func.h +++ b/src/viewport_func.h @@ -101,6 +101,7 @@ Point GetViewportStationMiddle(const ViewPort *vp, const Station *st); void ShowTooltipForTile(Window *w, const TileIndex tile); void ViewportMapClearTunnelCache(); +void ViewportClearStationSignCache(); void ViewportMapInvalidateTunnelCacheByTile(const TileIndex tile); void DrawTileSelectionRect(const TileInfo *ti, PaletteID pal); diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index a170dc420a..dfb7a8c5a6 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -44,6 +44,7 @@ void Waypoint::UpdateVirtCoord() this->sign.UpdatePosition(pt.x, pt.y - 32 * ZOOM_LVL_BASE, STR_VIEWPORT_WAYPOINT); /* Recenter viewport */ InvalidateWindowData(WC_WAYPOINT_VIEW, this->index); + ViewportClearStationSignCache(); } /**