Changeset - r11704:8083118c4aa4
[Not reviewed]
master
0 3 0
rubidium - 15 years ago 2009-04-19 21:26:06
rubidium@openttd.org
(svn r16095) -Change/Feature-ish: make the first 4 rail building tools behave more like autorail
3 files changed with 173 insertions and 39 deletions:
0 comments (0 inline, 0 general)
src/rail_gui.cpp
Show inline comments
 
@@ -76,29 +76,27 @@ static void GenericPlaceRail(TileIndex t
 

	
 
static void PlaceRail_N(TileIndex tile)
 
{
 
	int cmd = _tile_fract_coords.x > _tile_fract_coords.y ? 4 : 5;
 
	GenericPlaceRail(tile, cmd);
 
	VpStartPlaceSizing(tile, VPM_FIX_VERTICAL | VPM_RAILDIRS, DDSP_PLACE_RAIL);
 
}
 

	
 
static void PlaceRail_NE(TileIndex tile)
 
{
 
	VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_RAIL_NE);
 
	VpStartPlaceSizing(tile, VPM_FIX_Y | VPM_RAILDIRS, DDSP_PLACE_RAIL);
 
}
 

	
 
static void PlaceRail_E(TileIndex tile)
 
{
 
	int cmd = _tile_fract_coords.x + _tile_fract_coords.y <= 15 ? 2 : 3;
 
	GenericPlaceRail(tile, cmd);
 
	VpStartPlaceSizing(tile, VPM_FIX_HORIZONTAL | VPM_RAILDIRS, DDSP_PLACE_RAIL);
 
}
 

	
 
static void PlaceRail_NW(TileIndex tile)
 
{
 
	VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_RAIL_NW);
 
	VpStartPlaceSizing(tile, VPM_FIX_X | VPM_RAILDIRS, DDSP_PLACE_RAIL);
 
}
 

	
 
static void PlaceRail_AutoRail(TileIndex tile)
 
{
 
	VpStartPlaceSizing(tile, VPM_RAILDIRS, DDSP_PLACE_AUTORAIL);
 
	VpStartPlaceSizing(tile, VPM_RAILDIRS, DDSP_PLACE_RAIL);
 
}
 

	
 
/**
 
@@ -332,7 +330,7 @@ static bool RailToolbar_CtrlChanged(Wind
 
 */
 
static void BuildRailClick_N(Window *w)
 
{
 
	HandlePlacePushButton(w, RTW_BUILD_NS, GetRailTypeInfo(_cur_railtype)->cursor.rail_ns, HT_RECT, PlaceRail_N);
 
	HandlePlacePushButton(w, RTW_BUILD_NS, GetRailTypeInfo(_cur_railtype)->cursor.rail_ns, HT_LINE | HT_DIR_VL, PlaceRail_N);
 
}
 

	
 
/**
 
@@ -342,7 +340,7 @@ static void BuildRailClick_N(Window *w)
 
 */
 
static void BuildRailClick_NE(Window *w)
 
{
 
	HandlePlacePushButton(w, RTW_BUILD_X, GetRailTypeInfo(_cur_railtype)->cursor.rail_swne, HT_RECT, PlaceRail_NE);
 
	HandlePlacePushButton(w, RTW_BUILD_X, GetRailTypeInfo(_cur_railtype)->cursor.rail_swne, HT_LINE | HT_DIR_X, PlaceRail_NE);
 
}
 

	
 
/**
 
@@ -352,7 +350,7 @@ static void BuildRailClick_NE(Window *w)
 
 */
 
static void BuildRailClick_E(Window *w)
 
{
 
	HandlePlacePushButton(w, RTW_BUILD_EW, GetRailTypeInfo(_cur_railtype)->cursor.rail_ew, HT_RECT, PlaceRail_E);
 
	HandlePlacePushButton(w, RTW_BUILD_EW, GetRailTypeInfo(_cur_railtype)->cursor.rail_ew, HT_LINE | HT_DIR_HL, PlaceRail_E);
 
}
 

	
 
/**
 
@@ -362,7 +360,7 @@ static void BuildRailClick_E(Window *w)
 
 */
 
static void BuildRailClick_NW(Window *w)
 
{
 
	HandlePlacePushButton(w, RTW_BUILD_Y, GetRailTypeInfo(_cur_railtype)->cursor.rail_nwse, HT_RECT, PlaceRail_NW);
 
	HandlePlacePushButton(w, RTW_BUILD_Y, GetRailTypeInfo(_cur_railtype)->cursor.rail_nwse, HT_LINE | HT_DIR_Y, PlaceRail_NW);
 
}
 

	
 
/**
 
@@ -704,7 +702,7 @@ struct BuildRailToolbarWindow : Window {
 
					ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype);
 
					break;
 

	
 
				case DDSP_PLACE_AUTORAIL:
 
				case DDSP_PLACE_RAIL:
 
					HandleAutodirPlacement();
 
					break;
 

	
 
@@ -728,11 +726,6 @@ struct BuildRailToolbarWindow : Window {
 
					}
 
					HandleStationPlacement(start_tile, end_tile);
 
					break;
 

	
 
				case DDSP_PLACE_RAIL_NE:
 
				case DDSP_PLACE_RAIL_NW:
 
					DoRailroadTrack(select_proc == DDSP_PLACE_RAIL_NE ? TRACK_X : TRACK_Y);
 
					break;
 
			}
 
		}
 
	}
src/viewport.cpp
Show inline comments
 
@@ -900,7 +900,7 @@ static void DrawTileSelection(const Tile
 
				}
 
			}
 
			DrawSelectionSprite(_cur_dpi->zoom <= ZOOM_LVL_DETAIL ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti, z, foundation_part);
 
		} else if (_thd.drawstyle & HT_RAIL /* && _thd.place_mode == VHM_RAIL*/) {
 
		} else if (_thd.drawstyle & HT_RAIL) {
 
			/* autorail highlight piece under cursor */
 
			HighLightStyle type = _thd.drawstyle & HT_DIR_MASK;
 
			assert(type < HT_DIR_END);
 
@@ -2171,7 +2171,7 @@ void UpdateTileSelection()
 
		x1 = pt.x;
 
		y1 = pt.y;
 
		if (x1 != -1) {
 
			switch (_thd.place_mode) {
 
			switch (_thd.place_mode & HT_DRAG_MASK) {
 
				case HT_RECT:
 
					_thd.new_drawstyle = HT_RECT;
 
					break;
 
@@ -2181,7 +2181,28 @@ void UpdateTileSelection()
 
					y1 += TILE_SIZE / 2;
 
					break;
 
				case HT_RAIL:
 
					_thd.new_drawstyle = GetAutorailHT(pt.x, pt.y); // draw one highlighted tile
 
					/* Draw one highlighted tile in any direction */
 
					_thd.new_drawstyle = GetAutorailHT(pt.x, pt.y);
 
					break;
 
				case HT_LINE:
 
					switch (_thd.place_mode & HT_DIR_MASK) {
 
						case HT_DIR_X: _thd.new_drawstyle = HT_LINE | HT_DIR_X; break;
 
						case HT_DIR_Y: _thd.new_drawstyle = HT_LINE | HT_DIR_Y; break;
 

	
 
						case HT_DIR_HU:
 
						case HT_DIR_HL:
 
							_thd.new_drawstyle = (pt.x & TILE_UNIT_MASK) + (pt.y & TILE_UNIT_MASK) <= TILE_SIZE ? HT_LINE | HT_DIR_HU : HT_LINE | HT_DIR_HL;
 
							break;
 

	
 
						case HT_DIR_VL:
 
						case HT_DIR_VR:
 
							_thd.new_drawstyle = (pt.x & TILE_UNIT_MASK) > (pt.y & TILE_UNIT_MASK) ? HT_LINE | HT_DIR_VL : HT_LINE | HT_DIR_VR;
 
							break;
 

	
 
						default: NOT_REACHED();
 
					}
 
					_thd.selstart.x = x1 & ~TILE_UNIT_MASK;
 
					_thd.selstart.y = y1 & ~TILE_UNIT_MASK;
 
					break;
 
				default:
 
					NOT_REACHED();
 
@@ -2246,7 +2267,10 @@ void VpStartPlaceSizing(TileIndex tile, 
 
	if (_thd.place_mode == HT_RECT) {
 
		_thd.place_mode = HT_SPECIAL;
 
		_thd.next_drawstyle = HT_RECT;
 
	} else if (_thd.place_mode == HT_RAIL) { // autorail one piece
 
	} else if (_thd.place_mode & HT_RAIL) {
 
		_thd.place_mode = HT_SPECIAL;
 
		_thd.next_drawstyle = HT_RAIL;
 
	} else if (_thd.place_mode & HT_LINE) {
 
		_thd.place_mode = HT_SPECIAL;
 
		_thd.next_drawstyle = _thd.drawstyle;
 
	} else {
 
@@ -2436,6 +2460,35 @@ static int CalcHeightdiff(HighLightStyle
 

	
 
static const StringID measure_strings_length[] = {STR_NULL, STR_MEASURE_LENGTH, STR_MEASURE_LENGTH_HEIGHTDIFF};
 

	
 
/**
 
 * Check for underflowing the map.
 
 * @param test  the variable to test for underflowing
 
 * @param other the other variable to update to keep the line
 
 * @param mult  the constant to multiply the difference by for \c other
 
 */
 
static void CheckUnderflow(int &test, int &other, int mult)
 
{
 
	if (test >= 0) return;
 

	
 
	other += mult * test;
 
	test = 0;
 
}
 

	
 
/**
 
 * Check for overflowing the map.
 
 * @param test  the variable to test for overflowing
 
 * @param other the other variable to update to keep the line
 
 * @param max   the maximum value for the \c test variable
 
 * @param mult  the constant to multiply the difference by for \c other
 
 */
 
static void CheckOverflow(int &test, int &other, int max, int mult)
 
{
 
	if (test <= max) return;
 

	
 
	other += mult * (test - max);
 
	test = max;
 
}
 

	
 
/** while dragging */
 
static void CalcRaildirsDrawstyle(TileHighlightData *thd, int x, int y, int method)
 
{
 
@@ -2446,8 +2499,97 @@ static void CalcRaildirsDrawstyle(TileHi
 
	uint w = abs(dx) + TILE_SIZE;
 
	uint h = abs(dy) + TILE_SIZE;
 

	
 
	if (TileVirtXY(thd->selstart.x, thd->selstart.y) == TileVirtXY(x, y)) { // check if we're only within one tile
 
		if (method == VPM_RAILDIRS) {
 
	if (method & ~(VPM_RAILDIRS | VPM_SIGNALDIRS)) {
 
		/* We 'force' a selection direction; first four rail buttons. */
 
		method &= ~(VPM_RAILDIRS | VPM_SIGNALDIRS);
 
		int raw_dx = thd->selstart.x - thd->selend.x;
 
		int raw_dy = thd->selstart.y - thd->selend.y;
 
		switch (method) {
 
			case VPM_FIX_X:
 
				b = HT_LINE | HT_DIR_Y;
 
				x = thd->selstart.x;
 
				break;
 

	
 
			case VPM_FIX_Y:
 
				b = HT_LINE | HT_DIR_X;
 
				y = thd->selstart.y;
 
				break;
 

	
 
			case VPM_FIX_HORIZONTAL:
 
				if (dx == -dy) {
 
					/* We are on a straight horizontal line. Determine the 'rail'
 
					 * to build based the sub tile location. */
 
					b = (x & TILE_UNIT_MASK) + (y & TILE_UNIT_MASK) >= TILE_SIZE ? HT_LINE | HT_DIR_HL : HT_LINE | HT_DIR_HU;
 
				} else {
 
					/* We are not on a straight line. Determine the rail to build
 
					 * based on whether we are above or below it. */
 
					b = dx + dy >= TILE_SIZE ? HT_LINE | HT_DIR_HU : HT_LINE | HT_DIR_HL;
 

	
 
					/* Calculate where a horizontal line through the start point and
 
					 * a vertical line from the selected end point intersect and
 
					 * use that point as the end point. */
 
					int offset = (raw_dx - raw_dy) / 2;
 
					x = thd->selstart.x - (offset & ~TILE_UNIT_MASK);
 
					y = thd->selstart.y + (offset & ~TILE_UNIT_MASK);
 

	
 
					/* 'Build' the last half rail tile if needed */
 
					if ((offset & TILE_UNIT_MASK) > (TILE_SIZE / 2)) {
 
						if (dx + dy >= TILE_SIZE) {
 
							x += (dx + dy < 0) ? TILE_SIZE : -TILE_SIZE;
 
						} else {
 
							y += (dx + dy < 0) ? TILE_SIZE : -TILE_SIZE;
 
						}
 
					}
 

	
 
					/* Make sure we do not overflow the map! */
 
					CheckUnderflow(x, y, 1);
 
					CheckUnderflow(y, x, 1);
 
					CheckOverflow(x, y, (MapMaxX() - 1) * TILE_SIZE, 1);
 
					CheckOverflow(y, x, (MapMaxY() - 1) * TILE_SIZE, 1);
 
					assert(x >= 0 && y >= 0 && x <= (int)MapMaxX() * TILE_SIZE && y <= (int)MapMaxY() * TILE_SIZE);
 
				}
 
				break;
 

	
 
			case VPM_FIX_VERTICAL:
 
				if (dx == dy) {
 
					/* We are on a straight vertical line. Determine the 'rail'
 
					 * to build based the sub tile location. */
 
					b = (x & TILE_UNIT_MASK) > (y & TILE_UNIT_MASK) ? HT_LINE | HT_DIR_VL : HT_LINE | HT_DIR_VR;
 
				} else {
 
					/* We are not on a straight line. Determine the rail to build
 
					 * based on whether we are left or right from it. */
 
					b = dx < dy ? HT_LINE | HT_DIR_VL : HT_LINE | HT_DIR_VR;
 

	
 
					/* Calculate where a vertical line through the start point and
 
					 * a horizontal line from the selected end point intersect and
 
					 * use that point as the end point. */
 
					int offset = (raw_dx + raw_dy + TILE_SIZE) / 2;
 
					x = thd->selstart.x - (offset & ~TILE_UNIT_MASK);
 
					y = thd->selstart.y - (offset & ~TILE_UNIT_MASK);
 

	
 
					/* 'Build' the last half rail tile if needed */
 
					if ((offset & TILE_UNIT_MASK) > (TILE_SIZE / 2)) {
 
						if (dx - dy < 0) {
 
							y += (dx > dy) ? TILE_SIZE : -TILE_SIZE;
 
						} else {
 
							x += (dx < dy) ? TILE_SIZE : -TILE_SIZE;
 
						}
 
					}
 

	
 
					/* Make sure we do not overflow the map! */
 
					CheckUnderflow(x, y, -1);
 
					CheckUnderflow(y, x, -1);
 
					CheckOverflow(x, y, (MapMaxX() - 1) * TILE_SIZE, -1);
 
					CheckOverflow(y, x, (MapMaxY() - 1) * TILE_SIZE, -1);
 
					assert(x >= 0 && y >= 0 && x <= (int)MapMaxX() * TILE_SIZE && y <= (int)MapMaxY() * TILE_SIZE);
 
				}
 
				break;
 

	
 
			default:
 
				NOT_REACHED();
 
		}
 
	} else if (TileVirtXY(thd->selstart.x, thd->selstart.y) == TileVirtXY(x, y)) { // check if we're only within one tile
 
		if (method & VPM_RAILDIRS) {
 
			b = GetAutorailHT(x, y);
 
		} else { // rect for autosignals on one tile
 
			b = HT_RECT;
 
@@ -2578,7 +2720,7 @@ void VpSelectTilesWithMethod(int x, int 
 
	}
 

	
 
	/* Special handling of drag in any (8-way) direction */
 
	if (method == VPM_RAILDIRS || method == VPM_SIGNALDIRS) {
 
	if (method & (VPM_RAILDIRS | VPM_SIGNALDIRS)) {
 
		_thd.selend.x = x;
 
		_thd.selend.y = y;
 
		CalcRaildirsDrawstyle(&_thd, x, y, method);
 
@@ -2710,12 +2852,10 @@ bool VpHandlePlaceSizingDrag()
 
	_special_mouse_mode = WSM_NONE;
 
	if (_thd.next_drawstyle == HT_RECT) {
 
		_thd.place_mode = HT_RECT;
 
	} else if (_thd.select_method == VPM_SIGNALDIRS) { // some might call this a hack... -- Dominik
 
	} else if (_thd.select_method & VPM_SIGNALDIRS) {
 
		_thd.place_mode = HT_RECT;
 
	} else if (_thd.next_drawstyle & HT_LINE) {
 
		_thd.place_mode = HT_RAIL;
 
	} else if (_thd.next_drawstyle & HT_RAIL) {
 
		_thd.place_mode = HT_RAIL;
 
	} else if (_thd.select_method & VPM_RAILDIRS) {
 
		_thd.place_mode = (_thd.select_method & ~VPM_RAILDIRS) ? _thd.next_drawstyle : HT_RAIL;
 
	} else {
 
		_thd.place_mode = HT_POINT;
 
	}
src/viewport_type.h
Show inline comments
 
@@ -49,14 +49,17 @@ enum {
 

	
 
/** Viewport place method (type of highlighted area and placed objects) */
 
enum ViewportPlaceMethod {
 
	VPM_X_OR_Y          = 0, ///< drag in X or Y direction
 
	VPM_FIX_X           = 1, ///< drag only in X axis
 
	VPM_FIX_Y           = 2, ///< drag only in Y axis
 
	VPM_RAILDIRS        = 3, ///< all rail directions
 
	VPM_X_AND_Y         = 4, ///< area of land in X and Y directions
 
	VPM_X_AND_Y_LIMITED = 5, ///< area of land of limited size
 
	VPM_SIGNALDIRS      = 6, ///< similiar to VMP_RAILDIRS, but with different cursor
 
	VPM_X_OR_Y          =    0, ///< drag in X or Y direction
 
	VPM_FIX_X           =    1, ///< drag only in X axis
 
	VPM_FIX_Y           =    2, ///< drag only in Y axis
 
	VPM_X_AND_Y         =    3, ///< area of land in X and Y directions
 
	VPM_X_AND_Y_LIMITED =    4, ///< area of land of limited size
 
	VPM_FIX_HORIZONTAL  =    5, ///< drag only in horizontal direction
 
	VPM_FIX_VERTICAL    =    6, ///< drag only in vertical direction
 
	VPM_RAILDIRS        = 0x40, ///< all rail directions
 
	VPM_SIGNALDIRS      = 0x80, ///< similiar to VMP_RAILDIRS, but with different cursor
 
};
 
DECLARE_ENUM_AS_BIT_SET(ViewportPlaceMethod);
 

	
 
/** Drag and drop selection process, or, what to do with an area of land when
 
 * you've selected it. */
 
@@ -73,9 +76,7 @@ enum ViewportDragDropSelectionProcess {
 
	DDSP_BUILD_BRIDGE,
 

	
 
	/* Rail specific actions */
 
	DDSP_PLACE_RAIL_NE,
 
	DDSP_PLACE_RAIL_NW,
 
	DDSP_PLACE_AUTORAIL,
 
	DDSP_PLACE_RAIL,
 
	DDSP_BUILD_SIGNALS,
 
	DDSP_BUILD_STATION,
 
	DDSP_REMOVE_STATION,
0 comments (0 inline, 0 general)