Linkgraph: Scroll overlay pixel cache instead of clearing it on scroll

Reduce cost of preparing/drawing cache
Improve missing station checks in RefreshDrawCache
Remove need for checks in DrawLinks
Don't rebase overlay cache coordinate to screen in viewport map mode
This commit is contained in:
Jonathan G Rennison
2024-01-18 01:57:13 +00:00
parent 6c30e88890
commit 7a5e8dd991
5 changed files with 113 additions and 43 deletions

View File

@@ -116,16 +116,25 @@ void LinkGraphOverlay::RebuildCache(bool incremental)
this->cached_links.clear();
this->cached_stations.clear();
this->last_update_number = GetWindowUpdateNumber();
this->rebuild_counter++;
}
if (this->company_mask == 0) return;
const Rect old_cached_region = this->cached_region;
DrawPixelInfo dpi;
bool cache_all = false;
if (this->window->viewport) {
const Viewport *vp = this->window->viewport;
const int pixel_margin = 256;
const int vp_margin = ScaleByZoom(pixel_margin, vp->zoom);
this->GetWidgetDpi(&dpi, pixel_margin);
if (vp->zoom < ZOOM_LVL_DRAW_MAP) {
this->GetWidgetDpi(&dpi, pixel_margin);
} else {
dpi.left = UnScaleByZoomLower(vp->virtual_left - vp_margin, vp->zoom);
dpi.top = UnScaleByZoomLower(vp->virtual_top - vp_margin, vp->zoom);
dpi.width = UnScaleByZoom(vp->virtual_width + vp_margin * 2, vp->zoom);
dpi.height = UnScaleByZoom(vp->virtual_height + vp_margin * 2, vp->zoom);
}
this->cached_region = Rect({ vp->virtual_left - vp_margin, vp->virtual_top - vp_margin,
vp->virtual_left + vp->virtual_width + vp_margin, vp->virtual_top + vp->virtual_height + vp_margin });
} else {
@@ -237,6 +246,26 @@ void LinkGraphOverlay::RebuildCache(bool incremental)
this->cached_links.push_back({ iter.first.first, iter.first.second, iter.second.from_pt, iter.second.to_pt, iter.second.prop });
}
if (incremental && (this->cached_stations.size() > previous_cached_stations_count || this->cached_links.size() > previous_cached_links_count)) {
/* Check if newly added stations/links are visible in previous cached area */
DrawPixelInfo old_dpi;
old_dpi.left = old_cached_region.left;
old_dpi.top = old_cached_region.top;
old_dpi.width = old_cached_region.right - old_cached_region.left;
old_dpi.height = old_cached_region.bottom - old_cached_region.top;
auto check_found = [&]() -> bool {
for (size_t i = previous_cached_stations_count; i < this->cached_stations.size(); i++) {
if (this->IsPointVisible(this->cached_stations[i].pt, &old_dpi)) return true;
}
for (size_t i = previous_cached_links_count; i < this->cached_links.size(); i++) {
if (this->IsLinkVisible(this->cached_links[i].from_pt, this->cached_links[i].to_pt, &old_dpi)) return true;
}
return false;
};
if (check_found()) this->rebuild_counter++;
}
if (previous_cached_stations_count > 0) {
std::inplace_merge(this->cached_stations.begin(), this->cached_stations.begin() + previous_cached_stations_count, this->cached_stations.end(),
[](const StationSupplyInfo &a, const StationSupplyInfo &b) {
@@ -364,17 +393,32 @@ inline bool LinkGraphOverlay::IsLinkVisible(Point pta, Point ptb, const DrawPixe
void LinkGraphOverlay::RefreshDrawCache()
{
static const Point INVALID_POINT = Point{ INT_MIN / 2, INT_MIN / 2 };
for (StationSupplyList::iterator i(this->cached_stations.begin()); i != this->cached_stations.end(); ++i) {
const Station *st = Station::GetIfValid(i->id);
if (st == nullptr) continue;
if (st == nullptr) {
i->pt = INVALID_POINT;
continue;
}
i->pt = this->GetStationMiddle(st);
Point new_pt = this->GetStationMiddle(st);
if (i->pt.x != new_pt.x || i->pt.y != new_pt.y) {
i->pt = new_pt;
}
}
for (LinkList::iterator i(this->cached_links.begin()); i != this->cached_links.end(); ++i) {
const Station *sta = Station::GetIfValid(i->from_id);
if (sta == nullptr) continue;
if (sta == nullptr) {
i->from_pt = i->to_pt = INVALID_POINT;
continue;
}
const Station *stb = Station::GetIfValid(i->to_id);
if (stb == nullptr) continue;
if (stb == nullptr) {
i->from_pt = i->to_pt = INVALID_POINT;
continue;
}
i->from_pt = this->GetStationMiddle(sta);
i->to_pt = this->GetStationMiddle(stb);
@@ -389,7 +433,7 @@ void LinkGraphOverlay::PrepareDraw()
if (this->dirty) {
this->RebuildCache();
}
if (this->last_update_number != GetWindowUpdateNumber()) {
if (this->last_update_number != GetWindowUpdateNumber() && this->window->viewport->zoom < ZOOM_LVL_DRAW_MAP) {
this->last_update_number = GetWindowUpdateNumber();
this->RefreshDrawCache();
}
@@ -414,8 +458,6 @@ void LinkGraphOverlay::DrawLinks(const DrawPixelInfo *dpi) const
int width = ScaleGUITrad(this->scale);
for (const auto &i : this->cached_links) {
if (!this->IsLinkVisible(i.from_pt, i.to_pt, dpi, width + 2)) continue;
if (!Station::IsValidID(i.from_id)) continue;
if (!Station::IsValidID(i.to_id)) continue;
this->DrawContent(dpi, i.from_pt, i.to_pt, i.prop);
}
}