00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "gui.h"
00008 #include "window_gui.h"
00009 #include "station_gui.h"
00010 #include "terraform_gui.h"
00011 #include "viewport_func.h"
00012 #include "gfx_func.h"
00013 #include "command_func.h"
00014 #include "variables.h"
00015 #include "road_type.h"
00016 #include "road_cmd.h"
00017 #include "road_map.h"
00018 #include "station_map.h"
00019 #include "station.h"
00020 #include "functions.h"
00021 #include "window_func.h"
00022 #include "vehicle_func.h"
00023 #include "sound_func.h"
00024 #include "player_func.h"
00025 #include "settings_type.h"
00026
00027 #include "table/sprites.h"
00028 #include "table/strings.h"
00029
00030 static void ShowRVStationPicker(RoadStop::Type rs);
00031 static void ShowRoadDepotPicker();
00032
00033 static bool _remove_button_clicked;
00034 static bool _one_way_button_clicked;
00035
00040 enum RoadFlags {
00041 RF_NONE = 0x00,
00042 RF_START_HALFROAD_Y = 0x01,
00043 RF_END_HALFROAD_Y = 0x02,
00044 RF_DIR_Y = 0x04,
00045 RF_DIR_X = RF_NONE,
00046 RF_START_HALFROAD_X = 0x08,
00047 RF_END_HALFROAD_X = 0x10,
00048 };
00049 DECLARE_ENUM_AS_BIT_SET(RoadFlags);
00050
00051 static RoadFlags _place_road_flag;
00052
00053 static RoadType _cur_roadtype;
00054
00055 static DiagDirection _road_depot_orientation;
00056 static DiagDirection _road_station_picker_orientation;
00057
00058 void CcPlaySound1D(bool success, TileIndex tile, uint32 p1, uint32 p2)
00059 {
00060 if (success) SndPlayTileFx(SND_1F_SPLAT, tile);
00061 }
00062
00071 static void PlaceRoad_X_Dir(TileIndex tile)
00072 {
00073 _place_road_flag = RF_DIR_X;
00074 if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X;
00075 VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_ROAD_X_DIR);
00076 }
00077
00086 static void PlaceRoad_Y_Dir(TileIndex tile)
00087 {
00088 _place_road_flag = RF_DIR_Y;
00089 if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y;
00090 VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_ROAD_Y_DIR);
00091 }
00092
00101 static void PlaceRoad_AutoRoad(TileIndex tile)
00102 {
00103 _place_road_flag = RF_NONE;
00104 if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X;
00105 if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y;
00106 VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_PLACE_AUTOROAD);
00107 }
00108
00109 static void PlaceRoad_Bridge(TileIndex tile)
00110 {
00111 VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
00112 }
00113
00114
00115 void CcBuildRoadTunnel(bool success, TileIndex tile, uint32 p1, uint32 p2)
00116 {
00117 if (success) {
00118 SndPlayTileFx(SND_20_SPLAT_2, tile);
00119 ResetObjectToPlace();
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_1804_CAN_T_BUILD_ROAD_HERE,
00145 STR_1805_CAN_T_REMOVE_ROAD_FROM,
00146 STR_1807_CAN_T_BUILD_ROAD_VEHICLE,
00147 { STR_1808_CAN_T_BUILD_BUS_STATION, STR_1809_CAN_T_BUILD_TRUCK_STATION },
00148 { STR_CAN_T_REMOVE_BUS_STATION, STR_CAN_T_REMOVE_TRUCK_STATION },
00149 { STR_3042_BUS_STATION_ORIENTATION, STR_3043_TRUCK_STATION_ORIENT },
00150 { STR_3051_SELECT_BUS_STATION_ORIENTATION, STR_3052_SELECT_TRUCK_LOADING_BAY },
00151
00152 SPR_CURSOR_ROAD_NESW,
00153 SPR_CURSOR_ROAD_NWSE,
00154 SPR_CURSOR_AUTOROAD,
00155 },
00156 {
00157 STR_CAN_T_BUILD_TRAMWAY_HERE,
00158 STR_CAN_T_REMOVE_TRAMWAY_FROM,
00159 STR_CAN_T_BUILD_TRAM_VEHICLE,
00160 { STR_CAN_T_BUILD_PASSENGER_TRAM_STATION, STR_CAN_T_BUILD_CARGO_TRAM_STATION },
00161 { STR_CAN_T_REMOVE_PASSENGER_TRAM_STATION, STR_CAN_T_REMOVE_CARGO_TRAM_STATION },
00162 { STR_PASSENGER_TRAM_STATION_ORIENTATION, STR_CARGO_TRAM_STATION_ORIENT },
00163 { STR_SELECT_PASSENGER_TRAM_STATION_ORIENTATION, STR_SELECT_CARGO_TRAM_STATION_ORIENTATION },
00164
00165 SPR_CURSOR_TRAMWAY_NESW,
00166 SPR_CURSOR_TRAMWAY_NWSE,
00167 SPR_CURSOR_AUTOTRAM,
00168 },
00169 };
00170
00171 static void PlaceRoad_Tunnel(TileIndex tile)
00172 {
00173 DoCommandP(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, CcBuildRoadTunnel, CMD_BUILD_TUNNEL | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE));
00174 }
00175
00176 static void BuildRoadOutsideStation(TileIndex tile, DiagDirection direction)
00177 {
00178 tile += TileOffsByDiagDir(direction);
00179
00180 if (IsNormalRoadTile(tile)) {
00181 if (GetRoadBits(tile, _cur_roadtype) != ROAD_NONE) {
00182 DoCommandP(tile, _cur_roadtype << 4 | DiagDirToRoadBits(ReverseDiagDir(direction)), 0, NULL, CMD_BUILD_ROAD);
00183 }
00184 }
00185 }
00186
00187 void CcRoadDepot(bool success, TileIndex tile, uint32 p1, uint32 p2)
00188 {
00189 if (success) {
00190 DiagDirection dir = (DiagDirection)GB(p1, 0, 2);
00191 SndPlayTileFx(SND_1F_SPLAT, tile);
00192 ResetObjectToPlace();
00193 BuildRoadOutsideStation(tile, dir);
00194
00195 if (HasBit(p2, 1)) BuildRoadOutsideStation(tile, ReverseDiagDir(dir));
00196 }
00197 }
00198
00199 static void PlaceRoad_Depot(TileIndex tile)
00200 {
00201 DoCommandP(tile, _cur_roadtype << 2 | _road_depot_orientation, 0, CcRoadDepot, CMD_BUILD_ROAD_DEPOT | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_depot));
00202 }
00203
00204 static void PlaceRoadStop(TileIndex tile, uint32 p2, uint32 cmd)
00205 {
00206 uint32 p1 = _road_station_picker_orientation;
00207
00208 if (p1 >= DIAGDIR_END) {
00209 SetBit(p2, 1);
00210 p1 -= DIAGDIR_END;
00211 }
00212 DoCommandP(tile, p1, p2, CcRoadDepot, cmd);
00213 }
00214
00215 static void PlaceRoad_BusStation(TileIndex tile)
00216 {
00217 if (_remove_button_clicked) {
00218 DoCommandP(tile, 0, RoadStop::BUS, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[RoadStop::BUS]));
00219 } else {
00220 PlaceRoadStop(tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | RoadStop::BUS, CMD_BUILD_ROAD_STOP | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[RoadStop::BUS]));
00221 }
00222 }
00223
00224 static void PlaceRoad_TruckStation(TileIndex tile)
00225 {
00226 if (_remove_button_clicked) {
00227 DoCommandP(tile, 0, RoadStop::TRUCK, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[RoadStop::TRUCK]));
00228 } else {
00229 PlaceRoadStop(tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | RoadStop::TRUCK, CMD_BUILD_ROAD_STOP | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[RoadStop::TRUCK]));
00230 }
00231 }
00232
00233 static void PlaceRoad_DemolishArea(TileIndex tile)
00234 {
00235 VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
00236 }
00237
00239 enum RoadToolbarWidgets {
00240 RTW_CLOSEBOX = 0,
00241 RTW_CAPTION,
00242 RTW_STICKY,
00243 RTW_ROAD_X,
00244 RTW_ROAD_Y,
00245 RTW_AUTOROAD,
00246 RTW_DEMOLISH,
00247 RTW_DEPOT,
00248 RTW_BUS_STATION,
00249 RTW_TRUCK_STATION,
00250 RTW_ONE_WAY,
00251 RTW_BUILD_BRIDGE,
00252 RTW_BUILD_TUNNEL,
00253 RTW_REMOVE,
00254 };
00255
00256 typedef void OnButtonClick(Window *w);
00257
00258
00262 static void ToggleRoadButton_Remove(Window *w)
00263 {
00264 w->ToggleWidgetLoweredState(RTW_REMOVE);
00265 w->InvalidateWidget(RTW_REMOVE);
00266 _remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE);
00267 SetSelectionRed(_remove_button_clicked);
00268 }
00269
00274 static bool RoadToolbar_CtrlChanged(Window *w)
00275 {
00276 if (w->IsWidgetDisabled(RTW_REMOVE)) return false;
00277
00278
00279 for (uint i = RTW_ROAD_X; i <= RTW_AUTOROAD; i++) {
00280 if (w->IsWidgetLowered(i)) {
00281 ToggleRoadButton_Remove(w);
00282 return true;
00283 }
00284 }
00285
00286 return false;
00287 }
00288
00289
00296 static void BuildRoadClick_X_Dir(Window *w)
00297 {
00298 HandlePlacePushButton(w, RTW_ROAD_X, _road_type_infos[_cur_roadtype].cursor_nwse, VHM_RECT, PlaceRoad_X_Dir);
00299 }
00300
00307 static void BuildRoadClick_Y_Dir(Window *w)
00308 {
00309 HandlePlacePushButton(w, RTW_ROAD_Y, _road_type_infos[_cur_roadtype].cursor_nesw, VHM_RECT, PlaceRoad_Y_Dir);
00310 }
00311
00318 static void BuildRoadClick_AutoRoad(Window *w)
00319 {
00320 HandlePlacePushButton(w, RTW_AUTOROAD, _road_type_infos[_cur_roadtype].cursor_autoroad, VHM_RECT, PlaceRoad_AutoRoad);
00321 }
00322
00323 static void BuildRoadClick_Demolish(Window *w)
00324 {
00325 HandlePlacePushButton(w, RTW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceRoad_DemolishArea);
00326 }
00327
00328 static void BuildRoadClick_Depot(Window *w)
00329 {
00330 if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
00331 if (HandlePlacePushButton(w, RTW_DEPOT, SPR_CURSOR_ROAD_DEPOT, VHM_RECT, PlaceRoad_Depot)) ShowRoadDepotPicker();
00332 }
00333
00334 static void BuildRoadClick_BusStation(Window *w)
00335 {
00336 if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
00337 if (HandlePlacePushButton(w, RTW_BUS_STATION, SPR_CURSOR_BUS_STATION, VHM_RECT, PlaceRoad_BusStation)) ShowRVStationPicker(RoadStop::BUS);
00338 }
00339
00340 static void BuildRoadClick_TruckStation(Window *w)
00341 {
00342 if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
00343 if (HandlePlacePushButton(w, RTW_TRUCK_STATION, SPR_CURSOR_TRUCK_STATION, VHM_RECT, PlaceRoad_TruckStation)) ShowRVStationPicker(RoadStop::TRUCK);
00344 }
00345
00352 static void BuildRoadClick_OneWay(Window *w)
00353 {
00354 if (w->IsWidgetDisabled(RTW_ONE_WAY)) return;
00355 SetWindowDirty(w);
00356 w->ToggleWidgetLoweredState(RTW_ONE_WAY);
00357 SetSelectionRed(false);
00358 }
00359
00360 static void BuildRoadClick_Bridge(Window *w)
00361 {
00362 HandlePlacePushButton(w, RTW_BUILD_BRIDGE, SPR_CURSOR_BRIDGE, VHM_RECT, PlaceRoad_Bridge);
00363 }
00364
00365 static void BuildRoadClick_Tunnel(Window *w)
00366 {
00367 HandlePlacePushButton(w, RTW_BUILD_TUNNEL, SPR_CURSOR_ROAD_TUNNEL, VHM_SPECIAL, PlaceRoad_Tunnel);
00368 }
00369
00370 static void BuildRoadClick_Remove(Window *w)
00371 {
00372 if (w->IsWidgetDisabled(RTW_REMOVE)) return;
00373 ToggleRoadButton_Remove(w);
00374 SndPlayFx(SND_15_BEEP);
00375 }
00376
00378 static OnButtonClick* const _build_road_button_proc[] = {
00379 BuildRoadClick_X_Dir,
00380 BuildRoadClick_Y_Dir,
00381 BuildRoadClick_AutoRoad,
00382 BuildRoadClick_Demolish,
00383 BuildRoadClick_Depot,
00384 BuildRoadClick_BusStation,
00385 BuildRoadClick_TruckStation,
00386 BuildRoadClick_OneWay,
00387 BuildRoadClick_Bridge,
00388 BuildRoadClick_Tunnel,
00389 BuildRoadClick_Remove
00390 };
00391
00393 static const uint16 _road_keycodes[] = {
00394 '1',
00395 '2',
00396 '3',
00397 '4',
00398 '5',
00399 '6',
00400 '7',
00401 '8',
00402 'B',
00403 'T',
00404 'R',
00405 };
00406
00413 static void UpdateOptionWidgetStatus(Window *w, int clicked_widget)
00414 {
00415
00416
00417
00418 switch (clicked_widget) {
00419 case RTW_REMOVE:
00420 w->RaiseWidget(RTW_ONE_WAY);
00421 w->InvalidateWidget(RTW_ONE_WAY);
00422 break;
00423 case RTW_ONE_WAY:
00424 w->RaiseWidget(RTW_REMOVE);
00425 w->InvalidateWidget(RTW_REMOVE);
00426 break;
00427 case RTW_BUS_STATION:
00428 case RTW_TRUCK_STATION:
00429 w->DisableWidget(RTW_ONE_WAY);
00430 w->SetWidgetDisabledState(RTW_REMOVE, !w->IsWidgetLowered(clicked_widget));
00431 break;
00432 case RTW_ROAD_X:
00433 case RTW_ROAD_Y:
00434 case RTW_AUTOROAD:
00435 w->SetWidgetsDisabledState(!w->IsWidgetLowered(clicked_widget),
00436 RTW_REMOVE,
00437 RTW_ONE_WAY,
00438 WIDGET_LIST_END);
00439 break;
00440 default:
00441
00442
00443 w->SetWidgetsDisabledState(true,
00444 RTW_REMOVE,
00445 RTW_ONE_WAY,
00446 WIDGET_LIST_END);
00447 w->SetWidgetsLoweredState (false,
00448 RTW_REMOVE,
00449 RTW_ONE_WAY,
00450 WIDGET_LIST_END);
00451 break;
00452 }
00453 }
00454
00455 static void BuildRoadToolbWndProc(Window *w, WindowEvent *e)
00456 {
00457 switch (e->event) {
00458 case WE_CREATE:
00459 w->SetWidgetsDisabledState(true,
00460 RTW_REMOVE,
00461 RTW_ONE_WAY,
00462 WIDGET_LIST_END);
00463 break;
00464
00465 case WE_PAINT:
00466 w->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD),
00467 RTW_DEPOT,
00468 RTW_BUS_STATION,
00469 RTW_TRUCK_STATION,
00470 WIDGET_LIST_END);
00471 DrawWindowWidgets(w);
00472 break;
00473
00474 case WE_CLICK:
00475 if (e->we.click.widget >= RTW_ROAD_X) {
00476 _remove_button_clicked = false;
00477 _one_way_button_clicked = false;
00478 _build_road_button_proc[e->we.click.widget - RTW_ROAD_X](w);
00479 }
00480 UpdateOptionWidgetStatus(w, e->we.click.widget);
00481 if (_ctrl_pressed) RoadToolbar_CtrlChanged(w);
00482 break;
00483
00484 case WE_KEYPRESS:
00485 for (uint8 i = 0; i != lengthof(_road_keycodes); i++) {
00486 if (e->we.keypress.keycode == _road_keycodes[i]) {
00487 e->we.keypress.cont = false;
00488 _remove_button_clicked = false;
00489 _one_way_button_clicked = false;
00490 _build_road_button_proc[i](w);
00491 UpdateOptionWidgetStatus(w, i + RTW_ROAD_X);
00492 if (_ctrl_pressed) RoadToolbar_CtrlChanged(w);
00493 break;
00494 }
00495 }
00496 MarkTileDirty(_thd.pos.x, _thd.pos.y);
00497 break;
00498
00499 case WE_PLACE_OBJ:
00500 _remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE);
00501 _one_way_button_clicked = w->IsWidgetLowered(RTW_ONE_WAY);
00502 _place_proc(e->we.place.tile);
00503 break;
00504
00505 case WE_ABORT_PLACE_OBJ:
00506 w->RaiseButtons();
00507 w->SetWidgetsDisabledState(true,
00508 RTW_REMOVE,
00509 RTW_ONE_WAY,
00510 WIDGET_LIST_END);
00511 w->InvalidateWidget(RTW_REMOVE);
00512 w->InvalidateWidget(RTW_ONE_WAY);
00513
00514 w = FindWindowById(WC_BUS_STATION, 0);
00515 if (w != NULL) WP(w, def_d).close = true;
00516 w = FindWindowById(WC_TRUCK_STATION, 0);
00517 if (w != NULL) WP(w, def_d).close = true;
00518 w = FindWindowById(WC_BUILD_DEPOT, 0);
00519 if (w != NULL) WP(w, def_d).close = true;
00520 break;
00521
00522 case WE_PLACE_DRAG:
00523
00524
00525
00526
00527 switch (e->we.place.select_proc) {
00528 case DDSP_PLACE_ROAD_X_DIR:
00529 _place_road_flag &= ~RF_END_HALFROAD_X;
00530 if (e->we.place.pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
00531 break;
00532
00533 case DDSP_PLACE_ROAD_Y_DIR:
00534 _place_road_flag &= ~RF_END_HALFROAD_Y;
00535 if (e->we.place.pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
00536 break;
00537
00538 case DDSP_PLACE_AUTOROAD:
00539 _place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X);
00540 if (e->we.place.pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
00541 if (e->we.place.pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
00542
00543
00544
00545 if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y &&
00546 ( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) ||
00547 (_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) {
00548
00549 _place_road_flag &= ~RF_DIR_Y;
00550 } else {
00551
00552 _place_road_flag |= RF_DIR_Y;
00553 }
00554
00555 break;
00556 }
00557
00558 VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
00559 return;
00560
00561 case WE_PLACE_MOUSEUP:
00562 if (e->we.place.pt.x != -1) {
00563 TileIndex start_tile = e->we.place.starttile;
00564 TileIndex end_tile = e->we.place.tile;
00565
00566 switch (e->we.place.select_proc) {
00567 case DDSP_BUILD_BRIDGE:
00568 ResetObjectToPlace();
00569 ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype));
00570 break;
00571
00572 case DDSP_DEMOLISH_AREA:
00573 DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
00574 break;
00575
00576 case DDSP_PLACE_ROAD_X_DIR:
00577 case DDSP_PLACE_ROAD_Y_DIR:
00578 case DDSP_PLACE_AUTOROAD:
00579
00580
00581
00582
00583 _place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3));
00584
00585 DoCommandP(end_tile, start_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5), CcPlaySound1D,
00586 (_ctrl_pressed || _remove_button_clicked) ?
00587 CMD_REMOVE_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) :
00588 CMD_BUILD_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road));
00589 break;
00590 }
00591 }
00592 break;
00593
00594 case WE_PLACE_PRESIZE: {
00595 TileIndex tile = e->we.place.tile;
00596
00597 DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL);
00598 VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
00599 break;
00600 }
00601
00602 case WE_DESTROY:
00603 if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
00604 break;
00605
00606 case WE_CTRL_CHANGED:
00607 if (RoadToolbar_CtrlChanged(w)) e->we.ctrl.cont = false;
00608 break;
00609 }
00610 }
00611
00613 static const Widget _build_road_widgets[] = {
00614 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00615 { WWT_CAPTION, RESIZE_NONE, 7, 11, 250, 0, 13, STR_1802_ROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
00616 { WWT_STICKYBOX, RESIZE_NONE, 7, 251, 262, 0, 13, 0x0, STR_STICKY_BUTTON},
00617
00618 { WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_ROAD_X_DIR, STR_180B_BUILD_ROAD_SECTION},
00619 { WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_ROAD_Y_DIR, STR_180B_BUILD_ROAD_SECTION},
00620 { WWT_IMGBTN, RESIZE_NONE, 7, 44, 65, 14, 35, SPR_IMG_AUTOROAD, STR_BUILD_AUTOROAD_TIP},
00621 { WWT_IMGBTN, RESIZE_NONE, 7, 66, 87, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC},
00622 { WWT_IMGBTN, RESIZE_NONE, 7, 88, 109, 14, 35, SPR_IMG_ROAD_DEPOT, STR_180C_BUILD_ROAD_VEHICLE_DEPOT},
00623 { WWT_IMGBTN, RESIZE_NONE, 7, 110, 131, 14, 35, SPR_IMG_BUS_STATION, STR_180D_BUILD_BUS_STATION},
00624 { WWT_IMGBTN, RESIZE_NONE, 7, 132, 153, 14, 35, SPR_IMG_TRUCK_BAY, STR_180E_BUILD_TRUCK_LOADING_BAY},
00625 { WWT_IMGBTN, RESIZE_NONE, 7, 154, 175, 14, 35, SPR_IMG_ROAD_ONE_WAY, STR_TOGGLE_ONE_WAY_ROAD},
00626 { WWT_IMGBTN, RESIZE_NONE, 7, 176, 218, 14, 35, SPR_IMG_BRIDGE, STR_180F_BUILD_ROAD_BRIDGE},
00627 { WWT_IMGBTN, RESIZE_NONE, 7, 219, 240, 14, 35, SPR_IMG_ROAD_TUNNEL, STR_1810_BUILD_ROAD_TUNNEL},
00628 { WWT_IMGBTN, RESIZE_NONE, 7, 241, 262, 14, 35, SPR_IMG_REMOVE, STR_1811_TOGGLE_BUILD_REMOVE_FOR},
00629
00630 { WIDGETS_END},
00631 };
00632
00633 static const WindowDesc _build_road_desc = {
00634 WDP_ALIGN_TBR, 22, 263, 36, 263, 36,
00635 WC_BUILD_TOOLBAR, WC_NONE,
00636 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
00637 _build_road_widgets,
00638 BuildRoadToolbWndProc
00639 };
00640
00642 static const Widget _build_tramway_widgets[] = {
00643 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00644 { WWT_CAPTION, RESIZE_NONE, 7, 11, 228, 0, 13, STR_WHITE_TRAMWAY_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
00645 { WWT_STICKYBOX, RESIZE_NONE, 7, 229, 240, 0, 13, 0x0, STR_STICKY_BUTTON},
00646
00647 { WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_TRAMWAY_X_DIR, STR_BUILD_TRAMWAY_SECTION},
00648 { WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_TRAMWAY_Y_DIR, STR_BUILD_TRAMWAY_SECTION},
00649 { WWT_IMGBTN, RESIZE_NONE, 7, 44, 65, 14, 35, SPR_IMG_AUTOTRAM, STR_BUILD_AUTOTRAM_TIP},
00650 { WWT_IMGBTN, RESIZE_NONE, 7, 66, 87, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC},
00651 { WWT_IMGBTN, RESIZE_NONE, 7, 88, 109, 14, 35, SPR_IMG_ROAD_DEPOT, STR_BUILD_TRAM_VEHICLE_DEPOT},
00652 { WWT_IMGBTN, RESIZE_NONE, 7, 110, 131, 14, 35, SPR_IMG_BUS_STATION, STR_BUILD_PASSENGER_TRAM_STATION},
00653 { WWT_IMGBTN, RESIZE_NONE, 7, 132, 153, 14, 35, SPR_IMG_TRUCK_BAY, STR_BUILD_CARGO_TRAM_STATION},
00654 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
00655 { WWT_IMGBTN, RESIZE_NONE, 7, 154, 196, 14, 35, SPR_IMG_BRIDGE, STR_BUILD_TRAMWAY_BRIDGE},
00656 { WWT_IMGBTN, RESIZE_NONE, 7, 197, 218, 14, 35, SPR_IMG_ROAD_TUNNEL, STR_BUILD_TRAMWAY_TUNNEL},
00657 { WWT_IMGBTN, RESIZE_NONE, 7, 219, 240, 14, 35, SPR_IMG_REMOVE, STR_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS},
00658
00659 { WIDGETS_END},
00660 };
00661
00662 static const WindowDesc _build_tramway_desc = {
00663 WDP_ALIGN_TBR, 22, 241, 36, 241, 36,
00664 WC_BUILD_TOOLBAR, WC_NONE,
00665 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
00666 _build_tramway_widgets,
00667 BuildRoadToolbWndProc
00668 };
00669
00670 void ShowBuildRoadToolbar(RoadType roadtype)
00671 {
00672 if (!IsValidPlayer(_current_player)) return;
00673 _cur_roadtype = roadtype;
00674
00675 DeleteWindowById(WC_BUILD_TOOLBAR, 0);
00676 Window *w = AllocateWindowDesc(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc);
00677 if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
00678 }
00679
00681 static const Widget _build_road_scen_widgets[] = {
00682 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00683 { WWT_CAPTION, RESIZE_NONE, 7, 11, 184, 0, 13, STR_1802_ROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
00684 { WWT_STICKYBOX, RESIZE_NONE, 7, 185, 196, 0, 13, 0x0, STR_STICKY_BUTTON},
00685
00686 { WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_ROAD_X_DIR, STR_180B_BUILD_ROAD_SECTION},
00687 { WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_ROAD_Y_DIR, STR_180B_BUILD_ROAD_SECTION},
00688 { WWT_IMGBTN, RESIZE_NONE, 7, 44, 65, 14, 35, SPR_IMG_AUTOROAD, STR_BUILD_AUTOROAD_TIP},
00689 { WWT_IMGBTN, RESIZE_NONE, 7, 66, 87, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC},
00690 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
00691 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
00692 { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL},
00693 { WWT_IMGBTN, RESIZE_NONE, 7, 88, 109, 14, 35, SPR_IMG_ROAD_ONE_WAY, STR_TOGGLE_ONE_WAY_ROAD},
00694 { WWT_IMGBTN, RESIZE_NONE, 7, 110, 152, 14, 35, SPR_IMG_BRIDGE, STR_180F_BUILD_ROAD_BRIDGE},
00695 { WWT_IMGBTN, RESIZE_NONE, 7, 153, 174, 14, 35, SPR_IMG_ROAD_TUNNEL, STR_1810_BUILD_ROAD_TUNNEL},
00696 { WWT_IMGBTN, RESIZE_NONE, 7, 175, 196, 14, 35, SPR_IMG_REMOVE, STR_1811_TOGGLE_BUILD_REMOVE_FOR},
00697 { WIDGETS_END},
00698 };
00699
00700 static const WindowDesc _build_road_scen_desc = {
00701 WDP_AUTO, WDP_AUTO, 197, 36, 197, 36,
00702 WC_SCEN_BUILD_ROAD, WC_NONE,
00703 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
00704 _build_road_scen_widgets,
00705 BuildRoadToolbWndProc
00706 };
00707
00708 void ShowBuildRoadScenToolbar()
00709 {
00710 _cur_roadtype = ROADTYPE_ROAD;
00711 AllocateWindowDescFront(&_build_road_scen_desc, 0);
00712 }
00713
00715 enum BuildRoadDepotWidgets {
00716 BRDW_CLOSEBOX = 0,
00717 BRDW_CAPTION,
00718 BRDW_BACKGROUND,
00719 BRDW_DEPOT_NE,
00720 BRDW_DEPOT_SE,
00721 BRDW_DEPOT_SW,
00722 BRDW_DEPOT_NW,
00723 };
00724
00725 static void BuildRoadDepotWndProc(Window *w, WindowEvent *e)
00726 {
00727 switch (e->event) {
00728 case WE_CREATE: w->LowerWidget(_road_depot_orientation + BRDW_DEPOT_NE); break;
00729
00730 case WE_PAINT:
00731 DrawWindowWidgets(w);
00732
00733 DrawRoadDepotSprite(70, 17, DIAGDIR_NE, _cur_roadtype);
00734 DrawRoadDepotSprite(70, 69, DIAGDIR_SE, _cur_roadtype);
00735 DrawRoadDepotSprite( 2, 69, DIAGDIR_SW, _cur_roadtype);
00736 DrawRoadDepotSprite( 2, 17, DIAGDIR_NW, _cur_roadtype);
00737 break;
00738
00739 case WE_CLICK:
00740 switch (e->we.click.widget) {
00741 case BRDW_DEPOT_NW:
00742 case BRDW_DEPOT_NE:
00743 case BRDW_DEPOT_SW:
00744 case BRDW_DEPOT_SE:
00745 w->RaiseWidget(_road_depot_orientation + BRDW_DEPOT_NE);
00746 _road_depot_orientation = (DiagDirection)(e->we.click.widget - BRDW_DEPOT_NE);
00747 w->LowerWidget(_road_depot_orientation + BRDW_DEPOT_NE);
00748 SndPlayFx(SND_15_BEEP);
00749 SetWindowDirty(w);
00750 break;
00751 }
00752 break;
00753
00754 case WE_MOUSELOOP:
00755 if (WP(w, def_d).close) DeleteWindow(w);
00756 break;
00757
00758 case WE_DESTROY:
00759 if (!WP(w, def_d).close) ResetObjectToPlace();
00760 break;
00761 }
00762 }
00763
00765 static const Widget _build_road_depot_widgets[] = {
00766 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00767 { WWT_CAPTION, RESIZE_NONE, 7, 11, 139, 0, 13, STR_1806_ROAD_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
00768 { WWT_PANEL, RESIZE_NONE, 7, 0, 139, 14, 121, 0x0, STR_NULL},
00769 { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 17, 66, 0x0, STR_1813_SELECT_ROAD_VEHICLE_DEPOT},
00770 { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 69, 118, 0x0, STR_1813_SELECT_ROAD_VEHICLE_DEPOT},
00771 { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 69, 118, 0x0, STR_1813_SELECT_ROAD_VEHICLE_DEPOT},
00772 { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 17, 66, 0x0, STR_1813_SELECT_ROAD_VEHICLE_DEPOT},
00773 { WIDGETS_END},
00774 };
00775
00777 static const Widget _build_tram_depot_widgets[] = {
00778 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00779 { WWT_CAPTION, RESIZE_NONE, 7, 11, 139, 0, 13, STR_TRAM_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
00780 { WWT_PANEL, RESIZE_NONE, 7, 0, 139, 14, 121, 0x0, STR_NULL},
00781 { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 17, 66, 0x0, STR_SELECT_TRAM_VEHICLE_DEPOT},
00782 { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 69, 118, 0x0, STR_SELECT_TRAM_VEHICLE_DEPOT},
00783 { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 69, 118, 0x0, STR_SELECT_TRAM_VEHICLE_DEPOT},
00784 { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 17, 66, 0x0, STR_SELECT_TRAM_VEHICLE_DEPOT},
00785 { WIDGETS_END},
00786 };
00787
00788 static const WindowDesc _build_road_depot_desc = {
00789 WDP_AUTO, WDP_AUTO, 140, 122, 140, 122,
00790 WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
00791 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
00792 _build_road_depot_widgets,
00793 BuildRoadDepotWndProc
00794 };
00795
00796 static const WindowDesc _build_tram_depot_desc = {
00797 WDP_AUTO, WDP_AUTO, 140, 122, 140, 122,
00798 WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
00799 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
00800 _build_tram_depot_widgets,
00801 BuildRoadDepotWndProc
00802 };
00803
00804 static void ShowRoadDepotPicker()
00805 {
00806 AllocateWindowDesc(_cur_roadtype == ROADTYPE_ROAD ? &_build_road_depot_desc : &_build_tram_depot_desc);
00807 }
00808
00810 enum BuildRoadStationWidgets {
00811 BRSW_CLOSEBOX = 0,
00812 BRSW_CAPTION,
00813 BRSW_BACKGROUND,
00814 BRSW_STATION_NE,
00815 BRSW_STATION_SE,
00816 BRSW_STATION_SW,
00817 BRSW_STATION_NW,
00818 BRSW_STATION_X,
00819 BRSW_STATION_Y,
00820 BRSW_LT_OFF,
00821 BRSW_LT_ON,
00822 BRSW_INFO,
00823 };
00824
00825 static void RoadStationPickerWndProc(Window *w, WindowEvent *e)
00826 {
00827 switch (e->event) {
00828 case WE_CREATE:
00829
00830 if (_cur_roadtype == ROADTYPE_TRAM && _road_station_picker_orientation < DIAGDIR_END) {
00831 _road_station_picker_orientation = DIAGDIR_END;
00832 }
00833 w->SetWidgetsDisabledState(_cur_roadtype == ROADTYPE_TRAM,
00834 BRSW_STATION_NE,
00835 BRSW_STATION_SE,
00836 BRSW_STATION_SW,
00837 BRSW_STATION_NW,
00838 WIDGET_LIST_END);
00839
00840 w->LowerWidget(_road_station_picker_orientation + BRSW_STATION_NE);
00841 w->LowerWidget(_station_show_coverage + BRSW_LT_OFF);
00842 break;
00843
00844 case WE_PAINT: {
00845 if (WP(w, def_d).close) return;
00846
00847 DrawWindowWidgets(w);
00848
00849 if (_station_show_coverage) {
00850 int rad = _patches.modified_catchment ? CA_TRUCK : CA_UNMODIFIED;
00851 SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
00852 } else {
00853 SetTileSelectSize(1, 1);
00854 }
00855
00856 StationType st = (w->window_class == WC_BUS_STATION) ? STATION_BUS : STATION_TRUCK;
00857
00858 StationPickerDrawSprite(103, 35, st, INVALID_RAILTYPE, ROADTYPE_ROAD, 0);
00859 StationPickerDrawSprite(103, 85, st, INVALID_RAILTYPE, ROADTYPE_ROAD, 1);
00860 StationPickerDrawSprite( 35, 85, st, INVALID_RAILTYPE, ROADTYPE_ROAD, 2);
00861 StationPickerDrawSprite( 35, 35, st, INVALID_RAILTYPE, ROADTYPE_ROAD, 3);
00862
00863 StationPickerDrawSprite(171, 35, st, INVALID_RAILTYPE, _cur_roadtype, 4);
00864 StationPickerDrawSprite(171, 85, st, INVALID_RAILTYPE, _cur_roadtype, 5);
00865
00866 int text_end = DrawStationCoverageAreaText(2, 146,
00867 (w->window_class == WC_BUS_STATION) ? SCT_PASSENGERS_ONLY : SCT_NON_PASSENGERS_ONLY,
00868 3) + 4;
00869 if (text_end > w->widget[BRSW_BACKGROUND].bottom) {
00870 SetWindowDirty(w);
00871 ResizeWindowForWidget(w, BRSW_BACKGROUND, 0, text_end - w->widget[BRSW_BACKGROUND].bottom);
00872 SetWindowDirty(w);
00873 }
00874
00875 } break;
00876
00877 case WE_CLICK: {
00878 switch (e->we.click.widget) {
00879 case BRSW_STATION_NE:
00880 case BRSW_STATION_SE:
00881 case BRSW_STATION_SW:
00882 case BRSW_STATION_NW:
00883 case BRSW_STATION_X:
00884 case BRSW_STATION_Y:
00885 w->RaiseWidget(_road_station_picker_orientation + BRSW_STATION_NE);
00886 _road_station_picker_orientation = (DiagDirection)(e->we.click.widget - BRSW_STATION_NE);
00887 w->LowerWidget(_road_station_picker_orientation + BRSW_STATION_NE);
00888 SndPlayFx(SND_15_BEEP);
00889 SetWindowDirty(w);
00890 break;
00891
00892 case BRSW_LT_OFF:
00893 case BRSW_LT_ON:
00894 w->RaiseWidget(_station_show_coverage + BRSW_LT_OFF);
00895 _station_show_coverage = (e->we.click.widget != BRSW_LT_OFF);
00896 w->LowerWidget(_station_show_coverage + BRSW_LT_OFF);
00897 SndPlayFx(SND_15_BEEP);
00898 SetWindowDirty(w);
00899 break;
00900 }
00901 } break;
00902
00903 case WE_MOUSELOOP: {
00904 if (WP(w, def_d).close) {
00905 DeleteWindow(w);
00906 return;
00907 }
00908
00909 CheckRedrawStationCoverage(w);
00910 } break;
00911
00912 case WE_DESTROY:
00913 if (!WP(w, def_d).close) ResetObjectToPlace();
00914 break;
00915 }
00916 }
00917
00919 static const Widget _rv_station_picker_widgets[] = {
00920 { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00921 { WWT_CAPTION, RESIZE_NONE, 7, 11, 206, 0, 13, STR_NULL, STR_018C_WINDOW_TITLE_DRAG_THIS},
00922 { WWT_PANEL, RESIZE_NONE, 7, 0, 206, 14, 176, 0x0, STR_NULL},
00923
00924 { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 17, 66, 0x0, STR_NULL},
00925 { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 69, 118, 0x0, STR_NULL},
00926 { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 69, 118, 0x0, STR_NULL},
00927 { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 17, 66, 0x0, STR_NULL},
00928 { WWT_PANEL, RESIZE_NONE, 14, 139, 204, 17, 66, 0x0, STR_NULL},
00929 { WWT_PANEL, RESIZE_NONE, 14, 139, 204, 69, 118, 0x0, STR_NULL},
00930
00931 { WWT_TEXTBTN, RESIZE_NONE, 14, 10, 69, 133, 144, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
00932 { WWT_TEXTBTN, RESIZE_NONE, 14, 70, 129, 133, 144, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
00933 { WWT_LABEL, RESIZE_NONE, 7, 0, 139, 120, 133, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
00934 { WIDGETS_END},
00935 };
00936
00937 static const WindowDesc _rv_station_picker_desc = {
00938 WDP_AUTO, WDP_AUTO, 207, 177, 207, 177,
00939 WC_BUS_STATION, WC_BUILD_TOOLBAR,
00940 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
00941 _rv_station_picker_widgets,
00942 RoadStationPickerWndProc
00943 };
00944
00945 static void ShowRVStationPicker(RoadStop::Type rs)
00946 {
00947 Window *w = AllocateWindowDesc(&_rv_station_picker_desc);
00948 if (w == NULL) return;
00949
00950 w->window_class = (rs == RoadStop::BUS) ? WC_BUS_STATION : WC_TRUCK_STATION;
00951 w->widget[BRSW_CAPTION].data = _road_type_infos[_cur_roadtype].picker_title[rs];
00952 for (uint i = BRSW_STATION_NE; i < BRSW_LT_OFF; i++) w->widget[i].tooltips = _road_type_infos[_cur_roadtype].picker_tooltip[rs];
00953 }
00954
00955 void InitializeRoadGui()
00956 {
00957 _road_depot_orientation = DIAGDIR_NW;
00958 _road_station_picker_orientation = DIAGDIR_NW;
00959 }