mirror of https://github.com/OpenTTD/OpenTTD.git
(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:
parent
28df4a0e25
commit
aaf09ceb26
Binary file not shown.
BIN
data/openttd.grf
BIN
data/openttd.grf
Binary file not shown.
14
main_gui.c
14
main_gui.c
|
@ -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;
|
||||
|
|
99
rail_gui.c
99
rail_gui.c
|
@ -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,
|
||||
|
|
|
@ -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++);
|
||||
|
||||
|
|
|
@ -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 }
|
||||
};
|
|
@ -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)
|
||||
|
||||
|
|
242
viewport.c
242
viewport.c
|
@ -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)
|
||||
|
|
33
viewport.h
33
viewport.h
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue