Changeset - r7912:aac2d19fbcb0
[Not reviewed]
master
0 1 0
smatz - 17 years ago 2007-11-18 20:05:44
smatz@openttd.org
(svn r11465) -Fix: more user-friedly placement in X and Y directions (most noticeable with autoroad)
1 file changed with 14 insertions and 2 deletions:
0 comments (0 inline, 0 general)
src/viewport.cpp
Show inline comments
 
@@ -2196,160 +2196,171 @@ void SetRedErrorSquare(TileIndex tile)
 

	
 
	if (tile != old) {
 
		if (tile != 0) MarkTileDirtyByTile(tile);
 
		if (old  != 0) MarkTileDirtyByTile(old);
 
	}
 
}
 

	
 
void SetTileSelectSize(int w, int h)
 
{
 
	_thd.new_size.x = w * TILE_SIZE;
 
	_thd.new_size.y = h * TILE_SIZE;
 
	_thd.new_outersize.x = 0;
 
	_thd.new_outersize.y = 0;
 
}
 

	
 
void SetTileSelectBigSize(int ox, int oy, int sx, int sy)
 
{
 
	_thd.offs.x = ox * TILE_SIZE;
 
	_thd.offs.y = oy * TILE_SIZE;
 
	_thd.new_outersize.x = sx * TILE_SIZE;
 
	_thd.new_outersize.y = sy * TILE_SIZE;
 
}
 

	
 
/** returns the best autorail highlight type from map coordinates */
 
static byte GetAutorailHT(int x, int y)
 
{
 
	return HT_RAIL | _AutorailPiece[x & 0xF][y & 0xF];
 
}
 

	
 
/**
 
 * Updates tile highlighting for all cases.
 
 * Uses _thd.selstart and _thd.selend and _thd.place_mode (set elsewhere) to determine _thd.pos and _thd.size
 
 * Also drawstyle is determined. Uses _thd.new.* as a buffer and calls SetSelectionTilesDirty() twice,
 
 * Once for the old and once for the new selection.
 
 * _thd is TileHighlightData, found in viewport.h
 
 * Called by MouseLoop() in windows.cpp
 
 */
 
void UpdateTileSelection()
 
{
 
	int x1;
 
	int y1;
 

	
 
	_thd.new_drawstyle = 0;
 

	
 
	if (_thd.place_mode == VHM_SPECIAL) {
 
		x1 = _thd.selend.x;
 
		y1 = _thd.selend.y;
 
		if (x1 != -1) {
 
			int x2 = _thd.selstart.x;
 
			int y2 = _thd.selstart.y;
 
			int x2 = _thd.selstart.x & ~0xF;
 
			int y2 = _thd.selstart.y & ~0xF;
 
			x1 &= ~0xF;
 
			y1 &= ~0xF;
 

	
 
			if (x1 >= x2) Swap(x1, x2);
 
			if (y1 >= y2) Swap(y1, y2);
 
			_thd.new_pos.x = x1;
 
			_thd.new_pos.y = y1;
 
			_thd.new_size.x = x2 - x1 + TILE_SIZE;
 
			_thd.new_size.y = y2 - y1 + TILE_SIZE;
 
			_thd.new_drawstyle = _thd.next_drawstyle;
 
		}
 
	} else if (_thd.place_mode != VHM_NONE) {
 
		Point pt = GetTileBelowCursor();
 
		x1 = pt.x;
 
		y1 = pt.y;
 
		if (x1 != -1) {
 
			switch (_thd.place_mode) {
 
				case VHM_RECT:
 
					_thd.new_drawstyle = HT_RECT;
 
					break;
 
				case VHM_POINT:
 
					_thd.new_drawstyle = HT_POINT;
 
					x1 += 8;
 
					y1 += 8;
 
					break;
 
				case VHM_RAIL:
 
					_thd.new_drawstyle = GetAutorailHT(pt.x, pt.y); // draw one highlighted tile
 
			}
 
			_thd.new_pos.x = x1 & ~0xF;
 
			_thd.new_pos.y = y1 & ~0xF;
 
		}
 
	}
 

	
 
	/* redraw selection */
 
	if (_thd.drawstyle != _thd.new_drawstyle ||
 
			_thd.pos.x != _thd.new_pos.x || _thd.pos.y != _thd.new_pos.y ||
 
			_thd.size.x != _thd.new_size.x || _thd.size.y != _thd.new_size.y ||
 
			_thd.outersize.x != _thd.new_outersize.x ||
 
			_thd.outersize.y != _thd.new_outersize.y) {
 
		/* clear the old selection? */
 
		if (_thd.drawstyle) SetSelectionTilesDirty();
 

	
 
		_thd.drawstyle = _thd.new_drawstyle;
 
		_thd.pos = _thd.new_pos;
 
		_thd.size = _thd.new_size;
 
		_thd.outersize = _thd.new_outersize;
 
		_thd.dirty = 0xff;
 

	
 
		/* draw the new selection? */
 
		if (_thd.new_drawstyle) SetSelectionTilesDirty();
 
	}
 
}
 

	
 
/** highlighting tiles while only going over them with the mouse */
 
void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, byte process)
 
{
 
	_thd.select_method = method;
 
	_thd.select_proc   = process;
 
	_thd.selend.x = TileX(tile) * TILE_SIZE;
 
	_thd.selstart.x = TileX(tile) * TILE_SIZE;
 
	_thd.selend.y = TileY(tile) * TILE_SIZE;
 
	_thd.selstart.y = TileY(tile) * TILE_SIZE;
 

	
 
	/* Needed so several things (road, autoroad, bridges, ...) are placed correctly.
 
	 * In effect, placement starts from the centre of a tile
 
	 */
 
	if (method == VPM_X_OR_Y || method == VPM_FIX_X || method == VPM_FIX_Y) {
 
		_thd.selend.x += TILE_SIZE / 2;
 
		_thd.selend.y += TILE_SIZE / 2;
 
		_thd.selstart.x += TILE_SIZE / 2;
 
		_thd.selstart.y += TILE_SIZE / 2;
 
	}
 

	
 
	if (_thd.place_mode == VHM_RECT) {
 
		_thd.place_mode = VHM_SPECIAL;
 
		_thd.next_drawstyle = HT_RECT;
 
	} else if (_thd.place_mode == VHM_RAIL) { // autorail one piece
 
		_thd.place_mode = VHM_SPECIAL;
 
		_thd.next_drawstyle = _thd.drawstyle;
 
	} else {
 
		_thd.place_mode = VHM_SPECIAL;
 
		_thd.next_drawstyle = HT_POINT;
 
	}
 
	_special_mouse_mode = WSM_SIZING;
 
}
 

	
 
void VpSetPlaceSizingLimit(int limit)
 
{
 
	_thd.sizelimit = limit;
 
}
 

	
 
/**
 
* Highlights all tiles between a set of two tiles. Used in dock and tunnel placement
 
* @param from TileIndex of the first tile to highlight
 
* @param to TileIndex of the last tile to highlight */
 
void VpSetPresizeRange(TileIndex from, TileIndex to)
 
{
 
	uint64 distance = DistanceManhattan(from, to) + 1;
 

	
 
	_thd.selend.x = TileX(to) * TILE_SIZE;
 
	_thd.selend.y = TileY(to) * TILE_SIZE;
 
	_thd.selstart.x = TileX(from) * TILE_SIZE;
 
	_thd.selstart.y = TileY(from) * TILE_SIZE;
 
	_thd.next_drawstyle = HT_RECT;
 

	
 
	/* show measurement only if there is any length to speak of */
 
	if (distance > 1) GuiShowTooltipsWithArgs(STR_MEASURE_LENGTH, 1, &distance);
 
}
 

	
 
static void VpStartPreSizing()
 
{
 
	_thd.selend.x = -1;
 
	_special_mouse_mode = WSM_PRESIZE;
 
}
 

	
 
/** returns information about the 2x1 piece to be build.
 
 * The lower bits (0-3) are the track type. */
 
static byte Check2x1AutoRail(int mode)
 
{
 
	int fxpy = _tile_fract_coords.x + _tile_fract_coords.y;
 
	int sxpy = (_thd.selend.x & 0xF) + (_thd.selend.y & 0xF);
 
@@ -2607,96 +2618,97 @@ static void CalcRaildirsDrawstyle(TileHi
 
		byte index = 0;
 
		uint64 params[2];
 

	
 
		if (distance != 1) {
 
			int heightdiff = CalcHeightdiff(b, distance, t0, t1);
 
			/* If we are showing a tooltip for horizontal or vertical drags,
 
			 * 2 tiles have a length of 1. To bias towards the ceiling we add
 
			 * one before division. It feels more natural to count 3 lengths as 2 */
 
			if ((b & HT_DIR_MASK) != HT_DIR_X && (b & HT_DIR_MASK) != HT_DIR_Y) {
 
				distance = (distance + 1) / 2;
 
			}
 

	
 
			params[index++] = distance;
 
			if (heightdiff != 0) params[index++] = heightdiff;
 
		}
 

	
 
		GuiShowTooltipsWithArgs(measure_strings_length[index], index, params);
 
	}
 

	
 
	thd->selend.x = x;
 
	thd->selend.y = y;
 
	thd->next_drawstyle = b;
 
}
 

	
 
/**
 
 * Selects tiles while dragging
 
 * @param x X coordinate of end of selection
 
 * @param y Y coordinate of end of selection
 
 * @param method modifies the way tiles are selected. Possible
 
 * methods are VPM_* in viewport.h */
 
void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method)
 
{
 
	int sx, sy;
 
	HighLightStyle style;
 

	
 
	if (x == -1) {
 
		_thd.selend.x = -1;
 
		return;
 
	}
 

	
 
	/* Special handling of drag in any (8-way) direction */
 
	if (method == VPM_RAILDIRS || method == VPM_SIGNALDIRS) {
 
		_thd.selend.x = x;
 
		_thd.selend.y = y;
 
		CalcRaildirsDrawstyle(&_thd, x, y, method);
 
		return;
 
	}
 

	
 
	/* Needed so level-land is placed correctly */
 
	if (_thd.next_drawstyle == HT_POINT) {
 
		x += TILE_SIZE / 2;
 
		y += TILE_SIZE / 2;
 
	}
 

	
 
	sx = _thd.selstart.x;
 
	sy = _thd.selstart.y;
 

	
 
	switch (method) {
 
		case VPM_X_OR_Y: /* drag in X or Y direction */
 
			if (myabs(sy - y) < myabs(sx - x)) {
 
				y = sy;
 
				style = HT_DIR_X;
 
			} else {
 
				x = sx;
 
				style = HT_DIR_Y;
 
			}
 
			goto calc_heightdiff_single_direction;
 
		case VPM_FIX_X: /* drag in Y direction */
 
			x = sx;
 
			style = HT_DIR_Y;
 
			goto calc_heightdiff_single_direction;
 
		case VPM_FIX_Y: /* drag in X direction */
 
			y = sy;
 
			style = HT_DIR_X;
 

	
 
calc_heightdiff_single_direction:;
 
			if (_patches.measure_tooltip) {
 
				TileIndex t0 = TileVirtXY(sx, sy);
 
				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
 
					 * difference is enough. However if/when a point-tool is created
 
					 * with this method, function should be called with new_style (below)
 
					 * instead of HT_LINE | style case HT_POINT is handled specially
 
					 * 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;
 
				}
 

	
 
				GuiShowTooltipsWithArgs(measure_strings_length[index], index, params);
 
			} break;
0 comments (0 inline, 0 general)