# road_gui.cpp

Go to the documentation of this file.

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