(svn r1571) Feature: Visually enhanced autorail placing

When using the autorail tool, the rail pieces which are going to be build are highlighted.
If a piece is shown in red, this indicates that the slope/rail combination is impossible. It does not tell you if the rail line construction might not be possible because of other obstacles, e.g. houses or water.
This commit is contained in:
dominik 2005-01-19 20:55:23 +00:00
parent 28df4a0e25
commit aaf09ceb26
9 changed files with 359 additions and 105 deletions

BIN
data/autorail.grf Normal file

Binary file not shown.

Binary file not shown.

View File

@ -111,7 +111,19 @@ void HandleOnEditText(WindowEvent *e) {
}
}
// this code is shared for the majority of the pushbuttons
/**
* This code is shared for the majority of the pushbuttons.
* Handles e.g. the pressing of a button (to build things), playing of click sound and sets certain parameters
*
* @param w Window which called the function
* @param widget ID of the widget (=button) that called this function
* @param cursor How should the cursor image change? E.g. cursor with depot image in it
* @param mode Tile highlighting mode, e.g. drawing a rectangle or a dot on the ground
* @param placeproc Procedure which will be called when someone clicks on the map
* @return true if the button is clicked, false if it's unclicked
*/
bool HandlePlacePushButton(Window *w, int widget, uint32 cursor, int mode, PlaceProc *placeproc)
{
uint32 mask = 1 << widget;

View File

@ -232,7 +232,7 @@ static void BuildRailClick_NW(Window *w)
static void BuildRailClick_AutoRail(Window *w)
{
HandlePlacePushButton(w, 8, _cur_railtype + SPR_OPENTTD_BASE + 4, 1, PlaceRail_AutoRail);
HandlePlacePushButton(w, 8, _cur_railtype + SPR_CURSOR_AUTORAIL, VHM_RAIL, PlaceRail_AutoRail);
}
static void BuildRailClick_Demolish(Window *w)
@ -266,7 +266,7 @@ static void BuildRailClick_Station(Window *w)
static void BuildRailClick_AutoSignals(Window *w)
{
HandlePlacePushButton(w, 13, ANIMCURSOR_BUILDSIGNALS , 1, PlaceRail_AutoSignals);
HandlePlacePushButton(w, 13, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals);
}
static void BuildRailClick_Bridge(Window *w)
@ -320,6 +320,10 @@ static void DoRailroadTrack(int mode)
);
}
/* This code was used for ludde's special autorail autocomplete.
* It analyzes the adjecent tiles and bases it's decision which
* rail piece to place on this.
typedef struct {
byte bit, a,b, mouse;
} BestFitStruct;
@ -432,7 +436,9 @@ static int GetBestFit1x1(int x, int y)
return best;
}
*/
// This function is more or less a hack because DoRailroadTrack() would otherwise screw up
static void SwapSelection()
{
TileHighlightData *thd = &_thd;
@ -442,6 +448,8 @@ static void SwapSelection()
thd->selend = pt;
}
/* see above, residue from ludde's special autorail autocomplete
static bool Check2x1AutoRail(int mode)
{
TileHighlightData *thd = &_thd;
@ -474,46 +482,61 @@ static bool Check2x1AutoRail(int mode)
return false;
}
*/
static void HandleAutodirPlacement()
{
TileHighlightData *thd = &_thd;
int bit;
int dx = thd->selstart.x - (thd->selend.x&~0xF);
int dy = thd->selstart.y - (thd->selend.y&~0xF);
if (thd->drawstyle == HT_RECT) {
int dx = thd->selstart.x - (thd->selend.x&~0xF);
int dy = thd->selstart.y - (thd->selend.y&~0xF);
if (dx == 0 && dy == 0 ) {
// 1x1 tile
bit = GetBestFit1x1(thd->selend.x, thd->selend.y);
if (bit == -1) return;
GenericPlaceRail(TILE_FROM_XY(thd->selend.x, thd->selend.y), bit);
} else if (dx == 0) {
if (dy == -16) {
if (Check2x1AutoRail(0)) return;
} else if (dy == 16) {
if (Check2x1AutoRail(1)) return;
}
// same x coordinate
DoRailroadTrack(VPM_FIX_X);
if (thd->drawstyle & HT_RAIL) { // one tile case
bit = thd->drawstyle & 0xF;
GenericPlaceRail(TILE_FROM_XY(thd->selend.x, thd->selend.y), bit);
} else if ( !(thd->drawstyle & 0xE) ) { // x/y dir
if (dx == 0) { // Y dir
DoRailroadTrack(1);
} else {
// same y coordinate
// check it's it -16 or 16, then we must check if it should be normal tiles or special tiles.
if (dx == -16) {
if (Check2x1AutoRail(2)) return;
} else if (dx == 16) {
if (Check2x1AutoRail(3)) return;
}
DoRailroadTrack(VPM_FIX_Y);
DoRailroadTrack(2);
}
} else if (myabs(dx)+myabs(dy) >= 32) { // long line (more than 2 tiles)
if(thd->drawstyle == (HT_LINE | HT_DIR_HU))
DoRailroadTrack(0);
if(thd->drawstyle == (HT_LINE | HT_DIR_HL))
DoRailroadTrack(3);
if(thd->drawstyle == (HT_LINE | HT_DIR_VL))
DoRailroadTrack(3);
if(thd->drawstyle == (HT_LINE | HT_DIR_VR))
DoRailroadTrack(0);
} else { // 2x1 pieces line
if(thd->drawstyle == (HT_LINE | HT_DIR_HU)) {
DoRailroadTrack(0);
} else if (thd->drawstyle == (HT_LINE | HT_DIR_HL)) {
SwapSelection();
DoRailroadTrack(0);
SwapSelection();
} else if (thd->drawstyle == (HT_LINE | HT_DIR_VL)) {
if(dx == 0) {
SwapSelection();
DoRailroadTrack(0);
SwapSelection();
} else {
DoRailroadTrack(3);
}
} else if (thd->drawstyle == (HT_LINE | HT_DIR_VR)) {
if(dx == 0) {
DoRailroadTrack(0);
} else {
SwapSelection();
DoRailroadTrack(3);
SwapSelection();
}
}
} else {
DoRailroadTrack(thd->drawstyle & 1 ? 0 : 3);
}
}
static void HandleAutoSignalPlacement()
static void HandleAutoSignalPlacement(void)
{
TileHighlightData *thd = &_thd;
int mode = 0;
@ -525,7 +548,7 @@ static void HandleAutoSignalPlacement()
if (dx == 0 && dy == 0 ) // 1x1 tile signals
GenericPlaceSignals(TILE_FROM_XY(thd->selend.x, thd->selend.y));
else { // signals have been dragged
if (thd->drawstyle == HT_RECT) { // X,Y direction
if (!(thd->drawstyle & 0xE)) { // X,Y direction
if (dx == 0)
mode = VPM_FIX_X;
else if (dy == 0)
@ -533,16 +556,18 @@ static void HandleAutoSignalPlacement()
trackstat = 0xC0;
} else { // W-E or N-S direction
mode = thd->drawstyle & 1 ? 0 : 3;
if ((thd->drawstyle & 0xF) == 2 || (thd->drawstyle & 0xF) == 5)
mode = 0;
else
mode = 3;
if (dx == dy || abs(dx - dy) == 16) // North<->South track |
trackstat = (thd->drawstyle & 1) ? 0x20 : 0x10;
else if (dx == -dy || abs(dx + dy) == 16) // East<->West track --
trackstat = (thd->drawstyle & 1) ? 4 : 8;
trackstat = (thd->drawstyle & 1) ? 8 : 4;
}
/* _patches.drag_signals_density is given as a parameter such that each user in a network
* game can specify his/her own signal density */
// _patches.drag_signals_density is given as a parameter such that each user in a network
// game can specify his/her own signal density
DoCommandP(TILE_FROM_XY(thd->selstart.x, thd->selstart.y), TILE_FROM_XY(thd->selend.x, thd->selend.y),
(mode << 4) | (_remove_button_clicked + (_ctrl_pressed ? 8 : 0)) | (trackstat << 8) | (_patches.drag_signals_density << 24),
CcPlaySound1E,

View File

@ -883,6 +883,9 @@ static void LoadSpriteTables()
LoadGrfIndexed("trkfoundw.grf", _slopes_spriteindexes[_opt.landscape], i++);
load_index = SPR_AUTORAIL_BASE;
load_index += LoadGrfFile("autorail.grf", load_index, i++);
load_index = SPR_CANALS_BASE;
load_index += LoadGrfFile("canalsw.grf", load_index, i++);

70
table/autorail.h Normal file
View File

@ -0,0 +1,70 @@
/* Rail selection types (directions):
/ \ / \ / \ / \ / \ / \
/ /\ /\ \ /===\ / \ /| \ / |\
\/ / \ \/ \ / \===/ \| / \ |/
\ / \ / \ / \ / \ / \ /
0 1 2 3 4 5
*/
// mark invalid tiles red
#define RED(c) c | PALETTE_SEL_TILE_RED
// table maps each of the six rail directions and tileh combinations to a sprite
// invalid entries are required to make sure that this array can be quickly accessed
const int AutorailTilehSprite[31][6] = {
// type 0 1 2 3 4 5
{ 0, 8, 16, 25, 34, 42 }, // tileh = 0
{ 5, 13, RED(22), RED(31), 35, 42 }, // tileh = 1
{ 5, 10, 16, 26, RED(38), RED(46) }, // tileh = 2
{ 5, 9, RED(23), 26, 35, RED(46) }, // tileh = 3
{ 2, 10, RED(19), RED(28), 34, 43 }, // tileh = 4
{ 1, 9, 17, 26, 35, 43 }, // tileh = 5
{ 1, 10, RED(20), 26, RED(38), 43 }, // tileh = 6
{ 1, 9, 17, 26, 35, 43 }, // tileh = 7
{ 2, 13, 17, 25, RED(40), RED(48) }, // tileh = 8
{ 1, 13, 17, RED(32), 35, RED(48) }, // tileh = 9
{ 2, 9, 17, 26, 35, 43 }, // tileh = 10
{ 1, 9, 17, 26, 35, 43 }, // tileh = 11
{ 2, 9, 17, RED(29), RED(40), 43 }, // tileh = 12
{ 1, 9, 17, 26, 35, 43 }, // tileh = 13
{ 1, 9, 17, 26, 35, 43 }, // tileh = 14
{ 0, 1, 2, 3, 4, 5 }, // invalid (15)
{ 0, 1, 2, 3, 4, 5 }, // invalid (16)
{ 0, 1, 2, 3, 4, 5 }, // invalid (17)
{ 0, 1, 2, 3, 4, 5 }, // invalid (18)
{ 0, 1, 2, 3, 4, 5 }, // invalid (19)
{ 0, 1, 2, 3, 4, 5 }, // invalid (20)
{ 0, 1, 2, 3, 4, 5 }, // invalid (21)
{ 0, 1, 2, 3, 4, 5 }, // invalid (22)
{ RED(6), RED(11), RED(17), RED(27), RED(39), RED(47) }, // tileh = 23
{ 0, 1, 2, 3, 4, 5 }, // invalid (24)
{ 0, 1, 2, 3, 4, 5 }, // invalid (25)
{ 0, 1, 2, 3, 4, 5 }, // invalid (26)
{ RED(7), RED(15), RED(24), RED(33), RED(36), RED(44) }, // tileh = 27
{ 0, 1, 2, 3, 4, 5 }, // invalid (28)
{ RED(3), RED(14), RED(18), RED(26), RED(41), RED(49) }, // tileh = 29
{ RED(4), RED(12), RED(21), RED(30), RED(37), RED(45) }, // tileh = 30
};
#undef RED
// maps each pixel of a tile (16x16) to a selection type
// (0,0) is the top corner, (16,16) the bottom corner
const int AutorailPiece[16][16] = {
{ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5 },
{ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5 },
{ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5 },
{ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5 },
{ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5 },
{ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5 },
{ 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
{ 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3 },
{ 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3 },
{ 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3 },
{ 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3 },
{ 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3 },
{ 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3 }
};

View File

@ -44,7 +44,8 @@ enum Sprites {
/* Extra graphic spritenumbers */
SPR_CANALS_BASE = 5126,
SPR_SLOPES_BASE = SPR_CANALS_BASE + 70,
SPR_OPENTTD_BASE = SPR_SLOPES_BASE + 74, //5270
SPR_AUTORAIL_BASE = SPR_SLOPES_BASE + 78,
SPR_OPENTTD_BASE = SPR_AUTORAIL_BASE + 55, // can be lowered once autorail.grf is finalized
SPR_BLOT = SPR_OPENTTD_BASE + 32, // colored circle (mainly used as vehicle profit marker and for sever compatibility)

View File

@ -595,11 +595,7 @@ static int dbg_draw_pushed(const TileInfo *ti)
static void DrawSelectionSprite(uint32 image, const TileInfo *ti)
{
if (_added_tile_sprite) {
DrawGroundSpriteAt(image, ti->x, ti->y, ti->z + 7);
} else {
AddSortableSpriteToDraw(image, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
}
AddSortableSpriteToDraw(image, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
}
static bool IsPartOfAutoLine(int px, int py)
@ -610,10 +606,12 @@ static bool IsPartOfAutoLine(int px, int py)
py -= thd->selstart.y;
switch(thd->drawstyle) {
case HT_LINE | 0: return px == py || px == py + 16;
case HT_LINE | 1: return px == py || px == py - 16;
case HT_LINE | 2: return px == -py || px == -py + 16;
case HT_LINE | 3: return px == -py || px == -py - 16;
case HT_LINE | HT_DIR_X: return py == 0; // x direction
case HT_LINE | HT_DIR_Y: return px == 0; // y direction
case HT_LINE | HT_DIR_HU: return px == -py || px == -py - 16; // horizontal upper
case HT_LINE | HT_DIR_HL: return px == -py || px == -py + 16; // horizontal lower
case HT_LINE | HT_DIR_VL: return px == py || px == py + 16; // vertival left
case HT_LINE | HT_DIR_VR: return px == py || px == py - 16; // vertical right
default:
NOT_REACHED();
}
@ -622,6 +620,18 @@ static bool IsPartOfAutoLine(int px, int py)
return 0;
}
// [direction][side]
static const int AutorailType[6][2] = {
{ HT_DIR_X, HT_DIR_X },
{ HT_DIR_Y, HT_DIR_Y },
{ HT_DIR_HU, HT_DIR_HL },
{ HT_DIR_HL, HT_DIR_HU },
{ HT_DIR_VL, HT_DIR_VR },
{ HT_DIR_VR, HT_DIR_VL }
};
#include "table/autorail.h"
static void DrawTileSelection(const TileInfo *ti)
{
uint32 image;
@ -657,13 +667,32 @@ static void DrawTileSelection(const TileInfo *ti)
}
}
DrawGroundSpriteAt(_cur_dpi->zoom != 2 ? 0x306 : 0xFEE,ti->x, ti->y, z);
} else {
if (IsPartOfAutoLine(ti->x, ti->y)) {
image = 0x2F0 + _tileh_to_sprite[ti->tileh];
} else if (thd->drawstyle & HT_RAIL /*&& thd->place_mode == VHM_RAIL*/) { // autorail highlight piece under cursor
int type = thd->drawstyle & 0xF;
assert(type<=5);
image = SPR_AUTORAIL_BASE + AutorailTilehSprite[ ti->tileh ][ AutorailType[type][0] ];
if (thd->make_square_red) image |= 0x3048000;
DrawSelectionSprite(image, ti);
} else if (IsPartOfAutoLine(ti->x, ti->y)) { // autorail highlighting long line
int dir = thd->drawstyle & ~0xF0;
uint start = TILE_FROM_XY(thd->selstart.x, thd->selstart.y);
int diffx, diffy;
int side;
diffx = myabs(TileX(start)-TileX(ti->tile));
diffy = myabs(TileY(start)-TileY(ti->tile));
side = myabs( diffx-diffy );
if(dir<2) side = 0;
image = SPR_AUTORAIL_BASE + AutorailTilehSprite[ ti->tileh ][ AutorailType[dir][side] ];
if (thd->make_square_red) image |= 0x3048000;
DrawSelectionSprite(image, ti);
}
}
}
return;
}
@ -1715,7 +1744,7 @@ void PlaceObject()
if (pt.x == -1)
return;
if (_thd.place_mode == 2) {
if (_thd.place_mode == VHM_POINT) {
pt.x += 8;
pt.y += 8;
}
@ -1810,7 +1839,15 @@ void SetTileSelectBigSize(int ox, int oy, int sx, int sy) {
thd->new_outersize.y = sy * 16;
}
/* returns the best autorail highlight type from map coordinates */
static byte GetAutorailHT(int x, int y)
{
int i;
i = AutorailPiece[x&0xF][y&0xF];
return HT_RAIL | i;
}
// called regular to update tile highlighting in all cases
void UpdateTileSelection()
{
TileHighlightData *thd = _thd_ptr;
@ -1819,7 +1856,7 @@ void UpdateTileSelection()
thd->new_drawstyle = 0;
if (thd->place_mode == 3) {
if (thd->place_mode == VHM_SPECIAL) {
x1 = thd->selend.x;
y1 = thd->selend.y;
if (x1 != -1) {
@ -1836,23 +1873,29 @@ void UpdateTileSelection()
thd->new_size.y = y2 - y1 + 16;
thd->new_drawstyle = thd->next_drawstyle;
}
} else if (thd->place_mode != 0) {
} else if (thd->place_mode != VHM_NONE) {
pt = GetTileBelowCursor();
x1 = pt.x;
y1 = pt.y;
if (x1 != -1) {
if (thd->place_mode == 1) {
thd->new_drawstyle = HT_RECT;
} else {
thd->new_drawstyle = HT_POINT;
x1 += 8;
y1 += 8;
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) {
@ -1871,21 +1914,24 @@ void UpdateTileSelection()
}
}
// highlighting tiles while only going over them with the mouse
void VpStartPlaceSizing(uint tile, int user)
{
TileHighlightData *thd;
thd = _thd_ptr;
thd->userdata = user;
thd->selend.x = TileX(tile) * 16;
thd->selstart.x = TileX(tile) * 16;
thd->selend.y = TileY(tile) * 16;
thd->selstart.y = TileY(tile) * 16;
if (thd->place_mode == 1) {
thd->place_mode = 3;
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 = 3;
thd->place_mode = VHM_SPECIAL;
thd->next_drawstyle = HT_POINT;
}
_special_mouse_mode = WSM_SIZING;
@ -1912,51 +1958,114 @@ void VpStartPreSizing()
_special_mouse_mode = WSM_PRESIZE;
}
static void CalcRaildirsDrawstyle(TileHighlightData *thd, int x, int y)
/* returns information about the 2x1 piece to be build.
* The lower bits (0-3) are the track type. */
static byte Check2x1AutoRail(int mode)
{
TileHighlightData *thd = &_thd;
int fxpy = _tile_fract_coords.x + _tile_fract_coords.y;
int sxpy = (thd->selend.x & 0xF) + (thd->selend.y & 0xF);
int fxmy = _tile_fract_coords.x - _tile_fract_coords.y;
int sxmy = (thd->selend.x & 0xF) - (thd->selend.y & 0xF);
switch(mode) {
case 0: // end piece is lower right
if (fxpy >= 20 && sxpy <= 12) { /*SwapSelection(); DoRailroadTrack(0); */return 3; }
if (fxmy < -3 && sxmy > 3) {/* DoRailroadTrack(0); */return 5; }
return 1;
break;
case 1:
if (fxmy > 3 && sxmy < -3) { /*SwapSelection(); DoRailroadTrack(0); */return 4; }
if (fxpy <= 12 && sxpy >= 20) { /*DoRailroadTrack(0); */return 2; }
return 1;
break;
case 2:
if (fxmy > 3 && sxmy < -3) { /*DoRailroadTrack(3);*/ return 4; }
if (fxpy >= 20 && sxpy <= 12) { /*SwapSelection(); DoRailroadTrack(0); */return 3; }
return 0;
break;
case 3:
if (fxmy < -3 && sxmy > 3) { /*SwapSelection(); DoRailroadTrack(3);*/ return 5; }
if (fxpy <= 12 && sxpy >= 20) { /*DoRailroadTrack(0); */return 2; }
return 0;
break;
}
return 0; // avoids compiler warnings
}
// while dragging
static void CalcRaildirsDrawstyle(TileHighlightData *thd, int x, int y, int method)
{
int d;
bool b;
byte b=6;
uint w,h;
w = myabs((x & ~0xF) - thd->selstart.x) + 16;
h = myabs((y & ~0xF) - thd->selstart.y) + 16;
int dx = thd->selstart.x - (thd->selend.x&~0xF);
int dy = thd->selstart.y - (thd->selend.y&~0xF);
w = myabs(dx) + 16;
h = myabs(dy) + 16;
// vertical and horizontal lines are really simple
if (w == 16 || h == 16) {
b = HT_RECT;
} else if (w * 2 < h) { // see if we're closer to rect?
x = thd->selstart.x;
b = HT_RECT;
} else if (w > h * 2) {
if (TILE_FROM_XY(thd->selstart.x, thd->selstart.y) == TILE_FROM_XY(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;
} else if (h == 16) { // Is this in X direction?
if (dx==16) // 2x1 special handling
b = (Check2x1AutoRail(3)) | HT_LINE;
else if (dx==-16)
b = (Check2x1AutoRail(2)) | HT_LINE;
else
b = HT_LINE | HT_DIR_X;
y = thd->selstart.y;
b = HT_RECT;
} else {
} else if (w == 16) { // Or Y direction?
if (dy==16) // 2x1 special handling
b = (Check2x1AutoRail(1)) | HT_LINE;
else if (dy==-16) // 2x1 other direction
b = (Check2x1AutoRail(0)) | HT_LINE;
else
b = HT_LINE | HT_DIR_Y;
x = thd->selstart.x;
} else if (w > h * 2) { // still count as x dir?
b = HT_LINE | HT_DIR_X;
y = thd->selstart.y;
} else if (h > w * 2) { // still count as y dir?
b = HT_LINE | HT_DIR_Y;
x = thd->selstart.x;
} else { // complicated direction
d = w - h;
thd->selend.x = thd->selend.x&~0xF;
thd->selend.y = thd->selend.y&~0xF;
// four cases.
if (x > thd->selstart.x) {
if (y > thd->selstart.y) {
// south
if (d ==0) b = (x & 0xF) > (y & 0xF) ? HT_LINE | 0 : HT_LINE | 1;
else if (d >= 0) { x = thd->selstart.x + h; b = HT_LINE | 0; } // return px == py || px == py + 16;
else { y = thd->selstart.y + w; b = HT_LINE | 1; } // return px == py || px == py - 16;
if (d ==0) b = (x & 0xF) > (y & 0xF) ? HT_LINE | HT_DIR_VL : HT_LINE | HT_DIR_VR;
else if (d >= 0) { x = thd->selstart.x + h; b = HT_LINE | HT_DIR_VL; } // return px == py || px == py + 16;
else { y = thd->selstart.y + w; b = HT_LINE | HT_DIR_VR; } // return px == py || px == py - 16;
} else {
// west
if (d ==0) b = (x & 0xF) + (y & 0xF) >= 0x10 ? HT_LINE | 2 : HT_LINE | 3;
else if (d >= 0) { x = thd->selstart.x + h; b = HT_LINE | 2; }
else { y = thd->selstart.y - w; b = HT_LINE | 3; }
if (d ==0) b = (x & 0xF) + (y & 0xF) >= 0x10 ? HT_LINE | HT_DIR_HL : HT_LINE | HT_DIR_HU;
else if (d >= 0) { x = thd->selstart.x + h; b = HT_LINE | HT_DIR_HL; }
else { y = thd->selstart.y - w; b = HT_LINE | HT_DIR_HU; }
}
} else {
if (y > thd->selstart.y) {
// east
if (d ==0) b = (x & 0xF) + (y & 0xF) >= 0x10 ? HT_LINE | 2 : HT_LINE | 3;
else if (d >= 0) { x = thd->selstart.x - h; b = HT_LINE | 3; } // return px == -py || px == -py - 16;
else { y = thd->selstart.y + w; b = HT_LINE | 2; } // return px == -py || px == -py + 16;
if (d ==0) b = (x & 0xF) + (y & 0xF) >= 0x10 ? HT_LINE | HT_DIR_HL : HT_LINE | HT_DIR_HU;
else if (d >= 0) { x = thd->selstart.x - h; b = HT_LINE | HT_DIR_HU; } // return px == -py || px == -py - 16;
else { y = thd->selstart.y + w; b = HT_LINE | HT_DIR_HL; } // return px == -py || px == -py + 16;
} else {
// north
if (d ==0) b = (x & 0xF) > (y & 0xF) ? HT_LINE | 0 : HT_LINE | 1;
else if (d >= 0) { x = thd->selstart.x - h; b = HT_LINE | 1; } // return px == py || px == py - 16;
else { y = thd->selstart.y - w; b = HT_LINE | 0; } //return px == py || px == py + 16;
if (d ==0) b = (x & 0xF) > (y & 0xF) ? HT_LINE | HT_DIR_VL : HT_LINE | HT_DIR_VR;
else if (d >= 0) { x = thd->selstart.x - h; b = HT_LINE | HT_DIR_VR; } // return px == py || px == py - 16;
else { y = thd->selstart.y - w; b = HT_LINE | HT_DIR_VL; } //return px == py || px == py + 16;
}
}
}
@ -1965,11 +2074,11 @@ static void CalcRaildirsDrawstyle(TileHighlightData *thd, int x, int y)
thd->next_drawstyle = b;
}
// while dragging
void VpSelectTilesWithMethod(int x, int y, int method)
{
TileHighlightData *thd = _thd_ptr;
int sx,sy;
if (x == -1) {
thd->selend.x = -1;
return;
@ -1977,14 +2086,14 @@ void VpSelectTilesWithMethod(int x, int y, int method)
// allow drag in any rail direction
if (method == VPM_RAILDIRS || method == VPM_SIGNALDIRS) {
CalcRaildirsDrawstyle(thd, x, y);
thd->selend.x = x;
thd->selend.y = y;
CalcRaildirsDrawstyle(thd, x, y, method);
return;
}
if (_thd.next_drawstyle == HT_POINT) { x += 8; y += 8; }
//thd->next_drawstyle = HT_RECT;
sx = thd->selstart.x;
sy = thd->selstart.y;
@ -2017,6 +2126,7 @@ void VpSelectTilesWithMethod(int x, int y, int method)
thd->selend.y = y;
}
// while dragging
bool VpHandlePlaceSizingDrag()
{
Window *w;
@ -2027,13 +2137,14 @@ bool VpHandlePlaceSizingDrag()
e.place.userdata = _thd.userdata;
// stop drag mode if the window has been closed
w = FindWindowById(_thd.window_class,_thd.window_number);
if (w == NULL) {
ResetObjectToPlace();
return false;
}
// while dragging...
// while dragging execute the drag procedure of the corresponding window (mostly VpSelectTilesWithMethod() )
if (_left_button_down) {
e.event = WE_PLACE_DRAG;
e.place.pt = GetTileBelowCursor();
@ -2044,8 +2155,16 @@ bool VpHandlePlaceSizingDrag()
// mouse button released..
// keep the selected tool, but reset it to the original mode.
_special_mouse_mode = WSM_NONE;
_thd.place_mode = (_thd.next_drawstyle == HT_RECT || _thd.next_drawstyle & HT_LINE) ? 1 : 2;
if (_thd.next_drawstyle == HT_RECT)
_thd.place_mode = VHM_RECT;
else if ((e.place.userdata & 0xF) == VPM_SIGNALDIRS) // some might call this a hack... -- Dominik
_thd.place_mode = VHM_RECT;
else if (_thd.next_drawstyle & HT_LINE)
_thd.place_mode = VHM_RAIL;
else if (_thd.next_drawstyle & HT_RAIL)
_thd.place_mode = VHM_RAIL;
else
_thd.place_mode = VHM_POINT;
SetTileSelectSize(1, 1);
// and call the mouseup event.
@ -2070,6 +2189,7 @@ void SetObjectToPlace(int icon, byte mode, WindowClass window_class, WindowNumbe
TileHighlightData *thd = _thd_ptr;
Window *w;
// undo clicking on button
if (thd->place_mode != 0) {
thd->place_mode = 0;
w = FindWindowById(thd->window_class, thd->window_number);
@ -2081,7 +2201,7 @@ void SetObjectToPlace(int icon, byte mode, WindowClass window_class, WindowNumbe
thd->make_square_red = false;
if (mode == 4) {
if (mode == VHM_DRAG) { // mode 4 is for dragdropping trains in the depot window
mode = 0;
_special_mouse_mode = WSM_DRAGDROP;
} else {
@ -2092,7 +2212,7 @@ void SetObjectToPlace(int icon, byte mode, WindowClass window_class, WindowNumbe
thd->window_class = window_class;
thd->window_number = window_num;
if (mode == 3)
if (mode == VHM_SPECIAL) // special tools, like tunnels or docks start with presizing mode
VpStartPreSizing();
if ( (int)icon < 0)

View File

@ -54,16 +54,39 @@ enum {
VPM_RAILDIRS = 3,
VPM_X_AND_Y = 4,
VPM_X_AND_Y_LIMITED = 5,
VPM_SIGNALDIRS = 6,
VPM_SIGNALDIRS = 6
};
// viewport highlight mode (for highlighting tiles below cursor)
enum {
VHM_NONE = 0, // default
VHM_RECT = 1, // rectangle (stations, depots, ...)
VHM_POINT = 2, // point (lower land, raise land, level land, ...)
VHM_SPECIAL = 3, // special mode used for highlighting while dragging (and for tunnels/docks)
VHM_DRAG = 4, // dragging items in the depot windows
VHM_RAIL = 5, // rail pieces
};
void VpSelectTilesWithMethod(int x, int y, int method);
// highlighting draw styles
enum {
HT_NONE = 0,
HT_RECT = 0x80,
HT_POINT = 0x40,
HT_LINE = 0x20,
HT_LINE = 0x20, /* used for autorail highlighting (longer streches)
* (uses lower bits to indicate direction) */
HT_RAIL = 0x10, /* autorail (one piece)
* (uses lower bits to indicate direction) */
/* lower bits (used with HT_LINE and HT_RAIL):
* (see ASCII art in autorail.h for a visual interpretation) */
HT_DIR_X = 0, // X direction
HT_DIR_Y = 1, // Y direction
HT_DIR_HU = 2, // horizontal upper
HT_DIR_HL = 3, // horizontal lower
HT_DIR_VL = 4, // vertical left
HT_DIR_VR = 5, // vertical right
};
typedef struct TileHighlightData {
@ -81,9 +104,9 @@ typedef struct TileHighlightData {
byte dirty;
byte sizelimit;
byte drawstyle;
byte new_drawstyle;
byte next_drawstyle;
byte drawstyle; // lower bits 0-3 are reserved for detailed highlight information information
byte new_drawstyle; // only used in UpdateTileSelection() to as a buffer to compare if there was a change between old and new
byte next_drawstyle; // queued, but not yet drawn style
byte place_mode;
bool make_square_red;