summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/smallmap_gui.cpp74
-rw-r--r--src/smallmap_gui.h1
2 files changed, 63 insertions, 12 deletions
diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp
index 6be0a0fff..4c6b9a975 100644
--- a/src/smallmap_gui.cpp
+++ b/src/smallmap_gui.cpp
@@ -909,6 +909,30 @@ void SmallMapWindow::DrawTowns(const DrawPixelInfo *dpi) const
}
/**
+ * Convert a coordinate of the viewport to essentially a tile on the map,
+ * taking care of the different location due to height.
+ * @param viewport_coord The coordinate in the viewport.
+ * @return The tile location.
+ */
+Point SmallMapWindow::GetSmallMapCoordIncludingHeight(Point viewport_coord) const
+{
+ /* First find out which tile would be there if we ignore height */
+ Point pt = InverseRemapCoords(viewport_coord.x, viewport_coord.y);
+ Point pt_without_height = {pt.x / TILE_SIZE, pt.y / TILE_SIZE};
+
+ /* Problem: There are mountains. So the tile actually displayed at the given position
+ * might be the high mountain of 30 tiles south.
+ * Unfortunately, there is no closed formula for finding such a tile.
+ * We call GetRowAtTile originally implemented for the viewport code, which performs
+ * a interval search. For details, see its documentation. */
+ int row_without_height = pt_without_height.x + pt_without_height.y;
+ int row_with_height = GetRowAtTile(viewport_coord.y, pt_without_height, false);
+ int row_offset = row_with_height - row_without_height;
+ Point pt_with_height = {pt_without_height.x + row_offset / 2, pt_without_height.y + row_offset / 2};
+ return pt_with_height;
+}
+
+/**
* Adds map indicators to the smallmap.
*/
void SmallMapWindow::DrawMapIndicators() const
@@ -916,19 +940,22 @@ void SmallMapWindow::DrawMapIndicators() const
/* Find main viewport. */
const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
- Point tile = InverseRemapCoords(vp->virtual_left, vp->virtual_top);
- Point tl = this->RemapTile(tile.x >> 4, tile.y >> 4);
- tl.x -= this->subscroll;
+ Point upper_left_viewport_coord = {vp->virtual_left, vp->virtual_top};
+ Point upper_left_small_map_coord = GetSmallMapCoordIncludingHeight(upper_left_viewport_coord);
+ Point upper_left = this->RemapTile(upper_left_small_map_coord.x, upper_left_small_map_coord.y);
+ upper_left.x -= this->subscroll;
- tile = InverseRemapCoords(vp->virtual_left + vp->virtual_width, vp->virtual_top + vp->virtual_height);
- Point br = this->RemapTile(tile.x >> 4, tile.y >> 4);
- br.x -= this->subscroll;
+ Point lower_right_viewport_coord = {vp->virtual_left + vp->virtual_width, vp->virtual_top + vp->virtual_height};
+ Point lower_right_smallmap_coord = GetSmallMapCoordIncludingHeight(lower_right_viewport_coord);
+ Point lower_right = this->RemapTile(lower_right_smallmap_coord.x, lower_right_smallmap_coord.y);
+ /* why do we do this? in my tests subscroll was zero */
+ lower_right.x -= this->subscroll;
- SmallMapWindow::DrawVertMapIndicator(tl.x, tl.y, br.y);
- SmallMapWindow::DrawVertMapIndicator(br.x, tl.y, br.y);
+ SmallMapWindow::DrawVertMapIndicator(upper_left.x, upper_left.y, lower_right.y);
+ SmallMapWindow::DrawVertMapIndicator(lower_right.x, upper_left.y, lower_right.y);
- SmallMapWindow::DrawHorizMapIndicator(tl.x, br.x, tl.y);
- SmallMapWindow::DrawHorizMapIndicator(tl.x, br.x, br.y);
+ SmallMapWindow::DrawHorizMapIndicator(upper_left.x, lower_right.x, upper_left.y);
+ SmallMapWindow::DrawHorizMapIndicator(upper_left.x, lower_right.x, lower_right.y);
}
/**
@@ -1375,6 +1402,18 @@ int SmallMapWindow::GetPositionOnLegend(Point pt)
pt = RemapCoords(this->scroll_x + pt.x * TILE_SIZE + this->zoom * (TILE_SIZE - sub * TILE_SIZE / 4),
this->scroll_y + pt.y * TILE_SIZE + sub * this->zoom * TILE_SIZE / 4, 0);
+ /* correct y coordinate according to the height level at the chosen tile
+ * - so far we assumed height zero. Calculations here according to
+ * TranslateXYToTileCoord in viewport.cpp */
+ Point pt_scaled = {pt.x / (int)(4 * TILE_SIZE), pt.y / (int)(2 * TILE_SIZE)};
+ Point tile_coord = {pt_scaled.y - pt_scaled.x, pt_scaled.y + pt_scaled.x};
+
+ if (tile_coord.x >= 0 && tile_coord.y >= 0
+ && tile_coord.x < (int)MapMaxX() && tile_coord.y < (int)MapMaxY()) {
+ int clicked_tile_height = TileHeight(TileXY(tile_coord.x, tile_coord.y));
+ pt.y -= clicked_tile_height * TILE_HEIGHT;
+ }
+
w->viewport->follow_vehicle = INVALID_VEHICLE;
w->viewport->dest_scrollpos_x = pt.x - (w->viewport->virtual_width >> 1);
w->viewport->dest_scrollpos_y = pt.y - (w->viewport->virtual_height >> 1);
@@ -1595,14 +1634,25 @@ void SmallMapWindow::SetNewScroll(int sx, int sy, int sub)
this->SetDirty();
}
+/**
+ * Center the small map on the current center of the viewport.
+ */
void SmallMapWindow::SmallMapCenterOnCurrentPos()
{
+ /* Goal: Given the viewport coordinates of the middle of the map window, find
+ * out which tile is displayed there. */
+
+ /* First find out which tile would be there if we ignore height */
const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
- Point pt = InverseRemapCoords(vp->virtual_left + vp->virtual_width / 2, vp->virtual_top + vp->virtual_height / 2);
+ Point viewport_center = {vp->virtual_left + vp->virtual_width / 2, vp->virtual_top + vp->virtual_height / 2};
+ Point pt_with_height = GetSmallMapCoordIncludingHeight(viewport_center);
+
+ /* And finally scroll to that position. */
int sub;
const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
- Point sxy = this->ComputeScroll(pt.x / TILE_SIZE, pt.y / TILE_SIZE, max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
+ Point sxy = this->ComputeScroll(pt_with_height.x, pt_with_height.y,
+ max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
this->SetNewScroll(sxy.x, sxy.y, sub);
this->SetDirty();
}
diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h
index 6652f83d8..e180fabd1 100644
--- a/src/smallmap_gui.h
+++ b/src/smallmap_gui.h
@@ -155,6 +155,7 @@ protected:
void DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const;
void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const;
void DrawTowns(const DrawPixelInfo *dpi) const;
+ Point GetSmallMapCoordIncludingHeight(Point viewport_coord) const;
void DrawSmallMap(DrawPixelInfo *dpi) const;
Point RemapTile(int tile_x, int tile_y) const;