# road_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: road_gui.cpp 25496 2013-06-28 19:09:47Z 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 "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, 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, tile, other_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_20_SPLAT_2, 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, 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, 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(const WindowDesc *desc, WindowNumber window_number) : Window()
    00312   {
    00313     this->InitNested(desc, 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 OnKeyPress(uint16 key, uint16 keycode)
    00477   {
    00478     int num = CheckHotkeyMatch(roadtoolbar_hotkeys, keycode, this);
    00479     if (num == -1 || this->GetWidget<NWidgetBase>(num) == NULL) return ES_NOT_HANDLED;
    00480     this->OnClick(Point(), num, 1);
    00481     MarkTileDirtyByTile(TileVirtXY(_thd.pos.x, _thd.pos.y)); // redraw tile selection
    00482     return ES_HANDLED;
    00483   }
    00484
    00485   virtual void OnPlaceObject(Point pt, TileIndex tile)
    00486   {
    00487     _remove_button_clicked = this->IsWidgetLowered(WID_ROT_REMOVE);
    00488     _one_way_button_clicked = this->IsWidgetLowered(WID_ROT_ONE_WAY);
    00489     switch (this->last_started_action) {
    00490       case WID_ROT_ROAD_X:
    00491         _place_road_flag = RF_DIR_X;
    00492         if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X;
    00493         VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_ROAD_X_DIR);
    00494         break;
    00495
    00496       case WID_ROT_ROAD_Y:
    00497         _place_road_flag = RF_DIR_Y;
    00498         if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y;
    00499         VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_ROAD_Y_DIR);
    00500         break;
    00501
    00502       case WID_ROT_AUTOROAD:
    00503         _place_road_flag = RF_NONE;
    00504         if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X;
    00505         if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y;
    00506         VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_PLACE_AUTOROAD);
    00507         break;
    00508
    00509       case WID_ROT_DEMOLISH:
    00510         PlaceProc_DemolishArea(tile);
    00511         break;
    00512
    00513       case WID_ROT_DEPOT:
    00514         DoCommandP(tile, _cur_roadtype << 2 | _road_depot_orientation, 0,
    00515             CMD_BUILD_ROAD_DEPOT | CMD_MSG(_road_type_infos[_cur_roadtype].err_depot), CcRoadDepot);
    00516         break;
    00517
    00518       case WID_ROT_BUS_STATION:
    00519         PlaceRoad_BusStation(tile);
    00520         break;
    00521
    00522       case WID_ROT_TRUCK_STATION:
    00523         PlaceRoad_TruckStation(tile);
    00524         break;
    00525
    00526       case WID_ROT_BUILD_BRIDGE:
    00527         PlaceRoad_Bridge(tile, this);
    00528         break;
    00529
    00530       case WID_ROT_BUILD_TUNNEL:
    00531         DoCommandP(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0,
    00532             CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRoadTunnel);
    00533         break;
    00534
    00535       default: NOT_REACHED();
    00536     }
    00537   }
    00538
    00539   virtual void OnPlaceObjectAbort()
    00540   {
    00541     this->RaiseButtons();
    00542     this->SetWidgetsDisabledState(true,
    00543         WID_ROT_REMOVE,
    00544         WID_ROT_ONE_WAY,
    00545         WIDGET_LIST_END);
    00546     this->SetWidgetDirty(WID_ROT_REMOVE);
    00547     this->SetWidgetDirty(WID_ROT_ONE_WAY);
    00548
    00549     DeleteWindowById(WC_BUS_STATION, TRANSPORT_ROAD);
    00550     DeleteWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD);
    00551     DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_ROAD);
    00552     DeleteWindowById(WC_SELECT_STATION, 0);
    00553     DeleteWindowByClass(WC_BUILD_BRIDGE);
    00554   }
    00555
    00556   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
    00557   {
    00558     /* Here we update the end tile flags
    00559      * of the road placement actions.
    00560      * At first we reset the end halfroad
    00561      * bits and if needed we set them again. */
    00562     switch (select_proc) {
    00563       case DDSP_PLACE_ROAD_X_DIR:
    00564         _place_road_flag &= ~RF_END_HALFROAD_X;
    00565         if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
    00566         break;
    00567
    00568       case DDSP_PLACE_ROAD_Y_DIR:
    00569         _place_road_flag &= ~RF_END_HALFROAD_Y;
    00570         if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
    00571         break;
    00572
    00573       case DDSP_PLACE_AUTOROAD:
    00574         _place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X);
    00575         if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
    00576         if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
    00577
    00578         /* For autoroad we need to update the
    00579          * direction of the road */
    00580         if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y &&
    00581             ( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) ||
    00582             (_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) {
    00583           /* Set dir = X */
    00584           _place_road_flag &= ~RF_DIR_Y;
    00585         } else {
    00586           /* Set dir = Y */
    00587           _place_road_flag |= RF_DIR_Y;
    00588         }
    00589
    00590         break;
    00591
    00592       default:
    00593         break;
    00594     }
    00595
    00596     VpSelectTilesWithMethod(pt.x, pt.y, select_method);
    00597   }
    00598
    00599   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
    00600   {
    00601     if (pt.x != -1) {
    00602       switch (select_proc) {
    00603         default: NOT_REACHED();
    00604         case DDSP_BUILD_BRIDGE:
    00605           if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
    00606           ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype));
    00607           break;
    00608
    00609         case DDSP_DEMOLISH_AREA:
    00610           GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
    00611           break;
    00612
    00613         case DDSP_PLACE_ROAD_X_DIR:
    00614         case DDSP_PLACE_ROAD_Y_DIR:
    00615         case DDSP_PLACE_AUTOROAD:
    00616           /* Flag description:
    00617            * Use the first three bits (0x07) if dir == Y
    00618            * else use the last 2 bits (X dir has
    00619            * not the 3rd bit set) */
    00620           _place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3));
    00621
    00622           DoCommandP(start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5),
    00623               _remove_button_clicked ?
    00624               CMD_REMOVE_LONG_ROAD | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) :
    00625               CMD_BUILD_LONG_ROAD | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road), CcPlaySound1D);
    00626           break;
    00627
    00628         case DDSP_BUILD_BUSSTOP:
    00629           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]));
    00630           break;
    00631
    00632         case DDSP_BUILD_TRUCKSTOP:
    00633           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]));
    00634           break;
    00635
    00636         case DDSP_REMOVE_BUSSTOP: {
    00637           TileArea ta(start_tile, end_tile);
    00638           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);
    00639           break;
    00640         }
    00641
    00642         case DDSP_REMOVE_TRUCKSTOP: {
    00643           TileArea ta(start_tile, end_tile);
    00644           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);
    00645           break;
    00646         }
    00647       }
    00648     }
    00649   }
    00650
    00651   virtual void OnPlacePresize(Point pt, TileIndex tile)
    00652   {
    00653     DoCommand(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL);
    00654     VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
    00655   }
    00656
    00657   virtual EventState OnCTRLStateChange()
    00658   {
    00659     if (RoadToolbar_CtrlChanged(this)) return ES_HANDLED;
    00660     return ES_NOT_HANDLED;
    00661   }
    00662
    00663   static Hotkey<BuildRoadToolbarWindow> roadtoolbar_hotkeys[];
    00664 };
    00665
    00666 Hotkey<BuildRoadToolbarWindow> BuildRoadToolbarWindow::roadtoolbar_hotkeys[] = {
    00667   Hotkey<BuildRoadToolbarWindow>('1', "build_x", WID_ROT_ROAD_X),
    00668   Hotkey<BuildRoadToolbarWindow>('2', "build_y", WID_ROT_ROAD_Y),
    00669   Hotkey<BuildRoadToolbarWindow>('3', "autoroad", WID_ROT_AUTOROAD),
    00670   Hotkey<BuildRoadToolbarWindow>('4', "demolish", WID_ROT_DEMOLISH),
    00671   Hotkey<BuildRoadToolbarWindow>('5', "depot", WID_ROT_DEPOT),
    00672   Hotkey<BuildRoadToolbarWindow>('6', "bus_station", WID_ROT_BUS_STATION),
    00673   Hotkey<BuildRoadToolbarWindow>('7', "truck_station", WID_ROT_TRUCK_STATION),
    00674   Hotkey<BuildRoadToolbarWindow>('8', "oneway", WID_ROT_ONE_WAY),
    00675   Hotkey<BuildRoadToolbarWindow>('B', "bridge", WID_ROT_BUILD_BRIDGE),
    00676   Hotkey<BuildRoadToolbarWindow>('T', "tunnel", WID_ROT_BUILD_TUNNEL),
    00677   Hotkey<BuildRoadToolbarWindow>('R', "remove", WID_ROT_REMOVE),
    00678   HOTKEY_LIST_END(BuildRoadToolbarWindow)
    00679 };
    00680 Hotkey<BuildRoadToolbarWindow> *_roadtoolbar_hotkeys = BuildRoadToolbarWindow::roadtoolbar_hotkeys;
    00681
    00682
    00683 static const NWidgetPart _nested_build_road_widgets[] = {
    00684   NWidget(NWID_HORIZONTAL),
    00685     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00686     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00687     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00688   EndContainer(),
    00689   NWidget(NWID_HORIZONTAL),
    00690     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ROAD_X),
    00691             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_X_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION),
    00692     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ROAD_Y),
    00693             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_Y_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION),
    00694     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_AUTOROAD),
    00695             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_AUTOROAD, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD),
    00696     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_DEMOLISH),
    00697             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00698     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_DEPOT),
    00699             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_DEPOT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT),
    00700     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUS_STATION),
    00701             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_BUS_STATION, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION),
    00702     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_TRUCK_STATION),
    00703             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRUCK_BAY, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY),
    00704     NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
    00705     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ONE_WAY),
    00706             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_ONE_WAY, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD),
    00707     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_BRIDGE),
    00708             SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE),
    00709     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_TUNNEL),
    00710             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL),
    00711     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_REMOVE),
    00712             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD),
    00713   EndContainer(),
    00714 };
    00715
    00716 static const WindowDesc _build_road_desc(
    00717   WDP_ALIGN_TOOLBAR, 0, 0,
    00718   WC_BUILD_TOOLBAR, WC_NONE,
    00719   WDF_CONSTRUCTION,
    00720   _nested_build_road_widgets, lengthof(_nested_build_road_widgets)
    00721 );
    00722
    00723 static const NWidgetPart _nested_build_tramway_widgets[] = {
    00724   NWidget(NWID_HORIZONTAL),
    00725     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00726     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00727     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00728   EndContainer(),
    00729   NWidget(NWID_HORIZONTAL),
    00730     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ROAD_X),
    00731             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAMWAY_X_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION),
    00732     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ROAD_Y),
    00733             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAMWAY_Y_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION),
    00734     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_AUTOROAD),
    00735             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_AUTOTRAM, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM),
    00736     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_DEMOLISH),
    00737             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00738     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_DEPOT),
    00739             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_DEPOT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT),
    00740     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUS_STATION),
    00741             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_BUS_STATION, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_PASSENGER_TRAM_STATION),
    00742     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_TRUCK_STATION),
    00743             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRUCK_BAY, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION),
    00744     NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
    00745     NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, WID_ROT_ONE_WAY), SetMinimalSize(0, 0),
    00746     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_BRIDGE),
    00747             SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE),
    00748     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_TUNNEL),
    00749             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL),
    00750     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_REMOVE),
    00751             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS),
    00752   EndContainer(),
    00753 };
    00754
    00755 static const WindowDesc _build_tramway_desc(
    00756   WDP_ALIGN_TOOLBAR, 0, 0,
    00757   WC_BUILD_TOOLBAR, WC_NONE,
    00758   WDF_CONSTRUCTION,
    00759   _nested_build_tramway_widgets, lengthof(_nested_build_tramway_widgets)
    00760 );
    00761
    00769 Window *ShowBuildRoadToolbar(RoadType roadtype)
    00770 {
    00771   if (!Company::IsValidID(_local_company)) return NULL;
    00772   _cur_roadtype = roadtype;
    00773
    00774   DeleteWindowByClass(WC_BUILD_TOOLBAR);
    00775   return AllocateWindowDescFront<BuildRoadToolbarWindow>(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
    00776 }
    00777
    00778 EventState RoadToolbarGlobalHotkeys(uint16 key, uint16 keycode)
    00779 {
    00780   extern RoadType _last_built_roadtype;
    00781   int num = CheckHotkeyMatch<BuildRoadToolbarWindow>(_roadtoolbar_hotkeys, keycode, NULL, true);
    00782   if (num == -1) return ES_NOT_HANDLED;
    00783   Window *w = ShowBuildRoadToolbar(_last_built_roadtype);
    00784   if (w == NULL) return ES_NOT_HANDLED;
    00785   return w->OnKeyPress(key, keycode);
    00786 }
    00787
    00788 static const NWidgetPart _nested_build_road_scen_widgets[] = {
    00789   NWidget(NWID_HORIZONTAL),
    00790     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00791     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00792     NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
    00793   EndContainer(),
    00794   NWidget(NWID_HORIZONTAL),
    00795     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ROAD_X),
    00796             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_X_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION),
    00797     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ROAD_Y),
    00798             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_Y_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION),
    00799     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_AUTOROAD),
    00800             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_AUTOROAD, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD),
    00801     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_DEMOLISH),
    00802             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
    00803     NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
    00804     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ONE_WAY),
    00805             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_ONE_WAY, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD),
    00806     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_BRIDGE),
    00807             SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE),
    00808     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_TUNNEL),
    00809             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL),
    00810     NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_REMOVE),
    00811             SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD),
    00812   EndContainer(),
    00813 };
    00814
    00815 static const WindowDesc _build_road_scen_desc(
    00816   WDP_AUTO, 0, 0,
    00817   WC_SCEN_BUILD_TOOLBAR, WC_NONE,
    00818   WDF_CONSTRUCTION,
    00819   _nested_build_road_scen_widgets, lengthof(_nested_build_road_scen_widgets)
    00820 );
    00821
    00826 Window *ShowBuildRoadScenToolbar()
    00827 {
    00828   _cur_roadtype = ROADTYPE_ROAD;
    00829   return AllocateWindowDescFront<BuildRoadToolbarWindow>(&_build_road_scen_desc, TRANSPORT_ROAD);
    00830 }
    00831
    00832 EventState RoadToolbarEditorGlobalHotkeys(uint16 key, uint16 keycode)
    00833 {
    00834   int num = CheckHotkeyMatch<BuildRoadToolbarWindow>(_roadtoolbar_hotkeys, keycode, NULL, true);
    00835   if (num == -1) return ES_NOT_HANDLED;
    00836   Window *w = ShowBuildRoadScenToolbar();
    00837   if (w == NULL) return ES_NOT_HANDLED;
    00838   return w->OnKeyPress(key, keycode);
    00839 }
    00840
    00841 struct BuildRoadDepotWindow : public PickerWindowBase {
    00842   BuildRoadDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(parent)
    00843   {
    00844     this->CreateNestedTree(desc);
    00845
    00846     this->LowerWidget(_road_depot_orientation + WID_BROD_DEPOT_NE);
    00847     if ( _cur_roadtype == ROADTYPE_TRAM) {
    00848       this->GetWidget<NWidgetCore>(WID_BROD_CAPTION)->widget_data = STR_BUILD_DEPOT_TRAM_ORIENTATION_CAPTION;
    00849       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;
    00850     }
    00851
    00852     this->FinishInitNested(desc, TRANSPORT_ROAD);
    00853   }
    00854
    00855   virtual void DrawWidget(const Rect &r, int widget) const
    00856   {
    00857     if (!IsInsideMM(widget, WID_BROD_DEPOT_NE, WID_BROD_DEPOT_NW + 1)) return;
    00858
    00859     DrawRoadDepotSprite(r.left - 1, r.top, (DiagDirection)(widget - WID_BROD_DEPOT_NE + DIAGDIR_NE), _cur_roadtype);
    00860   }
    00861
    00862   virtual void OnClick(Point pt, int widget, int click_count)
    00863   {
    00864     switch (widget) {
    00865       case WID_BROD_DEPOT_NW:
    00866       case WID_BROD_DEPOT_NE:
    00867       case WID_BROD_DEPOT_SW:
    00868       case WID_BROD_DEPOT_SE:
    00869         this->RaiseWidget(_road_depot_orientation + WID_BROD_DEPOT_NE);
    00870         _road_depot_orientation = (DiagDirection)(widget - WID_BROD_DEPOT_NE);
    00871         this->LowerWidget(_road_depot_orientation + WID_BROD_DEPOT_NE);
    00872         if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    00873         this->SetDirty();
    00874         break;
    00875
    00876       default:
    00877         break;
    00878     }
    00879   }
    00880 };
    00881
    00882 static const NWidgetPart _nested_build_road_depot_widgets[] = {
    00883   NWidget(NWID_HORIZONTAL),
    00884     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    00885     NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_BROD_CAPTION), SetDataTip(STR_BUILD_DEPOT_ROAD_ORIENTATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    00886   EndContainer(),
    00887   NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
    00888     NWidget(NWID_SPACER), SetMinimalSize(0, 3),
    00889     NWidget(NWID_HORIZONTAL_LTR),
    00890       NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
    00891       NWidget(NWID_VERTICAL),
    00892         NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
    00893         EndContainer(),
    00894         NWidget(NWID_SPACER), SetMinimalSize(0, 2),
    00895         NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
    00896         EndContainer(),
    00897       EndContainer(),
    00898       NWidget(NWID_SPACER), SetMinimalSize(2, 0),
    00899       NWidget(NWID_VERTICAL),
    00900         NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NE), 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_SE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
    00904         EndContainer(),
    00905       EndContainer(),
    00906       NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
    00907     EndContainer(),
    00908     NWidget(NWID_SPACER), SetMinimalSize(0, 3),
    00909   EndContainer(),
    00910 };
    00911
    00912 static const WindowDesc _build_road_depot_desc(
    00913   WDP_AUTO, 0, 0,
    00914   WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
    00915   WDF_CONSTRUCTION,
    00916   _nested_build_road_depot_widgets, lengthof(_nested_build_road_depot_widgets)
    00917 );
    00918
    00919 static void ShowRoadDepotPicker(Window *parent)
    00920 {
    00921   new BuildRoadDepotWindow(&_build_road_depot_desc, parent);
    00922 }
    00923
    00924 struct BuildRoadStationWindow : public PickerWindowBase {
    00925   BuildRoadStationWindow(const WindowDesc *desc, Window *parent, RoadStopType rs) : PickerWindowBase(parent)
    00926   {
    00927     this->CreateNestedTree(desc);
    00928
    00929     /* Trams don't have non-drivethrough stations */
    00930     if (_cur_roadtype == ROADTYPE_TRAM && _road_station_picker_orientation < DIAGDIR_END) {
    00931       _road_station_picker_orientation = DIAGDIR_END;
    00932     }
    00933     this->SetWidgetsDisabledState(_cur_roadtype == ROADTYPE_TRAM,
    00934         WID_BROS_STATION_NE,
    00935         WID_BROS_STATION_SE,
    00936         WID_BROS_STATION_SW,
    00937         WID_BROS_STATION_NW,
    00938         WIDGET_LIST_END);
    00939
    00940     this->GetWidget<NWidgetCore>(WID_BROS_CAPTION)->widget_data = _road_type_infos[_cur_roadtype].picker_title[rs];
    00941     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];
    00942
    00943     this->LowerWidget(_road_station_picker_orientation + WID_BROS_STATION_NE);
    00944     this->LowerWidget(_settings_client.gui.station_show_coverage + WID_BROS_LT_OFF);
    00945
    00946     this->FinishInitNested(desc, TRANSPORT_ROAD);
    00947
    00948     this->window_class = (rs == ROADSTOP_BUS) ? WC_BUS_STATION : WC_TRUCK_STATION;
    00949   }
    00950
    00951   virtual ~BuildRoadStationWindow()
    00952   {
    00953     DeleteWindowById(WC_SELECT_STATION, 0);
    00954   }
    00955
    00956   virtual void OnPaint()
    00957   {
    00958     this->DrawWidgets();
    00959
    00960     int rad = _settings_game.station.modified_catchment ? ((this->window_class == WC_BUS_STATION) ? CA_BUS : CA_TRUCK) : CA_UNMODIFIED;
    00961     if (_settings_client.gui.station_show_coverage) {
    00962       SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
    00963     } else {
    00964       SetTileSelectSize(1, 1);
    00965     }
    00966
    00967     /* 'Accepts' and 'Supplies' texts. */
    00968     StationCoverageType sct = (this->window_class == WC_BUS_STATION) ? SCT_PASSENGERS_ONLY : SCT_NON_PASSENGERS_ONLY;
    00969     int top = this->GetWidget<NWidgetBase>(WID_BROS_LT_ON)->pos_y + this->GetWidget<NWidgetBase>(WID_BROS_LT_ON)->current_y + WD_PAR_VSEP_NORMAL;
    00970     NWidgetBase *back_nwi = this->GetWidget<NWidgetBase>(WID_BROS_BACKGROUND);
    00971     int right = back_nwi->pos_x +  back_nwi->current_x;
    00972     int bottom = back_nwi->pos_y +  back_nwi->current_y;
    00973     top = DrawStationCoverageAreaText(back_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, sct, rad, false) + WD_PAR_VSEP_NORMAL;
    00974     top = DrawStationCoverageAreaText(back_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, sct, rad, true) + WD_PAR_VSEP_NORMAL;
    00975     /* Resize background if the window is too small.
    00976      * Never make the window smaller to avoid oscillating if the size change affects the acceptance.
    00977      * (This is the case, if making the window bigger moves the mouse into the window.) */
    00978     if (top > bottom) {
    00979       ResizeWindow(this, 0, top - bottom);
    00980     }
    00981   }
    00982
    00983   virtual void DrawWidget(const Rect &r, int widget) const
    00984   {
    00985     if (!IsInsideMM(widget, WID_BROS_STATION_NE, WID_BROS_STATION_Y + 1)) return;
    00986
    00987     StationType st = (this->window_class == WC_BUS_STATION) ? STATION_BUS : STATION_TRUCK;
    00988     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);
    00989   }
    00990
    00991   virtual void OnClick(Point pt, int widget, int click_count)
    00992   {
    00993     switch (widget) {
    00994       case WID_BROS_STATION_NE:
    00995       case WID_BROS_STATION_SE:
    00996       case WID_BROS_STATION_SW:
    00997       case WID_BROS_STATION_NW:
    00998       case WID_BROS_STATION_X:
    00999       case WID_BROS_STATION_Y:
    01000         this->RaiseWidget(_road_station_picker_orientation + WID_BROS_STATION_NE);
    01001         _road_station_picker_orientation = (DiagDirection)(widget - WID_BROS_STATION_NE);
    01002         this->LowerWidget(_road_station_picker_orientation + WID_BROS_STATION_NE);
    01003         if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01004         this->SetDirty();
    01005         DeleteWindowById(WC_SELECT_STATION, 0);
    01006         break;
    01007
    01008       case WID_BROS_LT_OFF:
    01009       case WID_BROS_LT_ON:
    01010         this->RaiseWidget(_settings_client.gui.station_show_coverage + WID_BROS_LT_OFF);
    01011         _settings_client.gui.station_show_coverage = (widget != WID_BROS_LT_OFF);
    01012         this->LowerWidget(_settings_client.gui.station_show_coverage + WID_BROS_LT_OFF);
    01013         if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01014         this->SetDirty();
    01015         break;
    01016
    01017       default:
    01018         break;
    01019     }
    01020   }
    01021
    01022   virtual void OnTick()
    01023   {
    01024     CheckRedrawStationCoverage(this);
    01025   }
    01026 };
    01027
    01029 static const NWidgetPart _nested_rv_station_picker_widgets[] = {
    01030   NWidget(NWID_HORIZONTAL),
    01031     NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
    01032     NWidget(WWT_CAPTION,  COLOUR_DARK_GREEN, WID_BROS_CAPTION),
    01033   EndContainer(),
    01034   NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BROS_BACKGROUND),
    01035     NWidget(NWID_SPACER), SetMinimalSize(0, 3),
    01036     NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
    01037       NWidget(NWID_SPACER), SetFill(1, 0),
    01038       NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NW), SetMinimalSize(66, 50), EndContainer(),
    01039       NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_NE), SetMinimalSize(66, 50), EndContainer(),
    01040       NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_X),  SetMinimalSize(66, 50), EndContainer(),
    01041       NWidget(NWID_SPACER), SetFill(1, 0),
    01042     EndContainer(),
    01043     NWidget(NWID_SPACER), SetMinimalSize(0, 2),
    01044     NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
    01045       NWidget(NWID_SPACER), SetFill(1, 0),
    01046       NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SW), SetMinimalSize(66, 50), EndContainer(),
    01047       NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_SE), SetMinimalSize(66, 50), EndContainer(),
    01048       NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y),  SetMinimalSize(66, 50), EndContainer(),
    01049       NWidget(NWID_SPACER), SetFill(1, 0),
    01050     EndContainer(),
    01051     NWidget(NWID_SPACER), SetMinimalSize(0, 1),
    01052     NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
    01053       NWidget(WWT_LABEL, COLOUR_DARK_GREEN, WID_BROS_INFO), SetMinimalSize(140, 14), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL),
    01054       NWidget(NWID_SPACER), SetFill(1, 0),
    01055     EndContainer(),
    01056     NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
    01057       NWidget(NWID_SPACER), SetFill(1, 0),
    01058       NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROS_LT_OFF), SetMinimalSize(60, 12),
    01059                       SetDataTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
    01060       NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROS_LT_ON), SetMinimalSize(60, 12),
    01061                       SetDataTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
    01062       NWidget(NWID_SPACER), SetFill(1, 0),
    01063     EndContainer(),
    01064     NWidget(NWID_SPACER), SetMinimalSize(0, 10), SetResize(0, 1),
    01065   EndContainer(),
    01066 };
    01067
    01068 static const WindowDesc _rv_station_picker_desc(
    01069   WDP_AUTO, 0, 0,
    01070   WC_BUS_STATION, WC_BUILD_TOOLBAR,
    01071   WDF_CONSTRUCTION,
    01072   _nested_rv_station_picker_widgets, lengthof(_nested_rv_station_picker_widgets)
    01073 );
    01074
    01075 static void ShowRVStationPicker(Window *parent, RoadStopType rs)
    01076 {
    01077   new BuildRoadStationWindow(&_rv_station_picker_desc, parent, rs);
    01078 }
    01079
    01080 void InitializeRoadGui()
    01081 {
    01082   _road_depot_orientation = DIAGDIR_NW;
    01083   _road_station_picker_orientation = DIAGDIR_NW;
    01084 }