# road_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: road_gui.cpp 22018 2011-02-07 22:37:22Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "gui.h"
    00014 #include "window_gui.h"
    00015 #include "station_gui.h"
    00016 #include "terraform_gui.h"
    00017 #include "viewport_func.h"
    00018 #include "command_func.h"
    00019 #include "road_cmd.h"
    00020 #include "station_func.h"
    00021 #include "window_func.h"
    00022 #include "vehicle_func.h"
    00023 #include "sound_func.h"
    00024 #include "company_func.h"
    00025 #include "tunnelbridge.h"
    00026 #include "tunnelbridge_map.h"
    00027 #include "tilehighlight_func.h"
    00028 #include "company_base.h"
    00029 #include "hotkeys.h"
    00030 #include "road_gui.h"
    00031
    00032 #include "table/strings.h"
    00033
    00034 static void ShowRVStationPicker(Window *parent, RoadStopType rs);
    00035 static void ShowRoadDepotPicker(Window *parent);
    00036
    00037 static bool _remove_button_clicked;
    00038 static bool _one_way_button_clicked;
    00039
    00044 enum RoadFlags {
    00045   RF_NONE             = 0x00,
    00046   RF_START_HALFROAD_Y = 0x01,    // The start tile in Y-dir should have only a half road
    00047   RF_END_HALFROAD_Y   = 0x02,    // The end tile in Y-dir should have only a half road
    00048   RF_DIR_Y            = 0x04,    // The direction is Y-dir
    00049   RF_DIR_X            = RF_NONE, // Dummy; Dir X is set when RF_DIR_Y is not set
    00050   RF_START_HALFROAD_X = 0x08,    // The start tile in X-dir should have only a half road
    00051   RF_END_HALFROAD_X   = 0x10,    // The end tile in X-dir should have only a half road
    00052 };
    00053 DECLARE_ENUM_AS_BIT_SET(RoadFlags)
    00054
    00055 static RoadFlags _place_road_flag;
    00056
    00057 static RoadType _cur_roadtype;
    00058
    00059 static DiagDirection _road_depot_orientation;
    00060 static DiagDirection _road_station_picker_orientation;
    00061
    00062 void CcPlaySound1D(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
    00063 {
    00064   if (result.Succeeded()) SndPlayTileFx(SND_1F_SPLAT, tile);
    00065 }
    00066
    00071 static void PlaceRoad_Bridge(TileIndex tile, Window *w)
    00072 {
    00073   if (IsBridgeTile(tile)) {
    00074     TileIndex other_tile = GetOtherTunnelBridgeEnd(tile);
    00075     Point pt = {0, 0};
    00076     w->OnPlaceMouseUp(VPM_X_OR_Y, DDSP_BUILD_BRIDGE, pt, tile, other_tile);
    00077   } else {
    00078     VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
    00079   }
    00080 }
    00081
    00091 void CcBuildRoadTunnel(const CommandCost &result, TileIndex start_tile, uint32 p1, uint32 p2)
    00092 {
    00093   if (result.Succeeded()) {
    00094     SndPlayTileFx(SND_20_SPLAT_2, start_tile);
    00095     if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
    00096
    00097     DiagDirection start_direction = ReverseDiagDir(GetTunnelBridgeDirection(start_tile));
    00098     ConnectRoadToStructure(start_tile, start_direction);
    00099
    00100     TileIndex end_tile = GetOtherTunnelBridgeEnd(start_tile);
    00101     DiagDirection end_direction = ReverseDiagDir(GetTunnelBridgeDirection(end_tile));
    00102     ConnectRoadToStructure(end_tile, end_direction);
    00103   } else {
    00104     SetRedErrorSquare(_build_tunnel_endtile);
    00105   }
    00106 }
    00107
    00109 struct RoadTypeInfo {
    00110   StringID err_build_road;
    00111   StringID err_remove_road;
    00112   StringID err_depot;
    00113   StringID err_build_station[2];
    00114   StringID err_remove_station[2];
    00115
    00116   StringID picker_title[2];
    00117   StringID picker_tooltip[2];
    00118
    00119   SpriteID cursor_nesw;
    00120   SpriteID cursor_nwse;
    00121   SpriteID cursor_autoroad;
    00122 };
    00123
    00125 static const RoadTypeInfo _road_type_infos[] = {
    00126   {
    00127     STR_ERROR_CAN_T_BUILD_ROAD_HERE,
    00128     STR_ERROR_CAN_T_REMOVE_ROAD_FROM,
    00129     STR_ERROR_CAN_T_BUILD_ROAD_DEPOT,
    00130     { STR_ERROR_CAN_T_BUILD_BUS_STATION,         STR_ERROR_CAN_T_BUILD_TRUCK_STATION          },
    00131     { STR_ERROR_CAN_T_REMOVE_BUS_STATION,        STR_ERROR_CAN_T_REMOVE_TRUCK_STATION         },
    00132     { STR_STATION_BUILD_BUS_ORIENTATION,         STR_STATION_BUILD_TRUCK_ORIENTATION          },
    00133     { STR_STATION_BUILD_BUS_ORIENTATION_TOOLTIP, STR_STATION_BUILD_TRUCK_ORIENTATION_TOOLTIP  },
    00134
    00135     SPR_CURSOR_ROAD_NESW,
    00136     SPR_CURSOR_ROAD_NWSE,
    00137     SPR_CURSOR_AUTOROAD,
    00138   },
    00139   {
    00140     STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE,
    00141     STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM,
    00142     STR_ERROR_CAN_T_BUILD_TRAM_DEPOT,
    00143     { STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION,         STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION         },
    00144     { STR_ERROR_CAN_T_REMOVE_PASSENGER_TRAM_STATION,        STR_ERROR_CAN_T_REMOVE_CARGO_TRAM_STATION        },
    00145     { STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION,         STR_STATION_BUILD_CARGO_TRAM_ORIENTATION         },
    00146     { STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION_TOOLTIP, STR_STATION_BUILD_CARGO_TRAM_ORIENTATION_TOOLTIP },
    00147
    00148     SPR_CURSOR_TRAMWAY_NESW,
    00149     SPR_CURSOR_TRAMWAY_NWSE,
    00150     SPR_CURSOR_AUTOTRAM,
    00151   },
    00152 };
    00153
    00159 void ConnectRoadToStructure(TileIndex tile, DiagDirection direction)
    00160 {
    00161   tile += TileOffsByDiagDir(direction);
    00162   /* if there is a roadpiece just outside of the station entrance, build a connecting route */
    00163   if (IsNormalRoadTile(tile)) {
    00164     if (GetRoadBits(tile, _cur_roadtype) != ROAD_NONE) {
    00165       DoCommandP(tile, _cur_roadtype << 4 | DiagDirToRoadBits(ReverseDiagDir(direction)), 0, CMD_BUILD_ROAD);
    00166     }
    00167   }
    00168 }
    00169
    00170 void CcRoadDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
    00171 {
    00172   if (result.Failed()) return;
    00173
    00174   DiagDirection dir = (DiagDirection)GB(p1, 0, 2);
    00175   SndPlayTileFx(SND_1F_SPLAT, tile);
    00176   if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
    00177   ConnectRoadToStructure(tile, dir);
    00178 }
    00179
    00194 void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
    00195 {
    00196   if (result.Failed()) return;
    00197
    00198   DiagDirection dir = (DiagDirection)GB(p2, 6, 2);
    00199   SndPlayTileFx(SND_1F_SPLAT, tile);
    00200   if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
    00201   TileArea roadstop_area(tile, GB(p1, 0, 8), GB(p1, 8, 8));
    00202   TILE_AREA_LOOP(cur_tile, roadstop_area) {
    00203     ConnectRoadToStructure(cur_tile, dir);
    00204     /* For a drive-through road stop build connecting road for other entrance. */
    00205     if (HasBit(p2, 1)) ConnectRoadToStructure(cur_tile, ReverseDiagDir(dir));
    00206   }
    00207 }
    00208
    00219 static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, uint32 cmd)
    00220 {
    00221   uint8 ddir = _road_station_picker_orientation;
    00222   SB(p2, 16, 16, INVALID_STATION); // no station to join
    00223
    00224   if (ddir >= DIAGDIR_END) {
    00225     SetBit(p2, 1); // It's a drive-through stop.
    00226     ddir -= DIAGDIR_END; // Adjust picker result to actual direction.
    00227   }
    00228   p2 |= ddir << 6; // Set the DiagDirecion into p2 bits 6 and 7.
    00229
    00230   TileArea ta(start_tile, end_tile);
    00231   CommandContainer cmdcont = { ta.tile, ta.w | ta.h << 8, p2, cmd, CcRoadStop, "" };
    00232   ShowSelectStationIfNeeded(cmdcont, ta);
    00233 }
    00234
    00239 static void PlaceRoad_BusStation(TileIndex tile)
    00240 {
    00241   if (_remove_button_clicked) {
    00242     VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_REMOVE_BUSSTOP);
    00243   } else {
    00244     if (_road_station_picker_orientation < DIAGDIR_END) { // Not a drive-through stop.
    00245       VpStartPlaceSizing(tile, (DiagDirToAxis(_road_station_picker_orientation) == AXIS_X) ? VPM_X_LIMITED : VPM_Y_LIMITED, DDSP_BUILD_BUSSTOP);
    00246     } else {
    00247       VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_BUSSTOP);
    00248     }
    00249     VpSetPlaceSizingLimit(_settings_game.station.station_spread);
    00250   }
    00251 }
    00252
    00257 static void PlaceRoad_TruckStation(TileIndex tile)
    00258 {
    00259   if (_remove_button_clicked) {
    00260     VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_REMOVE_TRUCKSTOP);
    00261   } else {
    00262     if (_road_station_picker_orientation < DIAGDIR_END) { // Not a drive-through stop.
    00263       VpStartPlaceSizing(tile, (DiagDirToAxis(_road_station_picker_orientation) == AXIS_X) ? VPM_X_LIMITED : VPM_Y_LIMITED, DDSP_BUILD_TRUCKSTOP);
    00264     } else {
    00265       VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_TRUCKSTOP);
    00266     }
    00267     VpSetPlaceSizingLimit(_settings_game.station.station_spread);
    00268   }
    00269 }
    00270
    00272 enum RoadToolbarWidgets {
    00273   RTW_ROAD_X,
    00274   RTW_ROAD_Y,
    00275   RTW_AUTOROAD,
    00276   RTW_DEMOLISH,
    00277   RTW_DEPOT,
    00278   RTW_BUS_STATION,
    00279   RTW_TRUCK_STATION,
    00280   RTW_ONE_WAY,
    00281   RTW_BUILD_BRIDGE,
    00282   RTW_BUILD_TUNNEL,
    00283   RTW_REMOVE,
    00284 };
    00285
    00286 typedef void OnButtonClick(Window *w);
    00287
    00288
    00293 static void ToggleRoadButton_Remove(Window *w)
    00294 {
    00295   w->ToggleWidgetLoweredState(RTW_REMOVE);
    00296   w->SetWidgetDirty(RTW_REMOVE);
    00297   _remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE);
    00298   SetSelectionRed(_remove_button_clicked);
    00299 }
    00300
    00306 static bool RoadToolbar_CtrlChanged(Window *w)
    00307 {
    00308   if (w->IsWidgetDisabled(RTW_REMOVE)) return false;
    00309
    00310   /* allow ctrl to switch remove mode only for these widgets */
    00311   for (uint i = RTW_ROAD_X; i <= RTW_AUTOROAD; i++) {
    00312     if (w->IsWidgetLowered(i)) {
    00313       ToggleRoadButton_Remove(w);
    00314       return true;
    00315     }
    00316   }
    00317
    00318   return false;
    00319 }
    00320
    00322 struct BuildRoadToolbarWindow : Window {
    00323   int last_started_action;
    00324
    00325   BuildRoadToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
    00326   {
    00327     this->InitNested(desc, window_number);
    00328     this->SetWidgetsDisabledState(true,
    00329         RTW_REMOVE,
    00330         RTW_ONE_WAY,
    00331         WIDGET_LIST_END);
    00332
    00333     this->OnInvalidateData();
    00334     this->last_started_action = WIDGET_LIST_END;
    00335
    00336     if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
    00337   }
    00338
    00339   ~BuildRoadToolbarWindow()
    00340   {
    00341     if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
    00342   }
    00343
    00344   void OnInvalidateData(int data = 0)
    00345   {
    00346     this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD),
    00347         RTW_DEPOT,
    00348         RTW_BUS_STATION,
    00349         RTW_TRUCK_STATION,
    00350         WIDGET_LIST_END);
    00351   }
    00352
    00358   void UpdateOptionWidgetStatus(RoadToolbarWidgets clicked_widget)
    00359   {
    00360     /* The remove and the one way button state is driven
    00361      * by the other buttons so they don't act on themselfs.
    00362      * Both are only valid if they are able to apply as options. */
    00363     switch (clicked_widget) {
    00364       case RTW_REMOVE:
    00365         this->RaiseWidget(RTW_ONE_WAY);
    00366         this->SetWidgetDirty(RTW_ONE_WAY);
    00367         break;
    00368
    00369       case RTW_ONE_WAY:
    00370         this->RaiseWidget(RTW_REMOVE);
    00371         this->SetWidgetDirty(RTW_REMOVE);
    00372         break;
    00373
    00374       case RTW_BUS_STATION:
    00375       case RTW_TRUCK_STATION:
    00376         this->DisableWidget(RTW_ONE_WAY);
    00377         this->SetWidgetDisabledState(RTW_REMOVE, !this->IsWidgetLowered(clicked_widget));
    00378         break;
    00379
    00380       case RTW_ROAD_X:
    00381       case RTW_ROAD_Y:
    00382       case RTW_AUTOROAD:
    00383         this->SetWidgetsDisabledState(!this->IsWidgetLowered(clicked_widget),
    00384             RTW_REMOVE,
    00385             RTW_ONE_WAY,
    00386             WIDGET_LIST_END);
    00387         break;
    00388
    00389       default:
    00390         /* When any other buttons than road/station, raise and
    00391          * disable the removal button */
    00392         this->SetWidgetsDisabledState(true,
    00393             RTW_REMOVE,
    00394             RTW_ONE_WAY,
    00395             WIDGET_LIST_END);
    00396         this->SetWidgetsLoweredState(false,
    00397             RTW_REMOVE,
    00398             RTW_ONE_WAY,
    00399             WIDGET_LIST_END);
    00400         break;
    00401     }
    00402   }
    00403
    00404   virtual void OnClick(Point pt, int widget, int click_count)
    00405   {
    00406     _remove_button_clicked = false;
    00407     _one_way_button_clicked = false;
    00408     switch (widget) {
    00409       case RTW_ROAD_X:
    00410         HandlePlacePushButton(this, RTW_ROAD_X, _road_type_infos[_cur_roadtype].cursor_nwse, HT_RECT);
    00411         this->last_started_action = widget;
    00412         break;
    00413
    00414       case RTW_ROAD_Y:
    00415         HandlePlacePushButton(this, RTW_ROAD_Y, _road_type_infos[_cur_roadtype].cursor_nesw, HT_RECT);
    00416         this->last_started_action = widget;
    00417         break;
    00418
    00419       case RTW_AUTOROAD:
    00420         HandlePlacePushButton(this, RTW_AUTOROAD, _road_type_infos[_cur_roadtype].cursor_autoroad, HT_RECT);
    00421         this->last_started_action = widget;
    00422         break;
    00423
    00424       case RTW_DEMOLISH:
    00425         HandlePlacePushButton(this, RTW_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
    00426         this->last_started_action = widget;
    00427         break;
    00428
    00429       case RTW_DEPOT:
    00430         if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
    00431         if (HandlePlacePushButton(this, RTW_DEPOT, SPR_CURSOR_ROAD_DEPOT, HT_RECT)) {
    00432           ShowRoadDepotPicker(this);
    00433           this->last_started_action = widget;
    00434         }
    00435         break;
    00436
    00437       case RTW_BUS_STATION:
    00438         if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
    00439         if (HandlePlacePushButton(this, RTW_BUS_STATION, SPR_CURSOR_BUS_STATION, HT_RECT)) {
    00440           ShowRVStationPicker(this, ROADSTOP_BUS);
    00441           this->last_started_action = widget;
    00442         }
    00443         break;
    00444
    00445       case RTW_TRUCK_STATION:
    00446         if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
    00447         if (HandlePlacePushButton(this, RTW_TRUCK_STATION, SPR_CURSOR_TRUCK_STATION, HT_RECT)) {
    00448           ShowRVStationPicker(this, ROADSTOP_TRUCK);
    00449           this->last_started_action = widget;
    00450         }
    00451         break;
    00452
    00453       case RTW_ONE_WAY:
    00454         if (this->IsWidgetDisabled(RTW_ONE_WAY)) return;
    00455         this->SetDirty();
    00456         this->ToggleWidgetLoweredState(RTW_ONE_WAY);
    00457         SetSelectionRed(false);
    00458         break;
    00459
    00460       case RTW_BUILD_BRIDGE:
    00461         HandlePlacePushButton(this, RTW_BUILD_BRIDGE, SPR_CURSOR_BRIDGE, HT_RECT);
    00462         this->last_started_action = widget;
    00463         break;
    00464
    00465       case RTW_BUILD_TUNNEL:
    00466         HandlePlacePushButton(this, RTW_BUILD_TUNNEL, SPR_CURSOR_ROAD_TUNNEL, HT_SPECIAL);
    00467         this->last_started_action = widget;
    00468         break;
    00469
    00470       case RTW_REMOVE:
    00471         if (this->IsWidgetDisabled(RTW_REMOVE)) return;
    00472
    00473         DeleteWindowById(WC_SELECT_STATION, 0);
    00474         ToggleRoadButton_Remove(this);
    00475         SndPlayFx(SND_15_BEEP);
    00476         break;
    00477
    00478       default: NOT_REACHED();
    00479     }
    00480     this->UpdateOptionWidgetStatus((RoadToolbarWidgets)widget);
    00481     if (_ctrl_pressed) RoadToolbar_CtrlChanged(this);
    00482   }
    00483
    00484   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
    00485   {
    00486     int num = CheckHotkeyMatch(roadtoolbar_hotkeys, keycode, this);
    00487     if (num == -1 || this->GetWidget<NWidgetBase>(num) == NULL) return ES_NOT_HANDLED;
    00488     this->OnClick(Point(), num, 1);
    00489     MarkTileDirtyByTile(TileVirtXY(_thd.pos.x, _thd.pos.y)); // redraw tile selection
    00490     return ES_HANDLED;
    00491   }
    00492
    00493   virtual void OnPlaceObject(Point pt, TileIndex tile)
    00494   {
    00495     _remove_button_clicked = this->IsWidgetLowered(RTW_REMOVE);
    00496     _one_way_button_clicked = this->IsWidgetLowered(RTW_ONE_WAY);
    00497     switch (this->last_started_action) {
    00498       case RTW_ROAD_X:
    00499         _place_road_flag = RF_DIR_X;
    00500         if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X;
    00501         VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_ROAD_X_DIR);
    00502         break;
    00503
    00504       case RTW_ROAD_Y:
    00505         _place_road_flag = RF_DIR_Y;
    00506         if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y;
    00507         VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_ROAD_Y_DIR);
    00508         break;
    00509
    00510       case RTW_AUTOROAD:
    00511         _place_road_flag = RF_NONE;
    00512         if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X;
    00513         if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y;
    00514         VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_PLACE_AUTOROAD);
    00515         break;
    00516
    00517       case RTW_DEMOLISH:
    00518         PlaceProc_DemolishArea(tile);
    00519         break;
    00520
    00521       case RTW_DEPOT:
    00522         DoCommandP(tile, _cur_roadtype << 2 | _road_depot_orientation, 0,
    00523             CMD_BUILD_ROAD_DEPOT | CMD_MSG(_road_type_infos[_cur_roadtype].err_depot), CcRoadDepot);
    00524         break;
    00525
    00526       case RTW_BUS_STATION:
    00527         PlaceRoad_BusStation(tile);
    00528         break;
    00529
    00530       case RTW_TRUCK_STATION:
    00531         PlaceRoad_TruckStation(tile);
    00532         break;
    00533
    00534       case RTW_BUILD_BRIDGE:
    00535         PlaceRoad_Bridge(tile, this);
    00536         break;
    00537
    00538       case RTW_BUILD_TUNNEL:
    00539         DoCommandP(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0,
    00540             CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRoadTunnel);
    00541         break;
    00542
    00543       default: NOT_REACHED();
    00544     }
    00545   }
    00546
    00547   virtual void OnPlaceObjectAbort()
    00548   {
    00549     this->RaiseButtons();
    00550     this->SetWidgetsDisabledState(true,
    00551         RTW_REMOVE,
    00552         RTW_ONE_WAY,
    00553         WIDGET_LIST_END);
    00554     this->SetWidgetDirty(RTW_REMOVE);
    00555     this->SetWidgetDirty(RTW_ONE_WAY);
    00556
    00557     DeleteWindowById(WC_BUS_STATION, TRANSPORT_ROAD);
    00558     DeleteWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD);
    00559     DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_ROAD);
    00560     DeleteWindowById(WC_SELECT_STATION, 0);
    00561     DeleteWindowByClass(WC_BUILD_BRIDGE);
    00562   }
    00563
    00564   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
    00565   {
    00566     /* Here we update the end tile flags
    00567      * of the road placement actions.
    00568      * At first we reset the end halfroad
    00569      * bits and if needed we set them again. */
    00570     switch (select_proc) {
    00571       case DDSP_PLACE_ROAD_X_DIR:
    00572         _place_road_flag &= ~RF_END_HALFROAD_X;
    00573         if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
    00574         break;
    00575
    00576       case DDSP_PLACE_ROAD_Y_DIR:
    00577         _place_road_flag &= ~RF_END_HALFROAD_Y;
    00578         if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
    00579         break;
    00580
    00581       case DDSP_PLACE_AUTOROAD:
    00582         _place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X);
    00583         if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
    00584         if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
    00585
    00586         /* For autoroad we need to update the
    00587          * direction of the road */
    00588         if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y &&
    00589             ( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) ||
    00590             (_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) {
    00591           /* Set dir = X */
    00592           _place_road_flag &= ~RF_DIR_Y;
    00593         } else {
    00594           /* Set dir = Y */
    00595           _place_road_flag |= RF_DIR_Y;
    00596         }
    00597
    00598         break;
    00599
    00600       default:
    00601         break;
    00602     }
    00603
    00604     VpSelectTilesWithMethod(pt.x, pt.y, select_method);
    00605   }
    00606
    00607   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
    00608   {
    00609     if (pt.x != -1) {
    00610       switch (select_proc) {
    00611         default: NOT_REACHED();
    00612         case DDSP_BUILD_BRIDGE:
    00613           if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
    00614           ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype));
    00615           break;
    00616
    00617         case DDSP_DEMOLISH_AREA:
    00618           GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
    00619           break;
    00620
    00621         case DDSP_PLACE_ROAD_X_DIR:
    00622         case DDSP_PLACE_ROAD_Y_DIR:
    00623         case DDSP_PLACE_AUTOROAD:
    00624           /* Flag description:
    00625            * Use the first three bits (0x07) if dir == Y
    00626            * else use the last 2 bits (X dir has
    00627            * not the 3rd bit set) */
    00628           _place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3));
    00629
    00630           DoCommandP(start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5),
    00631               _remove_button_clicked ?
    00632               CMD_REMOVE_LONG_ROAD | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) :
    00633               CMD_BUILD_LONG_ROAD | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road), CcPlaySound1D);
    00634           break;
    00635
    00636         case DDSP_BUILD_BUSSTOP:
    00637           PlaceRoadStop(start_tile, end_tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | ROADSTOP_BUS, CMD_BUILD_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[ROADSTOP_BUS]));
    00638           break;
    00639
    00640         case DDSP_BUILD_TRUCKSTOP:
    00641           PlaceRoadStop(start_tile, end_tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | ROADSTOP_TRUCK, CMD_BUILD_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[ROADSTOP_TRUCK]));
    00642           break;
    00643
    00644         case DDSP_REMOVE_BUSSTOP: {
    00645           TileArea ta(start_tile, end_tile);
    00646           DoCommandP(ta.tile, ta.w | ta.h << 8, ROADSTOP_BUS, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_BUS]), CcPlaySound1D);
    00647           break;
    00648         }
    00649
    00650         case DDSP_REMOVE_TRUCKSTOP: {
    00651           TileArea ta(start_tile, end_tile);
    00652           DoCommandP(ta.tile, ta.w | ta.h << 8, ROADSTOP_TRUCK, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_TRUCK]), CcPlaySound1D);
    00653           break;
    00654         }
    00655       }
    00656     }
    00657   }
    00658
    00659   virtual void OnPlacePresize(Point pt, TileIndex tile)
    00660   {
    00661     DoCommand(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL);
    00662     VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
    00663   }
    00664
    00665   virtual EventState OnCTRLStateChange()
    00666   {
    00667     if (RoadToolbar_CtrlChanged(this)) return ES_HANDLED;
    00668     return ES_NOT_HANDLED;
    00669   }
    00670
    00671   static Hotkey<BuildRoadToolbarWindow> roadtoolbar_hotkeys[];
    00672 };
    00673
    00674 Hotkey<BuildRoadToolbarWindow> BuildRoadToolbarWindow::roadtoolbar_hotkeys[] = {
    00675   Hotkey<BuildRoadToolbarWindow>('1', "build_x", RTW_ROAD_X),
    00676   Hotkey<BuildRoadToolbarWindow>('2', "build_y", RTW_ROAD_Y),
    00677   Hotkey<BuildRoadToolbarWindow>('3', "autoroad", RTW_AUTOROAD),
    00678   Hotkey<BuildRoadToolbarWindow>('4', "demolish", RTW_DEMOLISH),
    00679   Hotkey<BuildRoadToolbarWindow>('5', "depot", RTW_DEPOT),
    00680   Hotkey<BuildRoadToolbarWindow>('6', "bus_station", RTW_BUS_STATION),
    00681   Hotkey<BuildRoadToolbarWindow>('7', "truck_station", RTW_TRUCK_STATION),
    00682   Hotkey<BuildRoadToolbarWindow>('8', "oneway", RTW_ONE_WAY),
    00683   Hotkey<BuildRoadToolbarWindow>('B', "bridge", RTW_BUILD_BRIDGE),
    00684   Hotkey<BuildRoadToolbarWindow>('T', "tunnel", RTW_BUILD_TUNNEL),
    00685   Hotkey<BuildRoadToolbarWindow>('R', "remove", RTW_REMOVE),
    00686   HOTKEY_LIST_END(BuildRoadToolbarWindow)
    00687 };
    00688 Hotkey<BuildRoadToolbarWindow> *_roadtoolbar_hotkeys = BuildRoadToolbarWindow::roadtoolbar_hotkeys;
    00689
    00690
    00691 static const NWidgetPart _nested_build_road_widgets[] = {
    00692   NWidget(NWID_HORIZONTAL),
    00693     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00694     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00695     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00696   EndContainer(),
    00697   NWidget(NWID_HORIZONTAL),
    00698     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ROAD_X),
    00699             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_X_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION),
    00700     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ROAD_Y),
    00701             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_Y_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION),
    00702     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_AUTOROAD),
    00703             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_AUTOROAD, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD),
    00704     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_DEMOLISH),
    00705             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00706     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_DEPOT),
    00707             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_DEPOT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT),
    00708     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUS_STATION),
    00709             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_BUS_STATION, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION),
    00710     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_TRUCK_STATION),
    00711             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRUCK_BAY, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY),
    00712     NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
    00713     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ONE_WAY),
    00714             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_ONE_WAY, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD),
    00715     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_BRIDGE),
    00716             SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE),
    00717     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_TUNNEL),
    00718             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL),
    00719     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_REMOVE),
    00720             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD),
    00721   EndContainer(),
    00722 };
    00723
    00724 static const WindowDesc _build_road_desc(
    00725   WDP_ALIGN_TOOLBAR, 0, 0,
    00726   WC_BUILD_TOOLBAR, WC_NONE,
    00727   WDF_CONSTRUCTION,
    00728   _nested_build_road_widgets, lengthof(_nested_build_road_widgets)
    00729 );
    00730
    00731 static const NWidgetPart _nested_build_tramway_widgets[] = {
    00732   NWidget(NWID_HORIZONTAL),
    00733     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00734     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00735     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00736   EndContainer(),
    00737   NWidget(NWID_HORIZONTAL),
    00738     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ROAD_X),
    00739             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAMWAY_X_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION),
    00740     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ROAD_Y),
    00741             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAMWAY_Y_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION),
    00742     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_AUTOROAD),
    00743             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_AUTOTRAM, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM),
    00744     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_DEMOLISH),
    00745             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00746     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_DEPOT),
    00747             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_DEPOT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT),
    00748     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUS_STATION),
    00749             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_BUS_STATION, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_PASSENGER_TRAM_STATION),
    00750     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_TRUCK_STATION),
    00751             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRUCK_BAY, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION),
    00752     NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
    00753     NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, RTW_ONE_WAY), SetMinimalSize(0, 0),
    00754     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_BRIDGE),
    00755             SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE),
    00756     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_TUNNEL),
    00757             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL),
    00758     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_REMOVE),
    00759             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS),
    00760   EndContainer(),
    00761 };
    00762
    00763 static const WindowDesc _build_tramway_desc(
    00764   WDP_ALIGN_TOOLBAR, 0, 0,
    00765   WC_BUILD_TOOLBAR, WC_NONE,
    00766   WDF_CONSTRUCTION,
    00767   _nested_build_tramway_widgets, lengthof(_nested_build_tramway_widgets)
    00768 );
    00769
    00777 Window *ShowBuildRoadToolbar(RoadType roadtype)
    00778 {
    00779   if (!Company::IsValidID(_local_company)) return NULL;
    00780   _cur_roadtype = roadtype;
    00781
    00782   DeleteWindowByClass(WC_BUILD_TOOLBAR);
    00783   return AllocateWindowDescFront<BuildRoadToolbarWindow>(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
    00784 }
    00785
    00786 EventState RoadToolbarGlobalHotkeys(uint16 key, uint16 keycode)
    00787 {
    00788   extern RoadType _last_built_roadtype;
    00789   int num = CheckHotkeyMatch<BuildRoadToolbarWindow>(_roadtoolbar_hotkeys, keycode, NULL, true);
    00790   if (num == -1) return ES_NOT_HANDLED;
    00791   Window *w = ShowBuildRoadToolbar(_last_built_roadtype);
    00792   if (w == NULL) return ES_NOT_HANDLED;
    00793   return w->OnKeyPress(key, keycode);
    00794 }
    00795
    00796 static const NWidgetPart _nested_build_road_scen_widgets[] = {
    00797   NWidget(NWID_HORIZONTAL),
    00798     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00799     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00800     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00801   EndContainer(),
    00802   NWidget(NWID_HORIZONTAL),
    00803     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ROAD_X),
    00804             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_X_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION),
    00805     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ROAD_Y),
    00806             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_Y_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION),
    00807     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_AUTOROAD),
    00808             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_AUTOROAD, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD),
    00809     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_DEMOLISH),
    00810             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00811     NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
    00812     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_ONE_WAY),
    00813             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_ONE_WAY, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD),
    00814     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_BRIDGE),
    00815             SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE),
    00816     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_BUILD_TUNNEL),
    00817             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL),
    00818     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, RTW_REMOVE),
    00819             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD),
    00820   EndContainer(),
    00821 };
    00822
    00823 static const WindowDesc _build_road_scen_desc(
    00824   WDP_AUTO, 0, 0,
    00825   WC_SCEN_BUILD_TOOLBAR, WC_NONE,
    00826   WDF_CONSTRUCTION,
    00827   _nested_build_road_scen_widgets, lengthof(_nested_build_road_scen_widgets)
    00828 );
    00829
    00830 Window *ShowBuildRoadScenToolbar()
    00831 {
    00832   _cur_roadtype = ROADTYPE_ROAD;
    00833   return AllocateWindowDescFront<BuildRoadToolbarWindow>(&_build_road_scen_desc, 0);
    00834 }
    00835
    00836 EventState RoadToolbarEditorGlobalHotkeys(uint16 key, uint16 keycode)
    00837 {
    00838   int num = CheckHotkeyMatch<BuildRoadToolbarWindow>(_roadtoolbar_hotkeys, keycode, NULL, true);
    00839   if (num == -1) return ES_NOT_HANDLED;
    00840   Window *w = ShowBuildRoadScenToolbar();
    00841   if (w == NULL) return ES_NOT_HANDLED;
    00842   return w->OnKeyPress(key, keycode);
    00843 }
    00844
    00846 enum BuildRoadDepotWidgets {
    00847   BRDW_CAPTION,
    00848   BRDW_DEPOT_NE,
    00849   BRDW_DEPOT_SE,
    00850   BRDW_DEPOT_SW,
    00851   BRDW_DEPOT_NW,
    00852 };
    00853
    00854 struct BuildRoadDepotWindow : public PickerWindowBase {
    00855   BuildRoadDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(parent)
    00856   {
    00857     this->CreateNestedTree(desc);
    00858
    00859     this->LowerWidget(_road_depot_orientation + BRDW_DEPOT_NE);
    00860     if ( _cur_roadtype == ROADTYPE_TRAM) {
    00861       this->GetWidget<NWidgetCore>(BRDW_CAPTION)->widget_data = STR_BUILD_DEPOT_TRAM_ORIENTATION_CAPTION;
    00862       for (int i = BRDW_DEPOT_NE; i <= BRDW_DEPOT_NW; i++) this->GetWidget<NWidgetCore>(i)->tool_tip = STR_BUILD_DEPOT_TRAM_ORIENTATION_SELECT_TOOLTIP;
    00863     }
    00864
    00865     this->FinishInitNested(desc, TRANSPORT_ROAD);
    00866   }
    00867
    00868   virtual void DrawWidget(const Rect &r, int widget) const
    00869   {
    00870     if (!IsInsideMM(widget, BRDW_DEPOT_NE, BRDW_DEPOT_NW + 1)) return;
    00871
    00872     DrawRoadDepotSprite(r.left - 1, r.top, (DiagDirection)(widget - BRDW_DEPOT_NE + DIAGDIR_NE), _cur_roadtype);
    00873   }
    00874
    00875   virtual void OnClick(Point pt, int widget, int click_count)
    00876   {
    00877     switch (widget) {
    00878       case BRDW_DEPOT_NW:
    00879       case BRDW_DEPOT_NE:
    00880       case BRDW_DEPOT_SW:
    00881       case BRDW_DEPOT_SE:
    00882         this->RaiseWidget(_road_depot_orientation + BRDW_DEPOT_NE);
    00883         _road_depot_orientation = (DiagDirection)(widget - BRDW_DEPOT_NE);
    00884         this->LowerWidget(_road_depot_orientation + BRDW_DEPOT_NE);
    00885         SndPlayFx(SND_15_BEEP);
    00886         this->SetDirty();
    00887         break;
    00888
    00889       default:
    00890         break;
    00891     }
    00892   }
    00893 };
    00894
    00895 static const NWidgetPart _nested_build_road_depot_widgets[] = {
    00896   NWidget(NWID_HORIZONTAL),
    00897     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00898     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, BRDW_CAPTION), SetDataTip(STR_BUILD_DEPOT_ROAD_ORIENTATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00899   EndContainer(),
    00900   NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
    00901     NWidget(NWID_SPACER), SetMinimalSize(0, 3),
    00902     NWidget(NWID_HORIZONTAL_LTR),
    00903       NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
    00904       NWidget(NWID_VERTICAL),
    00905         NWidget(WWT_PANEL, COLOUR_GREY, BRDW_DEPOT_NW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
    00906         EndContainer(),
    00907         NWidget(NWID_SPACER), SetMinimalSize(0, 2),
    00908         NWidget(WWT_PANEL, COLOUR_GREY, BRDW_DEPOT_SW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
    00909         EndContainer(),
    00910       EndContainer(),
    00911       NWidget(NWID_SPACER), SetMinimalSize(2, 0),
    00912       NWidget(NWID_VERTICAL),
    00913         NWidget(WWT_PANEL, COLOUR_GREY, BRDW_DEPOT_NE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
    00914         EndContainer(),
    00915         NWidget(NWID_SPACER), SetMinimalSize(0, 2),
    00916         NWidget(WWT_PANEL, COLOUR_GREY, BRDW_DEPOT_SE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
    00917         EndContainer(),
    00918       EndContainer(),
    00919       NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
    00920     EndContainer(),
    00921     NWidget(NWID_SPACER), SetMinimalSize(0, 3),
    00922   EndContainer(),
    00923 };
    00924
    00925 static const WindowDesc _build_road_depot_desc(
    00926   WDP_AUTO, 0, 0,
    00927   WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
    00928   WDF_CONSTRUCTION,
    00929   _nested_build_road_depot_widgets, lengthof(_nested_build_road_depot_widgets)
    00930 );
    00931
    00932 static void ShowRoadDepotPicker(Window *parent)
    00933 {
    00934   new BuildRoadDepotWindow(&_build_road_depot_desc, parent);
    00935 }
    00936
    00938 enum BuildRoadStationWidgets {
    00939   BRSW_CAPTION,
    00940   BRSW_BACKGROUND,
    00941   BRSW_STATION_NE,
    00942   BRSW_STATION_SE,
    00943   BRSW_STATION_SW,
    00944   BRSW_STATION_NW,
    00945   BRSW_STATION_X,
    00946   BRSW_STATION_Y,
    00947   BRSW_LT_OFF,
    00948   BRSW_LT_ON,
    00949   BRSW_INFO,
    00950 };
    00951
    00952 struct BuildRoadStationWindow : public PickerWindowBase {
    00953   BuildRoadStationWindow(const WindowDesc *desc, Window *parent, RoadStopType rs) : PickerWindowBase(parent)
    00954   {
    00955     this->CreateNestedTree(desc);
    00956
    00957     /* Trams don't have non-drivethrough stations */
    00958     if (_cur_roadtype == ROADTYPE_TRAM && _road_station_picker_orientation < DIAGDIR_END) {
    00959       _road_station_picker_orientation = DIAGDIR_END;
    00960     }
    00961     this->SetWidgetsDisabledState(_cur_roadtype == ROADTYPE_TRAM,
    00962         BRSW_STATION_NE,
    00963         BRSW_STATION_SE,
    00964         BRSW_STATION_SW,
    00965         BRSW_STATION_NW,
    00966         WIDGET_LIST_END);
    00967
    00968     this->GetWidget<NWidgetCore>(BRSW_CAPTION)->widget_data = _road_type_infos[_cur_roadtype].picker_title[rs];
    00969     for (uint i = BRSW_STATION_NE; i < BRSW_LT_OFF; i++) this->GetWidget<NWidgetCore>(i)->tool_tip = _road_type_infos[_cur_roadtype].picker_tooltip[rs];
    00970
    00971     this->LowerWidget(_road_station_picker_orientation + BRSW_STATION_NE);
    00972     this->LowerWidget(_settings_client.gui.station_show_coverage + BRSW_LT_OFF);
    00973
    00974     this->FinishInitNested(desc, TRANSPORT_ROAD);
    00975
    00976     this->window_class = (rs == ROADSTOP_BUS) ? WC_BUS_STATION : WC_TRUCK_STATION;
    00977   }
    00978
    00979   virtual ~BuildRoadStationWindow()
    00980   {
    00981     DeleteWindowById(WC_SELECT_STATION, 0);
    00982   }
    00983
    00984   virtual void OnPaint()
    00985   {
    00986     this->DrawWidgets();
    00987
    00988     int rad = _settings_game.station.modified_catchment ? CA_TRUCK /* = CA_BUS */ : CA_UNMODIFIED;
    00989     if (_settings_client.gui.station_show_coverage) {
    00990       SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
    00991     } else {
    00992       SetTileSelectSize(1, 1);
    00993     }
    00994
    00995     /* 'Accepts' and 'Supplies' texts. */
    00996     StationCoverageType sct = (this->window_class == WC_BUS_STATION) ? SCT_PASSENGERS_ONLY : SCT_NON_PASSENGERS_ONLY;
    00997     int top = this->GetWidget<NWidgetBase>(BRSW_LT_ON)->pos_y + this->GetWidget<NWidgetBase>(BRSW_LT_ON)->current_y + WD_PAR_VSEP_NORMAL;
    00998     NWidgetBase *back_nwi = this->GetWidget<NWidgetBase>(BRSW_BACKGROUND);
    00999     int right = back_nwi->pos_x +  back_nwi->current_x;
    01000     int bottom = back_nwi->pos_y +  back_nwi->current_y;
    01001     top = DrawStationCoverageAreaText(back_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, sct, rad, false) + WD_PAR_VSEP_NORMAL;
    01002     top = DrawStationCoverageAreaText(back_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, sct, rad, true) + WD_PAR_VSEP_NORMAL;
    01003     /* Resize background if the text is not equally long as the window. */
    01004     if (top > bottom || (top < bottom && back_nwi->current_y > back_nwi->smallest_y)) {
    01005       ResizeWindow(this, 0, top - bottom);
    01006     }
    01007   }
    01008
    01009   virtual void DrawWidget(const Rect &r, int widget) const
    01010   {
    01011     if (!IsInsideMM(widget, BRSW_STATION_NE, BRSW_STATION_Y + 1)) return;
    01012
    01013     StationType st = (this->window_class == WC_BUS_STATION) ? STATION_BUS : STATION_TRUCK;
    01014     StationPickerDrawSprite(r.left + TILE_PIXELS, r.bottom - TILE_PIXELS, st, INVALID_RAILTYPE, widget < BRSW_STATION_X ? ROADTYPE_ROAD : _cur_roadtype, widget - BRSW_STATION_NE);
    01015   }
    01016
    01017   virtual void OnClick(Point pt, int widget, int click_count)
    01018   {
    01019     switch (widget) {
    01020       case BRSW_STATION_NE:
    01021       case BRSW_STATION_SE:
    01022       case BRSW_STATION_SW:
    01023       case BRSW_STATION_NW:
    01024       case BRSW_STATION_X:
    01025       case BRSW_STATION_Y:
    01026         this->RaiseWidget(_road_station_picker_orientation + BRSW_STATION_NE);
    01027         _road_station_picker_orientation = (DiagDirection)(widget - BRSW_STATION_NE);
    01028         this->LowerWidget(_road_station_picker_orientation + BRSW_STATION_NE);
    01029         SndPlayFx(SND_15_BEEP);
    01030         this->SetDirty();
    01031         DeleteWindowById(WC_SELECT_STATION, 0);
    01032         break;
    01033
    01034       case BRSW_LT_OFF:
    01035       case BRSW_LT_ON:
    01036         this->RaiseWidget(_settings_client.gui.station_show_coverage + BRSW_LT_OFF);
    01037         _settings_client.gui.station_show_coverage = (widget != BRSW_LT_OFF);
    01038         this->LowerWidget(_settings_client.gui.station_show_coverage + BRSW_LT_OFF);
    01039         SndPlayFx(SND_15_BEEP);
    01040         this->SetDirty();
    01041         break;
    01042
    01043       default:
    01044         break;
    01045     }
    01046   }
    01047
    01048   virtual void OnTick()
    01049   {
    01050     CheckRedrawStationCoverage(this);
    01051   }
    01052 };
    01053
    01055 static const NWidgetPart _nested_rv_station_picker_widgets[] = {
    01056   NWidget(NWID_HORIZONTAL),
    01057     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    01058     NWidget(WWT_CAPTION,  COLOUR_DARK_GREEN, BRSW_CAPTION),
    01059   EndContainer(),
    01060   NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BRSW_BACKGROUND),
    01061     NWidget(NWID_SPACER), SetMinimalSize(0, 3),
    01062     NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
    01063       NWidget(NWID_SPACER), SetFill(1, 0),
    01064       NWidget(WWT_PANEL, COLOUR_GREY, BRSW_STATION_NW), SetMinimalSize(66, 50), EndContainer(),
    01065       NWidget(WWT_PANEL, COLOUR_GREY, BRSW_STATION_NE), SetMinimalSize(66, 50), EndContainer(),
    01066       NWidget(WWT_PANEL, COLOUR_GREY, BRSW_STATION_X),  SetMinimalSize(66, 50), EndContainer(),
    01067       NWidget(NWID_SPACER), SetFill(1, 0),
    01068     EndContainer(),
    01069     NWidget(NWID_SPACER), SetMinimalSize(0, 2),
    01070     NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
    01071       NWidget(NWID_SPACER), SetFill(1, 0),
    01072       NWidget(WWT_PANEL, COLOUR_GREY, BRSW_STATION_SW), SetMinimalSize(66, 50), EndContainer(),
    01073       NWidget(WWT_PANEL, COLOUR_GREY, BRSW_STATION_SE), SetMinimalSize(66, 50), EndContainer(),
    01074       NWidget(WWT_PANEL, COLOUR_GREY, BRSW_STATION_Y),  SetMinimalSize(66, 50), EndContainer(),
    01075       NWidget(NWID_SPACER), SetFill(1, 0),
    01076     EndContainer(),
    01077     NWidget(NWID_SPACER), SetMinimalSize(0, 1),
    01078     NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
    01079       NWidget(WWT_LABEL, COLOUR_DARK_GREEN, BRSW_INFO), SetMinimalSize(140, 14), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL),
    01080       NWidget(NWID_SPACER), SetFill(1, 0),
    01081     EndContainer(),
    01082     NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
    01083       NWidget(NWID_SPACER), SetFill(1, 0),
    01084       NWidget(WWT_TEXTBTN, COLOUR_GREY, BRSW_LT_OFF), SetMinimalSize(60, 12),
    01085                       SetDataTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
    01086       NWidget(WWT_TEXTBTN, COLOUR_GREY, BRSW_LT_ON), SetMinimalSize(60, 12),
    01087                       SetDataTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
    01088       NWidget(NWID_SPACER), SetFill(1, 0),
    01089     EndContainer(),
    01090     NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetResize(0, 1),
    01091   EndContainer(),
    01092 };
    01093
    01094 static const WindowDesc _rv_station_picker_desc(
    01095   WDP_AUTO, 0, 0,
    01096   WC_BUS_STATION, WC_BUILD_TOOLBAR,
    01097   WDF_CONSTRUCTION,
    01098   _nested_rv_station_picker_widgets, lengthof(_nested_rv_station_picker_widgets)
    01099 );
    01100
    01101 static void ShowRVStationPicker(Window *parent, RoadStopType rs)
    01102 {
    01103   new BuildRoadStationWindow(&_rv_station_picker_desc, parent, rs);
    01104 }
    01105
    01106 void InitializeRoadGui()
    01107 {
    01108   _road_depot_orientation = DIAGDIR_NW;
    01109   _road_station_picker_orientation = DIAGDIR_NW;
    01110 }