From f7e39977de019d2bf20c4850fa3aa28deeb75854 Mon Sep 17 00:00:00 2001 From: dominik Date: Wed, 19 Jan 2005 20:55:23 +0000 Subject: [PATCH] (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. --- data/autorail.grf | Bin 0 -> 9747 bytes data/openttd.grf | Bin 23244 -> 22917 bytes main_gui.c | 14 ++- rail_gui.c | 99 ++++++++++++------- spritecache.c | 3 + table/autorail.h | 70 ++++++++++++++ table/sprites.h | 3 +- viewport.c | 242 ++++++++++++++++++++++++++++++++++------------ viewport.h | 33 ++++++- 9 files changed, 359 insertions(+), 105 deletions(-) create mode 100644 data/autorail.grf create mode 100644 table/autorail.h diff --git a/data/autorail.grf b/data/autorail.grf new file mode 100644 index 0000000000000000000000000000000000000000..cd6fd293c2ac14699d930b41049242407bab7158 GIT binary patch literal 9747 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 literal 0 HcmV?d00001 diff --git a/data/openttd.grf b/data/openttd.grf index d67107ea984409a85a76744006c5d630adb6ff74..6145941abbde1a94777e7ed788bc2da34e4e8da6 100644 GIT binary patch delta 2162 zcmX@Jm9cd*;|6tR*40eRDi)K}r0W;(bV$5VpJC3Z*kRG(KEr~AkBf`z1@i+oCPjsg zf{ywHeT;k?EI=HKj%^bx72A0zJp3nm`k4)acxPU9UGFDyI#I%7Ku zcC6^I?3~=Wh?#+xXJY^(&%+Z;e0&!#GjnruzhJ(=wt(k?1QQp}1CW_JEb9-LKjMDj z^1yY4zy$AFyJ&uCOA9vEzj#Q>N(!s|^+p%r7ip zx}LeAWJ1n^;0GHRHD0nDE@I;1Ij~?y38TUbC8n&7894_wY*@j>!~0?(;Om`V9}5c=;YIWHdcc!lYF2;stZWSH%}44`Wv3Fq%GCzruo%_u;Mu zC5-hqZdM(fwjpPt#N~h+B`<%y_`|4p(&gkd#;hGVmkhc)9_hW3dH9D>;h@WbZ;TNa zayl$7OYD+)WX9OB(uFZ=mdnN;R}5Ck+>Bw2*y+O5;l9XahDDbQQ)cF?Rj+thvLZ4~ zXSvKWc(b5O=GB=8^BJ>VB`~@za(S&YF@RBVQpb&FjP<6k<(LbucTC#BsJQ9|BhQP1 zu8vDGEH@$)zIN?cP{72)_juE!4o1^kGK{7VN>=TdEbzkO_M1r^ufNZ7Ie4hU;*Q#a zoLw#_N;-dBc(5m7Q^%2_%Q{OEIxNo2I@ED&&EvC6R&U#N*Q1xWS7xpD3JXTASEt^3 zJYYG%(IK!wo>6golK2aA=7@+0NWuW6#5YGphfvb&uk9o3rx zHpoDe--X97b}(vmSZy$4(ctFMII!X{6DZZ?Gb(miO)z6rJkh(s;(|Fd7gq$BAF)&7 za1kTd$rDUBu6I~1Fso;}ext*JnSp`l)B~1d*RS80P_iS3<;L~v$2tmLJviOLcI^1c zQ>RaEShr&l>&ernP9E>DSS-PE{KUyqD_(54!E);4iQ^l8bO-GI```s**28HtZgg05 zSX_8gwpca9ij0{0@uPnrUc!G+e9jn+i6tWZ}6nPF*a|X{x8g!uV*Pd(0owI#4YlG{ee5PLe}*MRu@z^tYGKi z<2n7F^*aAxFsuR=y>shv7YLpvsRtm@dg;o=2Gg$L%Vc1$wZ)$#JzNf2N3;*T5Bw{|Sbc)R0u#j1{n8yFQX zalI3ih(!8dC_y>&4o4hXIK!G+&91HF_ft1V&oJNVE_Sl z4F)X+0|pBQCx#G)G=@rsE{0hQ%NaH^>|;2=aFO8_!y|@Q44)W&F*Go=@Ge@kXiFQ< zq9sd~EZNe*y=cjDe*Wc4wy-f@zkdA%^8+Cketv%b8$v7*SqfiY2r+KiAjGMl!Nq;O zlWWnI6XuNlCxl;^GH$sM#OTv^LFI-k>y|BBwshYxxe>y=WKq`x#}hn^oiBV(h%|jlP+?m1^#KP{#G)6|UI@IH%gFUW;>MK88`V2E J?@$#n1pwAK!SetB delta 2370 zcmZqO%y?!i;|6tRMPFuS9S?>N|L^{1W?*1=!F+*j0S^y9KOY}2FApy-A0PkZE?$@V z7e1U{H59&PU02Zfx*+0(DD(BKuNy==JXY#5@?Mzm!i^;&OHuKK*9Pwgt}onJ6cw`~ z4#am%Sm43PbD@VNyD+okgx85F7kVDJv2W?xv@abxA)mo_)tSWPppU%!69i|M+; ziXO&}7m`ewrWd?A6=rxaebu;df$4hYhA9(z9@Hm4c)+Of(xuB`#e@SFc1&SZcwxkp z)iI;zz=O^W3vMv-zPQME<6z2(DU3HB7BP0r=wZ%^xbfnC=Z~2i9$aKJJurnyso5 zXV;SxQ+fr~)iQEl@MPq@;C{kux5v>G?*{mrP@XK=%V ziA(Xs)xN5}&Sf($crabRKEZ>rp6kR_W(5TWNb=~AU{z31vhNVAMZ}+ z{?c91y`ukA_qy(DJ%0WF`_FcN>3`k*2Be;m;Rq9IrVzxIE8OZkqB}e~l`k4G@}8K$ zoOL~`W9Ehx8)TsAej_svw?>E81~(QBZXS(}8=c#k7#LpK+~{Xi?C_f4#;AB=ZKpzq z$HOef2rxgQGo#CGg$L7(>m6PT+?cN4=-klN_u$6KA1ueNU%xS7%8nkE8`rNN>-^Dm zZRG~GW5-XPsy}^l!@V7sSWlilb@F(JN4M<4AFN!*PnRN{u7DnkUa=<)jC|cpr$D@h-nb_gH$3VWdw{rC!g@~hG%#^xb$fIL z+~K)1zgM6;fsyOY;mID00&Z8_Q0a}hXN^dbclo+KR?RqF(Q#v6JtRrqaKHO{vB%m! zrz?72Z1A|@xx&5AywB}iC_Fh{xY}3Q*U{n8A8^Bi5s?(@*%t70NN|GFA_K$q>vJD$ zltf95j1ez9A9yVAI{M&-`vhrFqImysf!7{`3-0~@`;YZsT`*;D0JDaILPrlsu4Bsf z8>c4r|L;H1e|^Kf!!IsClh;ht)Oa0QIP!4U!&Bq@$B5L}#n@#EF=Uc^SAGBg{!{%o zCtdG4+5f-)OxNYfOx?o$|NGB%OLpsZ$AS`gcYJq6_wxRu-AlW#bRX*e2(rHaS^rl^ z_SuN1cxFYE&j);1g|A;%&{$y3eEqs`hexO4K?6qK6%$xA6cl(?c-?Sg;!&6o*_pAy zgOO*$7S=4q2t}R)UKiXLd0q%JW^GsuDUVP5V%JdAP>4{}xZribjafr6;)djo#hpJo zJUBHJxHP!9vm&xyOnKnN5^?={#0|F>g3J+F+%IG=n%8$`bWFIB|H6&=dX~Zi%Lg-= zxJ4eYKL}@5$h!W(>w+q%kY?lM63G%(cv1es?Zs_YE{&{+h?g2n++S}5Gjct6_rQx) zK|wT2r1MAT23A1@5gyS8Juj7*H558tYA|xY)VV3~AmXL*iz%$4JR%B$T@IZ;Sgv0e z)Og|b%JSt;ruwgn4>cGSc1qk>%&73fjYUK7`t`1kE{8{X54>L4Gbwz1`Hv~0W2eM} z7)HedZZ|T!S4`@7w1Y`V}FyY;%?;;?TC1B z`<3?tRz|K%Y>eES^+3h^ZI4R^FK#nsDc+P|(fG=(uqdEoLVZui;}54jE|uLfU{rWy zz^HgA;Niy872O}ESZwy#Wbmq<@y6>#FCIMncDMpm*fa5Qt@hYua4CRM;eq?=3TQdM z+v8Q&DUhJ(rH&iYw<~&1^fWxFSncu1fKlPntk>$BE4mYUKfX@bV|Lo((w<9Cc2{(N z*k{hj_3|-eeZ-T7*Qc*mo%UeNI<@Dv-boEm?Ex$DPq<$>_1J?^0VMPI&GYfROW#A3nO^b%CS*7pMTA;kL-2 z!wZznI@~r)>DB{fy^fxap6&`z7142NHxopxQ)03QSnOP9TKA#OE#T~UrH7}-r2pvh hE1TbN8A|Z;FmN(5GJpUJ6GH>Tselend = 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, diff --git a/spritecache.c b/spritecache.c index fae4238ead..c7f32b4f3a 100644 --- a/spritecache.c +++ b/spritecache.c @@ -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++); diff --git a/table/autorail.h b/table/autorail.h new file mode 100644 index 0000000000..f219f1c7d8 --- /dev/null +++ b/table/autorail.h @@ -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 } +}; diff --git a/table/sprites.h b/table/sprites.h index d17d2b4b7e..88929b4d7e 100644 --- a/table/sprites.h +++ b/table/sprites.h @@ -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) diff --git a/viewport.c b/viewport.c index 005379ef12..f1f99067bf 100644 --- a/viewport.c +++ b/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) diff --git a/viewport.h b/viewport.h index 85652efa81..beba02b400 100644 --- a/viewport.h +++ b/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;