mirror of https://github.com/OpenTTD/OpenTTD
(svn r27158) -Codechange: Simplify mapping from viewport to smallmap coordinates by duplicating less code.
parent
e8e49e5dda
commit
06d1d50884
|
@ -899,30 +899,6 @@ 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.
|
* Adds map indicators to the smallmap.
|
||||||
*/
|
*/
|
||||||
|
@ -931,15 +907,13 @@ void SmallMapWindow::DrawMapIndicators() const
|
||||||
/* Find main viewport. */
|
/* Find main viewport. */
|
||||||
const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
|
const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
|
||||||
|
|
||||||
Point upper_left_viewport_coord = {vp->virtual_left, vp->virtual_top};
|
Point upper_left_smallmap_coord = TranslateXYToTileCoord(vp, vp->left, vp->top, false);
|
||||||
Point upper_left_small_map_coord = GetSmallMapCoordIncludingHeight(upper_left_viewport_coord);
|
Point lower_right_smallmap_coord = TranslateXYToTileCoord(vp, vp->left + vp->width - 1, vp->top + vp->height - 1, false);
|
||||||
Point upper_left = this->RemapTile(upper_left_small_map_coord.x, upper_left_small_map_coord.y);
|
|
||||||
|
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;
|
upper_left.x -= this->subscroll;
|
||||||
|
|
||||||
Point lower_right_viewport_coord = {vp->virtual_left + vp->virtual_width, vp->virtual_top + vp->virtual_height};
|
Point lower_right = this->RemapTile(lower_right_smallmap_coord.x / (int)TILE_SIZE, lower_right_smallmap_coord.y / (int)TILE_SIZE);
|
||||||
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;
|
lower_right.x -= this->subscroll;
|
||||||
|
|
||||||
SmallMapWindow::DrawVertMapIndicator(upper_left.x, upper_left.y, lower_right.y);
|
SmallMapWindow::DrawVertMapIndicator(upper_left.x, upper_left.y, lower_right.y);
|
||||||
|
@ -1662,19 +1636,12 @@ void SmallMapWindow::SetNewScroll(int sx, int sy, int sub)
|
||||||
*/
|
*/
|
||||||
void SmallMapWindow::SmallMapCenterOnCurrentPos()
|
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;
|
const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
|
||||||
Point viewport_center = {vp->virtual_left + vp->virtual_width / 2, vp->virtual_top + vp->virtual_height / 2};
|
Point viewport_center = TranslateXYToTileCoord(vp, vp->left + vp->width / 2, vp->top + vp->height / 2);
|
||||||
Point pt_with_height = GetSmallMapCoordIncludingHeight(viewport_center);
|
|
||||||
|
|
||||||
/* And finally scroll to that position. */
|
|
||||||
|
|
||||||
int sub;
|
int sub;
|
||||||
const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
|
const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
|
||||||
Point sxy = this->ComputeScroll(pt_with_height.x, pt_with_height.y,
|
Point sxy = this->ComputeScroll(viewport_center.x / (int)TILE_SIZE, viewport_center.y / (int)TILE_SIZE,
|
||||||
max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
|
max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
|
||||||
this->SetNewScroll(sxy.x, sxy.y, sub);
|
this->SetNewScroll(sxy.x, sxy.y, sub);
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
|
|
|
@ -157,7 +157,6 @@ protected:
|
||||||
void DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const;
|
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 DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const;
|
||||||
void DrawTowns(const DrawPixelInfo *dpi) const;
|
void DrawTowns(const DrawPixelInfo *dpi) const;
|
||||||
Point GetSmallMapCoordIncludingHeight(Point viewport_coord) const;
|
|
||||||
void DrawSmallMap(DrawPixelInfo *dpi) const;
|
void DrawSmallMap(DrawPixelInfo *dpi) const;
|
||||||
|
|
||||||
Point RemapTile(int tile_x, int tile_y) const;
|
Point RemapTile(int tile_x, int tile_y) const;
|
||||||
|
|
|
@ -405,9 +405,10 @@ ViewPort *IsPtInWindowViewport(const Window *w, int x, int y)
|
||||||
* @param vp Viewport that contains the (\a x, \a y) screen coordinate
|
* @param vp Viewport that contains the (\a x, \a y) screen coordinate
|
||||||
* @param x Screen x coordinate
|
* @param x Screen x coordinate
|
||||||
* @param y Screen y coordinate
|
* @param y Screen y coordinate
|
||||||
|
* @param clamp_to_map Clamp the coordinate outside of the map to the closest tile within the map.
|
||||||
* @return Tile coordinate
|
* @return Tile coordinate
|
||||||
*/
|
*/
|
||||||
static Point TranslateXYToTileCoord(const ViewPort *vp, int x, int y)
|
Point TranslateXYToTileCoord(const ViewPort *vp, int x, int y, bool clamp_to_map)
|
||||||
{
|
{
|
||||||
Point pt;
|
Point pt;
|
||||||
int a, b;
|
int a, b;
|
||||||
|
@ -425,13 +426,15 @@ static Point TranslateXYToTileCoord(const ViewPort *vp, int x, int y)
|
||||||
a = y - x;
|
a = y - x;
|
||||||
b = y + x;
|
b = y + x;
|
||||||
|
|
||||||
/* Bring the coordinates near to a valid range. This is mostly due to the
|
if (clamp_to_map) {
|
||||||
* tiles on the north side of the map possibly being drawn too high due to
|
/* Bring the coordinates near to a valid range. This is mostly due to the
|
||||||
* the extra height levels. So at the top we allow a number of extra tiles.
|
* tiles on the north side of the map possibly being drawn too high due to
|
||||||
* This number is based on the tile height and pixels. */
|
* the extra height levels. So at the top we allow a number of extra tiles.
|
||||||
int extra_tiles = CeilDiv(_settings_game.construction.max_heightlevel * TILE_HEIGHT, TILE_PIXELS);
|
* This number is based on the tile height and pixels. */
|
||||||
a = Clamp(a, -extra_tiles * TILE_SIZE, MapMaxX() * TILE_SIZE - 1);
|
int extra_tiles = CeilDiv(_settings_game.construction.max_heightlevel * TILE_HEIGHT, TILE_PIXELS);
|
||||||
b = Clamp(b, -extra_tiles * TILE_SIZE, MapMaxY() * TILE_SIZE - 1);
|
a = Clamp(a, -extra_tiles * TILE_SIZE, MapMaxX() * TILE_SIZE - 1);
|
||||||
|
b = Clamp(b, -extra_tiles * TILE_SIZE, MapMaxY() * TILE_SIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* (a, b) is the X/Y-world coordinate that belongs to (x,y) if the landscape would be completely flat on height 0.
|
/* (a, b) is the X/Y-world coordinate that belongs to (x,y) if the landscape would be completely flat on height 0.
|
||||||
* Now find the Z-world coordinate by fix point iteration.
|
* Now find the Z-world coordinate by fix point iteration.
|
||||||
|
@ -448,8 +451,13 @@ static Point TranslateXYToTileCoord(const ViewPort *vp, int x, int y)
|
||||||
for (int malus = 3; malus > 0; malus--) z = GetSlopePixelZ(Clamp(a + max(z, malus) - malus, min_coord, MapMaxX() * TILE_SIZE - 1), Clamp(b + max(z, malus) - malus, min_coord, MapMaxY() * TILE_SIZE - 1)) / 2;
|
for (int malus = 3; malus > 0; malus--) z = GetSlopePixelZ(Clamp(a + max(z, malus) - malus, min_coord, MapMaxX() * TILE_SIZE - 1), Clamp(b + max(z, malus) - malus, min_coord, MapMaxY() * TILE_SIZE - 1)) / 2;
|
||||||
for (int i = 0; i < 5; i++) z = GetSlopePixelZ(Clamp(a + z, min_coord, MapMaxX() * TILE_SIZE - 1), Clamp(b + z, min_coord, MapMaxY() * TILE_SIZE - 1)) / 2;
|
for (int i = 0; i < 5; i++) z = GetSlopePixelZ(Clamp(a + z, min_coord, MapMaxX() * TILE_SIZE - 1), Clamp(b + z, min_coord, MapMaxY() * TILE_SIZE - 1)) / 2;
|
||||||
|
|
||||||
pt.x = Clamp(a + z, min_coord, MapMaxX() * TILE_SIZE - 1);
|
if (clamp_to_map) {
|
||||||
pt.y = Clamp(b + z, min_coord, MapMaxY() * TILE_SIZE - 1);
|
pt.x = Clamp(a + z, min_coord, MapMaxX() * TILE_SIZE - 1);
|
||||||
|
pt.y = Clamp(b + z, min_coord, MapMaxY() * TILE_SIZE - 1);
|
||||||
|
} else {
|
||||||
|
pt.x = a + z;
|
||||||
|
pt.y = b + z;
|
||||||
|
}
|
||||||
|
|
||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ void SetSelectionRed(bool);
|
||||||
void DeleteWindowViewport(Window *w);
|
void DeleteWindowViewport(Window *w);
|
||||||
void InitializeWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom);
|
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);
|
ViewPort *IsPtInWindowViewport(const Window *w, int x, int y);
|
||||||
|
Point TranslateXYToTileCoord(const ViewPort *vp, int x, int y, bool clamp_to_map = true);
|
||||||
Point GetTileBelowCursor();
|
Point GetTileBelowCursor();
|
||||||
void UpdateViewportPosition(Window *w);
|
void UpdateViewportPosition(Window *w);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue