Update to 14.0-beta1

This commit is contained in:
dP
2024-02-04 02:18:17 +05:30
parent 79037e2c65
commit 33ef333b57
1325 changed files with 138461 additions and 70983 deletions
+247 -160
View File
@@ -61,6 +61,7 @@
*/
#include "stdafx.h"
#include "core/backup_type.hpp"
#include "landscape.h"
#include "viewport_func.h"
#include "station_base.h"
@@ -91,7 +92,6 @@
#include "viewport_cmd.h"
#include <forward_list>
#include <map>
#include <stack>
#include "table/strings.h"
@@ -112,28 +112,28 @@ static const int MAX_TILE_EXTENT_TOP = ZOOM_LVL_BASE * MAX_BUILDING_PIXELS;
static const int MAX_TILE_EXTENT_BOTTOM = ZOOM_LVL_BASE * (TILE_PIXELS + 2 * TILE_HEIGHT); ///< Maximum bottom extent of tile relative to north corner (worst case: #SLOPE_STEEP_N).
struct StringSpriteToDraw {
StringID string;
std::string string;
StringID string_id;
Colours colour;
int32 x;
int32 y;
uint64 params[2];
uint16 width;
int32_t x;
int32_t y;
uint16_t width;
};
struct TileSpriteToDraw {
SpriteID image;
PaletteID pal;
const SubSprite *sub; ///< only draw a rectangular part of the sprite
int32 x; ///< screen X coordinate of sprite
int32 y; ///< screen Y coordinate of sprite
int32_t x; ///< screen X coordinate of sprite
int32_t y; ///< screen Y coordinate of sprite
};
struct ChildScreenSpriteToDraw {
SpriteID image;
PaletteID pal;
const SubSprite *sub; ///< only draw a rectangular part of the sprite
int32 x;
int32 y;
int32_t x;
int32_t y;
bool relative;
int next; ///< next child to draw (-1 at the end)
};
@@ -186,7 +186,7 @@ static bool MarkViewportDirty(const Viewport *vp, int left, int top, int right,
static ViewportDrawer _vd;
TileHighlightData _thd;
static TileInfo *_cur_ti;
static TileInfo _cur_ti;
bool _draw_bounding_boxes = false;
bool _draw_dirty_blocks = false;
uint _dirty_block_colour = 0;
@@ -202,10 +202,7 @@ static Point MapXYZToViewport(const Viewport *vp, int x, int y, int z)
void DeleteWindowViewport(Window *w)
{
if (w->viewport == nullptr) return;
delete w->viewport->overlay;
free(w->viewport);
delete w->viewport;
w->viewport = nullptr;
}
@@ -216,17 +213,15 @@ void DeleteWindowViewport(Window *w)
* @param y Offset of top edge of viewport with respect to top edge window \a w
* @param width Width of the viewport
* @param height Height of the viewport
* @param follow_flags Flags controlling the viewport.
* - If bit 31 is set, the lower 20 bits are the vehicle that the viewport should follow.
* - If bit 31 is clear, it is a #TileIndex.
* @param focus Either the tile index or vehicle ID to focus.
* @param zoom Zoomlevel to display
*/
void InitializeWindowViewport(Window *w, int x, int y,
int width, int height, uint32 follow_flags, ZoomLevel zoom)
int width, int height, std::variant<TileIndex, VehicleID> focus, ZoomLevel zoom)
{
assert(w->viewport == nullptr);
ViewportData *vp = CallocT<ViewportData>(1);
ViewportData *vp = new ViewportData();
vp->left = x + w->left;
vp->top = y + w->top;
@@ -240,18 +235,29 @@ void InitializeWindowViewport(Window *w, int x, int y,
Point pt;
if (follow_flags & 0x80000000) {
if (std::holds_alternative<VehicleID>(focus)) {
const Vehicle *veh;
vp->follow_vehicle = (VehicleID)(follow_flags & 0xFFFFF);
vp->follow_vehicle = std::get<VehicleID>(focus);
veh = Vehicle::Get(vp->follow_vehicle);
pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos);
} else {
x = TileX(follow_flags) * TILE_SIZE;
y = TileY(follow_flags) * TILE_SIZE;
TileIndex tile = std::get<TileIndex>(focus);
if (tile == INVALID_TILE) {
/* No tile? Use center of main viewport. */
const Window *mw = GetMainWindow();
/* center on same place as main window (zoom is maximum, no adjustment needed) */
pt.x = mw->viewport->scrollpos_x + mw->viewport->virtual_width / 2;
pt.x -= vp->virtual_width / 2;
pt.y = mw->viewport->scrollpos_y + mw->viewport->virtual_height / 2;
pt.y -= vp->virtual_height / 2;
} else {
x = TileX(tile) * TILE_SIZE;
y = TileY(tile) * TILE_SIZE;
pt = MapXYZToViewport(vp, x, y, GetSlopePixelZ(x, y));
}
vp->follow_vehicle = INVALID_VEHICLE;
pt = MapXYZToViewport(vp, x, y, GetSlopePixelZ(x, y));
}
vp->scrollpos_x = pt.x;
@@ -262,8 +268,8 @@ void InitializeWindowViewport(Window *w, int x, int y,
vp->overlay = nullptr;
w->viewport = vp;
vp->virtual_left = 0; // pt.x;
vp->virtual_top = 0; // pt.y;
vp->virtual_left = 0;
vp->virtual_top = 0;
}
static Point _vp_move_offs;
@@ -482,7 +488,7 @@ Point GetTileZoomCenterWindow(bool in, Window * w)
* @param widget_zoom_in widget index for window with zoom-in button
* @param widget_zoom_out widget index for window with zoom-out button
*/
void HandleZoomMessage(Window *w, const Viewport *vp, byte widget_zoom_in, byte widget_zoom_out)
void HandleZoomMessage(Window *w, const Viewport *vp, WidgetID widget_zoom_in, WidgetID widget_zoom_out)
{
w->SetWidgetDisabledState(widget_zoom_in, vp->zoom <= _settings_client.gui.zoom_min);
w->SetWidgetDirty(widget_zoom_in);
@@ -503,7 +509,7 @@ void HandleZoomMessage(Window *w, const Viewport *vp, byte widget_zoom_in, byte
* @param extra_offs_x Pixel X offset for the sprite position.
* @param extra_offs_y Pixel Y offset for the sprite position.
*/
static void AddTileSpriteToDraw(SpriteID image, PaletteID pal, int32 x, int32 y, int z, const SubSprite *sub = nullptr, int extra_offs_x = 0, int extra_offs_y = 0)
static void AddTileSpriteToDraw(SpriteID image, PaletteID pal, int32_t x, int32_t y, int z, const SubSprite *sub = nullptr, int extra_offs_x = 0, int extra_offs_y = 0)
{
assert((image & SPRITE_MASK) < MAX_SPRITES);
@@ -557,7 +563,7 @@ static void AddChildSpriteToFoundation(SpriteID image, PaletteID pal, const SubS
* @param extra_offs_x Pixel X offset for the sprite position.
* @param extra_offs_y Pixel Y offset for the sprite position.
*/
void DrawGroundSpriteAt(SpriteID image, PaletteID pal, int32 x, int32 y, int z, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
void DrawGroundSpriteAt(SpriteID image, PaletteID pal, int32_t x, int32_t y, int z, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
{
/* Switch to first foundation part, if no foundation was drawn */
if (_vd.foundation_part == FOUNDATION_PART_NONE) _vd.foundation_part = FOUNDATION_PART_NORMAL;
@@ -566,7 +572,7 @@ void DrawGroundSpriteAt(SpriteID image, PaletteID pal, int32 x, int32 y, int z,
Point pt = RemapCoords(x, y, z);
AddChildSpriteToFoundation(image, pal, sub, _vd.foundation_part, pt.x + extra_offs_x * ZOOM_LVL_BASE, pt.y + extra_offs_y * ZOOM_LVL_BASE);
} else {
AddTileSpriteToDraw(image, pal, _cur_ti->x + x, _cur_ti->y + y, _cur_ti->z + z, sub, extra_offs_x * ZOOM_LVL_BASE, extra_offs_y * ZOOM_LVL_BASE);
AddTileSpriteToDraw(image, pal, _cur_ti.x + x, _cur_ti.y + y, _cur_ti.z + z, sub, extra_offs_x * ZOOM_LVL_BASE, extra_offs_y * ZOOM_LVL_BASE);
}
}
@@ -627,7 +633,7 @@ void OffsetGroundSprite(int x, int y)
static void AddCombinedSprite(SpriteID image, PaletteID pal, int x, int y, int z, const SubSprite *sub)
{
Point pt = RemapCoords(x, y, z);
const Sprite *spr = GetSprite(image & SPRITE_MASK, ST_NORMAL);
const Sprite *spr = GetSprite(image & SPRITE_MASK, SpriteType::Normal);
if (pt.x + spr->x_offs >= _vd.dpi.left + _vd.dpi.width ||
pt.x + spr->x_offs + spr->width <= _vd.dpi.left ||
@@ -666,7 +672,7 @@ static void AddCombinedSprite(SpriteID image, PaletteID pal, int x, int y, int z
*/
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
{
int32 left, right, top, bottom;
int32_t left, right, top, bottom;
assert((image & SPRITE_MASK) < MAX_SPRITES);
@@ -693,7 +699,7 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w,
top = tmp_top = RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y;
bottom = RemapCoords(x + w , y + h , z + bb_offset_z).y + 1;
} else {
const Sprite *spr = GetSprite(image & SPRITE_MASK, ST_NORMAL);
const Sprite *spr = GetSprite(image & SPRITE_MASK, SpriteType::Normal);
left = tmp_left = (pt.x += spr->x_offs);
right = (pt.x + spr->width );
top = tmp_top = (pt.y += spr->y_offs);
@@ -852,15 +858,14 @@ void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool tran
_vd.last_child = &cs.next;
}
static void AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2, Colours colour, uint16 width)
static void AddStringToDraw(int x, int y, StringID string, Colours colour, uint16_t width)
{
assert(width != 0);
StringSpriteToDraw &ss = _vd.string_sprites_to_draw.emplace_back();
ss.string = string;
ss.string = GetString(string);
ss.string_id = string;
ss.x = x;
ss.y = y;
ss.params[0] = params_1;
ss.params[1] = params_2;
ss.width = width;
ss.colour = colour;
}
@@ -995,7 +1000,8 @@ enum TileHighlightType {
};
const Station *_viewport_highlight_station; ///< Currently selected station for coverage area highlight
const Town *_viewport_highlight_town; ///< Currently selected town for coverage area highlight
const Waypoint *_viewport_highlight_waypoint; ///< Currently selected waypoint for coverage area highlight
const Town *_viewport_highlight_town; ///< Currently selected town for coverage area highlight
/**
* Get tile highlight type of coverage area for a given tile.
@@ -1008,6 +1014,9 @@ static TileHighlightType GetTileHighlightType(TileIndex t)
if (IsTileType(t, MP_STATION) && GetStationIndex(t) == _viewport_highlight_station->index) return THT_WHITE;
if (_viewport_highlight_station->TileIsInCatchment(t)) return THT_BLUE;
}
if (_viewport_highlight_waypoint != nullptr) {
if (IsTileType(t, MP_STATION) && GetStationIndex(t) == _viewport_highlight_waypoint->index) return THT_BLUE;
}
if (_viewport_highlight_town != nullptr) {
if (IsTileType(t, MP_HOUSE)) {
@@ -1126,7 +1135,7 @@ draw_inner:
if (IsSteepSlope(ti->tileh)) z -= TILE_HEIGHT;
}
}
DrawSelectionSprite(_cur_dpi->zoom <= ZOOM_LVL_DETAIL ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti, z, foundation_part);
DrawSelectionSprite(SPR_DOT, PAL_NONE, ti, z, foundation_part);
} else if (_thd.drawstyle & HT_RAIL) {
/* autorail highlight piece under cursor */
HighLightStyle type = _thd.drawstyle & HT_DIR_MASK;
@@ -1219,26 +1228,24 @@ static void ViewportAddLandscape()
assert(row == tilecoord.y + tilecoord.x);
TileType tile_type;
TileInfo tile_info;
_cur_ti = &tile_info;
tile_info.x = tilecoord.x * TILE_SIZE; // FIXME tile_info should use signed integers
tile_info.y = tilecoord.y * TILE_SIZE;
_cur_ti.x = tilecoord.x * TILE_SIZE;
_cur_ti.y = tilecoord.y * TILE_SIZE;
if (IsInsideBS(tilecoord.x, 0, MapSizeX()) && IsInsideBS(tilecoord.y, 0, MapSizeY())) {
/* This includes the south border at MapMaxX / MapMaxY. When terraforming we still draw tile selections there. */
tile_info.tile = TileXY(tilecoord.x, tilecoord.y);
tile_type = GetTileType(tile_info.tile);
if (IsInsideBS(tilecoord.x, 0, Map::SizeX()) && IsInsideBS(tilecoord.y, 0, Map::SizeY())) {
/* This includes the south border at Map::MaxX / Map::MaxY. When terraforming we still draw tile selections there. */
_cur_ti.tile = TileXY(tilecoord.x, tilecoord.y);
tile_type = GetTileType(_cur_ti.tile);
} else {
tile_info.tile = INVALID_TILE;
_cur_ti.tile = INVALID_TILE;
tile_type = MP_VOID;
}
if (tile_type != MP_VOID) {
/* We are inside the map => paint landscape. */
tile_info.tileh = GetTilePixelSlope(tile_info.tile, &tile_info.z);
_cur_ti.tileh = GetTilePixelSlope(_cur_ti.tile, &_cur_ti.z);
} else {
/* We are outside the map => paint black. */
tile_info.tileh = GetTilePixelSlopeOutsideMap(tilecoord.x, tilecoord.y, &tile_info.z);
_cur_ti.tileh = GetTilePixelSlopeOutsideMap(tilecoord.x, tilecoord.y, &_cur_ti.z);
}
int viewport_y = GetViewportY(tilecoord);
@@ -1257,10 +1264,10 @@ static void ViewportAddLandscape()
/* Is tile with buildings visible? */
if (min_visible_height < MAX_TILE_EXTENT_TOP) tile_visible = true;
if (IsBridgeAbove(tile_info.tile)) {
if (IsBridgeAbove(_cur_ti.tile)) {
/* Is the bridge visible? */
TileIndex bridge_tile = GetNorthernBridgeEnd(tile_info.tile);
int bridge_height = ZOOM_LVL_BASE * (GetBridgePixelHeight(bridge_tile) - TilePixelHeight(tile_info.tile));
TileIndex bridge_tile = GetNorthernBridgeEnd(_cur_ti.tile);
int bridge_height = ZOOM_LVL_BASE * (GetBridgePixelHeight(bridge_tile) - TilePixelHeight(_cur_ti.tile));
if (min_visible_height < bridge_height + MAX_TILE_EXTENT_TOP) tile_visible = true;
}
@@ -1281,8 +1288,8 @@ static void ViewportAddLandscape()
_vd.last_foundation_child[0] = nullptr;
_vd.last_foundation_child[1] = nullptr;
_tile_type_procs[tile_type]->draw_tile_proc(&tile_info);
if (tile_info.tile != INVALID_TILE) DrawTileSelection(&tile_info);
_tile_type_procs[tile_type]->draw_tile_proc(&_cur_ti);
if (_cur_ti.tile != INVALID_TILE) DrawTileSelection(&_cur_ti);
}
}
}
@@ -1298,7 +1305,7 @@ static void ViewportAddLandscape()
* @param string_small_shadow Shadow string for 4x and 8x zoom level; or #STR_NULL if no shadow
* @param colour colour of the sign background; or INVALID_COLOUR if transparent
*/
void ViewportAddString(const DrawPixelInfo *dpi, ZoomLevel small_from, const ViewportSign *sign, StringID string_normal, StringID string_small, StringID string_small_shadow, uint64 params_1, uint64 params_2, Colours colour)
void ViewportAddString(const DrawPixelInfo *dpi, ZoomLevel small_from, const ViewportSign *sign, StringID string_normal, StringID string_small, StringID string_small_shadow, Colours colour)
{
bool small = dpi->zoom >= small_from;
@@ -1307,7 +1314,7 @@ void ViewportAddString(const DrawPixelInfo *dpi, ZoomLevel small_from, const Vie
int right = left + dpi->width;
int bottom = top + dpi->height;
int sign_height = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.fullbevel.bottom, dpi->zoom);
int sign_height = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom, dpi->zoom);
int sign_half_width = ScaleByZoom((small ? sign->width_small : sign->width_normal) / 2, dpi->zoom);
if (bottom < sign->top ||
@@ -1318,22 +1325,21 @@ void ViewportAddString(const DrawPixelInfo *dpi, ZoomLevel small_from, const Vie
}
if (!small) {
AddStringToDraw(sign->center - sign_half_width, sign->top, string_normal, params_1, params_2, colour, sign->width_normal);
AddStringToDraw(sign->center - sign_half_width, sign->top, string_normal, colour, sign->width_normal);
} else {
int shadow_offset = 0;
if (string_small_shadow != STR_NULL) {
shadow_offset = 4;
AddStringToDraw(sign->center - sign_half_width + shadow_offset, sign->top, string_small_shadow, params_1, params_2, INVALID_COLOUR, sign->width_small | 0x8000);
AddStringToDraw(sign->center - sign_half_width + shadow_offset, sign->top, string_small_shadow, INVALID_COLOUR, sign->width_small | 0x8000);
}
AddStringToDraw(sign->center - sign_half_width, sign->top - shadow_offset, string_small, params_1, params_2,
colour, sign->width_small | 0x8000);
AddStringToDraw(sign->center - sign_half_width, sign->top - shadow_offset, string_small, colour, sign->width_small | 0x8000);
}
}
static Rect ExpandRectWithViewportSignMargins(Rect r, ZoomLevel zoom)
{
/* Pessimistically always use normal font, but also assume small font is never larger in either dimension */
const int fh = FONT_HEIGHT_NORMAL;
const int fh = GetCharacterHeight(FS_NORMAL);
const int max_tw = _viewport_sign_maxwidth / 2 + 1;
const int expand_y = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + fh + WidgetDimensions::scaled.fullbevel.bottom, zoom);
const int expand_x = ScaleByZoom(WidgetDimensions::scaled.fullbevel.left + max_tw + WidgetDimensions::scaled.fullbevel.right, zoom);
@@ -1357,9 +1363,6 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi)
bool show_signs = HasBit(_display_opt, DO_SHOW_SIGNS) && !IsInvisibilitySet(TO_SIGNS);
bool show_competitors = HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS);
const BaseStation *st;
const Sign *si;
/* Collect all the items first and draw afterwards, to ensure layering */
std::vector<const BaseStation *> stations;
std::vector<const Town *> towns;
@@ -1367,42 +1370,45 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi)
_viewport_sign_kdtree.FindContained(search_rect.left, search_rect.top, search_rect.right, search_rect.bottom, [&](const ViewportSignKdtreeItem & item) {
switch (item.type) {
case ViewportSignKdtreeItem::VKI_STATION:
case ViewportSignKdtreeItem::VKI_STATION: {
if (!show_stations) break;
st = BaseStation::Get(item.id.station);
const BaseStation *st = BaseStation::Get(item.id.station);
/* Don't draw if station is owned by another company and competitor station names are hidden. Stations owned by none are never ignored. */
if (!show_competitors && _local_company != st->owner && st->owner != OWNER_NONE) break;
stations.push_back(st);
break;
}
case ViewportSignKdtreeItem::VKI_WAYPOINT:
case ViewportSignKdtreeItem::VKI_WAYPOINT: {
if (!show_waypoints) break;
st = BaseStation::Get(item.id.station);
const BaseStation *st = BaseStation::Get(item.id.station);
/* Don't draw if station is owned by another company and competitor station names are hidden. Stations owned by none are never ignored. */
if (!show_competitors && _local_company != st->owner && st->owner != OWNER_NONE) break;
stations.push_back(st);
break;
}
case ViewportSignKdtreeItem::VKI_TOWN:
if (!show_towns) break;
towns.push_back(Town::Get(item.id.town));
break;
case ViewportSignKdtreeItem::VKI_SIGN:
case ViewportSignKdtreeItem::VKI_SIGN: {
if (!show_signs) break;
si = Sign::Get(item.id.sign);
const Sign *si = Sign::Get(item.id.sign);
/* Don't draw if sign is owned by another company and competitor signs should be hidden.
* Note: It is intentional that also signs owned by OWNER_NONE are hidden. Bankrupt
* companies can leave OWNER_NONE signs after them. */
* Note: It is intentional that also signs owned by OWNER_NONE are hidden. Bankrupt
* companies can leave OWNER_NONE signs after them. */
if (!show_competitors && _local_company != si->owner && si->owner != OWNER_DEITY) break;
signs.push_back(si);
break;
}
default:
NOT_REACHED();
@@ -1412,30 +1418,37 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi)
/* Layering order (bottom to top): Town names, signs, stations */
for (const auto *t : towns) {
SetDParam(0, t->index);
SetDParam(1, t->cache.population);
ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &t->cache.sign,
_settings_client.gui.population_in_label ? STR_VIEWPORT_TOWN_POP : STR_VIEWPORT_TOWN,
STR_VIEWPORT_TOWN_TINY_WHITE, STR_VIEWPORT_TOWN_TINY_BLACK,
t->index, t->cache.population);
STR_VIEWPORT_TOWN_TINY_WHITE, STR_VIEWPORT_TOWN_TINY_BLACK);
}
/* Do not draw signs nor station names if they are set invisible */
if (IsInvisibilitySet(TO_SIGNS)) return;
for (const auto *si : signs) {
SetDParam(0, si->index);
ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &si->sign,
STR_WHITE_SIGN,
(IsTransparencySet(TO_SIGNS) || si->owner == OWNER_DEITY) ? STR_VIEWPORT_SIGN_SMALL_WHITE : STR_VIEWPORT_SIGN_SMALL_BLACK, STR_NULL,
si->index, 0, (si->owner == OWNER_NONE) ? COLOUR_GREY : (si->owner == OWNER_DEITY ? INVALID_COLOUR : _company_colours[si->owner]));
(si->owner == OWNER_NONE) ? COLOUR_GREY : (si->owner == OWNER_DEITY ? INVALID_COLOUR : _company_colours[si->owner]));
}
for (const auto *st : stations) {
SetDParam(0, st->index);
SetDParam(1, st->facilities);
if (Station::IsExpected(st)) {
/* Station */
ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &st->sign,
STR_VIEWPORT_STATION, STR_VIEWPORT_STATION_TINY, STR_NULL,
st->index, st->facilities, (st->owner == OWNER_NONE || !st->IsInUse()) ? COLOUR_GREY : _company_colours[st->owner]);
(st->owner == OWNER_NONE || !st->IsInUse()) ? COLOUR_GREY : _company_colours[st->owner]);
} else {
/* Waypoint */
ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &st->sign,
STR_VIEWPORT_WAYPOINT, STR_VIEWPORT_WAYPOINT_TINY, STR_NULL,
st->index, st->facilities, (st->owner == OWNER_NONE || !st->IsInUse()) ? COLOUR_GREY : _company_colours[st->owner]);
(st->owner == OWNER_NONE || !st->IsInUse()) ? COLOUR_GREY : _company_colours[st->owner]);
}
}
}
@@ -1454,17 +1467,15 @@ void ViewportSign::UpdatePosition(int center, int top, StringID str, StringID st
this->top = top;
char buffer[DRAW_STRING_BUFFER];
GetString(buffer, str, lastof(buffer));
this->width_normal = WidgetDimensions::scaled.fullbevel.left + Align(GetStringBoundingBox(buffer).width, 2) + WidgetDimensions::scaled.fullbevel.right;
std::string name = GetString(str);
this->width_normal = WidgetDimensions::scaled.fullbevel.left + Align(GetStringBoundingBox(name).width, 2) + WidgetDimensions::scaled.fullbevel.right;
this->center = center;
/* zoomed out version */
if (str_small != STR_NULL) {
GetString(buffer, str_small, lastof(buffer));
name = GetString(str_small);
}
this->width_small = WidgetDimensions::scaled.fullbevel.left + Align(GetStringBoundingBox(buffer, FS_SMALL).width, 2) + WidgetDimensions::scaled.fullbevel.right;
this->width_small = WidgetDimensions::scaled.fullbevel.left + Align(GetStringBoundingBox(name, FS_SMALL).width, 2) + WidgetDimensions::scaled.fullbevel.right;
this->MarkDirty();
}
@@ -1477,14 +1488,14 @@ void ViewportSign::UpdatePosition(int center, int top, StringID str, StringID st
*/
void ViewportSign::MarkDirty(ZoomLevel maxzoom) const
{
Rect zoomlevels[ZOOM_LVL_COUNT];
Rect zoomlevels[ZOOM_LVL_END];
for (ZoomLevel zoom = ZOOM_LVL_BEGIN; zoom != ZOOM_LVL_END; zoom++) {
/* FIXME: This doesn't switch to width_small when appropriate. */
zoomlevels[zoom].left = this->center - ScaleByZoom(this->width_normal / 2 + 1, zoom);
zoomlevels[zoom].top = this->top - ScaleByZoom(1, zoom);
zoomlevels[zoom].right = this->center + ScaleByZoom(this->width_normal / 2 + 1, zoom);
zoomlevels[zoom].bottom = this->top + ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.fullbevel.bottom + 1, zoom);
zoomlevels[zoom].bottom = this->top + ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom + 1, zoom);
}
for (const Window *w : Window::Iterate()) {
@@ -1522,12 +1533,12 @@ static void ViewportSortParentSprites(ParentSpriteToSortVector *psdv)
* Also use special constants to indicate sorting state without
* adding extra fields to ParentSpriteToDraw structure.
*/
const uint32 ORDER_COMPARED = UINT32_MAX; // Sprite was compared but we still need to compare the ones preceding it
const uint32 ORDER_RETURNED = UINT32_MAX - 1; // Makr sorted sprite in case there are other occurrences of it in the stack
const uint32_t ORDER_COMPARED = UINT32_MAX; // Sprite was compared but we still need to compare the ones preceding it
const uint32_t ORDER_RETURNED = UINT32_MAX - 1; // Makr sorted sprite in case there are other occurrences of it in the stack
std::stack<ParentSpriteToDraw *> sprite_order;
uint32 next_order = 0;
uint32_t next_order = 0;
std::forward_list<std::pair<int64, ParentSpriteToDraw *>> sprite_list; // We store sprites in a list sorted by xmin+ymin
std::forward_list<std::pair<int64_t, ParentSpriteToDraw *>> sprite_list; // We store sprites in a list sorted by xmin+ymin
/* Initialize sprite list and order. */
for (auto p = psdv->rbegin(); p != psdv->rend(); p++) {
@@ -1685,7 +1696,7 @@ static void ViewportDrawDirtyBlocks()
byte bo = UnScaleByZoom(dpi->left + dpi->top, dpi->zoom) & 1;
do {
for (int i = (bo ^= 1); i < right; i += 2) blitter->SetPixel(dst, i, 0, (uint8)colour);
for (int i = (bo ^= 1); i < right; i += 2) blitter->SetPixel(dst, i, 0, (uint8_t)colour);
dst = blitter->MoveTo(dst, 0, 1);
} while (--bottom > 0);
}
@@ -1698,16 +1709,10 @@ static void ViewportDrawStrings(ZoomLevel zoom, const StringSpriteToDrawVector *
int w = GB(ss.width, 0, 15);
int x = UnScaleByZoom(ss.x, zoom);
int y = UnScaleByZoom(ss.y, zoom);
int h = WidgetDimensions::scaled.fullbevel.top + (small ? FONT_HEIGHT_SMALL : FONT_HEIGHT_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom;
SetDParam(0, ss.params[0]);
SetDParam(1, ss.params[1]);
int h = WidgetDimensions::scaled.fullbevel.top + (small ? GetCharacterHeight(FS_SMALL) : GetCharacterHeight(FS_NORMAL)) + WidgetDimensions::scaled.fullbevel.bottom;
if (ss.colour != INVALID_COLOUR) {
/* Do not draw signs nor station names if they are set invisible */
if (IsInvisibilitySet(TO_SIGNS) && ss.string != STR_WHITE_SIGN) continue;
if (IsTransparencySet(TO_SIGNS) && ss.string != STR_WHITE_SIGN) {
if (IsTransparencySet(TO_SIGNS) && ss.string_id != STR_WHITE_SIGN) {
/* Don't draw the rectangle.
* Real colours need the TC_IS_PALETTE_COLOUR flag.
* Otherwise colours from _string_colourmap are assumed. */
@@ -1728,9 +1733,6 @@ static void ViewportDrawStrings(ZoomLevel zoom, const StringSpriteToDrawVector *
void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom)
{
DrawPixelInfo *old_dpi = _cur_dpi;
_cur_dpi = &_vd.dpi;
_vd.dpi.zoom = vp->zoom;
int mask = ScaleByZoom(-1, vp->zoom);
@@ -1740,13 +1742,14 @@ void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom
_vd.dpi.height = (bottom - top) & mask;
_vd.dpi.left = left & mask;
_vd.dpi.top = top & mask;
_vd.dpi.pitch = old_dpi->pitch;
_vd.dpi.pitch = _cur_dpi->pitch;
_vd.last_child = nullptr;
int x = UnScaleByZoom(_vd.dpi.left - (vp->virtual_left & mask), vp->zoom) + vp->left;
int y = UnScaleByZoom(_vd.dpi.top - (vp->virtual_top & mask), vp->zoom) + vp->top;
_vd.dpi.dst_ptr = BlitterFactory::GetCurrentBlitter()->MoveTo(old_dpi->dst_ptr, x - old_dpi->left, y - old_dpi->top);
_vd.dpi.dst_ptr = BlitterFactory::GetCurrentBlitter()->MoveTo(_cur_dpi->dst_ptr, x - _cur_dpi->left, y - _cur_dpi->top);
AutoRestoreBackup dpi_backup(_cur_dpi, &_vd.dpi);
ViewportAddLandscape();
ViewportAddVehicles(&_vd.dpi);
@@ -1755,7 +1758,7 @@ void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom
DrawTextEffects(&_vd.dpi);
if (_vd.tile_sprites_to_draw.size() != 0) ViewportDrawTileSprites(&_vd.tile_sprites_to_draw);
if (!_vd.tile_sprites_to_draw.empty()) ViewportDrawTileSprites(&_vd.tile_sprites_to_draw);
for (auto &psd : _vd.parent_sprites_to_draw) {
_vd.parent_sprites_to_sort.push_back(&psd);
@@ -1781,15 +1784,13 @@ void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom
vp->overlay->Draw(&dp);
}
if (_vd.string_sprites_to_draw.size() != 0) {
if (!_vd.string_sprites_to_draw.empty()) {
/* translate to world coordinates */
dp.left = UnScaleByZoom(_vd.dpi.left, zoom);
dp.top = UnScaleByZoom(_vd.dpi.top, zoom);
ViewportDrawStrings(zoom, &_vd.string_sprites_to_draw);
}
_cur_dpi = old_dpi;
_vd.string_sprites_to_draw.clear();
_vd.tile_sprites_to_draw.clear();
_vd.parent_sprites_to_draw.clear();
@@ -1867,11 +1868,46 @@ static inline void ClampViewportToMap(const Viewport *vp, int *scroll_x, int *sc
}
}
/**
* Clamp the smooth scroll to a maxmimum speed and distance based on time elapsed.
*
* Every 30ms, we move 1/4th of the distance, to give a smooth movement experience.
* But we never go over the max_scroll speed.
*
* @param delta_ms Time elapsed since last update.
* @param delta_hi The distance to move in highest dimension (can't be zero).
* @param delta_lo The distance to move in lowest dimension.
* @param[out] delta_hi_clamped The clamped distance to move in highest dimension.
* @param[out] delta_lo_clamped The clamped distance to move in lowest dimension.
*/
static void ClampSmoothScroll(uint32_t delta_ms, int64_t delta_hi, int64_t delta_lo, int &delta_hi_clamped, int &delta_lo_clamped)
{
/** A tile is 64 pixels in width at 1x zoom; viewport coordinates are in 4x zoom. */
constexpr int PIXELS_PER_TILE = TILE_PIXELS * 2 * ZOOM_LVL_BASE;
assert(delta_hi != 0);
/* Move at most 75% of the distance every 30ms, for a smooth experience */
int64_t delta_left = delta_hi * std::pow(0.75, delta_ms / 30.0);
/* Move never more than 16 tiles per 30ms. */
int max_scroll = Map::ScaleBySize1D(16 * PIXELS_PER_TILE * delta_ms / 30);
/* We never go over the max_scroll speed. */
delta_hi_clamped = Clamp(delta_hi - delta_left, -max_scroll, max_scroll);
/* The lower delta is in ratio of the higher delta, so we keep going straight at the destination. */
delta_lo_clamped = delta_lo * delta_hi_clamped / delta_hi;
/* Ensure we always move (delta_hi can't be zero). */
if (delta_hi_clamped == 0) {
delta_hi_clamped = delta_hi > 0 ? 1 : -1;
}
}
/**
* Update the viewport position being displayed.
* @param w %Window owning the viewport.
*/
void UpdateViewportPosition(Window *w)
void UpdateViewportPosition(Window *w, uint32_t delta_ms)
{
const Viewport *vp = w->viewport;
@@ -1889,13 +1925,23 @@ void UpdateViewportPosition(Window *w)
int delta_x = w->viewport->dest_scrollpos_x - w->viewport->scrollpos_x;
int delta_y = w->viewport->dest_scrollpos_y - w->viewport->scrollpos_y;
int current_x = w->viewport->scrollpos_x;
int current_y = w->viewport->scrollpos_y;
bool update_overlay = false;
if (delta_x != 0 || delta_y != 0) {
if (_settings_client.gui.smooth_scroll) {
int max_scroll = ScaleByMapSize1D(512 * ZOOM_LVL_BASE);
/* Not at our desired position yet... */
w->viewport->scrollpos_x += Clamp(DivAwayFromZero(delta_x, 4), -max_scroll, max_scroll);
w->viewport->scrollpos_y += Clamp(DivAwayFromZero(delta_y, 4), -max_scroll, max_scroll);
int delta_x_clamped;
int delta_y_clamped;
if (abs(delta_x) > abs(delta_y)) {
ClampSmoothScroll(delta_ms, delta_x, delta_y, delta_x_clamped, delta_y_clamped);
} else {
ClampSmoothScroll(delta_ms, delta_y, delta_x, delta_y_clamped, delta_x_clamped);
}
w->viewport->scrollpos_x += delta_x_clamped;
w->viewport->scrollpos_y += delta_y_clamped;
} else {
w->viewport->scrollpos_x = w->viewport->dest_scrollpos_x;
w->viewport->scrollpos_y = w->viewport->dest_scrollpos_y;
@@ -1906,6 +1952,13 @@ void UpdateViewportPosition(Window *w)
ClampViewportToMap(vp, &w->viewport->scrollpos_x, &w->viewport->scrollpos_y);
/* When moving small amounts around the border we can get stuck, and
* not actually move. In those cases, teleport to the destination. */
if ((delta_x != 0 || delta_y != 0) && current_x == w->viewport->scrollpos_x && current_y == w->viewport->scrollpos_y) {
w->viewport->scrollpos_x = w->viewport->dest_scrollpos_x;
w->viewport->scrollpos_y = w->viewport->dest_scrollpos_y;
}
SetViewportPosition(w, w->viewport->scrollpos_x, w->viewport->scrollpos_y);
if (update_overlay) RebuildViewportOverlay(w);
}
@@ -2034,11 +2087,11 @@ static void SetSelectionTilesDirty()
assert(x_size >= 0);
assert(y_size >= 0);
int x_end = Clamp(x_start + x_size, 0, MapSizeX() * TILE_SIZE - TILE_SIZE);
int y_end = Clamp(y_start + y_size, 0, MapSizeY() * TILE_SIZE - TILE_SIZE);
int x_end = Clamp(x_start + x_size, 0, Map::SizeX() * TILE_SIZE - TILE_SIZE);
int y_end = Clamp(y_start + y_size, 0, Map::SizeY() * TILE_SIZE - TILE_SIZE);
x_start = Clamp(x_start, 0, MapSizeX() * TILE_SIZE - TILE_SIZE);
y_start = Clamp(y_start, 0, MapSizeY() * TILE_SIZE - TILE_SIZE);
x_start = Clamp(x_start, 0, Map::SizeX() * TILE_SIZE - TILE_SIZE);
y_start = Clamp(y_start, 0, Map::SizeY() * TILE_SIZE - TILE_SIZE);
/* make sure everything is multiple of TILE_SIZE */
assert((x_end | y_end | x_start | y_start) % TILE_SIZE == 0);
@@ -2114,7 +2167,7 @@ static void SetSelectionTilesDirty()
uint x = (_thd.pos.x + (a + b) / 2) / TILE_SIZE;
uint y = (_thd.pos.y + (a - b) / 2) / TILE_SIZE;
if (x < MapMaxX() && y < MapMaxY()) {
if (x < Map::MaxX() && y < Map::MaxY()) {
MarkTileDirtyByTile(TileXY(x, y));
}
}
@@ -2141,7 +2194,7 @@ static bool CheckClickOnViewportSign(const Viewport *vp, int x, int y, const Vie
{
bool small = (vp->zoom >= ZOOM_LVL_OUT_16X);
int sign_half_width = ScaleByZoom((small ? sign->width_small : sign->width_normal) / 2, vp->zoom);
int sign_height = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + (small ? FONT_HEIGHT_SMALL : FONT_HEIGHT_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom, vp->zoom);
int sign_height = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + (small ? GetCharacterHeight(FS_SMALL) : GetCharacterHeight(FS_NORMAL)) + WidgetDimensions::scaled.fullbevel.bottom, vp->zoom);
return y >= sign->top && y < sign->top + sign_height &&
x >= sign->center - sign_half_width && x < sign->center + sign_half_width;
@@ -2411,8 +2464,8 @@ bool ScrollWindowTo(int x, int y, int z, Window *w, bool instant)
{
/* The slope cannot be acquired outside of the map, so make sure we are always within the map. */
if (z == -1) {
if ( x >= 0 && x <= (int)MapSizeX() * (int)TILE_SIZE - 1
&& y >= 0 && y <= (int)MapSizeY() * (int)TILE_SIZE - 1) {
if ( x >= 0 && x <= (int)Map::SizeX() * (int)TILE_SIZE - 1
&& y >= 0 && y <= (int)Map::SizeY() * (int)TILE_SIZE - 1) {
z = GetSlopePixelZ(x, y);
} else {
z = TileHeightOutsideMap(x / (int)TILE_SIZE, y / (int)TILE_SIZE);
@@ -2647,13 +2700,11 @@ void UpdateTileSelection()
* Displays the measurement tooltips when selecting multiple tiles
* @param str String to be displayed
* @param paramcount number of params to deal with
* @param params (optional) up to 5 pieces of additional information that may be added to a tooltip
* @param close_cond Condition for closing this tooltip.
*/
static inline void ShowMeasurementTooltips(StringID str, uint paramcount, const uint64 params[], TooltipCloseCondition close_cond = TCC_EXIT_VIEWPORT)
static inline void ShowMeasurementTooltips(StringID str, uint paramcount)
{
if (!_settings_client.gui.measure_tooltip) return;
GuiShowTooltips(_thd.GetCallbackWnd(), str, paramcount, params, close_cond);
GuiShowTooltips(_thd.GetCallbackWnd(), str, TCC_EXIT_VIEWPORT, paramcount);
}
static void HideMeasurementTooltips()
@@ -2719,7 +2770,7 @@ void VpSetPlaceSizingLimit(int limit)
*/
void VpSetPresizeRange(TileIndex from, TileIndex to)
{
uint64 distance = DistanceManhattan(from, to) + 1;
uint64_t distance = DistanceManhattan(from, to) + 1;
_thd.selend.x = TileX(to) * TILE_SIZE;
_thd.selend.y = TileY(to) * TILE_SIZE;
@@ -2729,7 +2780,8 @@ void VpSetPresizeRange(TileIndex from, TileIndex to)
/* show measurement only if there is any length to speak of */
if (distance > 1) {
ShowMeasurementTooltips(STR_MEASURE_LENGTH, 1, &distance);
SetDParam(0, distance);
ShowMeasurementTooltips(STR_MEASURE_LENGTH, 1);
} else {
HideMeasurementTooltips();
}
@@ -2843,7 +2895,7 @@ static int CalcHeightdiff(HighLightStyle style, uint distance, TileIndex start_t
byte style_t = (byte)(TileX(end_tile) > TileX(start_tile));
start_tile = TILE_ADD(start_tile, ToTileIndexDiff(heightdiff_area_by_dir[style_t]));
end_tile = TILE_ADD(end_tile, ToTileIndexDiff(heightdiff_area_by_dir[2 + style_t]));
FALLTHROUGH;
[[fallthrough]];
}
case HT_POINT:
@@ -2981,9 +3033,9 @@ static void CalcRaildirsDrawstyle(int x, int y, int method)
/* Make sure we do not overflow the map! */
CheckUnderflow(x, y, 1);
CheckUnderflow(y, x, 1);
CheckOverflow(x, y, (MapMaxX() - 1) * TILE_SIZE, 1);
CheckOverflow(y, x, (MapMaxY() - 1) * TILE_SIZE, 1);
assert(x >= 0 && y >= 0 && x <= (int)(MapMaxX() * TILE_SIZE) && y <= (int)(MapMaxY() * TILE_SIZE));
CheckOverflow(x, y, (Map::MaxX() - 1) * TILE_SIZE, 1);
CheckOverflow(y, x, (Map::MaxY() - 1) * TILE_SIZE, 1);
assert(x >= 0 && y >= 0 && x <= (int)(Map::MaxX() * TILE_SIZE) && y <= (int)(Map::MaxY() * TILE_SIZE));
}
break;
@@ -3016,9 +3068,9 @@ static void CalcRaildirsDrawstyle(int x, int y, int method)
/* Make sure we do not overflow the map! */
CheckUnderflow(x, y, -1);
CheckUnderflow(y, x, -1);
CheckOverflow(x, y, (MapMaxX() - 1) * TILE_SIZE, -1);
CheckOverflow(y, x, (MapMaxY() - 1) * TILE_SIZE, -1);
assert(x >= 0 && y >= 0 && x <= (int)(MapMaxX() * TILE_SIZE) && y <= (int)(MapMaxY() * TILE_SIZE));
CheckOverflow(x, y, (Map::MaxX() - 1) * TILE_SIZE, -1);
CheckOverflow(y, x, (Map::MaxY() - 1) * TILE_SIZE, -1);
assert(x >= 0 && y >= 0 && x <= (int)(Map::MaxX() * TILE_SIZE) && y <= (int)(Map::MaxY() * TILE_SIZE));
}
break;
@@ -3117,7 +3169,6 @@ static void CalcRaildirsDrawstyle(int x, int y, int method)
TileIndex t1 = TileVirtXY(x, y);
uint distance = DistanceManhattan(t0, t1) + 1;
byte index = 0;
uint64 params[2];
if (distance != 1) {
int heightdiff = CalcHeightdiff(b, distance, t0, t1);
@@ -3128,11 +3179,11 @@ static void CalcRaildirsDrawstyle(int x, int y, int method)
distance = CeilDiv(distance, 2);
}
params[index++] = distance;
if (heightdiff != 0) params[index++] = heightdiff;
SetDParam(index++, distance);
if (heightdiff != 0) SetDParam(index++, heightdiff);
}
ShowMeasurementTooltips(measure_strings_length[index], index, params);
ShowMeasurementTooltips(measure_strings_length[index], index);
}
_thd.selend.x = x;
@@ -3189,7 +3240,7 @@ void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method)
case VPM_X_LIMITED: // Drag in X direction (limited size).
limit = (_thd.sizelimit - 1) * TILE_SIZE;
FALLTHROUGH;
[[fallthrough]];
case VPM_FIX_X: // drag in Y direction
x = sx;
@@ -3198,7 +3249,7 @@ void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method)
case VPM_Y_LIMITED: // Drag in Y direction (limited size).
limit = (_thd.sizelimit - 1) * TILE_SIZE;
FALLTHROUGH;
[[fallthrough]];
case VPM_FIX_Y: // drag in X direction
y = sy;
@@ -3214,7 +3265,6 @@ calc_heightdiff_single_direction:;
TileIndex t1 = TileVirtXY(x, y);
uint distance = DistanceManhattan(t0, t1) + 1;
byte index = 0;
uint64 params[2];
if (distance != 1) {
/* With current code passing a HT_LINE style to calculate the height
@@ -3224,11 +3274,11 @@ calc_heightdiff_single_direction:;
* new_style := (_thd.next_drawstyle & HT_RECT) ? HT_LINE | style : _thd.next_drawstyle; */
int heightdiff = CalcHeightdiff(HT_LINE | style, 0, t0, t1);
params[index++] = distance;
if (heightdiff != 0) params[index++] = heightdiff;
SetDParam(index++, distance);
if (heightdiff != 0) SetDParam(index++, heightdiff);
}
ShowMeasurementTooltips(measure_strings_length[index], index, params);
ShowMeasurementTooltips(measure_strings_length[index], index);
}
break;
@@ -3236,7 +3286,7 @@ calc_heightdiff_single_direction:;
limit = (_thd.sizelimit - 1) * TILE_SIZE;
x = sx + Clamp(x - sx, -limit, limit);
y = sy + Clamp(y - sy, -limit, limit);
FALLTHROUGH;
[[fallthrough]];
case VPM_X_AND_Y: // drag an X by Y area
if (_settings_client.gui.measure_tooltip) {
@@ -3249,7 +3299,6 @@ calc_heightdiff_single_direction:;
uint dx = Delta(TileX(t0), TileX(t1)) + 1;
uint dy = Delta(TileY(t0), TileY(t1)) + 1;
byte index = 0;
uint64 params[3];
/* If dragging an area (eg dynamite tool) and it is actually a single
* row/column, change the type to 'line' to get proper calculation for height */
@@ -3294,12 +3343,12 @@ calc_heightdiff_single_direction:;
if (dx != 1 || dy != 1) {
int heightdiff = CalcHeightdiff(style, 0, t0, t1);
params[index++] = dx - (style & HT_POINT ? 1 : 0);
params[index++] = dy - (style & HT_POINT ? 1 : 0);
if (heightdiff != 0) params[index++] = heightdiff;
SetDParam(index++, dx - (style & HT_POINT ? 1 : 0));
SetDParam(index++, dy - (style & HT_POINT ? 1 : 0));
if (heightdiff != 0) SetDParam(index++, heightdiff);
}
ShowMeasurementTooltips(measure_strings_area[index], index, params);
ShowMeasurementTooltips(measure_strings_area[index], index);
}
break;
@@ -3440,7 +3489,7 @@ Point GetViewportStationMiddle(const Viewport *vp, const Station *st)
{
int x = TileX(st->xy) * TILE_SIZE;
int y = TileY(st->xy) * TILE_SIZE;
int z = GetSlopePixelZ(Clamp(x, 0, MapSizeX() * TILE_SIZE - 1), Clamp(y, 0, MapSizeY() * TILE_SIZE - 1));
int z = GetSlopePixelZ(Clamp(x, 0, Map::SizeX() * TILE_SIZE - 1), Clamp(y, 0, Map::SizeY() * TILE_SIZE - 1));
Point p = RemapCoords(x, y, z);
p.x = UnScaleByZoom(p.x - vp->virtual_left, vp->zoom) + vp->left;
@@ -3482,7 +3531,7 @@ void InitializeSpriteSorter()
* @param ref company or client id depending on the target
* @return the cost of this operation or an error
*/
CommandCost CmdScrollViewport(DoCommandFlag flags, TileIndex tile, ViewportScrollTarget target, uint32 ref)
CommandCost CmdScrollViewport(DoCommandFlag flags, TileIndex tile, ViewportScrollTarget target, uint32_t ref)
{
if (_current_company != OWNER_DEITY) return CMD_ERROR;
switch (target) {
@@ -3522,6 +3571,27 @@ void MarkCatchmentTilesDirty()
}
}
}
if (_viewport_highlight_waypoint != nullptr) {
if (!_viewport_highlight_waypoint->IsInUse()) {
_viewport_highlight_waypoint = nullptr;
}
MarkWholeScreenDirty();
}
}
static void SetWindowDirtyForViewportCatchment()
{
if (_viewport_highlight_station != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station->index);
if (_viewport_highlight_waypoint != nullptr) SetWindowDirty(WC_WAYPOINT_VIEW, _viewport_highlight_waypoint->index);
if (_viewport_highlight_town != nullptr) SetWindowDirty(WC_TOWN_VIEW, _viewport_highlight_town->index);
}
static void ClearViewportCatchment()
{
MarkCatchmentTilesDirty();
_viewport_highlight_station = nullptr;
_viewport_highlight_waypoint = nullptr;
_viewport_highlight_town = nullptr;
}
/**
@@ -3532,12 +3602,10 @@ void MarkCatchmentTilesDirty()
*/
void SetViewportCatchmentStation(const Station *st, bool sel)
{
if (_viewport_highlight_station != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station->index);
if (_viewport_highlight_town != nullptr) SetWindowDirty(WC_TOWN_VIEW, _viewport_highlight_town->index);
SetWindowDirtyForViewportCatchment();
if (sel && _viewport_highlight_station != st) {
MarkCatchmentTilesDirty();
ClearViewportCatchment();
_viewport_highlight_station = st;
_viewport_highlight_town = nullptr;
MarkCatchmentTilesDirty();
} else if (!sel && _viewport_highlight_station == st) {
MarkCatchmentTilesDirty();
@@ -3546,6 +3614,26 @@ void SetViewportCatchmentStation(const Station *st, bool sel)
if (_viewport_highlight_station != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station->index);
}
/**
* Select or deselect waypoint for coverage area highlight.
* Selecting a waypoint will deselect a town.
* @param *wp Waypoint in question
* @param sel Select or deselect given waypoint
*/
void SetViewportCatchmentWaypoint(const Waypoint *wp, bool sel)
{
SetWindowDirtyForViewportCatchment();
if (sel && _viewport_highlight_waypoint != wp) {
ClearViewportCatchment();
_viewport_highlight_waypoint = wp;
MarkCatchmentTilesDirty();
} else if (!sel && _viewport_highlight_waypoint == wp) {
MarkCatchmentTilesDirty();
_viewport_highlight_waypoint = nullptr;
}
if (_viewport_highlight_waypoint != nullptr) SetWindowDirty(WC_WAYPOINT_VIEW, _viewport_highlight_waypoint->index);
}
/**
* Select or deselect town for coverage area highlight.
* Selecting a town will deselect a station.
@@ -3554,10 +3642,9 @@ void SetViewportCatchmentStation(const Station *st, bool sel)
*/
void SetViewportCatchmentTown(const Town *t, bool sel)
{
if (_viewport_highlight_town != nullptr) SetWindowDirty(WC_TOWN_VIEW, _viewport_highlight_town->index);
if (_viewport_highlight_station != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station->index);
SetWindowDirtyForViewportCatchment();
if (sel && _viewport_highlight_town != t) {
_viewport_highlight_station = nullptr;
ClearViewportCatchment();
_viewport_highlight_town = t;
MarkWholeScreenDirty();
} else if (!sel && _viewport_highlight_town == t) {