changeset 14472:22e7dc22c3bd draft

(svn r19041) -Codechange: Improve selection of tile to draw in zoomed-out smallmaps.
author alberth <alberth@openttd.org>
date Sat, 06 Feb 2010 13:19:46 +0000
parents f3cfcaa79037
children 4387f17e9ff1
files src/smallmap_gui.cpp src/tilearea.cpp src/tilearea_type.h
diffstat 3 files changed, 70 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/smallmap_gui.cpp
+++ b/src/smallmap_gui.cpp
@@ -256,6 +256,22 @@
 
 typedef uint32 GetSmallMapPixels(TileIndex tile); ///< Typedef callthrough function
 
+/** Mapping of tile type to importance of the tile (higher number means more interesting to show). */
+static const byte _tiletype_importance[] = {
+	2, // MP_CLEAR
+	8, // MP_RAILWAY
+	7, // MP_ROAD
+	5, // MP_HOUSE
+	2, // MP_TREES
+	9, // MP_STATION
+	2, // MP_WATER
+	1, // MP_VOID
+	6, // MP_INDUSTRY
+	8, // MP_TUNNELBRIDGE
+	2, // MP_UNMOVABLE
+	0,
+};
+
 
 static inline TileType GetEffectiveTileType(TileIndex tile)
 {
@@ -564,6 +580,26 @@
 	}
 
 	/**
+	 * Decide which tile to show to the user from a group of tiles.
+	 * @param ta Tile area to investigate.
+	 * @return Most interesting tile. May be #INVALID_TILE if off-map.
+	 */
+	inline TileIndex GetMostImportantTileFromGroup(const TileArea &ta) const
+	{
+		int importance = 0;
+		TileIndex tile = INVALID_TILE;
+
+		TILE_AREA_LOOP(ti, ta) {
+			TileType ttype = GetEffectiveTileType(ti);
+			if (_tiletype_importance[ttype] > importance) {
+				importance = _tiletype_importance[ttype];
+				tile = ti;
+			}
+		}
+		return tile;
+	}
+
+	/**
 	 * Draws one column of tiles of the small map in a certain mode onto the screen buffer, skipping the shifted rows in between.
 	 *
 	 * @param dst Pointer to a part of the screen buffer to write to.
@@ -585,18 +621,29 @@
 
 		do {
 			/* Check if the tile (xc,yc) is within the map range */
-			if (IsInsideMM(xc, min_xy, MapMaxX()) && IsInsideMM(yc, min_xy, MapMaxY())) {
-				/* Check if the dst pointer points to a pixel inside the screen buffer */
-				if (dst < _screen.dst_ptr) continue;
-				if (dst >= dst_ptr_abs_end) continue;
+			if (xc >= MapMaxX() || yc >= MapMaxY()) continue;
+
+			/* Check if the dst pointer points to a pixel inside the screen buffer */
+			if (dst < _screen.dst_ptr) continue;
+			if (dst >= dst_ptr_abs_end) continue;
+
+			/* 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.
 
-				uint32 val = proc(TileXY(xc, yc));
-				uint8 *val8 = (uint8 *)&val;
-				int idx = max(0, -start_pos);
-				for (int pos = max(0, start_pos); pos < end_pos; pos++) {
-					blitter->SetPixel(dst, idx, 0, val8[idx]);
-					idx++;
-				}
+				ta = TileArea(TileXY(max(min_xy, xc), max(min_xy, yc)), this->zoom - (xc == 0), this->zoom - (yc == 0));
+			} else {
+				ta = TileArea(TileXY(xc, yc), this->zoom, this->zoom);
+			}
+			ta.ClampToMap(); // Clamp to map boundaries (may contain MP_VOID tiles!).
+
+			uint32 val = proc(this->GetMostImportantTileFromGroup(ta));
+			uint8 *val8 = (uint8 *)&val;
+			int idx = max(0, -start_pos);
+			for (int pos = max(0, start_pos); pos < end_pos; pos++) {
+				blitter->SetPixel(dst, idx, 0, val8[idx]);
+				idx++;
 			}
 		/* Switch to next tile in the column */
 		} while (xc += this->zoom, yc += this->zoom, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
--- a/src/tilearea.cpp
+++ b/src/tilearea.cpp
@@ -95,3 +95,13 @@
 		);
 }
 
+/**
+ * Clamp the tile area to map borders.
+ */
+void TileArea::ClampToMap()
+{
+	assert(this->tile < MapSize());
+	this->w = min(this->w, MapSizeX() - TileX(this->tile));
+	this->h = min(this->h, MapSizeY() - TileY(this->tile));
+}
+
--- a/src/tilearea_type.h
+++ b/src/tilearea_type.h
@@ -47,6 +47,8 @@
 	}
 
 	bool Intersects(const TileArea &ta) const;
+
+	void ClampToMap();
 };
 
 #endif /* TILEAREA_TYPE_H */