Cache vehicle positions across draw blocks in viewport map mode
This commit is contained in:
@@ -1423,7 +1423,7 @@ void RedrawScreenRect(int left, int top, int right, int bottom)
|
||||
}
|
||||
|
||||
static std::vector<Rect> _dirty_viewport_occlusions;
|
||||
static const ViewPort *_dirty_viewport;
|
||||
static ViewPort *_dirty_viewport;
|
||||
static NWidgetDisplay _dirty_viewport_disp_flags;
|
||||
|
||||
static void DrawDirtyViewport(uint occlusion, int left, int top, int right, int bottom)
|
||||
@@ -1677,6 +1677,9 @@ void DrawDirtyBlocks()
|
||||
|
||||
_dirty_blocks.clear();
|
||||
++_dirty_block_colour;
|
||||
|
||||
extern void ClearViewPortCaches();
|
||||
ClearViewPortCaches();
|
||||
}
|
||||
|
||||
void UnsetDirtyBlocks(int left, int top, int right, int bottom)
|
||||
|
@@ -672,6 +672,8 @@ static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, ui
|
||||
/* Switch back to rendering to the screen */
|
||||
_screen = old_screen;
|
||||
_screen_disable_anim = old_disable_anim;
|
||||
|
||||
ClearViewPortCache(vp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1593,13 +1593,13 @@ void ViewportAddVehicles(DrawPixelInfo *dpi)
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportMapDrawVehicles(DrawPixelInfo *dpi)
|
||||
void ViewportMapDrawVehicles(DrawPixelInfo *dpi, ViewPort *vp)
|
||||
{
|
||||
/* The bounding rectangle */
|
||||
const int l = dpi->left;
|
||||
const int r = dpi->left + dpi->width;
|
||||
const int t = dpi->top;
|
||||
const int b = dpi->top + dpi->height;
|
||||
/* The save rectangle */
|
||||
const int l = vp->virtual_left;
|
||||
const int r = vp->virtual_left + vp->virtual_width;
|
||||
const int t = vp->virtual_top;
|
||||
const int b = vp->virtual_top + vp->virtual_height;
|
||||
|
||||
/* The hash area to scan */
|
||||
const ViewportHashBound vhb = GetViewportHashBound(l, r, t, b);
|
||||
@@ -1607,18 +1607,21 @@ void ViewportMapDrawVehicles(DrawPixelInfo *dpi)
|
||||
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
|
||||
for (int y = vhb.yl;; y = (y + (1 << 6)) & (0x3F << 6)) {
|
||||
for (int x = vhb.xl;; x = (x + 1) & 0x3F) {
|
||||
const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
|
||||
if (!HasBit(vp->map_draw_vehicles_cache.done_hash_bits[y >> 6], x)) {
|
||||
SetBit(vp->map_draw_vehicles_cache.done_hash_bits[y >> 6], x);
|
||||
const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
|
||||
|
||||
while (v != nullptr) {
|
||||
if (!(v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) && (v->type != VEH_EFFECT)) {
|
||||
Point pt = RemapCoords(v->x_pos, v->y_pos, v->z_pos);
|
||||
if (pt.x >= l && pt.x < r && pt.y >= t && pt.y < b) {
|
||||
const int pixel_x = UnScaleByZoomLower(pt.x - dpi->left, dpi->zoom);
|
||||
const int pixel_y = UnScaleByZoomLower(pt.y - dpi->top, dpi->zoom);
|
||||
blitter->SetPixel(dpi->dst_ptr, pixel_x, pixel_y, PC_WHITE);
|
||||
while (v != nullptr) {
|
||||
if (!(v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) && (v->type != VEH_EFFECT)) {
|
||||
Point pt = RemapCoords(v->x_pos, v->y_pos, v->z_pos);
|
||||
if (pt.x >= l && pt.x < r && pt.y >= t && pt.y < b) {
|
||||
const int pixel_x = UnScaleByZoomLower(pt.x - l, dpi->zoom);
|
||||
const int pixel_y = UnScaleByZoomLower(pt.y - t, dpi->zoom);
|
||||
vp->map_draw_vehicles_cache.vehicle_pixels[pixel_x + (pixel_y) * vp->width] = true;
|
||||
}
|
||||
}
|
||||
v = v->hash_viewport_next;
|
||||
}
|
||||
v = v->hash_viewport_next;
|
||||
}
|
||||
|
||||
if (x == vhb.xu) break;
|
||||
@@ -1626,6 +1629,21 @@ void ViewportMapDrawVehicles(DrawPixelInfo *dpi)
|
||||
|
||||
if (y == vhb.yu) break;
|
||||
}
|
||||
|
||||
/* The drawing rectangle */
|
||||
int mask = ScaleByZoom(-1, vp->zoom);
|
||||
const int dl = UnScaleByZoomLower(dpi->left - (vp->virtual_left & mask), dpi->zoom);
|
||||
const int dr = UnScaleByZoomLower(dpi->left + dpi->width - (vp->virtual_left & mask), dpi->zoom);
|
||||
const int dt = UnScaleByZoomLower(dpi->top - (vp->virtual_top & mask), dpi->zoom);
|
||||
const int db = UnScaleByZoomLower(dpi->top + dpi->height - (vp->virtual_top & mask), dpi->zoom);
|
||||
int y_ptr = vp->width * dt;
|
||||
for (int y = dt; y < db; y++, y_ptr += vp->width) {
|
||||
for (int x = dl; x < dr; x++) {
|
||||
if (vp->map_draw_vehicles_cache.vehicle_pixels[y_ptr + x]) {
|
||||
blitter->SetPixel(dpi->dst_ptr, x - dl, y - dt, PC_WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -27,6 +27,8 @@
|
||||
static const int VEHICLE_PROFIT_MIN_AGE = DAYS_IN_YEAR * 2; ///< Only vehicles older than this have a meaningful profit.
|
||||
static const Money VEHICLE_PROFIT_THRESHOLD = 10000; ///< Threshold for a vehicle to be considered making good profit.
|
||||
|
||||
struct ViewPort;
|
||||
|
||||
/**
|
||||
* Helper to check whether an image index is valid for a particular vehicle.
|
||||
* @tparam T The type of vehicle.
|
||||
@@ -126,7 +128,7 @@ void ResetVehicleColourMap();
|
||||
byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_type);
|
||||
|
||||
void ViewportAddVehicles(DrawPixelInfo *dpi);
|
||||
void ViewportMapDrawVehicles(DrawPixelInfo *dpi);
|
||||
void ViewportMapDrawVehicles(DrawPixelInfo *dpi, ViewPort *vp);
|
||||
|
||||
void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRFBugs bug_type, bool critical);
|
||||
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore = nullptr, bool across_only = false);
|
||||
|
@@ -334,6 +334,21 @@ static Point MapXYZToViewport(const ViewPort *vp, int x, int y, int z)
|
||||
return p;
|
||||
}
|
||||
|
||||
void ClearViewPortCache(ViewPort *vp)
|
||||
{
|
||||
if (vp->zoom >= ZOOM_LVL_DRAW_MAP) {
|
||||
memset(vp->map_draw_vehicles_cache.done_hash_bits, 0, sizeof(vp->map_draw_vehicles_cache.done_hash_bits));
|
||||
vp->map_draw_vehicles_cache.vehicle_pixels.assign(vp->map_draw_vehicles_cache.vehicle_pixels.size(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearViewPortCaches()
|
||||
{
|
||||
for (ViewPort *vp : _viewport_window_cache) {
|
||||
ClearViewPortCache(vp);
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteWindowViewport(Window *w)
|
||||
{
|
||||
if (w->viewport == nullptr) return;
|
||||
@@ -512,11 +527,10 @@ static void DoSetViewportPositionFillRegion(int left, int top, int width, int he
|
||||
DrawOverlappedWindowForAll(left, top, left + width, top + height);
|
||||
};
|
||||
|
||||
static void DoSetViewportPosition(const Window *w, const int left, const int top, const int width, const int height)
|
||||
static void DoSetViewportPosition(Window *w, const int left, const int top, const int width, const int height)
|
||||
{
|
||||
const int xo = _vp_move_offs.x;
|
||||
const int yo = _vp_move_offs.y;
|
||||
if (xo == 0 && yo == 0) return;
|
||||
|
||||
|
||||
IncrementWindowUpdateNumber();
|
||||
@@ -648,7 +662,10 @@ static void SetViewportPosition(Window *w, int x, int y, bool force_update_overl
|
||||
i = top + height - _screen.height;
|
||||
if (i >= 0) height -= i;
|
||||
|
||||
if (height > 0) DoSetViewportPosition((const Window *) w->z_front, left, top, width, height);
|
||||
if (height > 0 && (_vp_move_offs.x != 0 || _vp_move_offs.y != 0)) {
|
||||
DoSetViewportPosition((Window *) w->z_front, left, top, width, height);
|
||||
ClearViewPortCache(w->viewport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3009,7 +3026,7 @@ static void ViewportProcessParentSprites()
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom)
|
||||
void ViewportDoDraw(ViewPort *vp, int left, int top, int right, int bottom)
|
||||
{
|
||||
DrawPixelInfo *old_dpi = _cur_dpi;
|
||||
_cur_dpi = &_vd.dpi;
|
||||
@@ -3048,7 +3065,7 @@ void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom
|
||||
if (_settings_client.gui.show_slopes_on_viewport_map) ViewportMapDraw<false, true>(vp);
|
||||
else ViewportMapDraw<false, false>(vp);
|
||||
}
|
||||
ViewportMapDrawVehicles(&_vd.dpi);
|
||||
ViewportMapDrawVehicles(&_vd.dpi, vp);
|
||||
if (_scrolling_viewport && _settings_client.gui.show_scrolling_viewport_on_map) ViewportMapDrawScrollingViewportBox(vp);
|
||||
if (vp->zoom < ZOOM_LVL_OUT_256X) ViewportAddKdtreeSigns(&_vd.dpi, true);
|
||||
} else {
|
||||
@@ -3124,7 +3141,7 @@ void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom
|
||||
* Make sure we don't draw a too big area at a time.
|
||||
* If we do, the sprite sorter will run into major performance problems and the sprite memory may overflow.
|
||||
*/
|
||||
void ViewportDrawChk(const ViewPort *vp, int left, int top, int right, int bottom)
|
||||
void ViewportDrawChk(ViewPort *vp, int left, int top, int right, int bottom)
|
||||
{
|
||||
if ((vp->zoom < ZOOM_LVL_DRAW_MAP) && ((int64)ScaleByZoom(bottom - top, vp->zoom) * (int64)ScaleByZoom(right - left, vp->zoom) > (int64)(1000000 * ZOOM_LVL_BASE * ZOOM_LVL_BASE))) {
|
||||
if ((bottom - top) > (right - left)) {
|
||||
@@ -3265,6 +3282,12 @@ void UpdateViewportSizeZoom(ViewPort *vp)
|
||||
uint size = vp->dirty_blocks_per_row * vp->dirty_blocks_per_column;
|
||||
vp->dirty_blocks.assign(size, false);
|
||||
UpdateViewportDirtyBlockLeftMargin(vp);
|
||||
if (vp->zoom >= ZOOM_LVL_DRAW_MAP) {
|
||||
memset(vp->map_draw_vehicles_cache.done_hash_bits, 0, sizeof(vp->map_draw_vehicles_cache.done_hash_bits));
|
||||
vp->map_draw_vehicles_cache.vehicle_pixels.assign(vp->width * vp->height, false);
|
||||
} else {
|
||||
vp->map_draw_vehicles_cache.vehicle_pixels.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateActiveScrollingViewport(Window *w)
|
||||
|
@@ -23,6 +23,8 @@ static const int TILE_HEIGHT_STEP = 50; ///< One Z unit tile height difference i
|
||||
|
||||
void SetSelectionRed(bool);
|
||||
|
||||
void ClearViewPortCache(ViewPort *vp);
|
||||
void ClearViewPortCaches();
|
||||
void DeleteWindowViewport(Window *w);
|
||||
void InitializeWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom);
|
||||
ViewPort *IsPtInWindowViewport(const Window *w, int x, int y);
|
||||
@@ -73,7 +75,7 @@ void SetRedErrorSquare(TileIndex tile);
|
||||
void SetTileSelectSize(int w, int h);
|
||||
void SetTileSelectBigSize(int ox, int oy, int sx, int sy);
|
||||
|
||||
void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom);
|
||||
void ViewportDoDraw(ViewPort *vp, int left, int top, int right, int bottom);
|
||||
|
||||
bool ScrollWindowToTile(TileIndex tile, Window *w, bool instant = false);
|
||||
bool ScrollWindowTo(int x, int y, int z, Window *w, bool instant = false);
|
||||
|
@@ -29,6 +29,11 @@ enum ViewportMapType {
|
||||
VPMT_MAX = VPMT_INDUSTRY,
|
||||
};
|
||||
|
||||
struct ViewPortMapDrawVehiclesCache {
|
||||
uint64 done_hash_bits[64];
|
||||
std::vector<bool> vehicle_pixels;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data structure for viewport, display of a part of the world
|
||||
*/
|
||||
@@ -54,6 +59,7 @@ struct ViewPort {
|
||||
uint8 dirty_block_left_margin;
|
||||
bool is_dirty = false;
|
||||
bool is_drawn = false;
|
||||
ViewPortMapDrawVehiclesCache map_draw_vehicles_cache;
|
||||
|
||||
uint GetDirtyBlockWidthShift() const { return this->GetDirtyBlockShift(); }
|
||||
uint GetDirtyBlockHeightShift() const { return this->GetDirtyBlockShift(); }
|
||||
|
Reference in New Issue
Block a user