road_gui.cpp

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