00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "tile_cmd.h"
00008 #include "landscape.h"
00009 #include "gui.h"
00010 #include "window_gui.h"
00011 #include "station_gui.h"
00012 #include "terraform_gui.h"
00013 #include "viewport_func.h"
00014 #include "gfx_func.h"
00015 #include "command_func.h"
00016 #include "station.h"
00017 #include "waypoint.h"
00018 #include "debug.h"
00019 #include "variables.h"
00020 #include "newgrf_callbacks.h"
00021 #include "newgrf_station.h"
00022 #include "train.h"
00023 #include "strings_func.h"
00024 #include "functions.h"
00025 #include "window_func.h"
00026 #include "date_func.h"
00027 #include "sound_func.h"
00028 #include "player_func.h"
00029 #include "settings_type.h"
00030 #include "widgets/dropdown_type.h"
00031 #include "widgets/dropdown_func.h"
00032
00033 #include "bridge_map.h"
00034 #include "rail_map.h"
00035 #include "road_map.h"
00036 #include "station_map.h"
00037 #include "tunnel_map.h"
00038 #include "tunnelbridge_map.h"
00039
00040 #include "table/sprites.h"
00041 #include "table/strings.h"
00042
00043 static RailType _cur_railtype;
00044 static bool _remove_button_clicked;
00045 static DiagDirection _build_depot_direction;
00046 static byte _waypoint_count = 1;
00047 static byte _cur_waypoint_type;
00048 static bool _convert_signal_button;
00049 static SignalVariant _cur_signal_variant;
00050 static SignalType _cur_signal_type;
00051
00052 static struct {
00053 byte orientation;
00054 byte numtracks;
00055 byte platlength;
00056 bool dragdrop;
00057
00058 bool newstations;
00059 StationClassIDByte station_class;
00060 byte station_type;
00061 byte station_count;
00062 } _railstation;
00063
00064
00065 static void HandleStationPlacement(TileIndex start, TileIndex end);
00066 static void ShowBuildTrainDepotPicker();
00067 static void ShowBuildWaypointPicker();
00068 static void ShowStationBuilder();
00069 static void ShowSignalBuilder();
00070
00071 void CcPlaySound1E(bool success, TileIndex tile, uint32 p1, uint32 p2)
00072 {
00073 if (success) SndPlayTileFx(SND_20_SPLAT_2, tile);
00074 }
00075
00076 static void GenericPlaceRail(TileIndex tile, int cmd)
00077 {
00078 DoCommandP(tile, _cur_railtype, cmd, CcPlaySound1E,
00079 _remove_button_clicked ?
00080 CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_1012_CAN_T_REMOVE_RAILROAD_TRACK) | CMD_NO_WATER :
00081 CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_1011_CAN_T_BUILD_RAILROAD_TRACK) | CMD_NO_WATER
00082 );
00083 }
00084
00085 static void PlaceRail_N(TileIndex tile)
00086 {
00087 int cmd = _tile_fract_coords.x > _tile_fract_coords.y ? 4 : 5;
00088 GenericPlaceRail(tile, cmd);
00089 }
00090
00091 static void PlaceRail_NE(TileIndex tile)
00092 {
00093 VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_RAIL_NE);
00094 }
00095
00096 static void PlaceRail_E(TileIndex tile)
00097 {
00098 int cmd = _tile_fract_coords.x + _tile_fract_coords.y <= 15 ? 2 : 3;
00099 GenericPlaceRail(tile, cmd);
00100 }
00101
00102 static void PlaceRail_NW(TileIndex tile)
00103 {
00104 VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_RAIL_NW);
00105 }
00106
00107 static void PlaceRail_AutoRail(TileIndex tile)
00108 {
00109 VpStartPlaceSizing(tile, VPM_RAILDIRS, DDSP_PLACE_AUTORAIL);
00110 }
00111
00112 static void PlaceExtraDepotRail(TileIndex tile, uint16 extra)
00113 {
00114 if (GetRailTileType(tile) != RAIL_TILE_NORMAL) return;
00115 if ((GetTrackBits(tile) & GB(extra, 8, 8)) == 0) return;
00116
00117 DoCommandP(tile, _cur_railtype, extra & 0xFF, NULL, CMD_BUILD_SINGLE_RAIL | CMD_NO_WATER);
00118 }
00119
00120 static const uint16 _place_depot_extra[12] = {
00121 0x0604, 0x2102, 0x1202, 0x0505,
00122 0x2400, 0x2801, 0x1800, 0x1401,
00123 0x2203, 0x0904, 0x0A05, 0x1103,
00124 };
00125
00126
00127 void CcRailDepot(bool success, TileIndex tile, uint32 p1, uint32 p2)
00128 {
00129 if (success) {
00130 DiagDirection dir = (DiagDirection)p2;
00131
00132 SndPlayTileFx(SND_20_SPLAT_2, tile);
00133 ResetObjectToPlace();
00134
00135 tile += TileOffsByDiagDir(dir);
00136
00137 if (IsTileType(tile, MP_RAILWAY)) {
00138 PlaceExtraDepotRail(tile, _place_depot_extra[dir]);
00139 PlaceExtraDepotRail(tile, _place_depot_extra[dir + 4]);
00140 PlaceExtraDepotRail(tile, _place_depot_extra[dir + 8]);
00141 }
00142 }
00143 }
00144
00145 static void PlaceRail_Depot(TileIndex tile)
00146 {
00147 DoCommandP(tile, _cur_railtype, _build_depot_direction, CcRailDepot,
00148 CMD_BUILD_TRAIN_DEPOT | CMD_NO_WATER | CMD_MSG(STR_100E_CAN_T_BUILD_TRAIN_DEPOT));
00149 }
00150
00151 static void PlaceRail_Waypoint(TileIndex tile)
00152 {
00153 if (_remove_button_clicked) {
00154 DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_REMOVE_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_REMOVE_TRAIN_WAYPOINT));
00155 } else {
00156 DoCommandP(tile, _cur_waypoint_type, 0, CcPlaySound1E, CMD_BUILD_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_BUILD_TRAIN_WAYPOINT));
00157 }
00158 }
00159
00160 void CcStation(bool success, TileIndex tile, uint32 p1, uint32 p2)
00161 {
00162 if (success) {
00163 SndPlayTileFx(SND_20_SPLAT_2, tile);
00164
00165 if (_railstation.station_class == STAT_CLASS_DFLT && _railstation.station_type == 0) ResetObjectToPlace();
00166 }
00167 }
00168
00169 static void PlaceRail_Station(TileIndex tile)
00170 {
00171 if (_remove_button_clicked) {
00172 VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_REMOVE_STATION);
00173 VpSetPlaceSizingLimit(-1);
00174 } else if (_railstation.dragdrop) {
00175 VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_STATION);
00176 VpSetPlaceSizingLimit(_patches.station_spread);
00177 } else {
00178 DoCommandP(tile,
00179 _railstation.orientation | (_railstation.numtracks << 8) | (_railstation.platlength << 16) | (_ctrl_pressed << 24),
00180 _cur_railtype | (_railstation.station_class << 8) | (_railstation.station_type << 16), CcStation,
00181 CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION));
00182 }
00183 }
00184
00190 static void GenericPlaceSignals(TileIndex tile)
00191 {
00192 TrackBits trackbits = TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0));
00193
00194 if (trackbits & TRACK_BIT_VERT) {
00195 trackbits = (_tile_fract_coords.x <= _tile_fract_coords.y) ? TRACK_BIT_RIGHT : TRACK_BIT_LEFT;
00196 }
00197
00198 if (trackbits & TRACK_BIT_HORZ) {
00199 trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? TRACK_BIT_UPPER : TRACK_BIT_LOWER;
00200 }
00201
00202 Track track = FindFirstTrack(trackbits);
00203
00204 if (_remove_button_clicked) {
00205 DoCommandP(tile, track, 0, CcPlaySound1E,
00206 CMD_REMOVE_SIGNALS | CMD_MSG(STR_1013_CAN_T_REMOVE_SIGNALS_FROM));
00207 } else {
00208 if (!_patches.enable_signal_gui) _cur_signal_variant = _cur_year < _patches.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC;
00209
00210
00211 uint32 p1 = track;
00212 SB(p1, 3, 1, _ctrl_pressed);
00213 SB(p1, 4, 1, _cur_signal_variant);
00214 SB(p1, 5, 2, _patches.enable_signal_gui ? _cur_signal_type : SIGTYPE_NORMAL);
00215 SB(p1, 7, 1, _convert_signal_button);
00216
00217 DoCommandP(tile, p1, 0, CcPlaySound1E, CMD_BUILD_SIGNALS |
00218 CMD_MSG(_convert_signal_button ? STR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE : STR_1010_CAN_T_BUILD_SIGNALS_HERE));
00219 }
00220 }
00221
00222 static void PlaceRail_Bridge(TileIndex tile)
00223 {
00224 VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
00225 }
00226
00227 void CcBuildRailTunnel(bool success, TileIndex tile, uint32 p1, uint32 p2)
00228 {
00229 if (success) {
00230 SndPlayTileFx(SND_20_SPLAT_2, tile);
00231 ResetObjectToPlace();
00232 } else {
00233 SetRedErrorSquare(_build_tunnel_endtile);
00234 }
00235 }
00236
00237 static void PlaceRail_Tunnel(TileIndex tile)
00238 {
00239 DoCommandP(tile, _cur_railtype, 0, CcBuildRailTunnel,
00240 CMD_BUILD_TUNNEL | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE));
00241 }
00242
00243 void PlaceProc_BuyLand(TileIndex tile)
00244 {
00245 DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_PURCHASE_LAND_AREA | CMD_NO_WATER | CMD_MSG(STR_5806_CAN_T_PURCHASE_THIS_LAND));
00246 }
00247
00248 static void PlaceRail_ConvertRail(TileIndex tile)
00249 {
00250 VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CONVERT_RAIL);
00251 }
00252
00253 static void PlaceRail_AutoSignals(TileIndex tile)
00254 {
00255 VpStartPlaceSizing(tile, VPM_SIGNALDIRS, DDSP_BUILD_SIGNALS);
00256 }
00257
00258
00260 enum RailToolbarWidgets {
00261 RTW_CLOSEBOX = 0,
00262 RTW_CAPTION,
00263 RTW_STICKY,
00264 RTW_SPACER,
00265 RTW_BUILD_NS,
00266 RTW_BUILD_X,
00267 RTW_BUILD_EW,
00268 RTW_BUILD_Y,
00269 RTW_AUTORAIL,
00270 RTW_DEMOLISH,
00271 RTW_BUILD_DEPOT,
00272 RTW_BUILD_WAYPOINT,
00273 RTW_BUILD_STATION,
00274 RTW_BUILD_SIGNALS,
00275 RTW_BUILD_BRIDGE,
00276 RTW_BUILD_TUNNEL,
00277 RTW_REMOVE,
00278 RTW_CONVERT_RAIL,
00279 };
00280
00281
00285 static void ToggleRailButton_Remove(Window *w)
00286 {
00287 w->ToggleWidgetLoweredState(RTW_REMOVE);
00288 w->InvalidateWidget(RTW_REMOVE);
00289 _remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE);
00290 SetSelectionRed(_remove_button_clicked);
00291 }
00292
00297 static bool RailToolbar_CtrlChanged(Window *w)
00298 {
00299 if (w->IsWidgetDisabled(RTW_REMOVE)) return false;
00300
00301
00302 for (uint i = RTW_BUILD_NS; i <= RTW_BUILD_STATION; i++) {
00303 if ((i <= RTW_AUTORAIL || i >= RTW_BUILD_WAYPOINT) && w->IsWidgetLowered(i)) {
00304 ToggleRailButton_Remove(w);
00305 return true;
00306 }
00307 }
00308
00309 return false;
00310 }
00311
00312
00313 static void BuildRailClick_N(Window *w)
00314 {
00315 HandlePlacePushButton(w, RTW_BUILD_NS, GetRailTypeInfo(_cur_railtype)->cursor.rail_ns, VHM_RECT, PlaceRail_N);
00316 }
00317
00318 static void BuildRailClick_NE(Window *w)
00319 {
00320 HandlePlacePushButton(w, RTW_BUILD_X, GetRailTypeInfo(_cur_railtype)->cursor.rail_swne, VHM_RECT, PlaceRail_NE);
00321 }
00322
00323 static void BuildRailClick_E(Window *w)
00324 {
00325 HandlePlacePushButton(w, RTW_BUILD_EW, GetRailTypeInfo(_cur_railtype)->cursor.rail_ew, VHM_RECT, PlaceRail_E);
00326 }
00327
00328 static void BuildRailClick_NW(Window *w)
00329 {
00330 HandlePlacePushButton(w, RTW_BUILD_Y, GetRailTypeInfo(_cur_railtype)->cursor.rail_nwse, VHM_RECT, PlaceRail_NW);
00331 }
00332
00333 static void BuildRailClick_AutoRail(Window *w)
00334 {
00335 HandlePlacePushButton(w, RTW_AUTORAIL, GetRailTypeInfo(_cur_railtype)->cursor.autorail, VHM_RAIL, PlaceRail_AutoRail);
00336 }
00337
00338 static void BuildRailClick_Demolish(Window *w)
00339 {
00340 HandlePlacePushButton(w, RTW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceProc_DemolishArea);
00341 }
00342
00343 static void BuildRailClick_Depot(Window *w)
00344 {
00345 if (HandlePlacePushButton(w, RTW_BUILD_DEPOT, GetRailTypeInfo(_cur_railtype)->cursor.depot, VHM_RECT, PlaceRail_Depot)) {
00346 ShowBuildTrainDepotPicker();
00347 }
00348 }
00349
00350 static void BuildRailClick_Waypoint(Window *w)
00351 {
00352 _waypoint_count = GetNumCustomStations(STAT_CLASS_WAYP);
00353 if (HandlePlacePushButton(w, RTW_BUILD_WAYPOINT, SPR_CURSOR_WAYPOINT, VHM_RECT, PlaceRail_Waypoint) &&
00354 _waypoint_count > 1) {
00355 ShowBuildWaypointPicker();
00356 }
00357 }
00358
00359 static void BuildRailClick_Station(Window *w)
00360 {
00361 if (HandlePlacePushButton(w, RTW_BUILD_STATION, SPR_CURSOR_RAIL_STATION, VHM_RECT, PlaceRail_Station)) ShowStationBuilder();
00362 }
00363
00365 static void BuildRailClick_AutoSignals(Window *w)
00366 {
00367 if (_patches.enable_signal_gui) {
00368 if (HandlePlacePushButton(w, RTW_BUILD_SIGNALS, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals)) ShowSignalBuilder();
00369 } else {
00370 HandlePlacePushButton(w, RTW_BUILD_SIGNALS, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals);
00371 }
00372 }
00373
00374 static void BuildRailClick_Bridge(Window *w)
00375 {
00376 HandlePlacePushButton(w, RTW_BUILD_BRIDGE, SPR_CURSOR_BRIDGE, VHM_RECT, PlaceRail_Bridge);
00377 }
00378
00379 static void BuildRailClick_Tunnel(Window *w)
00380 {
00381 HandlePlacePushButton(w, RTW_BUILD_TUNNEL, GetRailTypeInfo(_cur_railtype)->cursor.tunnel, VHM_SPECIAL, PlaceRail_Tunnel);
00382 }
00383
00384 static void BuildRailClick_Remove(Window *w)
00385 {
00386 if (w->IsWidgetDisabled(RTW_REMOVE)) return;
00387 ToggleRailButton_Remove(w);
00388 SndPlayFx(SND_15_BEEP);
00389
00390
00391 if (w->IsWidgetLowered(RTW_BUILD_STATION)) {
00392 if (_remove_button_clicked) {
00393
00394 if (!_railstation.dragdrop) {
00395 SetTileSelectSize(1, 1);
00396 } else {
00397 VpSetPlaceSizingLimit(-1);
00398 }
00399 } else {
00400
00401 if (!_railstation.dragdrop) {
00402 int x = _railstation.numtracks;
00403 int y = _railstation.platlength;
00404 if (_railstation.orientation == 0) Swap(x, y);
00405 SetTileSelectSize(x, y);
00406 } else {
00407 VpSetPlaceSizingLimit(_patches.station_spread);
00408 }
00409 }
00410 }
00411 }
00412
00413 static void BuildRailClick_Convert(Window *w)
00414 {
00415 HandlePlacePushButton(w, RTW_CONVERT_RAIL, GetRailTypeInfo(_cur_railtype)->cursor.convert, VHM_RECT, PlaceRail_ConvertRail);
00416 }
00417
00418
00419 static void DoRailroadTrack(int mode)
00420 {
00421 DoCommandP(TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), _cur_railtype | (mode << 4), NULL,
00422 _remove_button_clicked ?
00423 CMD_REMOVE_RAILROAD_TRACK | CMD_NO_WATER | CMD_MSG(STR_1012_CAN_T_REMOVE_RAILROAD_TRACK) :
00424 CMD_BUILD_RAILROAD_TRACK | CMD_NO_WATER | CMD_MSG(STR_1011_CAN_T_BUILD_RAILROAD_TRACK)
00425 );
00426 }
00427
00428 static void HandleAutodirPlacement()
00429 {
00430 TileHighlightData *thd = &_thd;
00431 int trackstat = thd->drawstyle & 0xF;
00432
00433 if (thd->drawstyle & HT_RAIL) {
00434 GenericPlaceRail(TileVirtXY(thd->selend.x, thd->selend.y), trackstat);
00435 return;
00436 }
00437
00438 DoRailroadTrack(trackstat);
00439 }
00440
00447 static void HandleAutoSignalPlacement()
00448 {
00449 TileHighlightData *thd = &_thd;
00450 uint32 p2 = GB(thd->drawstyle, 0, 3);
00451
00452 if (thd->drawstyle == HT_RECT) {
00453 GenericPlaceSignals(TileVirtXY(thd->selend.x, thd->selend.y));
00454 return;
00455 }
00456
00457
00458 SB(p2, 3, 1, 0);
00459 SB(p2, 4, 1, _cur_year < _patches.semaphore_build_before);
00460 SB(p2, 6, 1, _ctrl_pressed);
00461 SB(p2, 24, 8, _patches.drag_signals_density);
00462
00463
00464
00465 DoCommandP(
00466 TileVirtXY(thd->selstart.x, thd->selstart.y),
00467 TileVirtXY(thd->selend.x, thd->selend.y),
00468 p2,
00469 CcPlaySound1E,
00470 _remove_button_clicked ?
00471 CMD_REMOVE_SIGNAL_TRACK | CMD_NO_WATER | CMD_MSG(STR_1013_CAN_T_REMOVE_SIGNALS_FROM) :
00472 CMD_BUILD_SIGNAL_TRACK | CMD_NO_WATER | CMD_MSG(STR_1010_CAN_T_BUILD_SIGNALS_HERE)
00473 );
00474 }
00475
00476
00477 typedef void OnButtonClick(Window *w);
00478
00479 static OnButtonClick * const _build_railroad_button_proc[] = {
00480 BuildRailClick_N,
00481 BuildRailClick_NE,
00482 BuildRailClick_E,
00483 BuildRailClick_NW,
00484 BuildRailClick_AutoRail,
00485 BuildRailClick_Demolish,
00486 BuildRailClick_Depot,
00487 BuildRailClick_Waypoint,
00488 BuildRailClick_Station,
00489 BuildRailClick_AutoSignals,
00490 BuildRailClick_Bridge,
00491 BuildRailClick_Tunnel,
00492 BuildRailClick_Remove,
00493 BuildRailClick_Convert
00494 };
00495
00496 static const uint16 _rail_keycodes[] = {
00497 '1',
00498 '2',
00499 '3',
00500 '4',
00501 '5',
00502 '6',
00503 '7',
00504 '8',
00505 '9',
00506 'S',
00507 'B',
00508 'T',
00509 'R',
00510 'C',
00511 };
00512
00513
00514 static void UpdateRemoveWidgetStatus(Window *w, int clicked_widget)
00515 {
00516 switch (clicked_widget) {
00517 case RTW_REMOVE:
00518
00519
00520 return;
00521 break;
00522 case RTW_BUILD_NS:
00523 case RTW_BUILD_X:
00524 case RTW_BUILD_EW:
00525 case RTW_BUILD_Y:
00526 case RTW_AUTORAIL:
00527 case RTW_BUILD_WAYPOINT:
00528 case RTW_BUILD_STATION:
00529 case RTW_BUILD_SIGNALS:
00530
00531
00532 w->SetWidgetDisabledState(RTW_REMOVE, !w->IsWidgetLowered(clicked_widget));
00533 break;
00534
00535 default:
00536
00537
00538 w->DisableWidget(RTW_REMOVE);
00539 w->RaiseWidget(RTW_REMOVE);
00540 break;
00541 }
00542 }
00543
00550 static void BuildRailToolbWndProc(Window *w, WindowEvent *e)
00551 {
00552 switch (e->event) {
00553 case WE_CREATE: w->DisableWidget(RTW_REMOVE); break;
00554
00555 case WE_PAINT: DrawWindowWidgets(w); break;
00556
00557 case WE_CLICK:
00558 if (e->we.click.widget >= RTW_BUILD_NS) {
00559 _remove_button_clicked = false;
00560 _build_railroad_button_proc[e->we.click.widget - RTW_BUILD_NS](w);
00561 }
00562 UpdateRemoveWidgetStatus(w, e->we.click.widget);
00563 if (_ctrl_pressed) RailToolbar_CtrlChanged(w);
00564 break;
00565
00566 case WE_KEYPRESS:
00567 for (uint8 i = 0; i != lengthof(_rail_keycodes); i++) {
00568 if (e->we.keypress.keycode == _rail_keycodes[i]) {
00569 e->we.keypress.cont = false;
00570 _remove_button_clicked = false;
00571 _build_railroad_button_proc[i](w);
00572 UpdateRemoveWidgetStatus(w, i + RTW_BUILD_NS);
00573 if (_ctrl_pressed) RailToolbar_CtrlChanged(w);
00574 break;
00575 }
00576 }
00577 MarkTileDirty(_thd.pos.x, _thd.pos.y);
00578 break;
00579
00580 case WE_PLACE_OBJ:
00581 _place_proc(e->we.place.tile);
00582 return;
00583
00584 case WE_PLACE_DRAG: {
00585
00586 if (FindWindowById(WC_BUILD_SIGNAL, 0) != NULL && _convert_signal_button && w->IsWidgetLowered(RTW_BUILD_SIGNALS)) return;
00587
00588 VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
00589 return;
00590 }
00591
00592 case WE_PLACE_MOUSEUP:
00593 if (e->we.place.pt.x != -1) {
00594 TileIndex start_tile = e->we.place.starttile;
00595 TileIndex end_tile = e->we.place.tile;
00596
00597 switch (e->we.place.select_proc) {
00598 case DDSP_BUILD_BRIDGE:
00599 ResetObjectToPlace();
00600 ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype);
00601 break;
00602
00603 case DDSP_PLACE_AUTORAIL:
00604 HandleAutodirPlacement();
00605 break;
00606
00607 case DDSP_BUILD_SIGNALS:
00608 HandleAutoSignalPlacement();
00609 break;
00610
00611 case DDSP_DEMOLISH_AREA:
00612 GUIPlaceProcDragXY(e);
00613 break;
00614
00615 case DDSP_CONVERT_RAIL:
00616 DoCommandP(end_tile, start_tile, _cur_railtype, CcPlaySound10, CMD_CONVERT_RAIL | CMD_MSG(STR_CANT_CONVERT_RAIL));
00617 break;
00618
00619 case DDSP_REMOVE_STATION:
00620 case DDSP_BUILD_STATION:
00621 if (_remove_button_clicked) {
00622 DoCommandP(end_tile, start_tile, 0, CcPlaySound1E, CMD_REMOVE_FROM_RAILROAD_STATION | CMD_MSG(STR_CANT_REMOVE_PART_OF_STATION));
00623 break;
00624 }
00625 HandleStationPlacement(start_tile, end_tile);
00626 break;
00627
00628 case DDSP_PLACE_RAIL_NE:
00629 case DDSP_PLACE_RAIL_NW:
00630 DoRailroadTrack(e->we.place.select_proc == DDSP_PLACE_RAIL_NE ? TRACK_X : TRACK_Y);
00631 break;
00632 }
00633 }
00634 break;
00635
00636 case WE_ABORT_PLACE_OBJ:
00637 w->RaiseButtons();
00638 w->DisableWidget(RTW_REMOVE);
00639 w->InvalidateWidget(RTW_REMOVE);
00640
00641 w = FindWindowById(WC_BUILD_SIGNAL, 0);
00642 if (w != NULL) WP(w, def_d).close = true;
00643 w = FindWindowById(WC_BUILD_STATION, 0);
00644 if (w != NULL) WP(w, def_d).close = true;
00645 w = FindWindowById(WC_BUILD_DEPOT, 0);
00646 if (w != NULL) WP(w, def_d).close = true;
00647 break;
00648
00649 case WE_PLACE_PRESIZE: {
00650 TileIndex tile = e->we.place.tile;
00651
00652 DoCommand(tile, 0, 0, DC_AUTO, CMD_BUILD_TUNNEL);
00653 VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
00654 } break;
00655
00656 case WE_DESTROY:
00657 if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
00658 break;
00659
00660 case WE_CTRL_CHANGED:
00661
00662 if (!w->IsWidgetLowered(RTW_BUILD_STATION) && RailToolbar_CtrlChanged(w)) e->we.ctrl.cont = false;
00663 break;
00664 }
00665 }
00666
00668 static const Widget _build_rail_widgets[] = {
00669 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00670 { WWT_CAPTION, RESIZE_NONE, 7, 11, 337, 0, 13, STR_100A_RAILROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
00671 { WWT_STICKYBOX, RESIZE_NONE, 7, 338, 349, 0, 13, 0x0, STR_STICKY_BUTTON},
00672
00673 { WWT_PANEL, RESIZE_NONE, 7, 110, 113, 14, 35, 0x0, STR_NULL},
00674
00675 { WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_RAIL_NS, STR_1018_BUILD_RAILROAD_TRACK},
00676 { WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_RAIL_NE, STR_1018_BUILD_RAILROAD_TRACK},
00677 { WWT_IMGBTN, RESIZE_NONE, 7, 44, 65, 14, 35, SPR_IMG_RAIL_EW, STR_1018_BUILD_RAILROAD_TRACK},
00678 { WWT_IMGBTN, RESIZE_NONE, 7, 66, 87, 14, 35, SPR_IMG_RAIL_NW, STR_1018_BUILD_RAILROAD_TRACK},
00679 { WWT_IMGBTN, RESIZE_NONE, 7, 88, 109, 14, 35, SPR_IMG_AUTORAIL, STR_BUILD_AUTORAIL_TIP},
00680
00681 { WWT_IMGBTN, RESIZE_NONE, 7, 114, 135, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC},
00682 { WWT_IMGBTN, RESIZE_NONE, 7, 136, 157, 14, 35, SPR_IMG_DEPOT_RAIL, STR_1019_BUILD_TRAIN_DEPOT_FOR_BUILDING},
00683 { WWT_IMGBTN, RESIZE_NONE, 7, 158, 179, 14, 35, SPR_IMG_WAYPOINT, STR_CONVERT_RAIL_TO_WAYPOINT_TIP},
00684
00685 { WWT_IMGBTN, RESIZE_NONE, 7, 180, 221, 14, 35, SPR_IMG_RAIL_STATION, STR_101A_BUILD_RAILROAD_STATION},
00686 { WWT_IMGBTN, RESIZE_NONE, 7, 222, 243, 14, 35, SPR_IMG_RAIL_SIGNALS, STR_101B_BUILD_RAILROAD_SIGNALS},
00687 { WWT_IMGBTN, RESIZE_NONE, 7, 244, 285, 14, 35, SPR_IMG_BRIDGE, STR_101C_BUILD_RAILROAD_BRIDGE},
00688 { WWT_IMGBTN, RESIZE_NONE, 7, 286, 305, 14, 35, SPR_IMG_TUNNEL_RAIL, STR_101D_BUILD_RAILROAD_TUNNEL},
00689 { WWT_IMGBTN, RESIZE_NONE, 7, 306, 327, 14, 35, SPR_IMG_REMOVE, STR_101E_TOGGLE_BUILD_REMOVE_FOR},
00690 { WWT_IMGBTN, RESIZE_NONE, 7, 328, 349, 14, 35, SPR_IMG_CONVERT_RAIL, STR_CONVERT_RAIL_TIP},
00691
00692 { WIDGETS_END},
00693 };
00694
00695 static const WindowDesc _build_rail_desc = {
00696 WDP_ALIGN_TBR, 22, 350, 36, 350, 36,
00697 WC_BUILD_TOOLBAR, WC_NONE,
00698 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
00699 _build_rail_widgets,
00700 BuildRailToolbWndProc
00701 };
00702
00703
00708 static void SetupRailToolbar(RailType railtype, Window *w)
00709 {
00710 const RailtypeInfo *rti = GetRailTypeInfo(railtype);
00711
00712 assert(railtype < RAILTYPE_END);
00713 w->widget[RTW_CAPTION].data = rti->strings.toolbar_caption;
00714 w->widget[RTW_BUILD_NS].data = rti->gui_sprites.build_ns_rail;
00715 w->widget[RTW_BUILD_X].data = rti->gui_sprites.build_x_rail;
00716 w->widget[RTW_BUILD_EW].data = rti->gui_sprites.build_ew_rail;
00717 w->widget[RTW_BUILD_Y].data = rti->gui_sprites.build_y_rail;
00718 w->widget[RTW_AUTORAIL].data = rti->gui_sprites.auto_rail;
00719 w->widget[RTW_BUILD_DEPOT].data = rti->gui_sprites.build_depot;
00720 w->widget[RTW_CONVERT_RAIL].data = rti->gui_sprites.convert_rail;
00721 w->widget[RTW_BUILD_TUNNEL].data = rti->gui_sprites.build_tunnel;
00722 }
00723
00724 void ShowBuildRailToolbar(RailType railtype, int button)
00725 {
00726 Window *w;
00727
00728 if (!IsValidPlayer(_current_player)) return;
00729 if (!ValParamRailtype(railtype)) return;
00730
00731
00732 if (button < 0 || !(w = FindWindowById(WC_BUILD_TOOLBAR, 0)) || w->wndproc != BuildRailToolbWndProc) {
00733 DeleteWindowById(WC_BUILD_TOOLBAR, 0);
00734 _cur_railtype = railtype;
00735 w = AllocateWindowDesc(&_build_rail_desc);
00736 SetupRailToolbar(railtype, w);
00737 }
00738
00739 _remove_button_clicked = false;
00740 if (w != NULL && button >= RTW_CLOSEBOX) {
00741 _build_railroad_button_proc[button](w);
00742 UpdateRemoveWidgetStatus(w, button + RTW_BUILD_NS);
00743 }
00744 if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
00745 }
00746
00748 enum BuildRailStationWidgets {
00749 BRSW_CLOSEBOX = 0,
00750 BRSW_CAPTION,
00751 BRSW_BACKGROUND,
00752
00753 BRSW_PLATFORM_DIR_X,
00754 BRSW_PLATFORM_DIR_Y,
00755
00756 BRSW_PLATFORM_NUM_BEGIN = BRSW_PLATFORM_DIR_Y,
00757 BRSW_PLATFORM_NUM_1,
00758 BRSW_PLATFORM_NUM_2,
00759 BRSW_PLATFORM_NUM_3,
00760 BRSW_PLATFORM_NUM_4,
00761 BRSW_PLATFORM_NUM_5,
00762 BRSW_PLATFORM_NUM_6,
00763 BRSW_PLATFORM_NUM_7,
00764
00765 BRSW_PLATFORM_LEN_BEGIN = BRSW_PLATFORM_NUM_7,
00766 BRSW_PLATFORM_LEN_1,
00767 BRSW_PLATFORM_LEN_2,
00768 BRSW_PLATFORM_LEN_3,
00769 BRSW_PLATFORM_LEN_4,
00770 BRSW_PLATFORM_LEN_5,
00771 BRSW_PLATFORM_LEN_6,
00772 BRSW_PLATFORM_LEN_7,
00773
00774 BRSW_PLATFORM_DRAG_N_DROP,
00775
00776 BRSW_HIGHLIGHT_OFF,
00777 BRSW_HIGHLIGHT_ON,
00778
00779 BRSW_NEWST_DROPDOWN,
00780 BRSW_NEWST_LIST,
00781 BRSW_NEWST_SCROLL
00782 };
00783
00784
00785
00786
00787 static void HandleStationPlacement(TileIndex start, TileIndex end)
00788 {
00789 uint sx = TileX(start);
00790 uint sy = TileY(start);
00791 uint ex = TileX(end);
00792 uint ey = TileY(end);
00793 uint w,h;
00794
00795 if (sx > ex) Swap(sx, ex);
00796 if (sy > ey) Swap(sy, ey);
00797 w = ex - sx + 1;
00798 h = ey - sy + 1;
00799 if (!_railstation.orientation) Swap(w, h);
00800
00801 DoCommandP(TileXY(sx, sy),
00802 _railstation.orientation | (w << 8) | (h << 16) | (_ctrl_pressed << 24),
00803 _cur_railtype | (_railstation.station_class << 8) | (_railstation.station_type << 16), CcStation,
00804 CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION));
00805 }
00806
00807
00808 static void CheckSelectedSize(Window *w, const StationSpec *statspec)
00809 {
00810 if (statspec == NULL || _railstation.dragdrop) return;
00811
00812 if (HasBit(statspec->disallowed_platforms, _railstation.numtracks - 1)) {
00813 w->RaiseWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
00814 _railstation.numtracks = 1;
00815 while (HasBit(statspec->disallowed_platforms, _railstation.numtracks - 1)) {
00816 _railstation.numtracks++;
00817 }
00818 w->LowerWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
00819 }
00820
00821 if (HasBit(statspec->disallowed_lengths, _railstation.platlength - 1)) {
00822 w->RaiseWidget(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN);
00823 _railstation.platlength = 1;
00824 while (HasBit(statspec->disallowed_lengths, _railstation.platlength - 1)) {
00825 _railstation.platlength++;
00826 }
00827 w->LowerWidget(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN);
00828 }
00829 }
00830
00831 static DropDownList *BuildStationClassDropDown()
00832 {
00833 DropDownList *list = new DropDownList();
00834
00835 for (uint i = 0; i < GetNumStationClasses(); i++) {
00836 if (i == STAT_CLASS_WAYP) continue;
00837 list->push_back(new DropDownListStringItem(GetStationClassName((StationClassID)i), i, false));
00838 }
00839
00840 return list;
00841 }
00842
00843 static void StationBuildWndProc(Window *w, WindowEvent *e)
00844 {
00845 switch (e->event) {
00846 case WE_CREATE:
00847 w->LowerWidget(_railstation.orientation + BRSW_PLATFORM_DIR_X);
00848 if (_railstation.dragdrop) {
00849 w->LowerWidget(BRSW_PLATFORM_DRAG_N_DROP);
00850 } else {
00851 w->LowerWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
00852 w->LowerWidget(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN);
00853 }
00854 w->SetWidgetLoweredState(BRSW_HIGHLIGHT_OFF, !_station_show_coverage);
00855 w->SetWidgetLoweredState(BRSW_HIGHLIGHT_ON, _station_show_coverage);
00856 break;
00857
00858 case WE_PAINT: {
00859 bool newstations = _railstation.newstations;
00860 DrawPixelInfo tmp_dpi, *old_dpi;
00861 const StationSpec *statspec = newstations ? GetCustomStationSpec(_railstation.station_class, _railstation.station_type) : NULL;
00862
00863 if (WP(w, def_d).close) return;
00864
00865 if (_railstation.dragdrop) {
00866 SetTileSelectSize(1, 1);
00867 } else {
00868 int x = _railstation.numtracks;
00869 int y = _railstation.platlength;
00870 if (_railstation.orientation == 0) Swap(x, y);
00871 if (!_remove_button_clicked)
00872 SetTileSelectSize(x, y);
00873 }
00874
00875 int rad = (_patches.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED;
00876
00877 if (_station_show_coverage)
00878 SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
00879
00880 for (uint bits = 0; bits < 7; bits++) {
00881 bool disable = bits >= _patches.station_spread;
00882 if (statspec == NULL) {
00883 w->SetWidgetDisabledState(bits + BRSW_PLATFORM_NUM_1, disable);
00884 w->SetWidgetDisabledState(bits + BRSW_PLATFORM_LEN_1, disable);
00885 } else {
00886 w->SetWidgetDisabledState(bits + BRSW_PLATFORM_NUM_1, HasBit(statspec->disallowed_platforms, bits) || disable);
00887 w->SetWidgetDisabledState(bits + BRSW_PLATFORM_LEN_1, HasBit(statspec->disallowed_lengths, bits) || disable);
00888 }
00889 }
00890
00891 SetDParam(0, GetStationClassName(_railstation.station_class));
00892 DrawWindowWidgets(w);
00893
00894 int y_offset = newstations ? 90 : 0;
00895
00896
00897 if (FillDrawPixelInfo(&tmp_dpi, 7, 26 + y_offset, 66, 48)) {
00898 old_dpi = _cur_dpi;
00899 _cur_dpi = &tmp_dpi;
00900 if (!DrawStationTile(32, 16, _cur_railtype, AXIS_X, _railstation.station_class, _railstation.station_type)) {
00901 StationPickerDrawSprite(32, 16, STATION_RAIL, _cur_railtype, INVALID_ROADTYPE, 2);
00902 }
00903 _cur_dpi = old_dpi;
00904 }
00905
00906
00907 if (FillDrawPixelInfo(&tmp_dpi, 75, 26 + y_offset, 66, 48)) {
00908 old_dpi = _cur_dpi;
00909 _cur_dpi = &tmp_dpi;
00910 if (!DrawStationTile(32, 16, _cur_railtype, AXIS_Y, _railstation.station_class, _railstation.station_type)) {
00911 StationPickerDrawSprite(32, 16, STATION_RAIL, _cur_railtype, INVALID_ROADTYPE, 3);
00912 }
00913 _cur_dpi = old_dpi;
00914 }
00915
00916 DrawStringCentered(74, 15 + y_offset, STR_3002_ORIENTATION, TC_FROMSTRING);
00917 DrawStringCentered(74, 76 + y_offset, STR_3003_NUMBER_OF_TRACKS, TC_FROMSTRING);
00918 DrawStringCentered(74, 101 + y_offset, STR_3004_PLATFORM_LENGTH, TC_FROMSTRING);
00919 DrawStringCentered(74, 141 + y_offset, STR_3066_COVERAGE_AREA_HIGHLIGHT, TC_FROMSTRING);
00920
00921 int text_end = DrawStationCoverageAreaText(2, 166 + y_offset, SCT_ALL, rad) + 4;
00922 if (text_end > w->widget[BRSW_BACKGROUND].bottom) {
00923 SetWindowDirty(w);
00924 ResizeWindowForWidget(w, BRSW_BACKGROUND, 0, text_end - w->widget[BRSW_BACKGROUND].bottom);
00925 SetWindowDirty(w);
00926 }
00927
00928 if (newstations) {
00929 uint y = 35;
00930
00931 for (uint16 i = w->vscroll.pos; i < _railstation.station_count && i < (uint)(w->vscroll.pos + w->vscroll.cap); i++) {
00932 const StationSpec *statspec = GetCustomStationSpec(_railstation.station_class, i);
00933
00934 if (statspec != NULL && statspec->name != 0) {
00935 if (HasBit(statspec->callbackmask, CBM_STATION_AVAIL) && GB(GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE), 0, 8) == 0) {
00936 GfxFillRect(8, y - 2, 127, y + 10, (1 << PALETTE_MODIFIER_GREYOUT));
00937 }
00938
00939 DrawStringTruncated(9, y, statspec->name, i == _railstation.station_type ? TC_WHITE : TC_BLACK, 118);
00940 } else {
00941 DrawStringTruncated(9, y, STR_STAT_CLASS_DFLT, i == _railstation.station_type ? TC_WHITE : TC_BLACK, 118);
00942 }
00943
00944 y += 14;
00945 }
00946 }
00947 } break;
00948
00949 case WE_CLICK: {
00950 switch (e->we.click.widget) {
00951 case BRSW_PLATFORM_DIR_X:
00952 case BRSW_PLATFORM_DIR_Y:
00953 w->RaiseWidget(_railstation.orientation + BRSW_PLATFORM_DIR_X);
00954 _railstation.orientation = e->we.click.widget - BRSW_PLATFORM_DIR_X;
00955 w->LowerWidget(_railstation.orientation + BRSW_PLATFORM_DIR_X);
00956 SndPlayFx(SND_15_BEEP);
00957 SetWindowDirty(w);
00958 break;
00959
00960 case BRSW_PLATFORM_NUM_1:
00961 case BRSW_PLATFORM_NUM_2:
00962 case BRSW_PLATFORM_NUM_3:
00963 case BRSW_PLATFORM_NUM_4:
00964 case BRSW_PLATFORM_NUM_5:
00965 case BRSW_PLATFORM_NUM_6:
00966 case BRSW_PLATFORM_NUM_7: {
00967 w->RaiseWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
00968 w->RaiseWidget(BRSW_PLATFORM_DRAG_N_DROP);
00969
00970 _railstation.numtracks = e->we.click.widget - BRSW_PLATFORM_NUM_BEGIN;
00971 _railstation.dragdrop = false;
00972
00973 const StationSpec *statspec = _railstation.newstations ? GetCustomStationSpec(_railstation.station_class, _railstation.station_type) : NULL;
00974 if (statspec != NULL && HasBit(statspec->disallowed_lengths, _railstation.platlength - 1)) {
00975
00976 for (uint i = 0; i < 7; i++) {
00977 if (!HasBit(statspec->disallowed_lengths, i)) {
00978 w->RaiseWidget(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN);
00979 _railstation.platlength = i + 1;
00980 break;
00981 }
00982 }
00983 }
00984
00985 w->LowerWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
00986 w->LowerWidget(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN);
00987 SndPlayFx(SND_15_BEEP);
00988 SetWindowDirty(w);
00989 break;
00990 }
00991
00992 case BRSW_PLATFORM_LEN_1:
00993 case BRSW_PLATFORM_LEN_2:
00994 case BRSW_PLATFORM_LEN_3:
00995 case BRSW_PLATFORM_LEN_4:
00996 case BRSW_PLATFORM_LEN_5:
00997 case BRSW_PLATFORM_LEN_6:
00998 case BRSW_PLATFORM_LEN_7: {
00999 w->RaiseWidget(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN);
01000 w->RaiseWidget(BRSW_PLATFORM_DRAG_N_DROP);
01001
01002 _railstation.platlength = e->we.click.widget - BRSW_PLATFORM_LEN_BEGIN;
01003 _railstation.dragdrop = false;
01004
01005 const StationSpec *statspec = _railstation.newstations ? GetCustomStationSpec(_railstation.station_class, _railstation.station_type) : NULL;
01006 if (statspec != NULL && HasBit(statspec->disallowed_platforms, _railstation.numtracks - 1)) {
01007
01008 for (uint i = 0; i < 7; i++) {
01009 if (!HasBit(statspec->disallowed_platforms, i)) {
01010 w->RaiseWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
01011 _railstation.numtracks = i + 1;
01012 break;
01013 }
01014 }
01015 }
01016
01017 w->LowerWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
01018 w->LowerWidget(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN);
01019 SndPlayFx(SND_15_BEEP);
01020 SetWindowDirty(w);
01021 break;
01022 }
01023
01024 case BRSW_PLATFORM_DRAG_N_DROP: {
01025 _railstation.dragdrop ^= true;
01026 w->ToggleWidgetLoweredState(BRSW_PLATFORM_DRAG_N_DROP);
01027
01028
01029 const StationSpec *statspec = _railstation.newstations ? GetCustomStationSpec(_railstation.station_class, _railstation.station_type) : NULL;
01030 if (statspec != NULL && HasBit(statspec->disallowed_lengths, _railstation.platlength - 1)) {
01031 for (uint i = 0; i < 7; i++) {
01032 if (!HasBit(statspec->disallowed_lengths, i)) {
01033 w->RaiseWidget(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN);
01034 _railstation.platlength = i + 1;
01035 break;
01036 }
01037 }
01038 }
01039 if (statspec != NULL && HasBit(statspec->disallowed_platforms, _railstation.numtracks - 1)) {
01040 for (uint i = 0; i < 7; i++) {
01041 if (!HasBit(statspec->disallowed_platforms, i)) {
01042 w->RaiseWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN);
01043 _railstation.numtracks = i + 1;
01044 break;
01045 }
01046 }
01047 }
01048
01049 w->SetWidgetLoweredState(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN, !_railstation.dragdrop);
01050 w->SetWidgetLoweredState(_railstation.platlength + BRSW_PLATFORM_LEN_BEGIN, !_railstation.dragdrop);
01051 SndPlayFx(SND_15_BEEP);
01052 SetWindowDirty(w);
01053 } break;
01054
01055 case BRSW_HIGHLIGHT_OFF:
01056 case BRSW_HIGHLIGHT_ON:
01057 _station_show_coverage = (e->we.click.widget != BRSW_HIGHLIGHT_OFF);
01058 w->SetWidgetLoweredState(BRSW_HIGHLIGHT_OFF, !_station_show_coverage);
01059 w->SetWidgetLoweredState(BRSW_HIGHLIGHT_ON, _station_show_coverage);
01060 SndPlayFx(SND_15_BEEP);
01061 SetWindowDirty(w);
01062 break;
01063
01064 case BRSW_NEWST_DROPDOWN:
01065 ShowDropDownList(w, BuildStationClassDropDown(), _railstation.station_class, BRSW_NEWST_DROPDOWN);
01066 break;
01067
01068 case BRSW_NEWST_LIST: {
01069 const StationSpec *statspec;
01070 int y = (e->we.click.pt.y - 32) / 14;
01071
01072 if (y >= w->vscroll.cap) return;
01073 y += w->vscroll.pos;
01074 if (y >= _railstation.station_count) return;
01075
01076
01077 statspec = GetCustomStationSpec(_railstation.station_class, y);
01078 if (statspec != NULL &&
01079 HasBit(statspec->callbackmask, CBM_STATION_AVAIL) &&
01080 GB(GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE), 0, 8) == 0) return;
01081
01082 _railstation.station_type = y;
01083
01084 CheckSelectedSize(w, statspec);
01085
01086 SndPlayFx(SND_15_BEEP);
01087 SetWindowDirty(w);
01088 break;
01089 }
01090 }
01091 } break;
01092
01093 case WE_DROPDOWN_SELECT:
01094 if (_railstation.station_class != e->we.dropdown.index) {
01095 _railstation.station_class = (StationClassID)e->we.dropdown.index;
01096 _railstation.station_type = 0;
01097 _railstation.station_count = GetNumCustomStations(_railstation.station_class);
01098
01099 CheckSelectedSize(w, GetCustomStationSpec(_railstation.station_class, _railstation.station_type));
01100
01101 w->vscroll.count = _railstation.station_count;
01102 w->vscroll.pos = _railstation.station_type;
01103 }
01104
01105 SndPlayFx(SND_15_BEEP);
01106 SetWindowDirty(w);
01107 break;
01108
01109 case WE_MOUSELOOP:
01110 if (WP(w, def_d).close) {
01111 DeleteWindow(w);
01112 return;
01113 }
01114 CheckRedrawStationCoverage(w);
01115 break;
01116
01117 case WE_DESTROY:
01118 if (!WP(w, def_d).close) ResetObjectToPlace();
01119 break;
01120 }
01121 }
01122
01124 static const Widget _station_builder_widgets[] = {
01125 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
01126 { WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3000_RAIL_STATION_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
01127 { WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 199, 0x0, STR_NULL},
01128 { WWT_PANEL, RESIZE_NONE, 14, 7, 72, 26, 73, 0x0, STR_304E_SELECT_RAILROAD_STATION},
01129 { WWT_PANEL, RESIZE_NONE, 14, 75, 140, 26, 73, 0x0, STR_304E_SELECT_RAILROAD_STATION},
01130
01131 { WWT_TEXTBTN, RESIZE_NONE, 14, 22, 36, 87, 98, STR_00CB_1, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01132 { WWT_TEXTBTN, RESIZE_NONE, 14, 37, 51, 87, 98, STR_00CC_2, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01133 { WWT_TEXTBTN, RESIZE_NONE, 14, 52, 66, 87, 98, STR_00CD_3, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01134 { WWT_TEXTBTN, RESIZE_NONE, 14, 67, 81, 87, 98, STR_00CE_4, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01135 { WWT_TEXTBTN, RESIZE_NONE, 14, 82, 96, 87, 98, STR_00CF_5, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01136 { WWT_TEXTBTN, RESIZE_NONE, 14, 97, 111, 87, 98, STR_6, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01137 { WWT_TEXTBTN, RESIZE_NONE, 14, 112, 126, 87, 98, STR_7, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01138
01139 { WWT_TEXTBTN, RESIZE_NONE, 14, 22, 36, 112, 123, STR_00CB_1, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01140 { WWT_TEXTBTN, RESIZE_NONE, 14, 37, 51, 112, 123, STR_00CC_2, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01141 { WWT_TEXTBTN, RESIZE_NONE, 14, 52, 66, 112, 123, STR_00CD_3, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01142 { WWT_TEXTBTN, RESIZE_NONE, 14, 67, 81, 112, 123, STR_00CE_4, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01143 { WWT_TEXTBTN, RESIZE_NONE, 14, 82, 96, 112, 123, STR_00CF_5, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01144 { WWT_TEXTBTN, RESIZE_NONE, 14, 97, 111, 112, 123, STR_6, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01145 { WWT_TEXTBTN, RESIZE_NONE, 14, 112, 126, 112, 123, STR_7, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01146
01147 { WWT_TEXTBTN, RESIZE_NONE, 14, 37, 111, 126, 137, STR_DRAG_DROP, STR_STATION_DRAG_DROP},
01148 { WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 152, 163, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
01149 { WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 152, 163, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
01150 { WIDGETS_END},
01151 };
01152
01154 static const Widget _newstation_builder_widgets[] = {
01155 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
01156 { WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3000_RAIL_STATION_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
01157 { WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 289, 0x0, STR_NULL},
01158 { WWT_PANEL, RESIZE_NONE, 14, 7, 72, 116, 163, 0x0, STR_304E_SELECT_RAILROAD_STATION},
01159 { WWT_PANEL, RESIZE_NONE, 14, 75, 140, 116, 163, 0x0, STR_304E_SELECT_RAILROAD_STATION},
01160
01161 { WWT_TEXTBTN, RESIZE_NONE, 14, 22, 36, 177, 188, STR_00CB_1, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01162 { WWT_TEXTBTN, RESIZE_NONE, 14, 37, 51, 177, 188, STR_00CC_2, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01163 { WWT_TEXTBTN, RESIZE_NONE, 14, 52, 66, 177, 188, STR_00CD_3, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01164 { WWT_TEXTBTN, RESIZE_NONE, 14, 67, 81, 177, 188, STR_00CE_4, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01165 { WWT_TEXTBTN, RESIZE_NONE, 14, 82, 96, 177, 188, STR_00CF_5, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01166 { WWT_TEXTBTN, RESIZE_NONE, 14, 97, 111, 177, 188, STR_6, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01167 { WWT_TEXTBTN, RESIZE_NONE, 14, 112, 126, 177, 188, STR_7, STR_304F_SELECT_NUMBER_OF_PLATFORMS},
01168
01169 { WWT_TEXTBTN, RESIZE_NONE, 14, 22, 36, 202, 213, STR_00CB_1, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01170 { WWT_TEXTBTN, RESIZE_NONE, 14, 37, 51, 202, 213, STR_00CC_2, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01171 { WWT_TEXTBTN, RESIZE_NONE, 14, 52, 66, 202, 213, STR_00CD_3, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01172 { WWT_TEXTBTN, RESIZE_NONE, 14, 67, 81, 202, 213, STR_00CE_4, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01173 { WWT_TEXTBTN, RESIZE_NONE, 14, 82, 96, 202, 213, STR_00CF_5, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01174 { WWT_TEXTBTN, RESIZE_NONE, 14, 97, 111, 202, 213, STR_6, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01175 { WWT_TEXTBTN, RESIZE_NONE, 14, 112, 126, 202, 213, STR_7, STR_3050_SELECT_LENGTH_OF_RAILROAD},
01176
01177 { WWT_TEXTBTN, RESIZE_NONE, 14, 37, 111, 216, 227, STR_DRAG_DROP, STR_STATION_DRAG_DROP},
01178 { WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 242, 253, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
01179 { WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 242, 253, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
01180
01181
01182 { WWT_DROPDOWNIN, RESIZE_NONE, 14, 7, 140, 17, 28, STR_02BD, STR_SELECT_STATION_CLASS_TIP},
01183 { WWT_MATRIX, RESIZE_NONE, 14, 7, 128, 32, 102, 0x501, STR_SELECT_STATION_TYPE_TIP},
01184 { WWT_SCROLLBAR, RESIZE_NONE, 14, 129, 140, 32, 102, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
01185 { WIDGETS_END},
01186 };
01187
01188 static const WindowDesc _station_builder_desc = {
01189 WDP_AUTO, WDP_AUTO, 148, 200, 148, 200,
01190 WC_BUILD_STATION, WC_BUILD_TOOLBAR,
01191 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
01192 _station_builder_widgets,
01193 StationBuildWndProc
01194 };
01195
01196 static const WindowDesc _newstation_builder_desc = {
01197 WDP_AUTO, WDP_AUTO, 148, 290, 148, 290,
01198 WC_BUILD_STATION, WC_BUILD_TOOLBAR,
01199 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
01200 _newstation_builder_widgets,
01201 StationBuildWndProc
01202 };
01203
01204 static void ShowStationBuilder()
01205 {
01206 Window *w;
01207 if (GetNumStationClasses() <= 2 && GetNumCustomStations(STAT_CLASS_DFLT) == 1) {
01208 w = AllocateWindowDesc(&_station_builder_desc);
01209 _railstation.newstations = false;
01210 } else {
01211 w = AllocateWindowDesc(&_newstation_builder_desc);
01212 _railstation.newstations = true;
01213 _railstation.station_count = GetNumCustomStations(_railstation.station_class);
01214
01215 w->vscroll.count = _railstation.station_count;
01216 w->vscroll.cap = 5;
01217 w->vscroll.pos = Clamp(_railstation.station_type - 2, 0, w->vscroll.count - w->vscroll.cap);
01218 }
01219 }
01220
01222 enum BuildSignalWidgets {
01223 BSW_CLOSEBOX = 0,
01224 BSW_CAPTION,
01225 BSW_SEMAPHORE_NORM,
01226 BSW_SEMAPHORE_ENTRY,
01227 BSW_SEMAPHORE_EXIT,
01228 BSW_SEMAPHORE_COMBO,
01229 BSW_ELECTRIC_NORM,
01230 BSW_ELECTRIC_ENTRY,
01231 BSW_ELECTRIC_EXIT,
01232 BSW_ELECTRIC_COMBO,
01233 BSW_CONVERT,
01234 BSW_DRAG_SIGNALS_DENSITY,
01235 BSW_DRAG_SIGNALS_DENSITY_DECREASE,
01236 BSW_DRAG_SIGNALS_DENSITY_INCREASE,
01237 };
01238
01249 static void DrawSignalSprite(const Window *w, byte widget_index, SpriteID image, int8 xrel, uint8 xsize)
01250 {
01251 DrawSprite(image + w->IsWidgetLowered(widget_index), PAL_NONE,
01252 w->widget[widget_index].left + (w->widget[widget_index].right - w->widget[widget_index].left) / 2 - xrel - xsize / 2 +
01253 w->IsWidgetLowered(widget_index), w->widget[widget_index].bottom - 3 + w->IsWidgetLowered(widget_index));
01254 }
01255
01262 static void SignalBuildWndProc(Window *w, WindowEvent *e)
01263 {
01264 switch (e->event) {
01265 case WE_PAINT:
01266 w->LowerWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_type);
01267
01268 w->SetWidgetLoweredState(BSW_CONVERT, _convert_signal_button);
01269
01270 w->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_DECREASE, _patches.drag_signals_density == 1);
01271 w->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_INCREASE, _patches.drag_signals_density == 20);
01272
01273 DrawWindowWidgets(w);
01274
01275
01276 DrawSignalSprite(w, BSW_SEMAPHORE_NORM, SPR_IMG_SIGNAL_SEMAPHORE_NORM, 0, 12);
01277 DrawSignalSprite(w, BSW_SEMAPHORE_ENTRY, SPR_IMG_SIGNAL_SEMAPHORE_ENTRY, -1, 13);
01278 DrawSignalSprite(w, BSW_SEMAPHORE_EXIT, SPR_IMG_SIGNAL_SEMAPHORE_EXIT, 0, 12);
01279 DrawSignalSprite(w, BSW_SEMAPHORE_COMBO, SPR_IMG_SIGNAL_SEMAPHORE_COMBO, 0, 12);
01280 DrawSignalSprite(w, BSW_ELECTRIC_NORM, SPR_IMG_SIGNAL_ELECTRIC_NORM, -1, 4);
01281 DrawSignalSprite(w, BSW_ELECTRIC_ENTRY, SPR_IMG_SIGNAL_ELECTRIC_ENTRY, -2, 6);
01282 DrawSignalSprite(w, BSW_ELECTRIC_EXIT, SPR_IMG_SIGNAL_ELECTRIC_EXIT, -2, 6);
01283 DrawSignalSprite(w, BSW_ELECTRIC_COMBO, SPR_IMG_SIGNAL_ELECTRIC_COMBO, -2, 6);
01284
01285
01286 SetDParam(0, _patches.drag_signals_density);
01287 DrawStringCentered(w->widget[BSW_DRAG_SIGNALS_DENSITY].left + (w->widget[BSW_DRAG_SIGNALS_DENSITY].right -
01288 w->widget[BSW_DRAG_SIGNALS_DENSITY].left) / 2 + 1,
01289 w->widget[BSW_DRAG_SIGNALS_DENSITY].top + 2, STR_JUST_INT, TC_ORANGE);
01290 break;
01291
01292 case WE_CLICK:
01293 switch (e->we.click.widget) {
01294 case BSW_SEMAPHORE_NORM:
01295 case BSW_SEMAPHORE_ENTRY:
01296 case BSW_SEMAPHORE_EXIT:
01297 case BSW_SEMAPHORE_COMBO:
01298 case BSW_ELECTRIC_NORM:
01299 case BSW_ELECTRIC_ENTRY:
01300 case BSW_ELECTRIC_EXIT:
01301 case BSW_ELECTRIC_COMBO:
01302 w->RaiseWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_type);
01303
01304 _cur_signal_type = (SignalType)((uint)((e->we.click.widget - BSW_SEMAPHORE_NORM) % (SIGTYPE_COMBO + 1)));
01305 _cur_signal_variant = e->we.click.widget >= BSW_ELECTRIC_NORM ? SIG_ELECTRIC : SIG_SEMAPHORE;
01306 break;
01307
01308 case BSW_CONVERT:
01309 _convert_signal_button = !_convert_signal_button;
01310 break;
01311
01312 case BSW_DRAG_SIGNALS_DENSITY_DECREASE:
01313 if (_patches.drag_signals_density > 1) {
01314 _patches.drag_signals_density--;
01315 const Window *w = FindWindowById(WC_GAME_OPTIONS, 0);
01316 if (w != NULL) SetWindowDirty(w);
01317 }
01318 break;
01319
01320 case BSW_DRAG_SIGNALS_DENSITY_INCREASE:
01321 if (_patches.drag_signals_density < 20) {
01322 _patches.drag_signals_density++;
01323 const Window *w = FindWindowById(WC_GAME_OPTIONS, 0);
01324 if (w != NULL) SetWindowDirty(w);
01325 }
01326 break;
01327
01328 default: break;
01329 }
01330
01331 SetWindowDirty(w);
01332 break;
01333
01334 case WE_MOUSELOOP:
01335 if (WP(w, def_d).close) DeleteWindow(w);
01336 return;
01337
01338 case WE_DESTROY:
01339 if (!WP(w, def_d).close) ResetObjectToPlace();
01340 break;
01341 }
01342 }
01343
01345 static const Widget _signal_builder_widgets[] = {
01346 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
01347 { WWT_CAPTION, RESIZE_NONE, 7, 11, 109, 0, 13, STR_SIGNAL_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
01348
01349 { WWT_PANEL, RESIZE_NONE, 7, 0, 21, 14, 40, STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_NORM_TIP},
01350 { WWT_PANEL, RESIZE_NONE, 7, 22, 43, 14, 40, STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TIP},
01351 { WWT_PANEL, RESIZE_NONE, 7, 44, 65, 14, 40, STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TIP},
01352 { WWT_PANEL, RESIZE_NONE, 7, 66, 87, 14, 40, STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TIP},
01353
01354 { WWT_PANEL, RESIZE_NONE, 7, 0, 21, 41, 67, STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_NORM_TIP},
01355 { WWT_PANEL, RESIZE_NONE, 7, 22, 43, 41, 67, STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TIP},
01356 { WWT_PANEL, RESIZE_NONE, 7, 44, 65, 41, 67, STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_EXIT_TIP},
01357 { WWT_PANEL, RESIZE_NONE, 7, 66, 87, 41, 67, STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_COMBO_TIP},
01358
01359 { WWT_IMGBTN, RESIZE_NONE, 7, 88, 109, 14, 40, SPR_IMG_SIGNAL_CONVERT, STR_SIGNAL_CONVERT_TIP},
01360 { WWT_PANEL, RESIZE_NONE, 7, 88, 109, 41, 67, STR_NULL, STR_DRAG_SIGNALS_DENSITY_TIP},
01361 { WWT_PUSHIMGBTN, RESIZE_NONE, 14, 90, 98, 54, 65, SPR_ARROW_LEFT, STR_DRAG_SIGNALS_DENSITY_DECREASE_TIP},
01362 { WWT_PUSHIMGBTN, RESIZE_NONE, 14, 99, 107, 54, 65, SPR_ARROW_RIGHT, STR_DRAG_SIGNALS_DENSITY_INCREASE_TIP},
01363
01364 { WIDGETS_END},
01365 };
01366
01368 static const WindowDesc _signal_builder_desc = {
01369 WDP_AUTO, WDP_AUTO, 110, 68, 110, 68,
01370 WC_BUILD_SIGNAL, WC_BUILD_TOOLBAR,
01371 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
01372 _signal_builder_widgets,
01373 SignalBuildWndProc
01374 };
01375
01380 static void ShowSignalBuilder()
01381 {
01382 _convert_signal_button = false;
01383 _cur_signal_variant = _cur_year < _patches.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC;
01384 _cur_signal_type = SIGTYPE_NORMAL;
01385
01386 AllocateWindowDesc(&_signal_builder_desc);
01387 }
01388
01390 enum BuildRailDepotWidgets {
01391 BRDW_CLOSEBOX = 0,
01392 BRDW_CAPTION,
01393 BRDW_BACKGROUND,
01394 BRDW_DEPOT_NE,
01395 BRDW_DEPOT_SE,
01396 BRDW_DEPOT_SW,
01397 BRDW_DEPOT_NW,
01398 };
01399
01400 static void BuildTrainDepotWndProc(Window *w, WindowEvent *e)
01401 {
01402 switch (e->event) {
01403 case WE_CREATE: w->LowerWidget(_build_depot_direction + BRDW_DEPOT_NE); break;
01404
01405 case WE_PAINT: {
01406 DrawWindowWidgets(w);
01407
01408 DrawTrainDepotSprite(70, 17, DIAGDIR_NE, _cur_railtype);
01409 DrawTrainDepotSprite(70, 69, DIAGDIR_SE, _cur_railtype);
01410 DrawTrainDepotSprite( 2, 69, DIAGDIR_SW, _cur_railtype);
01411 DrawTrainDepotSprite( 2, 17, DIAGDIR_NW, _cur_railtype);
01412 break;
01413 }
01414
01415 case WE_CLICK:
01416 switch (e->we.click.widget) {
01417 case BRDW_DEPOT_NE:
01418 case BRDW_DEPOT_SE:
01419 case BRDW_DEPOT_SW:
01420 case BRDW_DEPOT_NW:
01421 w->RaiseWidget(_build_depot_direction + BRDW_DEPOT_NE);
01422 _build_depot_direction = (DiagDirection)(e->we.click.widget - BRDW_DEPOT_NE);
01423 w->LowerWidget(_build_depot_direction + BRDW_DEPOT_NE);
01424 SndPlayFx(SND_15_BEEP);
01425 SetWindowDirty(w);
01426 break;
01427 }
01428 break;
01429
01430 case WE_MOUSELOOP:
01431 if (WP(w, def_d).close) DeleteWindow(w);
01432 return;
01433
01434 case WE_DESTROY:
01435 if (!WP(w, def_d).close) ResetObjectToPlace();
01436 break;
01437 }
01438 }
01439
01441 static const Widget _build_depot_widgets[] = {
01442 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
01443 { WWT_CAPTION, RESIZE_NONE, 7, 11, 139, 0, 13, STR_1014_TRAIN_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
01444 { WWT_PANEL, RESIZE_NONE, 7, 0, 139, 14, 121, 0x0, STR_NULL},
01445 { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 17, 66, 0x0, STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO},
01446 { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 69, 118, 0x0, STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO},
01447 { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 69, 118, 0x0, STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO},
01448 { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 17, 66, 0x0, STR_1020_SELECT_RAILROAD_DEPOT_ORIENTATIO},
01449 { WIDGETS_END},
01450 };
01451
01452 static const WindowDesc _build_depot_desc = {
01453 WDP_AUTO, WDP_AUTO, 140, 122, 140, 122,
01454 WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
01455 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
01456 _build_depot_widgets,
01457 BuildTrainDepotWndProc
01458 };
01459
01460 static void ShowBuildTrainDepotPicker()
01461 {
01462 AllocateWindowDesc(&_build_depot_desc);
01463 }
01464
01466 enum BuildRailWaypointWidgets {
01467 BRWW_CLOSEBOX = 0,
01468 BRWW_CAPTION,
01469 BRWW_BACKGROUND,
01470 BRWW_WAYPOINT_1,
01471 BRWW_WAYPOINT_2,
01472 BRWW_WAYPOINT_3,
01473 BRWW_WAYPOINT_4,
01474 BRWW_WAYPOINT_5,
01475 BRWW_SCROLL,
01476 };
01477
01478 static void BuildWaypointWndProc(Window *w, WindowEvent *e)
01479 {
01480 switch (e->event) {
01481 case WE_PAINT: {
01482 uint i;
01483
01484 for (i = 0; i < w->hscroll.cap; i++) {
01485 w->SetWidgetLoweredState(i + BRWW_WAYPOINT_1, (w->hscroll.pos + i) == _cur_waypoint_type);
01486 }
01487
01488 DrawWindowWidgets(w);
01489
01490 for (i = 0; i < w->hscroll.cap; i++) {
01491 if (w->hscroll.pos + i < w->hscroll.count) {
01492 const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, w->hscroll.pos + i);
01493
01494 DrawWaypointSprite(2 + i * 68, 25, w->hscroll.pos + i, _cur_railtype);
01495
01496 if (statspec != NULL &&
01497 HasBit(statspec->callbackmask, CBM_STATION_AVAIL) &&
01498 GB(GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE), 0, 8) == 0) {
01499 GfxFillRect(4 + i * 68, 18, 67 + i * 68, 75, (1 << PALETTE_MODIFIER_GREYOUT));
01500 }
01501 }
01502 }
01503 break;
01504 }
01505 case WE_CLICK: {
01506 switch (e->we.click.widget) {
01507 case BRWW_WAYPOINT_1:
01508 case BRWW_WAYPOINT_2:
01509 case BRWW_WAYPOINT_3:
01510 case BRWW_WAYPOINT_4:
01511 case BRWW_WAYPOINT_5: {
01512 byte type = e->we.click.widget - BRWW_WAYPOINT_1 + w->hscroll.pos;
01513
01514
01515 const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, type);
01516 if (statspec != NULL &&
01517 HasBit(statspec->callbackmask, CBM_STATION_AVAIL) &&
01518 GB(GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE), 0, 8) == 0) return;
01519
01520 _cur_waypoint_type = type;
01521 SndPlayFx(SND_15_BEEP);
01522 SetWindowDirty(w);
01523 break;
01524 }
01525 }
01526 break;
01527 }
01528
01529 case WE_MOUSELOOP:
01530 if (WP(w, def_d).close) DeleteWindow(w);
01531 break;
01532
01533 case WE_DESTROY:
01534 if (!WP(w, def_d).close) ResetObjectToPlace();
01535 break;
01536 }
01537 }
01538
01540 static const Widget _build_waypoint_widgets[] = {
01541 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
01542 { WWT_CAPTION, RESIZE_NONE, 7, 11, 343, 0, 13, STR_WAYPOINT, STR_018C_WINDOW_TITLE_DRAG_THIS},
01543 { WWT_PANEL, RESIZE_NONE, 7, 0, 343, 14, 91, 0x0, STR_NULL},
01544
01545 { WWT_PANEL, RESIZE_NONE, 7, 3, 68, 17, 76, 0x0, STR_WAYPOINT_GRAPHICS_TIP},
01546 { WWT_PANEL, RESIZE_NONE, 7, 71, 136, 17, 76, 0x0, STR_WAYPOINT_GRAPHICS_TIP},
01547 { WWT_PANEL, RESIZE_NONE, 7, 139, 204, 17, 76, 0x0, STR_WAYPOINT_GRAPHICS_TIP},
01548 { WWT_PANEL, RESIZE_NONE, 7, 207, 272, 17, 76, 0x0, STR_WAYPOINT_GRAPHICS_TIP},
01549 { WWT_PANEL, RESIZE_NONE, 7, 275, 340, 17, 76, 0x0, STR_WAYPOINT_GRAPHICS_TIP},
01550
01551 { WWT_HSCROLLBAR, RESIZE_NONE, 7, 1, 343, 80, 91, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
01552 { WIDGETS_END},
01553 };
01554
01555 static const WindowDesc _build_waypoint_desc = {
01556 WDP_AUTO, WDP_AUTO, 344, 92, 344, 92,
01557 WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
01558 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
01559 _build_waypoint_widgets,
01560 BuildWaypointWndProc
01561 };
01562
01563 static void ShowBuildWaypointPicker()
01564 {
01565 Window *w = AllocateWindowDesc(&_build_waypoint_desc);
01566 w->hscroll.cap = 5;
01567 w->hscroll.count = _waypoint_count;
01568 }
01569
01570
01571 void InitializeRailGui()
01572 {
01573 _build_depot_direction = DIAGDIR_NW;
01574 _railstation.numtracks = 1;
01575 _railstation.platlength = 1;
01576 _railstation.dragdrop = true;
01577 }
01578
01579 void ReinitGuiAfterToggleElrail(bool disable)
01580 {
01581 extern RailType _last_built_railtype;
01582 if (disable && _last_built_railtype == RAILTYPE_ELECTRIC) {
01583 Window *w;
01584 _last_built_railtype = _cur_railtype = RAILTYPE_RAIL;
01585 w = FindWindowById(WC_BUILD_TOOLBAR, 0);
01586 if (w != NULL && w->wndproc == BuildRailToolbWndProc) {
01587 SetupRailToolbar(_cur_railtype, w);
01588 SetWindowDirty(w);
01589 }
01590 }
01591 MarkWholeScreenDirty();
01592 }
01593
01594 void SetDefaultRailGui()
01595 {
01596 if (_local_player == PLAYER_SPECTATOR || !IsValidPlayer(_local_player)) return;
01597
01598 extern RailType _last_built_railtype;
01599 RailType rt = (RailType)_patches.default_rail_type;
01600 if (rt >= RAILTYPE_END) {
01601 if (rt == RAILTYPE_END + 2) {
01602
01603 RailType count[RAILTYPE_END];
01604 memset(count, 0, sizeof(count));
01605 for (TileIndex t = 0; t < MapSize(); t++) {
01606 if (IsTileType(t, MP_RAILWAY) || IsLevelCrossingTile(t) || IsRailwayStationTile(t) ||
01607 (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL)) {
01608 count[GetRailType(t)]++;
01609 }
01610 }
01611
01612 rt = RAILTYPE_RAIL;
01613 for (RailType r = RAILTYPE_ELECTRIC; r < RAILTYPE_END; r++) {
01614 if (count[r] >= count[rt]) rt = r;
01615 }
01616
01617
01618 if (count[rt] == 0) rt = RAILTYPE_END;
01619 }
01620 switch (rt) {
01621 case RAILTYPE_END + 0:
01622 rt = RAILTYPE_RAIL;
01623 while (rt < RAILTYPE_END && !HasRailtypeAvail(_local_player, rt)) rt++;
01624 break;
01625
01626 case RAILTYPE_END + 1:
01627 rt = GetBestRailtype(_local_player);
01628 break;
01629
01630 default:
01631 break;
01632 }
01633 }
01634
01635 _last_built_railtype = _cur_railtype = rt;
01636 Window *w = FindWindowById(WC_BUILD_TOOLBAR, 0);
01637 if (w != NULL && w->wndproc == BuildRailToolbWndProc) {
01638 SetupRailToolbar(_cur_railtype, w);
01639 SetWindowDirty(w);
01640 }
01641 }
01642
01643
01644