Use overlay layer for plan rendering in viewport map mode

Scroll overlay layer when viewport is scrolled
pull/642/head
Jonathan G Rennison 4 months ago
parent 3d87cfeca5
commit 6c30e88890

@ -326,6 +326,7 @@ struct ViewportDrawerDynamic {
static void MarkRouteStepDirty(RouteStepsMap::const_iterator cit);
static void MarkRouteStepDirty(const TileIndex tile, uint order_nr);
static void HideMeasurementTooltips();
static void ViewportDrawPlans(const Viewport *vp, DrawPixelInfo *plan_dpi);
static std::unique_ptr<ViewportDrawerDynamic> _vdd;
std::vector<std::unique_ptr<ViewportDrawerDynamic>> _spare_viewport_drawers;
@ -480,20 +481,12 @@ static void FillViewportCoverageRect()
}
}
void ClearViewportLandPixelCache(Viewport *vp)
{
vp->land_pixel_cache.assign(vp->land_pixel_cache.size(), 0xD7);
}
using ScrollViewportPixelCacheGenericFillRegion = void (*)(Viewport *vp, int x, int y, int width, int height);
void ScrollViewportLandPixelCache(Viewport *vp, int offset_x, int offset_y)
static bool ScrollViewportPixelCacheGeneric(Viewport *vp, std::vector<byte> &cache, int offset_x, int offset_y, uint pixel_width, ScrollViewportPixelCacheGenericFillRegion fill_region)
{
if (vp->land_pixel_cache.empty()) return;
if (abs(offset_x) >= vp->width || abs(offset_y) >= vp->height) {
ClearViewportLandPixelCache(vp);
return;
}
const uint pixel_width = BlitterFactory::GetCurrentBlitter()->GetScreenDepth() / 8;
if (cache.empty()) return false;
if (abs(offset_x) >= vp->width || abs(offset_y) >= vp->height) return true;
int width = vp->width * pixel_width;
offset_x *= pixel_width;
@ -504,27 +497,73 @@ void ScrollViewportLandPixelCache(Viewport *vp, int offset_x, int offset_y)
/* Blitter_8bppDrawing::ScrollBuffer can be used on 32 bit buffers if widths and offsets are suitably adjusted */
Blitter_8bppDrawing blitter;
blitter.ScrollBuffer(vp->land_pixel_cache.data(), 0, 0, width, height, offset_x, offset_y);
blitter.ScrollBuffer(cache.data(), 0, 0, width, height, offset_x, offset_y);
auto fill_rect = [&](int x, int y, int w, int h) {
blitter.DrawRectAt(cache.data(), x, y, w, h, 0xD7);
if (fill_region != nullptr) fill_region(vp, x, y, w, h);
};
int x = 0;
if (offset_x < 0) {
/* scrolling right, moving pixels left, fill in on right */
width += offset_x;
blitter.DrawRectAt(vp->land_pixel_cache.data(), width, 0, -offset_x, height, 0xD7);
fill_rect(width, 0, -offset_x, height);
} else if (offset_x > 0) {
/* scrolling left, moving pixels right, fill in on left */
blitter.DrawRectAt(vp->land_pixel_cache.data(), 0, 0, offset_x, height, 0xD7);
fill_rect(0, 0, offset_x, height);
width -= offset_x;
x += offset_x;
}
if (offset_y < 0) {
/* scrolling down, moving pixels up, fill in at bottom */
height += offset_y;
blitter.DrawRectAt(vp->land_pixel_cache.data(), x, height, width, -offset_y, 0xD7);
fill_rect(x, height, width, -offset_y);
} else if (offset_y > 0) {
/* scrolling up, moving pixels down, fill in at top */
blitter.DrawRectAt(vp->land_pixel_cache.data(), x, 0, width, offset_y, 0xD7);
fill_rect(x, 0, width, offset_y);
}
return false;
}
void ClearViewportLandPixelCache(Viewport *vp)
{
vp->land_pixel_cache.assign(vp->land_pixel_cache.size(), 0xD7);
}
static void ScrollViewportLandPixelCache(Viewport *vp, int offset_x, int offset_y)
{
bool clear = ScrollViewportPixelCacheGeneric(vp, vp->land_pixel_cache, offset_x, offset_y, BlitterFactory::GetCurrentBlitter()->GetScreenDepth() / 8, nullptr);
if (clear) ClearViewportLandPixelCache(vp);
}
static void ClearViewportPlanPixelCache(Viewport *vp)
{
vp->plan_pixel_cache.clear();
vp->last_plan_update_number = 0;
}
static void ScrollPlanPixelCache(Viewport *vp, int offset_x, int offset_y)
{
if (vp->last_plan_update_number != _plan_update_counter) {
ClearViewportPlanPixelCache(vp);
return;
}
bool clear = ScrollViewportPixelCacheGeneric(vp, vp->plan_pixel_cache, offset_x, offset_y, 1, [](Viewport *vp, int x, int y, int width, int height) {
DrawPixelInfo plan_dpi;
plan_dpi.dst_ptr = vp->plan_pixel_cache.data() + x + (y * vp->width);
plan_dpi.height = height;
plan_dpi.width = width;
plan_dpi.pitch = vp->width;
plan_dpi.zoom = ZOOM_LVL_NORMAL;
plan_dpi.left = UnScaleByZoomLower(vp->virtual_left, vp->zoom) + x;
plan_dpi.top = UnScaleByZoomLower(vp->virtual_top, vp->zoom) + y;
Blitter_8bppDrawing blitter;
BlitterFactory::TemporaryCurrentBlitterOverride current_blitter(&blitter);
ViewportDrawPlans(vp, &plan_dpi);
});
if (clear) ClearViewportPlanPixelCache(vp);
}
void ClearViewportCache(Viewport *vp)
@ -873,6 +912,7 @@ static void SetViewportPosition(Window *w, int x, int y, bool force_update_overl
if (height > 0 && (move_offset.x != 0 || move_offset.y != 0)) {
SCOPE_INFO_FMT([&], "DoSetViewportPosition: %d, %d, %d, %d, %d, %d, %s", left, top, width, height, move_offset.x, move_offset.y, scope_dumper().WindowInfo(w));
ScrollViewportLandPixelCache(vp, move_offset.x, move_offset.y);
ScrollPlanPixelCache(vp, move_offset.x, move_offset.y);
w->viewport->update_vehicles = true;
DoSetViewportPosition((Window *) w->z_front, move_offset, left, top, width, height);
ClearViewportCache(w->viewport);
@ -2724,18 +2764,13 @@ static void ViewportDrawVehicleRouteSteps(const Viewport * const vp)
}
}
void ViewportDrawPlans(const Viewport *vp)
static void ViewportDrawPlans(const Viewport *vp, DrawPixelInfo *plan_dpi)
{
if (!AreAnyPlansVisible()) return;
DrawPixelInfo dpi_for_text = _vdd->MakeDPIForText();
_cur_dpi = &dpi_for_text;
const Rect bounds = {
ScaleByZoom(dpi_for_text.left - 2, vp->zoom),
ScaleByZoom(dpi_for_text.top - 2, vp->zoom),
ScaleByZoom(dpi_for_text.left + dpi_for_text.width + 2, vp->zoom),
ScaleByZoom(dpi_for_text.top + dpi_for_text.height + 2, vp->zoom) + (int)(ZOOM_LVL_BASE * TILE_HEIGHT * _settings_game.construction.map_height_limit)
ScaleByZoom(plan_dpi->left - 2, vp->zoom),
ScaleByZoom(plan_dpi->top - 2, vp->zoom),
ScaleByZoom(plan_dpi->left + plan_dpi->width + 2, vp->zoom),
ScaleByZoom(plan_dpi->top + plan_dpi->height + 2, vp->zoom) + (int)(ZOOM_LVL_BASE * TILE_HEIGHT * _settings_game.construction.map_height_limit)
};
const int min_coord_delta = bounds.left / (int)(2 * ZOOM_LVL_BASE * TILE_SIZE);
@ -2775,11 +2810,11 @@ void ViewportDrawPlans(const Viewport *vp)
const int to_x = UnScaleByZoom(to_pt.x, vp->zoom);
const int to_y = UnScaleByZoom(to_pt.y, vp->zoom);
GfxDrawLine(from_x, from_y, to_x, to_y, PC_BLACK, 3);
GfxDrawLine(plan_dpi, from_x, from_y, to_x, to_y, PC_BLACK, 3);
if (pl->focused) {
GfxDrawLine(from_x, from_y, to_x, to_y, PC_RED, 1);
GfxDrawLine(plan_dpi, from_x, from_y, to_x, to_y, PC_RED, 1);
} else {
GfxDrawLine(from_x, from_y, to_x, to_y, _colour_value[p->colour], 1);
GfxDrawLine(plan_dpi, from_x, from_y, to_x, to_y, _colour_value[p->colour], 1);
}
}
}
@ -2806,11 +2841,9 @@ void ViewportDrawPlans(const Viewport *vp)
const int to_x = UnScaleByZoom(to_pt.x, vp->zoom);
const int to_y = UnScaleByZoom(to_pt.y, vp->zoom);
GfxDrawLine(from_x, from_y, to_x, to_y, _colour_value[_current_plan->colour], 3, 1);
GfxDrawLine(plan_dpi, from_x, from_y, to_x, to_y, _colour_value[_current_plan->colour], 3, 1);
}
}
_cur_dpi = nullptr;
}
#define SLOPIFY_COLOUR(tile, height, vF, vW, vS, vE, vN, action) { \
@ -3867,6 +3900,30 @@ void ViewportDoDraw(Viewport *vp, int left, int top, int right, int bottom, uint
if (unlikely(_thd.place_mode == (HT_SPECIAL | HT_MAP) && (_thd.drawstyle & HT_DRAG_MASK) == HT_RECT && _thd.select_proc == DDSP_MEASURE)) ViewportMapDrawSelection(vp);
if (vp->zoom < ZOOM_LVL_OUT_256X) ViewportAddKdtreeSigns(_vdd.get(), &_vdd->dpi, true);
if (AreAnyPlansVisible()) {
if (vp->last_plan_update_number != _plan_update_counter) {
vp->last_plan_update_number = _plan_update_counter;
vp->plan_pixel_cache.assign(vp->ScreenArea(), 0xD7);
DrawPixelInfo plan_dpi;
plan_dpi.dst_ptr = vp->plan_pixel_cache.data();
plan_dpi.height = vp->height;
plan_dpi.width = vp->width;
plan_dpi.pitch = vp->width;
plan_dpi.zoom = ZOOM_LVL_NORMAL;
plan_dpi.left = UnScaleByZoomLower(vp->virtual_left, vp->zoom);
plan_dpi.top = UnScaleByZoomLower(vp->virtual_top, vp->zoom);
Blitter_8bppDrawing blitter;
BlitterFactory::TemporaryCurrentBlitterOverride current_blitter(&blitter);
TemporaryScreenPitchOverride screen_pitch(vp->width);
ViewportDrawPlans(vp, &plan_dpi);
}
} else {
vp->plan_pixel_cache.clear();
}
ViewportDoDrawPhase2(vp, _vdd.get());
ViewportDoDrawPhase3(vp);
} else {
@ -4031,7 +4088,14 @@ static void ViewportDoDrawPhase3(Viewport *vp)
}
_cur_dpi = nullptr;
ViewportDrawPlans(vp);
if (vp->zoom < ZOOM_LVL_DRAW_MAP && AreAnyPlansVisible()) {
DrawPixelInfo plan_dpi = _vdd->MakeDPIForText();
ViewportDrawPlans(vp, &plan_dpi);
} else if (vp->zoom >= ZOOM_LVL_DRAW_MAP && !vp->plan_pixel_cache.empty()) {
const int pixel_cache_start = _vdd->offset_x + (_vdd->offset_y * vp->width);
BlitterFactory::GetCurrentBlitter()->SetRectNoD7(_vdd->dpi.dst_ptr, 0, 0, vp->plan_pixel_cache.data() + pixel_cache_start,
dp.height, dp.width, vp->width);
}
if (_vdd->display_flags & (ND_SHADE_GREY | ND_SHADE_DIMMED)) {
DrawPixelInfo dp = _vdd->MakeDPIForText();
@ -4219,13 +4283,17 @@ void UpdateViewportSizeZoom(Viewport *vp)
} else {
vp->land_pixel_cache.assign(vp->ScreenArea(), 0xD7);
}
vp->plan_pixel_cache.clear();
} else {
vp->map_draw_vehicles_cache.vehicle_pixels.clear();
vp->land_pixel_cache.clear();
vp->land_pixel_cache.shrink_to_fit();
vp->overlay_pixel_cache.clear();
vp->overlay_pixel_cache.shrink_to_fit();
vp->plan_pixel_cache.clear();
vp->plan_pixel_cache.shrink_to_fit();
}
vp->last_plan_update_number = 0;
vp->update_vehicles = true;
FillViewportCoverageRect();
}

@ -62,9 +62,11 @@ struct Viewport {
bool is_drawn = false;
bool update_vehicles = false;
uint64_t last_overlay_update_number = 0;
uint64_t last_plan_update_number = 0;
ViewPortMapDrawVehiclesCache map_draw_vehicles_cache;
std::vector<byte> land_pixel_cache;
std::vector<byte> overlay_pixel_cache;
std::vector<byte> plan_pixel_cache;
uint GetDirtyBlockWidthShift() const { return this->GetDirtyBlockShift(); }
uint GetDirtyBlockHeightShift() const { return this->GetDirtyBlockShift(); }

Loading…
Cancel
Save