road_gui.cpp

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

Generated on Fri Dec 31 17:15:37 2010 for OpenTTD by  doxygen 1.6.1