Add zoom in support to the small map
Heavily referenced from citimania
6f8e0c144b
This commit is contained in:
@@ -631,32 +631,12 @@ static const byte _vehicle_type_colours[6] = {
|
||||
InvalidateWindowClassesData(WC_INDUSTRY_CARGOES, NUM_INDUSTRYTYPES);
|
||||
}
|
||||
|
||||
inline Point SmallMapWindow::SmallmapRemapCoords(int x, int y) const
|
||||
inline Point SmallMapWindow::TileToPixel(int tx, int ty) const
|
||||
{
|
||||
Point pt;
|
||||
pt.x = (y - x) * 2;
|
||||
pt.y = y + x;
|
||||
return pt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remap tile to location on this smallmap.
|
||||
* @param tile_x X coordinate of the tile.
|
||||
* @param tile_y Y coordinate of the tile.
|
||||
* @return Position to draw on.
|
||||
*/
|
||||
inline Point SmallMapWindow::RemapTile(int tile_x, int tile_y) const
|
||||
{
|
||||
int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE;
|
||||
int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE;
|
||||
|
||||
if (this->zoom == 1) return SmallmapRemapCoords(x_offset, y_offset);
|
||||
|
||||
/* For negative offsets, round towards -inf. */
|
||||
if (x_offset < 0) x_offset -= this->zoom - 1;
|
||||
if (y_offset < 0) y_offset -= this->zoom - 1;
|
||||
|
||||
return SmallmapRemapCoords(x_offset / this->zoom, y_offset / this->zoom);
|
||||
return {
|
||||
(ty - tx) * 2 / this->zoom + this->scroll_x,
|
||||
(ty + tx) / this->zoom + this->scroll_y,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,63 +644,16 @@ inline Point SmallMapWindow::RemapTile(int tile_x, int tile_y) const
|
||||
* that tile for a point in the smallmap.
|
||||
* @param px Horizontal coordinate of the pixel.
|
||||
* @param py Vertical coordinate of the pixel.
|
||||
* @param[out] sub Pixel position at the tile (0..3).
|
||||
* @param add_sub Add current #subscroll to the position.
|
||||
* @return Tile being displayed at the given position relative to #scroll_x and #scroll_y.
|
||||
* @note The #subscroll offset is already accounted for.
|
||||
*/
|
||||
inline Point SmallMapWindow::PixelToTile(int px, int py, int *sub, bool add_sub) const
|
||||
inline Point SmallMapWindow::PixelToTile(int px, int py) const
|
||||
{
|
||||
if (add_sub) px += this->subscroll; // Total horizontal offset.
|
||||
px -= this->scroll_x;
|
||||
py -= this->scroll_y;
|
||||
|
||||
/* For each two rows down, add a x and a y tile, and
|
||||
* For each four pixels to the right, move a tile to the right. */
|
||||
Point pt = {((py >> 1) - (px >> 2)) * this->zoom, ((py >> 1) + (px >> 2)) * this->zoom};
|
||||
px &= 3;
|
||||
|
||||
if (py & 1) { // Odd number of rows, handle the 2 pixel shift.
|
||||
if (px < 2) {
|
||||
pt.x += this->zoom;
|
||||
px += 2;
|
||||
} else {
|
||||
pt.y += this->zoom;
|
||||
px -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
*sub = px;
|
||||
return pt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute base parameters of the smallmap such that tile (\a tx, \a ty) starts at pixel (\a x, \a y).
|
||||
* @param tx Tile x coordinate.
|
||||
* @param ty Tile y coordinate.
|
||||
* @param x Non-negative horizontal position in the display where the tile starts.
|
||||
* @param y Non-negative vertical position in the display where the tile starts.
|
||||
* @param[out] sub Value of #subscroll needed.
|
||||
* @return #scroll_x, #scroll_y values.
|
||||
*/
|
||||
Point SmallMapWindow::ComputeScroll(int tx, int ty, int x, int y, int *sub)
|
||||
{
|
||||
assert(x >= 0 && y >= 0);
|
||||
|
||||
int new_sub;
|
||||
Point tile_xy = PixelToTile(x, y, &new_sub, false);
|
||||
tx -= tile_xy.x;
|
||||
ty -= tile_xy.y;
|
||||
|
||||
Point scroll;
|
||||
if (new_sub == 0) {
|
||||
*sub = 0;
|
||||
scroll.x = (tx + this->zoom) * TILE_SIZE;
|
||||
scroll.y = (ty - this->zoom) * TILE_SIZE;
|
||||
} else {
|
||||
*sub = 4 - new_sub;
|
||||
scroll.x = (tx + 2 * this->zoom) * TILE_SIZE;
|
||||
scroll.y = (ty - 2 * this->zoom) * TILE_SIZE;
|
||||
}
|
||||
return scroll;
|
||||
return {
|
||||
(py * 2 - px) * this->zoom / 4,
|
||||
(py * 2 + px) * this->zoom / 4,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -731,27 +664,28 @@ Point SmallMapWindow::ComputeScroll(int tx, int ty, int x, int y, int *sub)
|
||||
*/
|
||||
void SmallMapWindow::SetZoomLevel(ZoomLevelChange change, const Point *zoom_pt)
|
||||
{
|
||||
static const int zoomlevels[] = {1, 2, 4, 6, 8}; // Available zoom levels. Bigger number means more zoom-out (further away).
|
||||
static const int tile_zoomlevels[] = {1, 1, 1, 2, 4, 6, 8}; // Available zoom levels. Bigger number means more zoom-out (further away).
|
||||
static const int ui_zoomlevels[] = {4, 2, 1, 1, 1, 1, 1};
|
||||
static const int MIN_ZOOM_INDEX = 0;
|
||||
static const int MAX_ZOOM_INDEX = lengthof(zoomlevels) - 1;
|
||||
static const int MAX_ZOOM_INDEX = lengthof(tile_zoomlevels) - 1;
|
||||
|
||||
int new_index, cur_index, sub;
|
||||
int new_index, cur_index;
|
||||
Point tile;
|
||||
switch (change) {
|
||||
case ZLC_INITIALIZE:
|
||||
cur_index = - 1; // Definitely different from new_index.
|
||||
new_index = MIN_ZOOM_INDEX;
|
||||
new_index = Clamp((int)ZOOM_LVL_GUI, MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
|
||||
tile.x = tile.y = 0;
|
||||
break;
|
||||
|
||||
case ZLC_ZOOM_IN:
|
||||
case ZLC_ZOOM_OUT:
|
||||
for (cur_index = MIN_ZOOM_INDEX; cur_index <= MAX_ZOOM_INDEX; cur_index++) {
|
||||
if (this->zoom == zoomlevels[cur_index]) break;
|
||||
if (this->tile_zoom == tile_zoomlevels[cur_index] && this->ui_zoom == ui_zoomlevels[cur_index]) break;
|
||||
}
|
||||
assert(cur_index <= MAX_ZOOM_INDEX);
|
||||
|
||||
tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
|
||||
tile = this->PixelToTile(zoom_pt->x, zoom_pt->y);
|
||||
new_index = Clamp(cur_index + ((change == ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
|
||||
break;
|
||||
|
||||
@@ -759,14 +693,16 @@ void SmallMapWindow::SetZoomLevel(ZoomLevelChange change, const Point *zoom_pt)
|
||||
}
|
||||
|
||||
if (new_index != cur_index) {
|
||||
this->zoom = zoomlevels[new_index];
|
||||
this->tile_zoom = tile_zoomlevels[new_index];
|
||||
this->ui_zoom = ui_zoomlevels[new_index];
|
||||
this->zoom = this->tile_zoom * TILE_SIZE / this->ui_zoom;
|
||||
if (cur_index >= 0) {
|
||||
Point new_tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
|
||||
this->SetNewScroll(this->scroll_x + (tile.x - new_tile.x) * TILE_SIZE,
|
||||
this->scroll_y + (tile.y - new_tile.y) * TILE_SIZE, sub);
|
||||
Point new_tile = this->TileToPixel(tile.x, tile.y);
|
||||
this->scroll_x += zoom_pt->x - new_tile.x;
|
||||
this->scroll_y += zoom_pt->y - new_tile.y;
|
||||
}
|
||||
this->SetWidgetDisabledState(WID_SM_ZOOM_IN, this->zoom == zoomlevels[MIN_ZOOM_INDEX]);
|
||||
this->SetWidgetDisabledState(WID_SM_ZOOM_OUT, this->zoom == zoomlevels[MAX_ZOOM_INDEX]);
|
||||
this->SetWidgetDisabledState(WID_SM_ZOOM_IN, this->ui_zoom == ui_zoomlevels[MIN_ZOOM_INDEX]);
|
||||
this->SetWidgetDisabledState(WID_SM_ZOOM_OUT, this->tile_zoom == tile_zoomlevels[MAX_ZOOM_INDEX]);
|
||||
this->SetDirty();
|
||||
}
|
||||
}
|
||||
@@ -865,11 +801,15 @@ inline uint32 SmallMapWindow::GetTileColours(const TileArea &ta) const
|
||||
* @param blitter current blitter
|
||||
* @note If pixel position is below \c 0, skip drawing.
|
||||
*/
|
||||
void SmallMapWindow::DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const
|
||||
void SmallMapWindow::DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, int y, int end_y, Blitter *blitter) const
|
||||
{
|
||||
void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
|
||||
uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
|
||||
|
||||
int hidden_x = std::max(0, -start_pos);
|
||||
int hidden_idx = hidden_x / this->ui_zoom;
|
||||
int hidden_mod = hidden_x % this->ui_zoom;
|
||||
|
||||
do {
|
||||
/* Check if the tile (xc,yc) is within the map range */
|
||||
if (xc >= MapMaxX() || yc >= MapMaxY()) continue;
|
||||
@@ -881,23 +821,47 @@ void SmallMapWindow::DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch,
|
||||
/* Construct tilearea covered by (xc, yc, xc + this->zoom, yc + this->zoom) such that it is within min_xy limits. */
|
||||
TileArea ta;
|
||||
if (min_xy == 1 && (xc == 0 || yc == 0)) {
|
||||
if (this->zoom == 1) continue; // The tile area is empty, don't draw anything.
|
||||
|
||||
ta = TileArea(TileXY(std::max(min_xy, xc), std::max(min_xy, yc)), this->zoom - (xc == 0), this->zoom - (yc == 0));
|
||||
if (this->tile_zoom == 1) continue; // The tile area is empty, don't draw anything.
|
||||
ta = TileArea(TileXY(std::max(min_xy, xc), std::max(min_xy, yc)), this->tile_zoom - (xc == 0), this->tile_zoom - (yc == 0));
|
||||
} else {
|
||||
ta = TileArea(TileXY(xc, yc), this->zoom, this->zoom);
|
||||
ta = TileArea(TileXY(xc, yc), this->tile_zoom, this->tile_zoom);
|
||||
}
|
||||
ta.ClampToMap(); // Clamp to map boundaries (may contain MP_VOID tiles!).
|
||||
|
||||
uint32 val = this->GetTileColours(ta);
|
||||
uint8 *val8 = (uint8 *)&val;
|
||||
int idx = std::max(0, -start_pos);
|
||||
for (int pos = std::max(0, start_pos); pos < end_pos; pos++) {
|
||||
blitter->SetPixel(dst, idx, 0, val8[idx]);
|
||||
idx++;
|
||||
if (this->ui_zoom == 1) {
|
||||
int idx = std::max(0, -start_pos);
|
||||
if (y >= 0 && y < end_y) {
|
||||
for (int pos = std::max(0, start_pos); pos < end_pos; pos++) {
|
||||
blitter->SetPixel(dst, idx, 0, val8[idx]);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto ndst = dst;
|
||||
auto ny = y;
|
||||
for (auto i = 0; i < this->ui_zoom; i++) {
|
||||
if (ny >= 0 && ny < end_y) {
|
||||
int idx = hidden_idx;
|
||||
int j = hidden_mod;
|
||||
int x = hidden_x;
|
||||
for (int pos = std::max(0, start_pos); pos < end_pos; pos++) {
|
||||
blitter->SetPixel(ndst, x, 0, val8[idx]);
|
||||
j++;
|
||||
x++;
|
||||
if (j == this->ui_zoom) {
|
||||
idx++;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ndst = blitter->MoveTo(ndst, pitch, 0);
|
||||
ny++;
|
||||
}
|
||||
}
|
||||
/* Switch to next tile in the column */
|
||||
} while (xc += this->zoom, yc += this->zoom, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
|
||||
} while (xc += this->tile_zoom, yc += this->tile_zoom, dst = blitter->MoveTo(dst, pitch * this->ui_zoom * 2, 0), y += 2 * this->ui_zoom, --reps != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -912,30 +876,23 @@ void SmallMapWindow::DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) co
|
||||
if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
|
||||
|
||||
/* Remap into flat coordinates. */
|
||||
Point pt = this->RemapTile(v->x_pos / (int)TILE_SIZE, v->y_pos / (int)TILE_SIZE);
|
||||
Point pt = this->TileToPixel(v->x_pos & ~TILE_UNIT_MASK, v->y_pos & ~TILE_UNIT_MASK);
|
||||
|
||||
int y = pt.y - dpi->top;
|
||||
if (!IsInsideMM(y, 0, dpi->height)) continue; // y is out of bounds.
|
||||
|
||||
bool skip = false; // Default is to draw both pixels.
|
||||
int x = pt.x - this->subscroll - 3 - dpi->left; // Offset X coordinate.
|
||||
if (x < 0) {
|
||||
/* if x+1 is 0, that means we're on the very left edge,
|
||||
* and should thus only draw a single pixel */
|
||||
if (++x != 0) continue;
|
||||
skip = true;
|
||||
} else if (x >= dpi->width - 1) {
|
||||
/* Check if we're at the very right edge, and if so draw only a single pixel */
|
||||
if (x != dpi->width - 1) continue;
|
||||
skip = true;
|
||||
}
|
||||
int x = pt.x - 1 * this->ui_zoom - dpi->left; // Offset X coordinate.
|
||||
if (!IsInsideMM(y, -this->ui_zoom + 1, dpi->height)) continue; // y is out of bounds.
|
||||
|
||||
/* Calculate pointer to pixel and the colour */
|
||||
byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE;
|
||||
|
||||
/* And draw either one or two pixels depending on clipping */
|
||||
blitter->SetPixel(dpi->dst_ptr, x, y, colour);
|
||||
if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
|
||||
auto min_i = std::max(0, -y);
|
||||
auto max_i = std::min(this->ui_zoom, dpi->height - y);
|
||||
auto min_j = std::max(0, -x);
|
||||
auto max_j = std::min(2 * this->ui_zoom, dpi->width - x);
|
||||
if (min_i < max_i && min_j < max_j) {
|
||||
blitter->DrawRectAt(dpi->dst_ptr, x + min_j, y + min_i, max_j - min_j, max_i - min_i, colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -947,8 +904,8 @@ void SmallMapWindow::DrawTowns(const DrawPixelInfo *dpi) const
|
||||
{
|
||||
for (const Town *t : Town::Iterate()) {
|
||||
/* Remap the town coordinate */
|
||||
Point pt = this->RemapTile(TileX(t->xy), TileY(t->xy));
|
||||
int x = pt.x - this->subscroll - (t->cache.sign.width_small >> 1);
|
||||
Point pt = this->TileToPixel(TileX(t->xy) * TILE_SIZE, TileY(t->xy) * TILE_SIZE);
|
||||
int x = pt.x - (t->cache.sign.width_small >> 1);
|
||||
int y = pt.y;
|
||||
|
||||
/* Check if the town sign is within bounds */
|
||||
@@ -974,11 +931,8 @@ void SmallMapWindow::DrawMapIndicators() const
|
||||
Point upper_left_smallmap_coord = InverseRemapCoords2(vp->virtual_left, vp->virtual_top);
|
||||
Point lower_right_smallmap_coord = InverseRemapCoords2(vp->virtual_left + vp->virtual_width - 1, vp->virtual_top + vp->virtual_height - 1);
|
||||
|
||||
Point upper_left = this->RemapTile(upper_left_smallmap_coord.x / (int)TILE_SIZE, upper_left_smallmap_coord.y / (int)TILE_SIZE);
|
||||
upper_left.x -= this->subscroll;
|
||||
|
||||
Point lower_right = this->RemapTile(lower_right_smallmap_coord.x / (int)TILE_SIZE, lower_right_smallmap_coord.y / (int)TILE_SIZE);
|
||||
lower_right.x -= this->subscroll;
|
||||
Point upper_left = this->TileToPixel(upper_left_smallmap_coord.x, upper_left_smallmap_coord.y);
|
||||
Point lower_right = this->TileToPixel(lower_right_smallmap_coord.x, lower_right_smallmap_coord.y);
|
||||
|
||||
SmallMapWindow::DrawVertMapIndicator(upper_left.x, upper_left.y, lower_right.y);
|
||||
SmallMapWindow::DrawVertMapIndicator(lower_right.x, upper_left.y, lower_right.y);
|
||||
@@ -1010,38 +964,43 @@ void SmallMapWindow::DrawSmallMap(DrawPixelInfo *dpi, bool draw_indicators) cons
|
||||
GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, PC_BLACK);
|
||||
|
||||
/* Which tile is displayed at (dpi->left, dpi->top)? */
|
||||
int dx;
|
||||
Point tile = this->PixelToTile(dpi->left, dpi->top, &dx);
|
||||
int tile_x = this->scroll_x / (int)TILE_SIZE + tile.x;
|
||||
int tile_y = this->scroll_y / (int)TILE_SIZE + tile.y;
|
||||
Point tile = this->PixelToTile(dpi->left, dpi->top);
|
||||
int tile_x = tile.x / (int)TILE_SIZE + this->tile_zoom;
|
||||
int tile_y = tile.y / (int)TILE_SIZE - 2 * this->tile_zoom;
|
||||
tile_x -= tile_x % this->tile_zoom;
|
||||
tile_y -= tile_y % this->tile_zoom;
|
||||
Point tile_pos = this->TileToPixel(tile_x * TILE_SIZE, tile_y * TILE_SIZE);
|
||||
int dx = tile_pos.x - dpi->left;
|
||||
int dy = tile_pos.y - dpi->top;
|
||||
|
||||
void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
|
||||
int x = - dx - 4;
|
||||
int y = 0;
|
||||
int x = dx - 2 * this->ui_zoom;
|
||||
int y = dy;
|
||||
void *ptr = blitter->MoveTo(dpi->dst_ptr, x, y);
|
||||
bool even = true;
|
||||
|
||||
for (;;) {
|
||||
/* Distance from left edge */
|
||||
if (x >= -3) {
|
||||
if (x > -4 * this->ui_zoom) {
|
||||
if (x >= dpi->width) break; // Exit the loop.
|
||||
|
||||
int end_pos = std::min(dpi->width, x + 4);
|
||||
int reps = (dpi->height - y + 1) / 2; // Number of lines.
|
||||
int end_pos = std::min(dpi->width, x + 4 * this->ui_zoom);
|
||||
int reps = (dpi->height - y + 3 * this->ui_zoom - 1) / 2 / this->ui_zoom; // Number of lines.
|
||||
if (reps > 0) {
|
||||
this->DrawSmallMapColumn(ptr, tile_x, tile_y, dpi->pitch * 2, reps, x, end_pos, blitter);
|
||||
this->DrawSmallMapColumn(ptr, tile_x, tile_y, dpi->pitch, reps, x, end_pos, y, dpi->height, blitter);
|
||||
}
|
||||
}
|
||||
|
||||
if (y == 0) {
|
||||
tile_y += this->zoom;
|
||||
y++;
|
||||
ptr = blitter->MoveTo(ptr, 0, 1);
|
||||
if (even) {
|
||||
tile_y += this->tile_zoom;
|
||||
y += this->ui_zoom;
|
||||
ptr = blitter->MoveTo(ptr, 0, this->ui_zoom);
|
||||
} else {
|
||||
tile_x -= this->zoom;
|
||||
y--;
|
||||
ptr = blitter->MoveTo(ptr, 0, -1);
|
||||
tile_x -= this->tile_zoom;
|
||||
y -= this->ui_zoom;
|
||||
ptr = blitter->MoveTo(ptr, 0, -this->ui_zoom);
|
||||
}
|
||||
ptr = blitter->MoveTo(ptr, 2, 0);
|
||||
x += 2;
|
||||
even = !even;
|
||||
ptr = blitter->MoveTo(ptr, 2 * this->ui_zoom, 0);
|
||||
x += 2 * this->ui_zoom;
|
||||
}
|
||||
|
||||
/* Draw vehicles */
|
||||
@@ -1462,10 +1421,8 @@ int SmallMapWindow::GetPositionOnLegend(Point pt)
|
||||
|
||||
const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
|
||||
Window *w = GetMainWindow();
|
||||
int sub;
|
||||
pt = this->PixelToTile(pt.x - wid->pos_x, pt.y - wid->pos_y, &sub);
|
||||
ScrollWindowTo(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, -1, w);
|
||||
|
||||
pt = this->PixelToTile(pt.x - wid->pos_x, pt.y - wid->pos_y);
|
||||
ScrollWindowTo(pt.x, pt.y, -1, w);
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
@@ -1652,13 +1609,13 @@ uint SmallMapWindow::GetRefreshPeriod() const
|
||||
switch (map_type) {
|
||||
case SMT_CONTOUR:
|
||||
case SMT_VEHICLES:
|
||||
return FORCE_REFRESH_PERIOD_VEH * (1 + (this->zoom / 2));
|
||||
return FORCE_REFRESH_PERIOD_VEH * (1 + (this->tile_zoom / 2));
|
||||
|
||||
case SMT_LINKSTATS:
|
||||
return FORCE_REFRESH_PERIOD_LINK_GRAPH * (1 + (this->zoom / 6));
|
||||
return FORCE_REFRESH_PERIOD_LINK_GRAPH * (1 + (this->tile_zoom / 6));
|
||||
|
||||
default:
|
||||
return FORCE_REFRESH_PERIOD * (1 + (this->zoom / 6));
|
||||
return FORCE_REFRESH_PERIOD * (1 + (this->tile_zoom / 6));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1679,51 +1636,12 @@ uint SmallMapWindow::PausedAdjustRefreshTimeDelta(uint delta_ms) const
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new #scroll_x, #scroll_y, and #subscroll values after limiting them such that the center
|
||||
* of the smallmap always contains a part of the map.
|
||||
* @param sx Proposed new #scroll_x
|
||||
* @param sy Proposed new #scroll_y
|
||||
* @param sub Proposed new #subscroll
|
||||
*/
|
||||
void SmallMapWindow::SetNewScroll(int sx, int sy, int sub)
|
||||
{
|
||||
const NWidgetBase *wi = this->GetWidget<NWidgetBase>(WID_SM_MAP);
|
||||
Point hv = InverseRemapCoords(wi->current_x * ZOOM_LVL_BASE * TILE_SIZE / 2, wi->current_y * ZOOM_LVL_BASE * TILE_SIZE / 2);
|
||||
hv.x *= this->zoom;
|
||||
hv.y *= this->zoom;
|
||||
|
||||
if (sx < -hv.x) {
|
||||
sx = -hv.x;
|
||||
sub = 0;
|
||||
}
|
||||
if (sx > (int)(MapMaxX() * TILE_SIZE) - hv.x) {
|
||||
sx = MapMaxX() * TILE_SIZE - hv.x;
|
||||
sub = 0;
|
||||
}
|
||||
if (sy < -hv.y) {
|
||||
sy = -hv.y;
|
||||
sub = 0;
|
||||
}
|
||||
if (sy > (int)(MapMaxY() * TILE_SIZE) - hv.y) {
|
||||
sy = MapMaxY() * TILE_SIZE - hv.y;
|
||||
sub = 0;
|
||||
}
|
||||
|
||||
this->scroll_x = sx;
|
||||
this->scroll_y = sy;
|
||||
this->subscroll = sub;
|
||||
}
|
||||
|
||||
/* virtual */ void SmallMapWindow::OnScroll(Point delta)
|
||||
{
|
||||
if (_settings_client.gui.scroll_mode == VSM_VIEWPORT_RMB_FIXED || _settings_client.gui.scroll_mode == VSM_MAP_RMB_FIXED) _cursor.fix_at = true;
|
||||
|
||||
/* While tile is at (delta.x, delta.y)? */
|
||||
int sub;
|
||||
Point pt = this->PixelToTile(delta.x, delta.y, &sub);
|
||||
this->SetNewScroll(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, sub);
|
||||
|
||||
this->scroll_x -= delta.x;
|
||||
this->scroll_y -= delta.y;
|
||||
this->SetDirty();
|
||||
}
|
||||
|
||||
@@ -1735,11 +1653,10 @@ void SmallMapWindow::SmallMapCenterOnCurrentPos()
|
||||
const Viewport *vp = GetMainWindow()->viewport;
|
||||
Point viewport_center = InverseRemapCoords2(vp->virtual_left + vp->virtual_width / 2, vp->virtual_top + vp->virtual_height / 2);
|
||||
|
||||
int sub;
|
||||
const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
|
||||
Point sxy = this->ComputeScroll(viewport_center.x / (int)TILE_SIZE, viewport_center.y / (int)TILE_SIZE,
|
||||
std::max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
|
||||
this->SetNewScroll(sxy.x, sxy.y, sub);
|
||||
auto pt = this->TileToPixel(viewport_center.x, viewport_center.y);
|
||||
this->scroll_x += std::max(0, (int)wid->current_x / 2 - 2) - pt.x;
|
||||
this->scroll_y += wid->current_y / 2 - pt.y;
|
||||
this->SetDirty();
|
||||
}
|
||||
|
||||
@@ -1750,14 +1667,14 @@ void SmallMapWindow::SmallMapCenterOnCurrentPos()
|
||||
*/
|
||||
Point SmallMapWindow::GetStationMiddle(const Station *st) const
|
||||
{
|
||||
int x = CenterBounds(st->rect.left, st->rect.right, 0);
|
||||
int y = CenterBounds(st->rect.top, st->rect.bottom, 0);
|
||||
Point ret = this->RemapTile(x, y);
|
||||
int x = (st->rect.right + st->rect.left + 1) * TILE_SIZE / 2;
|
||||
int y = (st->rect.bottom + st->rect.top + 1) * TILE_SIZE / 2;
|
||||
Point ret = this->TileToPixel(x, y);
|
||||
|
||||
/* Same magic 3 as in DrawVehicles; that's where I got it from.
|
||||
* No idea what it is, but without it the result looks bad.
|
||||
*/
|
||||
ret.x -= 3 + this->subscroll;
|
||||
ret.x -= 3;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1767,17 +1684,14 @@ Point SmallMapWindow::GetStationMiddle(const Station *st) const
|
||||
*/
|
||||
void SmallMapWindow::TakeScreenshot()
|
||||
{
|
||||
int32 width = ((MapMaxX() + MapMaxY()) * 2) / this->zoom;
|
||||
int32 height = (MapMaxX() + MapMaxY() + 1) / this->zoom;
|
||||
int32 width = (((MapMaxX() + MapMaxY()) * 2) * this->ui_zoom) / this->tile_zoom;
|
||||
int32 height = ((MapMaxX() + MapMaxY() + 1) * this->ui_zoom) / this->tile_zoom;
|
||||
|
||||
int32 saved_scroll_x = this->scroll_x;
|
||||
int32 saved_scroll_y = this->scroll_y;
|
||||
int32 saved_subscroll = this->subscroll;
|
||||
this->subscroll = 0;
|
||||
MakeSmallMapScreenshot(width, height, this);
|
||||
this->scroll_x = saved_scroll_x;
|
||||
this->scroll_y = saved_scroll_y;
|
||||
this->subscroll = saved_subscroll;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1806,7 +1720,7 @@ void SmallMapWindow::ScreenshotCallbackHandler(void *buf, uint y, uint pitch, ui
|
||||
|
||||
dpi.dst_ptr = buf;
|
||||
dpi.height = n;
|
||||
dpi.width = ((MapMaxX() + MapMaxY()) * 2) / this->zoom;
|
||||
dpi.width = (((MapMaxX() + MapMaxY()) * 2) * this->ui_zoom) / this->tile_zoom;
|
||||
dpi.pitch = pitch;
|
||||
dpi.zoom = ZOOM_LVL_NORMAL;
|
||||
dpi.left = 0;
|
||||
|
Reference in New Issue
Block a user