OpenTTD Source  20241130-master-g8d394c697c
rail_gui.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * 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.
4  * 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.
5  * 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/>.
6  */
7 
10 #include "stdafx.h"
11 #include "gui.h"
12 #include "station_base.h"
13 #include "waypoint_base.h"
14 #include "window_gui.h"
15 #include "station_gui.h"
16 #include "terraform_gui.h"
17 #include "viewport_func.h"
18 #include "command_func.h"
19 #include "waypoint_func.h"
20 #include "newgrf_station.h"
21 #include "company_base.h"
22 #include "strings_func.h"
23 #include "window_func.h"
24 #include "sound_func.h"
25 #include "company_func.h"
26 #include "dropdown_type.h"
27 #include "dropdown_func.h"
28 #include "tunnelbridge.h"
29 #include "tilehighlight_func.h"
30 #include "spritecache.h"
31 #include "core/geometry_func.hpp"
32 #include "hotkeys.h"
33 #include "engine_base.h"
34 #include "vehicle_func.h"
35 #include "zoom_func.h"
36 #include "rail_gui.h"
37 #include "station_cmd.h"
38 #include "tunnelbridge_cmd.h"
39 #include "waypoint_cmd.h"
40 #include "rail_cmd.h"
41 #include "timer/timer.h"
43 #include "picker_gui.h"
44 
45 #include "station_map.h"
46 #include "tunnelbridge_map.h"
47 
48 #include "widgets/rail_widget.h"
49 
50 #include "safeguards.h"
51 
52 
59 
62  uint16_t sel_type;
63 };
65 
68  uint16_t sel_type;
70 };
72 
73 
74 static void HandleStationPlacement(TileIndex start, TileIndex end);
75 static void ShowBuildTrainDepotPicker(Window *parent);
76 static void ShowBuildWaypointPicker(Window *parent);
77 static Window *ShowStationBuilder(Window *parent);
78 static void ShowSignalBuilder(Window *parent);
79 
84 static bool IsStationAvailable(const StationSpec *statspec)
85 {
86  if (statspec == nullptr || !HasBit(statspec->callback_mask, CBM_STATION_AVAIL)) return true;
87 
88  uint16_t cb_res = GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, nullptr, INVALID_TILE);
89  if (cb_res == CALLBACK_FAILED) return true;
90 
92 }
93 
94 void CcPlaySound_CONSTRUCTION_RAIL(Commands, const CommandCost &result, TileIndex tile)
95 {
96  if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
97 }
98 
99 static void GenericPlaceRail(TileIndex tile, Track track)
100 {
102  Command<CMD_REMOVE_SINGLE_RAIL>::Post(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK, CcPlaySound_CONSTRUCTION_RAIL,
103  tile, track);
104  } else {
105  Command<CMD_BUILD_SINGLE_RAIL>::Post(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK, CcPlaySound_CONSTRUCTION_RAIL,
107  }
108 }
109 
117 static void PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Track track)
118 {
119  if (GetRailTileType(tile) == RAIL_TILE_DEPOT) return;
121  if ((GetTrackBits(tile) & DiagdirReachesTracks(dir)) == 0) return;
122 
124 }
125 
127 static const Track _place_depot_extra_track[12] = {
128  TRACK_LEFT, TRACK_UPPER, TRACK_UPPER, TRACK_RIGHT, // First additional track for directions 0..3
129  TRACK_X, TRACK_Y, TRACK_X, TRACK_Y, // Second additional track
130  TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT, TRACK_LOWER, // Third additional track
131 };
132 
138 };
139 
140 void CcRailDepot(Commands, const CommandCost &result, TileIndex tile, RailType, DiagDirection dir)
141 {
142  if (result.Failed()) return;
143 
144  if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
146 
147  tile += TileOffsByDiagDir(dir);
148 
149  if (IsTileType(tile, MP_RAILWAY)) {
151 
152  /* Don't place the rail straight out of the depot of there is another depot across from it. */
153  Tile double_depot_tile = tile + TileOffsByDiagDir(dir);
154  bool is_double_depot = IsValidTile(double_depot_tile) && IsRailDepotTile(double_depot_tile);
155  if (!is_double_depot) PlaceExtraDepotRail(tile, _place_depot_extra_dir[dir + 4], _place_depot_extra_track[dir + 4]);
156 
158  }
159 }
160 
165 static void PlaceRail_Waypoint(TileIndex tile)
166 {
169  return;
170  }
171 
172  Axis axis = GetAxisForNewRailWaypoint(tile);
173  if (IsValidAxis(axis)) {
174  /* Valid tile for waypoints */
176  VpSetPlaceSizingLimit(_settings_game.station.station_spread);
177  } else {
178  /* Tile where we can't build rail waypoints. This is always going to fail,
179  * but provides the user with a proper error message. */
180  Command<CMD_BUILD_RAIL_WAYPOINT>::Post(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT, tile, AXIS_X, 1, 1, STAT_CLASS_WAYP, 0, INVALID_STATION, false);
181  }
182 }
183 
184 void CcStation(Commands, const CommandCost &result, TileIndex tile)
185 {
186  if (result.Failed()) return;
187 
188  if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
189  /* Only close the station builder window if the default station and non persistent building is chosen. */
191 }
192 
197 static void PlaceRail_Station(TileIndex tile)
198 {
201  VpSetPlaceSizingLimit(-1);
204  VpSetPlaceSizingLimit(_settings_game.station.station_spread);
205  } else {
208  if (!_station_gui.axis) Swap(w, h);
209 
211  RailType rt = _cur_railtype;
212  uint8_t numtracks = _settings_client.gui.station_numtracks;
213  uint8_t platlength = _settings_client.gui.station_platlength;
214  bool adjacent = _ctrl_pressed;
215 
216  auto proc = [=](bool test, StationID to_join) -> bool {
217  if (test) {
218  return Command<CMD_BUILD_RAIL_STATION>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_RAIL_STATION>()), tile, rt, params.axis, numtracks, platlength, params.sel_class, params.sel_type, INVALID_STATION, adjacent).Succeeded();
219  } else {
220  return Command<CMD_BUILD_RAIL_STATION>::Post(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION, CcStation, tile, rt, params.axis, numtracks, platlength, params.sel_class, params.sel_type, to_join, adjacent);
221  }
222  };
223 
224  ShowSelectStationIfNeeded(TileArea(tile, w, h), proc);
225  }
226 }
227 
234 {
236 
237  if (trackbits & TRACK_BIT_VERT) { // N-S direction
238  trackbits = (_tile_fract_coords.x <= _tile_fract_coords.y) ? TRACK_BIT_RIGHT : TRACK_BIT_LEFT;
239  }
240 
241  if (trackbits & TRACK_BIT_HORZ) { // E-W direction
242  trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? TRACK_BIT_UPPER : TRACK_BIT_LOWER;
243  }
244 
245  Track track = FindFirstTrack(trackbits);
246 
248  Command<CMD_REMOVE_SINGLE_SIGNAL>::Post(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM, CcPlaySound_CONSTRUCTION_RAIL, tile, track);
249  } else {
250  /* Which signals should we cycle through? */
251  bool tile_has_signal = IsPlainRailTile(tile) && IsValidTrack(track) && HasSignalOnTrack(tile, track);
252  SignalType cur_signal_on_tile = tile_has_signal ? GetSignalType(tile, track) : _cur_signal_type;
253  SignalType cycle_start;
254  SignalType cycle_end;
255 
256  /* Start with the least restrictive case: the player wants to cycle through all signals they can see. */
259  cycle_end = SIGTYPE_LAST;
260  } else {
261  /* Only cycle through signals of the same group (block or path) as the current signal on the tile. */
262  if (cur_signal_on_tile <= SIGTYPE_LAST_NOPBS) {
263  /* Block signals only. */
264  cycle_start = SIGTYPE_BLOCK;
265  cycle_end = SIGTYPE_LAST_NOPBS;
266  } else {
267  /* Path signals only. */
268  cycle_start = SIGTYPE_PBS;
269  cycle_end = SIGTYPE_LAST;
270  }
271  }
272 
273  if (FindWindowById(WC_BUILD_SIGNAL, 0) != nullptr) {
274  /* signal GUI is used */
275  Command<CMD_BUILD_SINGLE_SIGNAL>::Post(_convert_signal_button ? STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE : STR_ERROR_CAN_T_BUILD_SIGNALS_HERE, CcPlaySound_CONSTRUCTION_RAIL,
276  tile, track, _cur_signal_type, _cur_signal_variant, _convert_signal_button, false, _ctrl_pressed, cycle_start, cycle_end, 0, 0);
277  } else {
279  Command<CMD_BUILD_SINGLE_SIGNAL>::Post(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE, CcPlaySound_CONSTRUCTION_RAIL,
280  tile, track, _settings_client.gui.default_signal_type, sigvar, false, false, _ctrl_pressed, cycle_start, cycle_end, 0, 0);
281 
282  }
283  }
284 }
285 
291 static void PlaceRail_Bridge(TileIndex tile, Window *w)
292 {
293  if (IsBridgeTile(tile)) {
294  TileIndex other_tile = GetOtherTunnelBridgeEnd(tile);
295  Point pt = {0, 0};
296  w->OnPlaceMouseUp(VPM_X_OR_Y, DDSP_BUILD_BRIDGE, pt, other_tile, tile);
297  } else {
299  }
300 }
301 
304 {
305  if (result.Succeeded()) {
306  if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
308  } else {
310  }
311 }
312 
318 {
323  SetSelectionRed(_remove_button_clicked);
324 }
325 
332 {
333  if (w->IsWidgetDisabled(WID_RAT_REMOVE)) return false;
334 
335  /* allow ctrl to switch remove mode only for these widgets */
336  for (WidgetID i = WID_RAT_BUILD_NS; i <= WID_RAT_BUILD_STATION; i++) {
337  if ((i <= WID_RAT_AUTORAIL || i >= WID_RAT_BUILD_WAYPOINT) && w->IsWidgetLowered(i)) {
339  return true;
340  }
341  }
342 
343  return false;
344 }
345 
346 
353 {
354  if (w->IsWidgetDisabled(WID_RAT_REMOVE)) return;
357 
358  /* handle station builder */
361  /* starting drag & drop remove */
363  SetTileSelectSize(1, 1);
364  } else {
365  VpSetPlaceSizingLimit(-1);
366  }
367  } else {
368  /* starting station build mode */
372  if (_station_gui.axis == 0) Swap(x, y);
373  SetTileSelectSize(x, y);
374  } else {
375  VpSetPlaceSizingLimit(_settings_game.station.station_spread);
376  }
377  }
378  }
379 }
380 
381 static void DoRailroadTrack(Track track)
382 {
384  Command<CMD_REMOVE_RAILROAD_TRACK>::Post(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK, CcPlaySound_CONSTRUCTION_RAIL,
385  TileVirtXY(_thd.selend.x, _thd.selend.y), TileVirtXY(_thd.selstart.x, _thd.selstart.y), track);
386  } else {
387  Command<CMD_BUILD_RAILROAD_TRACK>::Post(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK, CcPlaySound_CONSTRUCTION_RAIL,
388  TileVirtXY(_thd.selend.x, _thd.selend.y), TileVirtXY(_thd.selstart.x, _thd.selstart.y), _cur_railtype, track, _settings_client.gui.auto_remove_signals, false);
389  }
390 }
391 
392 static void HandleAutodirPlacement()
393 {
394  Track trackstat = static_cast<Track>( _thd.drawstyle & HT_DIR_MASK); // 0..5
395 
396  if (_thd.drawstyle & HT_RAIL) { // one tile case
397  GenericPlaceRail(TileVirtXY(_thd.selend.x, _thd.selend.y), trackstat);
398  return;
399  }
400 
401  DoRailroadTrack(trackstat);
402 }
403 
411 {
412  Track track = (Track)GB(_thd.drawstyle, 0, 3); // 0..5
413 
414  if ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT) { // one tile case
415  GenericPlaceSignals(TileVirtXY(_thd.selend.x, _thd.selend.y));
416  return;
417  }
418 
419  /* _settings_client.gui.drag_signals_density is given as a parameter such that each user
420  * in a network game can specify their own signal density */
422  Command<CMD_REMOVE_SIGNAL_TRACK>::Post(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM, CcPlaySound_CONSTRUCTION_RAIL,
423  TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), track, _ctrl_pressed);
424  } else {
425  bool sig_gui = FindWindowById(WC_BUILD_SIGNAL, 0) != nullptr;
428  Command<CMD_BUILD_SIGNAL_TRACK>::Post(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE, CcPlaySound_CONSTRUCTION_RAIL,
430  }
431 }
432 
433 
438 
440  {
441  this->railtype = railtype;
442  this->CreateNestedTree();
445  this->OnInvalidateData();
446  this->last_user_action = INVALID_WID_RAT;
447 
449  }
450 
451  void Close([[maybe_unused]] int data = 0) override
452  {
457  this->Window::Close();
458  }
459 
461  static inline const std::initializer_list<WidgetID> can_build_widgets = {
465  };
466 
467  void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
468  {
469  if (!gui_scope) return;
470 
471  if (!ValParamRailType(this->railtype)) {
472  /* Close toolbar if rail type is not available. */
473  this->Close();
474  return;
475  }
476 
477  bool can_build = CanBuildVehicleInfrastructure(VEH_TRAIN);
478  for (const WidgetID widget : can_build_widgets) this->SetWidgetDisabledState(widget, !can_build);
479  if (!can_build) {
485  }
486  }
487 
488  bool OnTooltip([[maybe_unused]] Point pt, WidgetID widget, TooltipCloseCondition close_cond) override
489  {
490  bool can_build = CanBuildVehicleInfrastructure(VEH_TRAIN);
491  if (can_build) return false;
492 
493  if (std::ranges::find(can_build_widgets, widget) == std::end(can_build_widgets)) return false;
494 
495  GuiShowTooltips(this, STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE, close_cond);
496  return true;
497  }
498 
499  void OnInit() override
500  {
501  /* Configure the rail toolbar for the railtype. */
502  const RailTypeInfo *rti = GetRailTypeInfo(this->railtype);
503  this->GetWidget<NWidgetCore>(WID_RAT_BUILD_NS)->widget_data = rti->gui_sprites.build_ns_rail;
504  this->GetWidget<NWidgetCore>(WID_RAT_BUILD_X)->widget_data = rti->gui_sprites.build_x_rail;
505  this->GetWidget<NWidgetCore>(WID_RAT_BUILD_EW)->widget_data = rti->gui_sprites.build_ew_rail;
506  this->GetWidget<NWidgetCore>(WID_RAT_BUILD_Y)->widget_data = rti->gui_sprites.build_y_rail;
507  this->GetWidget<NWidgetCore>(WID_RAT_AUTORAIL)->widget_data = rti->gui_sprites.auto_rail;
508  this->GetWidget<NWidgetCore>(WID_RAT_BUILD_DEPOT)->widget_data = rti->gui_sprites.build_depot;
509  this->GetWidget<NWidgetCore>(WID_RAT_CONVERT_RAIL)->widget_data = rti->gui_sprites.convert_rail;
510  this->GetWidget<NWidgetCore>(WID_RAT_BUILD_TUNNEL)->widget_data = rti->gui_sprites.build_tunnel;
511  }
512 
518  {
519  this->railtype = railtype;
520  this->ReInit();
521  }
522 
523  void UpdateRemoveWidgetStatus(WidgetID clicked_widget)
524  {
525  switch (clicked_widget) {
526  case WID_RAT_REMOVE:
527  /* If it is the removal button that has been clicked, do nothing,
528  * as it is up to the other buttons to drive removal status */
529  return;
530 
531  case WID_RAT_BUILD_NS:
532  case WID_RAT_BUILD_X:
533  case WID_RAT_BUILD_EW:
534  case WID_RAT_BUILD_Y:
535  case WID_RAT_AUTORAIL:
539  /* Removal button is enabled only if the rail/signal/waypoint/station
540  * button is still lowered. Once raised, it has to be disabled */
541  this->SetWidgetDisabledState(WID_RAT_REMOVE, !this->IsWidgetLowered(clicked_widget));
542  break;
543 
544  default:
545  /* When any other buttons than rail/signal/waypoint/station, raise and
546  * disable the removal button */
549  break;
550  }
551  }
552 
553  void SetStringParameters(WidgetID widget) const override
554  {
555  if (widget == WID_RAT_CAPTION) {
556  const RailTypeInfo *rti = GetRailTypeInfo(this->railtype);
557  if (rti->max_speed > 0) {
558  SetDParam(0, STR_TOOLBAR_RAILTYPE_VELOCITY);
561  } else {
563  }
564  }
565  }
566 
567  void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
568  {
569  if (widget < WID_RAT_BUILD_NS) return;
570 
571  _remove_button_clicked = false;
572  switch (widget) {
573  case WID_RAT_BUILD_NS:
575  this->last_user_action = widget;
576  break;
577 
578  case WID_RAT_BUILD_X:
580  this->last_user_action = widget;
581  break;
582 
583  case WID_RAT_BUILD_EW:
585  this->last_user_action = widget;
586  break;
587 
588  case WID_RAT_BUILD_Y:
590  this->last_user_action = widget;
591  break;
592 
593  case WID_RAT_AUTORAIL:
595  this->last_user_action = widget;
596  break;
597 
598  case WID_RAT_DEMOLISH:
600  this->last_user_action = widget;
601  break;
602 
603  case WID_RAT_BUILD_DEPOT:
605  ShowBuildTrainDepotPicker(this);
606  this->last_user_action = widget;
607  }
608  break;
609 
611  this->last_user_action = widget;
612  if (HandlePlacePushButton(this, WID_RAT_BUILD_WAYPOINT, SPR_CURSOR_WAYPOINT, HT_RECT)) {
613  ShowBuildWaypointPicker(this);
614  }
615  break;
616 
618  if (HandlePlacePushButton(this, WID_RAT_BUILD_STATION, SPR_CURSOR_RAIL_STATION, HT_RECT)) {
619  ShowStationBuilder(this);
620  this->last_user_action = widget;
621  }
622  break;
623 
624  case WID_RAT_BUILD_SIGNALS: {
625  this->last_user_action = widget;
627  if (started != _ctrl_pressed) {
628  ShowSignalBuilder(this);
629  }
630  break;
631  }
632 
634  HandlePlacePushButton(this, WID_RAT_BUILD_BRIDGE, SPR_CURSOR_BRIDGE, HT_RECT);
635  this->last_user_action = widget;
636  break;
637 
640  this->last_user_action = widget;
641  break;
642 
643  case WID_RAT_REMOVE:
644  BuildRailClick_Remove(this);
645  break;
646 
649  this->last_user_action = widget;
650  break;
651 
652  default: NOT_REACHED();
653  }
654  this->UpdateRemoveWidgetStatus(widget);
656  }
657 
658  EventState OnHotkey(int hotkey) override
659  {
660  MarkTileDirtyByTile(TileVirtXY(_thd.pos.x, _thd.pos.y)); // redraw tile selection
661  return Window::OnHotkey(hotkey);
662  }
663 
664  void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
665  {
666  switch (this->last_user_action) {
667  case WID_RAT_BUILD_NS:
669  break;
670 
671  case WID_RAT_BUILD_X:
673  break;
674 
675  case WID_RAT_BUILD_EW:
677  break;
678 
679  case WID_RAT_BUILD_Y:
681  break;
682 
683  case WID_RAT_AUTORAIL:
685  break;
686 
687  case WID_RAT_DEMOLISH:
689  break;
690 
691  case WID_RAT_BUILD_DEPOT:
692  Command<CMD_BUILD_TRAIN_DEPOT>::Post(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT, CcRailDepot, tile, _cur_railtype, _build_depot_direction);
693  break;
694 
696  PlaceRail_Waypoint(tile);
697  break;
698 
700  PlaceRail_Station(tile);
701  break;
702 
705  break;
706 
708  PlaceRail_Bridge(tile, this);
709  break;
710 
712  Command<CMD_BUILD_TUNNEL>::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRailTunnel, tile, TRANSPORT_RAIL, _cur_railtype);
713  break;
714 
717  break;
718 
719  default: NOT_REACHED();
720  }
721  }
722 
723  void OnPlaceDrag(ViewportPlaceMethod select_method, [[maybe_unused]] ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt) override
724  {
725  /* no dragging if you have pressed the convert button */
727 
728  VpSelectTilesWithMethod(pt.x, pt.y, select_method);
729  }
730 
731  void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, TileIndex start_tile, TileIndex end_tile) override
732  {
733  if (pt.x != -1) {
734  switch (select_proc) {
735  default: NOT_REACHED();
736  case DDSP_BUILD_BRIDGE:
738  ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype);
739  break;
740 
741  case DDSP_PLACE_RAIL:
742  HandleAutodirPlacement();
743  break;
744 
745  case DDSP_BUILD_SIGNALS:
747  break;
748 
749  case DDSP_DEMOLISH_AREA:
750  GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
751  break;
752 
753  case DDSP_CONVERT_RAIL:
754  Command<CMD_CONVERT_RAIL>::Post(STR_ERROR_CAN_T_CONVERT_RAIL, CcPlaySound_CONSTRUCTION_RAIL, end_tile, start_tile, _cur_railtype, _ctrl_pressed);
755  break;
756 
757  case DDSP_REMOVE_STATION:
758  case DDSP_BUILD_STATION:
760  /* Station */
762  bool keep_rail = !_ctrl_pressed;
763  Command<CMD_REMOVE_FROM_RAIL_STATION>::Post(STR_ERROR_CAN_T_REMOVE_PART_OF_STATION, CcPlaySound_CONSTRUCTION_RAIL, end_tile, start_tile, keep_rail);
764  } else {
765  HandleStationPlacement(start_tile, end_tile);
766  }
767  } else {
768  /* Waypoint */
770  bool keep_rail = !_ctrl_pressed;
771  Command<CMD_REMOVE_FROM_RAIL_WAYPOINT>::Post(STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT, CcPlaySound_CONSTRUCTION_RAIL, end_tile, start_tile, keep_rail);
772  } else {
773  TileArea ta(start_tile, end_tile);
774  Axis axis = select_method == VPM_X_LIMITED ? AXIS_X : AXIS_Y;
775  bool adjacent = _ctrl_pressed;
776 
777  auto proc = [=](bool test, StationID to_join) -> bool {
778  if (test) {
779  return Command<CMD_BUILD_RAIL_WAYPOINT>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_RAIL_WAYPOINT>()), ta.tile, axis, ta.w, ta.h, _waypoint_gui.sel_class, _waypoint_gui.sel_type, INVALID_STATION, adjacent).Succeeded();
780  } else {
781  return Command<CMD_BUILD_RAIL_WAYPOINT>::Post(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT, CcPlaySound_CONSTRUCTION_RAIL, ta.tile, axis, ta.w, ta.h, _waypoint_gui.sel_class, _waypoint_gui.sel_type, to_join, adjacent);
782  }
783  };
784 
786  }
787  }
788  break;
789  }
790  }
791  }
792 
793  void OnPlaceObjectAbort() override
794  {
797 
798  this->RaiseButtons();
801 
808  }
809 
810  void OnPlacePresize([[maybe_unused]] Point pt, TileIndex tile) override
811  {
814  }
815 
817  {
818  /* do not toggle Remove button by Ctrl when placing station */
820  return ES_NOT_HANDLED;
821  }
822 
823  void OnRealtimeTick([[maybe_unused]] uint delta_ms) override
824  {
825  if (this->IsWidgetLowered(WID_RAT_BUILD_WAYPOINT)) CheckRedrawRailWaypointCoverage(this);
826  }
827 
834  {
835  if (_game_mode != GM_NORMAL) return ES_NOT_HANDLED;
836  extern RailType _last_built_railtype;
837  Window *w = ShowBuildRailToolbar(_last_built_railtype);
838  if (w == nullptr) return ES_NOT_HANDLED;
839  return w->OnHotkey(hotkey);
840  }
841 
842  static inline HotkeyList hotkeys{"railtoolbar", {
843  Hotkey('1', "build_ns", WID_RAT_BUILD_NS),
844  Hotkey('2', "build_x", WID_RAT_BUILD_X),
845  Hotkey('3', "build_ew", WID_RAT_BUILD_EW),
846  Hotkey('4', "build_y", WID_RAT_BUILD_Y),
847  Hotkey({'5', 'A' | WKC_GLOBAL_HOTKEY}, "autorail", WID_RAT_AUTORAIL),
848  Hotkey('6', "demolish", WID_RAT_DEMOLISH),
849  Hotkey('7', "depot", WID_RAT_BUILD_DEPOT),
850  Hotkey('8', "waypoint", WID_RAT_BUILD_WAYPOINT),
851  Hotkey('9', "station", WID_RAT_BUILD_STATION),
852  Hotkey('S', "signal", WID_RAT_BUILD_SIGNALS),
853  Hotkey('B', "bridge", WID_RAT_BUILD_BRIDGE),
854  Hotkey('T', "tunnel", WID_RAT_BUILD_TUNNEL),
855  Hotkey('R', "remove", WID_RAT_REMOVE),
856  Hotkey('C', "convert", WID_RAT_CONVERT_RAIL),
858 };
859 
860 static constexpr NWidgetPart _nested_build_rail_widgets[] = {
862  NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
863  NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_RAT_CAPTION), SetDataTip(STR_JUST_STRING2, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), SetTextStyle(TC_WHITE),
864  NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
865  EndContainer(),
867  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_NS),
868  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_RAIL_NS, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK),
869  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_X),
870  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_RAIL_NE, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK),
871  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_EW),
872  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_RAIL_EW, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK),
873  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_Y),
874  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_RAIL_NW, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK),
875  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_AUTORAIL),
876  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_AUTORAIL, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_AUTORAIL),
877 
878  NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
879 
880  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_DEMOLISH),
881  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
882  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_DEPOT),
883  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DEPOT_RAIL, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING),
884  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_WAYPOINT),
885  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_WAYPOINT, STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL_TO_WAYPOINT),
886  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_STATION),
887  SetFill(0, 1), SetMinimalSize(42, 22), SetDataTip(SPR_IMG_RAIL_STATION, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION),
888  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_SIGNALS),
889  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_RAIL_SIGNALS, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS),
890  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_BRIDGE),
891  SetFill(0, 1), SetMinimalSize(42, 22), SetDataTip(SPR_IMG_BRIDGE, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_BRIDGE),
892  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_BUILD_TUNNEL),
893  SetFill(0, 1), SetMinimalSize(20, 22), SetDataTip(SPR_IMG_TUNNEL_RAIL, STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TUNNEL),
894  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_REMOVE),
895  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_RAIL_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR),
896  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_RAT_CONVERT_RAIL),
897  SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_CONVERT_RAIL, STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL),
898  EndContainer(),
899 };
900 
901 static WindowDesc _build_rail_desc(
902  WDP_ALIGN_TOOLBAR, "toolbar_rail", 0, 0,
905  _nested_build_rail_widgets,
906  &BuildRailToolbarWindow::hotkeys
907 );
908 
909 
919 {
920  if (!Company::IsValidID(_local_company)) return nullptr;
921  if (!ValParamRailType(railtype)) return nullptr;
922 
924  _cur_railtype = railtype;
925  _remove_button_clicked = false;
926  return new BuildRailToolbarWindow(_build_rail_desc, railtype);
927 }
928 
929 /* TODO: For custom stations, respect their allowed platforms/lengths bitmasks!
930  * --pasky */
931 
932 static void HandleStationPlacement(TileIndex start, TileIndex end)
933 {
934  TileArea ta(start, end);
935  uint numtracks = ta.w;
936  uint platlength = ta.h;
937 
938  if (_station_gui.axis == AXIS_X) Swap(numtracks, platlength);
939 
941  RailType rt = _cur_railtype;
942  bool adjacent = _ctrl_pressed;
943 
944  auto proc = [=](bool test, StationID to_join) -> bool {
945  if (test) {
946  return Command<CMD_BUILD_RAIL_STATION>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_RAIL_STATION>()), ta.tile, rt, params.axis, numtracks, platlength, params.sel_class, params.sel_type, INVALID_STATION, adjacent).Succeeded();
947  } else {
948  return Command<CMD_BUILD_RAIL_STATION>::Post(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION, CcStation, ta.tile, rt, params.axis, numtracks, platlength, params.sel_class, params.sel_type, to_join, adjacent);
949  }
950  };
951 
952  ShowSelectStationIfNeeded(ta, proc);
953 }
954 
960 static bool StationUsesDefaultType(const BaseStation *bst)
961 {
962  for (TileIndex t : bst->train_station) {
963  if (bst->TileBelongsToRailStation(t) && HasStationRail(t) && GetCustomStationSpecIndex(t) == 0) return true;
964  }
965  return false;
966 }
967 
969 public:
971 
972  StringID GetClassTooltip() const override { return STR_PICKER_STATION_CLASS_TOOLTIP; }
973  StringID GetTypeTooltip() const override { return STR_PICKER_STATION_TYPE_TOOLTIP; }
974 
975  bool IsActive() const override
976  {
977  for (const auto &cls : StationClass::Classes()) {
978  if (IsWaypointClass(cls)) continue;
979  for (const auto *spec : cls.Specs()) {
980  if (spec != nullptr) return true;
981  }
982  }
983  return false;
984  }
985 
986  bool HasClassChoice() const override
987  {
988  return std::ranges::count_if(StationClass::Classes(), std::not_fn(IsWaypointClass)) > 1;
989  }
990 
991  int GetSelectedClass() const override { return _station_gui.sel_class; }
992  void SetSelectedClass(int id) const override { _station_gui.sel_class = this->GetClassIndex(id); }
993 
994  StringID GetClassName(int id) const override
995  {
996  const auto *sc = GetClass(id);
997  if (IsWaypointClass(*sc)) return INVALID_STRING_ID;
998  return sc->name;
999  }
1000 
1001  int GetSelectedType() const override { return _station_gui.sel_type; }
1002  void SetSelectedType(int id) const override { _station_gui.sel_type = id; }
1003 
1004  StringID GetTypeName(int cls_id, int id) const override
1005  {
1006  const auto *spec = this->GetSpec(cls_id, id);
1007  return (spec == nullptr) ? STR_STATION_CLASS_DFLT_STATION : spec->name;
1008  }
1009 
1010  bool IsTypeAvailable(int cls_id, int id) const override
1011  {
1012  return IsStationAvailable(this->GetSpec(cls_id, id));
1013  }
1014 
1015  void DrawType(int x, int y, int cls_id, int id) const override
1016  {
1017  if (!DrawStationTile(x, y, _cur_railtype, _station_gui.axis, this->GetClassIndex(cls_id), id)) {
1018  StationPickerDrawSprite(x, y, STATION_RAIL, _cur_railtype, INVALID_ROADTYPE, 2 + _station_gui.axis);
1019  }
1020  }
1021 
1022  void FillUsedItems(std::set<PickerItem> &items) override
1023  {
1024  bool default_added = false;
1025  for (const Station *st : Station::Iterate()) {
1026  if (st->owner != _local_company) continue;
1027  if (!default_added && StationUsesDefaultType(st)) {
1028  items.insert({0, 0, STAT_CLASS_DFLT, 0});
1029  default_added = true;
1030  }
1031  for (const auto &sm : st->speclist) {
1032  if (sm.spec == nullptr) continue;
1033  items.insert({sm.grfid, sm.localidx, sm.spec->class_index, sm.spec->index});
1034  }
1035  }
1036  }
1037 
1038  static StationPickerCallbacks instance;
1039 };
1040 /* static */ StationPickerCallbacks StationPickerCallbacks::instance;
1041 
1043 private:
1045 
1051  void CheckSelectedSize(const StationSpec *statspec)
1052  {
1053  if (statspec == nullptr || _settings_client.gui.station_dragdrop) return;
1054 
1055  /* If current number of tracks is not allowed, make it as big as possible */
1059  if (statspec->disallowed_platforms != UINT8_MAX) {
1062  }
1064  }
1065  }
1066 
1070  if (statspec->disallowed_lengths != UINT8_MAX) {
1073  }
1075  }
1076  }
1077  }
1078 
1079 public:
1081  {
1082  this->coverage_height = 2 * GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal;
1083  this->ConstructWindow();
1084  this->InvalidateData();
1085  }
1086 
1087  void OnInit() override
1088  {
1089  this->LowerWidget(WID_BRAS_PLATFORM_DIR_X + _station_gui.axis);
1092  } else {
1095  }
1098 
1099  this->PickerWindow::OnInit();
1100  }
1101 
1102  void Close([[maybe_unused]] int data = 0) override
1103  {
1105  this->PickerWindow::Close();
1106  }
1107 
1108  void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1109  {
1110  if (gui_scope) {
1112  this->CheckSelectedSize(statspec);
1113  }
1114 
1115  this->PickerWindow::OnInvalidateData(data, gui_scope);
1116  }
1117 
1118  void OnPaint() override
1119  {
1121 
1123  SetTileSelectSize(1, 1);
1124  } else {
1127  if (_station_gui.axis == AXIS_X) Swap(x, y);
1128  if (!_remove_button_clicked) {
1129  SetTileSelectSize(x, y);
1130  }
1131  }
1132 
1134 
1135  if (_settings_client.gui.station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
1136 
1137  for (uint bits = 0; bits < 7; bits++) {
1138  bool disable = bits >= _settings_game.station.station_spread;
1139  if (statspec == nullptr) {
1140  this->SetWidgetDisabledState(bits + WID_BRAS_PLATFORM_NUM_1, disable);
1141  this->SetWidgetDisabledState(bits + WID_BRAS_PLATFORM_LEN_1, disable);
1142  } else {
1143  this->SetWidgetDisabledState(bits + WID_BRAS_PLATFORM_NUM_1, HasBit(statspec->disallowed_platforms, bits) || disable);
1144  this->SetWidgetDisabledState(bits + WID_BRAS_PLATFORM_LEN_1, HasBit(statspec->disallowed_lengths, bits) || disable);
1145  }
1146  }
1147 
1148  this->DrawWidgets();
1149 
1150  if (this->IsShaded()) return;
1151  /* 'Accepts' and 'Supplies' texts. */
1152  Rect r = this->GetWidget<NWidgetBase>(WID_BRAS_COVERAGE_TEXTS)->GetCurrentRect();
1153  int top = r.top;
1155  top = DrawStationCoverageAreaText(r.left, r.right, top, SCT_ALL, rad, true);
1156  /* Resize background if the window is too small.
1157  * Never make the window smaller to avoid oscillating if the size change affects the acceptance.
1158  * (This is the case, if making the window bigger moves the mouse into the window.) */
1159  if (top > r.bottom) {
1160  this->coverage_height += top - r.bottom;
1161  this->ReInit();
1162  }
1163  }
1164 
1165  void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1166  {
1167  switch (widget) {
1172  break;
1173 
1175  size.height = this->coverage_height;
1176  break;
1177 
1178  default:
1179  this->PickerWindow::UpdateWidgetSize(widget, size, padding, fill, resize);
1180  break;
1181  }
1182  }
1183 
1184  void DrawWidget(const Rect &r, WidgetID widget) const override
1185  {
1186  DrawPixelInfo tmp_dpi;
1187 
1188  switch (widget) {
1189  case WID_BRAS_PLATFORM_DIR_X: {
1190  /* Set up a clipping area for the '/' station preview */
1191  Rect ir = r.Shrink(WidgetDimensions::scaled.bevel);
1192  if (FillDrawPixelInfo(&tmp_dpi, ir)) {
1193  AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
1197  StationPickerDrawSprite(x, y, STATION_RAIL, _cur_railtype, INVALID_ROADTYPE, 2);
1198  }
1199  }
1200  break;
1201  }
1202 
1203  case WID_BRAS_PLATFORM_DIR_Y: {
1204  /* Set up a clipping area for the '\' station preview */
1205  Rect ir = r.Shrink(WidgetDimensions::scaled.bevel);
1206  if (FillDrawPixelInfo(&tmp_dpi, ir)) {
1207  AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
1211  StationPickerDrawSprite(x, y, STATION_RAIL, _cur_railtype, INVALID_ROADTYPE, 3);
1212  }
1213  }
1214  break;
1215  }
1216 
1217  default:
1218  this->PickerWindow::DrawWidget(r, widget);
1219  break;
1220  }
1221  }
1222 
1223  void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1224  {
1225  switch (widget) {
1228  this->RaiseWidget(WID_BRAS_PLATFORM_DIR_X + _station_gui.axis);
1230  this->LowerWidget(WID_BRAS_PLATFORM_DIR_X + _station_gui.axis);
1231  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1232  this->SetDirty();
1234  break;
1235 
1242  case WID_BRAS_PLATFORM_NUM_7: {
1245 
1248 
1250  if (statspec != nullptr && HasBit(statspec->disallowed_lengths, _settings_client.gui.station_platlength - 1)) {
1251  /* The previously selected number of platforms in invalid */
1252  for (uint i = 0; i < 7; i++) {
1253  if (!HasBit(statspec->disallowed_lengths, i)) {
1256  break;
1257  }
1258  }
1259  }
1260 
1261  this->LowerWidget(_settings_client.gui.station_numtracks + WID_BRAS_PLATFORM_NUM_BEGIN);
1263  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1264  this->SetDirty();
1266  break;
1267  }
1268 
1275  case WID_BRAS_PLATFORM_LEN_7: {
1278 
1281 
1283  if (statspec != nullptr && HasBit(statspec->disallowed_platforms, _settings_client.gui.station_numtracks - 1)) {
1284  /* The previously selected number of tracks in invalid */
1285  for (uint i = 0; i < 7; i++) {
1286  if (!HasBit(statspec->disallowed_platforms, i)) {
1287  this->RaiseWidget(_settings_client.gui.station_numtracks + WID_BRAS_PLATFORM_NUM_BEGIN);
1289  break;
1290  }
1291  }
1292  }
1293 
1294  this->LowerWidget(_settings_client.gui.station_numtracks + WID_BRAS_PLATFORM_NUM_BEGIN);
1295  this->LowerWidget(_settings_client.gui.station_platlength + WID_BRAS_PLATFORM_LEN_BEGIN);
1296  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1297  this->SetDirty();
1299  break;
1300  }
1301 
1304 
1306 
1307  /* get the first allowed length/number of platforms */
1309  if (statspec != nullptr && HasBit(statspec->disallowed_lengths, _settings_client.gui.station_platlength - 1)) {
1310  for (uint i = 0; i < 7; i++) {
1311  if (!HasBit(statspec->disallowed_lengths, i)) {
1312  this->RaiseWidget(_settings_client.gui.station_platlength + WID_BRAS_PLATFORM_LEN_BEGIN);
1314  break;
1315  }
1316  }
1317  }
1318  if (statspec != nullptr && HasBit(statspec->disallowed_platforms, _settings_client.gui.station_numtracks - 1)) {
1319  for (uint i = 0; i < 7; i++) {
1320  if (!HasBit(statspec->disallowed_platforms, i)) {
1321  this->RaiseWidget(_settings_client.gui.station_numtracks + WID_BRAS_PLATFORM_NUM_BEGIN);
1323  break;
1324  }
1325  }
1326  }
1327 
1330  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1331  this->SetDirty();
1333  break;
1334  }
1335 
1337  case WID_BRAS_HIGHLIGHT_ON:
1339 
1342  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1343  this->SetDirty();
1344  SetViewportCatchmentStation(nullptr, true);
1345  break;
1346 
1347  default:
1348  this->PickerWindow::OnClick(pt, widget, click_count);
1349  break;
1350  }
1351  }
1352 
1353  void OnRealtimeTick([[maybe_unused]] uint delta_ms) override
1354  {
1356  }
1357 
1364  {
1365  if (_game_mode == GM_MENU) return ES_NOT_HANDLED;
1367  if (w == nullptr) return ES_NOT_HANDLED;
1368  return w->OnHotkey(hotkey);
1369  }
1370 
1371  static inline HotkeyList hotkeys{"buildrailstation", {
1372  Hotkey('F', "focus_filter_box", PCWHK_FOCUS_FILTER_BOX),
1374 };
1375 
1376 static constexpr NWidgetPart _nested_station_builder_widgets[] = {
1378  NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
1379  NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_RAIL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1380  NWidget(WWT_SHADEBOX, COLOUR_DARK_GREEN),
1381  NWidget(WWT_DEFSIZEBOX, COLOUR_DARK_GREEN),
1382  EndContainer(),
1386  NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
1388  NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(144, 11), SetFill(1, 0), SetDataTip(STR_STATION_BUILD_ORIENTATION, STR_NULL),
1389  NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1),
1390  NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAS_PLATFORM_DIR_X), SetFill(0, 0), SetDataTip(0x0, STR_STATION_BUILD_RAILROAD_ORIENTATION_TOOLTIP), EndContainer(),
1391  NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAS_PLATFORM_DIR_Y), SetFill(0, 0), SetDataTip(0x0, STR_STATION_BUILD_RAILROAD_ORIENTATION_TOOLTIP), EndContainer(),
1392  EndContainer(),
1393  NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(144, 11), SetFill(1, 0), SetDataTip(STR_STATION_BUILD_NUMBER_OF_TRACKS, STR_NULL),
1394  NWidget(NWID_HORIZONTAL), SetPIPRatio(1, 0, 1),
1395  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_NUM_1), SetAspect(1.25f), SetDataTip(STR_BLACK_1, STR_STATION_BUILD_NUMBER_OF_TRACKS_TOOLTIP),
1396  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_NUM_2), SetAspect(1.25f), SetDataTip(STR_BLACK_2, STR_STATION_BUILD_NUMBER_OF_TRACKS_TOOLTIP),
1397  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_NUM_3), SetAspect(1.25f), SetDataTip(STR_BLACK_3, STR_STATION_BUILD_NUMBER_OF_TRACKS_TOOLTIP),
1398  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_NUM_4), SetAspect(1.25f), SetDataTip(STR_BLACK_4, STR_STATION_BUILD_NUMBER_OF_TRACKS_TOOLTIP),
1399  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_NUM_5), SetAspect(1.25f), SetDataTip(STR_BLACK_5, STR_STATION_BUILD_NUMBER_OF_TRACKS_TOOLTIP),
1400  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_NUM_6), SetAspect(1.25f), SetDataTip(STR_BLACK_6, STR_STATION_BUILD_NUMBER_OF_TRACKS_TOOLTIP),
1401  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_NUM_7), SetAspect(1.25f), SetDataTip(STR_BLACK_7, STR_STATION_BUILD_NUMBER_OF_TRACKS_TOOLTIP),
1402  EndContainer(),
1403  NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(144, 11), SetFill(1, 0), SetDataTip(STR_STATION_BUILD_PLATFORM_LENGTH, STR_NULL),
1404  NWidget(NWID_HORIZONTAL), SetPIPRatio(1, 0, 1),
1405  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_LEN_1), SetAspect(1.25f), SetDataTip(STR_BLACK_1, STR_STATION_BUILD_PLATFORM_LENGTH_TOOLTIP),
1406  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_LEN_2), SetAspect(1.25f), SetDataTip(STR_BLACK_2, STR_STATION_BUILD_PLATFORM_LENGTH_TOOLTIP),
1407  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_LEN_3), SetAspect(1.25f), SetDataTip(STR_BLACK_3, STR_STATION_BUILD_PLATFORM_LENGTH_TOOLTIP),
1408  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_LEN_4), SetAspect(1.25f), SetDataTip(STR_BLACK_4, STR_STATION_BUILD_PLATFORM_LENGTH_TOOLTIP),
1409  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_LEN_5), SetAspect(1.25f), SetDataTip(STR_BLACK_5, STR_STATION_BUILD_PLATFORM_LENGTH_TOOLTIP),
1410  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_LEN_6), SetAspect(1.25f), SetDataTip(STR_BLACK_6, STR_STATION_BUILD_PLATFORM_LENGTH_TOOLTIP),
1411  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_LEN_7), SetAspect(1.25f), SetDataTip(STR_BLACK_7, STR_STATION_BUILD_PLATFORM_LENGTH_TOOLTIP),
1412  EndContainer(),
1413  NWidget(NWID_HORIZONTAL), SetPIPRatio(1, 0, 1),
1414  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_PLATFORM_DRAG_N_DROP), SetMinimalSize(75, 12), SetDataTip(STR_STATION_BUILD_DRAG_DROP, STR_STATION_BUILD_DRAG_DROP_TOOLTIP),
1415  EndContainer(),
1416  NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL), SetFill(1, 0),
1417  NWidget(NWID_HORIZONTAL), SetPIPRatio(1, 0, 1),
1418  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_HIGHLIGHT_OFF), SetMinimalSize(60, 12), SetDataTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP),
1419  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAS_HIGHLIGHT_ON), SetMinimalSize(60, 12), SetDataTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP),
1420  EndContainer(),
1421  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BRAS_COVERAGE_TEXTS), SetFill(1, 1), SetResize(1, 0), SetMinimalTextLines(2, 0),
1422  EndContainer(),
1423  EndContainer(),
1424  EndContainer(),
1426  EndContainer(),
1427 };
1428 
1431  WDP_AUTO, "build_station_rail", 0, 0,
1434  _nested_station_builder_widgets,
1435  &BuildRailStationWindow::hotkeys
1436 );
1437 
1440 {
1441  return new BuildRailStationWindow(_station_builder_desc, parent);
1442 }
1443 
1445 private:
1448 
1453  void DrawSignalSprite(const Rect &r, SpriteID image) const
1454  {
1455  Point offset;
1456  Dimension sprite_size = GetSpriteSize(image, &offset);
1457  Rect ir = r.Shrink(WidgetDimensions::scaled.imgbtn);
1458  int x = CenterBounds(ir.left, ir.right, sprite_size.width - offset.x) - offset.x; // centered
1459  int y = ir.top - sig_sprite_bottom_offset +
1460  (ir.Height() + sig_sprite_size.height) / 2; // aligned to bottom
1461 
1462  DrawSprite(image, PAL_NONE, x, y);
1463  }
1464 
1467  {
1468  bool show_non_path_signals = (_settings_client.gui.signal_gui_mode == SIGNAL_GUI_ALL);
1469 
1470  this->GetWidget<NWidgetStacked>(WID_BS_BLOCK_SEL)->SetDisplayedPlane(show_non_path_signals ? 0 : SZSP_NONE);
1471  this->GetWidget<NWidgetStacked>(WID_BS_BLOCK_SPACER_SEL)->SetDisplayedPlane(show_non_path_signals ? 0 : SZSP_NONE);
1472  }
1473 
1474 public:
1476  {
1477  this->CreateNestedTree();
1478  this->SetSignalUIMode();
1480  this->OnInvalidateData();
1481  }
1482 
1483  void Close([[maybe_unused]] int data = 0) override
1484  {
1485  _convert_signal_button = false;
1486  this->PickerWindowBase::Close();
1487  }
1488 
1489  void OnInit() override
1490  {
1491  /* Calculate maximum signal sprite size. */
1492  this->sig_sprite_size.width = 0;
1493  this->sig_sprite_size.height = 0;
1494  this->sig_sprite_bottom_offset = 0;
1496  for (uint type = SIGTYPE_BLOCK; type < SIGTYPE_END; type++) {
1497  for (uint variant = SIG_ELECTRIC; variant <= SIG_SEMAPHORE; variant++) {
1498  for (uint lowered = 0; lowered < 2; lowered++) {
1499  Point offset;
1500  Dimension sprite_size = GetSpriteSize(rti->gui_sprites.signals[type][variant][lowered], &offset);
1501  this->sig_sprite_bottom_offset = std::max<int>(this->sig_sprite_bottom_offset, sprite_size.height);
1502  this->sig_sprite_size.width = std::max<int>(this->sig_sprite_size.width, sprite_size.width - offset.x);
1503  this->sig_sprite_size.height = std::max<int>(this->sig_sprite_size.height, sprite_size.height - offset.y);
1504  }
1505  }
1506  }
1507  }
1508 
1509  void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1510  {
1511  if (widget == WID_BS_DRAG_SIGNALS_DENSITY_LABEL) {
1512  /* Two digits for signals density. */
1513  size.width = std::max(size.width, 2 * GetDigitWidth() + padding.width + WidgetDimensions::scaled.framerect.Horizontal());
1514  } else if (IsInsideMM(widget, WID_BS_SEMAPHORE_NORM, WID_BS_ELECTRIC_PBS_OWAY + 1)) {
1515  size.width = std::max(size.width, this->sig_sprite_size.width + padding.width);
1516  size.height = std::max(size.height, this->sig_sprite_size.height + padding.height);
1517  }
1518  }
1519 
1520  void SetStringParameters(WidgetID widget) const override
1521  {
1522  switch (widget) {
1525  break;
1526  }
1527  }
1528 
1529  void DrawWidget(const Rect &r, WidgetID widget) const override
1530  {
1532  /* Extract signal from widget number. */
1533  int type = (widget - WID_BS_SEMAPHORE_NORM) % SIGTYPE_END;
1534  int var = SIG_SEMAPHORE - (widget - WID_BS_SEMAPHORE_NORM) / SIGTYPE_END; // SignalVariant order is reversed compared to the widgets.
1535  SpriteID sprite = GetRailTypeInfo(_cur_railtype)->gui_sprites.signals[type][var][this->IsWidgetLowered(widget)];
1536 
1537  this->DrawSignalSprite(r, sprite);
1538  }
1539  }
1540 
1541  void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1542  {
1543  switch (widget) {
1544  case WID_BS_SEMAPHORE_NORM:
1546  case WID_BS_SEMAPHORE_EXIT:
1548  case WID_BS_SEMAPHORE_PBS:
1550  case WID_BS_ELECTRIC_NORM:
1551  case WID_BS_ELECTRIC_ENTRY:
1552  case WID_BS_ELECTRIC_EXIT:
1553  case WID_BS_ELECTRIC_COMBO:
1554  case WID_BS_ELECTRIC_PBS:
1557 
1558  _cur_signal_type = (SignalType)((uint)((widget - WID_BS_SEMAPHORE_NORM) % (SIGTYPE_LAST + 1)));
1560 
1561  /* Update default (last-used) signal type in config file. */
1563 
1564  /* If 'remove' button of rail build toolbar is active, disable it. */
1565  if (_remove_button_clicked) {
1567  if (w != nullptr) ToggleRailButton_Remove(w);
1568  }
1569 
1570  break;
1571 
1572  case WID_BS_CONVERT:
1574  break;
1575 
1580  }
1581  break;
1582 
1587  }
1588  break;
1589 
1590  case WID_BS_TOGGLE_SIZE:
1592  this->SetSignalUIMode();
1593  this->ReInit();
1594  break;
1595 
1596  default: break;
1597  }
1598 
1599  this->InvalidateData();
1600  }
1601 
1607  void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1608  {
1609  if (!gui_scope) return;
1611 
1613 
1616  }
1617 };
1618 
1621  /* Title bar and buttons. */
1623  NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
1624  NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_BS_CAPTION), SetDataTip(STR_BUILD_SIGNAL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1625  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_BS_TOGGLE_SIZE), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_BUILD_SIGNAL_TOGGLE_ADVANCED_SIGNAL_TOOLTIP), SetAspect(WidgetDimensions::ASPECT_TOGGLE_SIZE),
1626  EndContainer(),
1627 
1628  /* Container for both signal groups, spacers, and convert/autofill buttons. */
1630  /* Block signals (can be hidden). */
1631  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_BS_BLOCK_SEL),
1633  /* Semaphore block signals. */
1635  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_SEMAPHORE_NORM), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_NORM_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1636  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_SEMAPHORE_ENTRY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1637  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_SEMAPHORE_EXIT), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1638  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_SEMAPHORE_COMBO), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1639  EndContainer(),
1640  /* Electric block signals. */
1642  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_NORM), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_NORM_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1643  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_ENTRY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_ENTRY_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1644  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_EXIT), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1645  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_COMBO), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1646  EndContainer(),
1647  EndContainer(),
1648  EndContainer(),
1649 
1650  /* Divider (only shown if block signals visible). */
1652  NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetFill(0, 0), SetMinimalSize(4, 0), EndContainer(),
1653  EndContainer(),
1654 
1655  /* Path signals. */
1657  /* Semaphore path signals. */
1659  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_SEMAPHORE_PBS), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1660  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_SEMAPHORE_PBS_OWAY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1661  EndContainer(),
1662  /* Electric path signals. */
1664  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_PBS), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1665  NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BS_ELECTRIC_PBS_OWAY), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP), SetMinimalSize(22, 22), EndContainer(),
1666  EndContainer(),
1667  EndContainer(),
1668 
1669  /* Convert/autofill buttons. */
1671  NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_BS_CONVERT), SetDataTip(SPR_IMG_SIGNAL_CONVERT, STR_BUILD_SIGNAL_CONVERT_TOOLTIP), SetFill(0, 1),
1672  NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetFill(0, 1),
1674  NWidget(WWT_LABEL, COLOUR_DARK_GREEN, WID_BS_DRAG_SIGNALS_DENSITY_LABEL), SetDataTip(STR_JUST_INT, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP), SetTextStyle(TC_ORANGE), SetFill(1, 1),
1675  NWidget(NWID_HORIZONTAL), SetPIPRatio(1, 0, 1),
1676  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_BS_DRAG_SIGNALS_DENSITY_DECREASE), SetMinimalSize(9, 12), SetDataTip(AWV_DECREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP),
1677  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_BS_DRAG_SIGNALS_DENSITY_INCREASE), SetMinimalSize(9, 12), SetDataTip(AWV_INCREASE, STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP),
1678  EndContainer(),
1679  EndContainer(),
1680  EndContainer(),
1681  EndContainer(),
1682  EndContainer(),
1683 };
1684 
1687  WDP_AUTO, nullptr, 0, 0,
1691 );
1692 
1696 static void ShowSignalBuilder(Window *parent)
1697 {
1699 }
1700 
1703  {
1704  this->InitNested(TRANSPORT_RAIL);
1706  }
1707 
1708  void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1709  {
1710  if (!IsInsideMM(widget, WID_BRAD_DEPOT_NE, WID_BRAD_DEPOT_NW + 1)) return;
1711 
1714  }
1715 
1716  void DrawWidget(const Rect &r, WidgetID widget) const override
1717  {
1718  if (!IsInsideMM(widget, WID_BRAD_DEPOT_NE, WID_BRAD_DEPOT_NW + 1)) return;
1719 
1720  DrawPixelInfo tmp_dpi;
1721  Rect ir = r.Shrink(WidgetDimensions::scaled.bevel);
1722  if (FillDrawPixelInfo(&tmp_dpi, ir)) {
1723  AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
1724  int x = (ir.Width() - ScaleSpriteTrad(64)) / 2 + ScaleSpriteTrad(31);
1725  int y = (ir.Height() + ScaleSpriteTrad(48)) / 2 - ScaleSpriteTrad(31);
1726  DrawTrainDepotSprite(x, y, widget - WID_BRAD_DEPOT_NE + DIAGDIR_NE, _cur_railtype);
1727  }
1728  }
1729 
1730  void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1731  {
1732  switch (widget) {
1733  case WID_BRAD_DEPOT_NE:
1734  case WID_BRAD_DEPOT_SE:
1735  case WID_BRAD_DEPOT_SW:
1736  case WID_BRAD_DEPOT_NW:
1740  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1741  this->SetDirty();
1742  break;
1743  }
1744  }
1745 };
1746 
1750  NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
1751  NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1752  EndContainer(),
1753  NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
1756  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_NW), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
1757  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_SW), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
1758  EndContainer(),
1760  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_NE), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
1761  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_SE), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
1762  EndContainer(),
1763  EndContainer(),
1764  EndContainer(),
1765 };
1766 
1767 static WindowDesc _build_depot_desc(
1768  WDP_AUTO, nullptr, 0, 0,
1772 );
1773 
1774 static void ShowBuildTrainDepotPicker(Window *parent)
1775 {
1776  new BuildRailDepotWindow(_build_depot_desc, parent);
1777 }
1778 
1780 public:
1782 
1783  StringID GetClassTooltip() const override { return STR_PICKER_WAYPOINT_CLASS_TOOLTIP; }
1784  StringID GetTypeTooltip() const override { return STR_PICKER_WAYPOINT_TYPE_TOOLTIP; }
1785 
1786  bool IsActive() const override
1787  {
1788  for (const auto &cls : StationClass::Classes()) {
1789  if (!IsWaypointClass(cls)) continue;
1790  for (const auto *spec : cls.Specs()) {
1791  if (spec != nullptr) return true;
1792  }
1793  }
1794  return false;
1795  }
1796 
1797  bool HasClassChoice() const override
1798  {
1799  return std::ranges::count_if(StationClass::Classes(), IsWaypointClass) > 1;
1800  }
1801 
1802  void Close(int) override { ResetObjectToPlace(); }
1803  int GetSelectedClass() const override { return _waypoint_gui.sel_class; }
1804  void SetSelectedClass(int id) const override { _waypoint_gui.sel_class = this->GetClassIndex(id); }
1805 
1806  StringID GetClassName(int id) const override
1807  {
1808  const auto *sc = GetClass(id);
1809  if (!IsWaypointClass(*sc)) return INVALID_STRING_ID;
1810  return sc->name;
1811  }
1812 
1813  int GetSelectedType() const override { return _waypoint_gui.sel_type; }
1814  void SetSelectedType(int id) const override { _waypoint_gui.sel_type = id; }
1815 
1816  StringID GetTypeName(int cls_id, int id) const override
1817  {
1818  const auto *spec = this->GetSpec(cls_id, id);
1819  return (spec == nullptr) ? STR_STATION_CLASS_WAYP_WAYPOINT : spec->name;
1820  }
1821 
1822  bool IsTypeAvailable(int cls_id, int id) const override
1823  {
1824  return IsStationAvailable(this->GetSpec(cls_id, id));
1825  }
1826 
1827  void DrawType(int x, int y, int cls_id, int id) const override
1828  {
1829  DrawWaypointSprite(x, y, this->GetClassIndex(cls_id), id, _cur_railtype);
1830  }
1831 
1832  void FillUsedItems(std::set<PickerItem> &items) override
1833  {
1834  bool default_added = false;
1835  for (const Waypoint *wp : Waypoint::Iterate()) {
1836  if (wp->owner != _local_company || HasBit(wp->waypoint_flags, WPF_ROAD)) continue;
1837  if (!default_added && StationUsesDefaultType(wp)) {
1838  items.insert({0, 0, STAT_CLASS_WAYP, 0});
1839  default_added = true;
1840  }
1841  for (const auto &sm : wp->speclist) {
1842  if (sm.spec == nullptr) continue;
1843  items.insert({sm.grfid, sm.localidx, sm.spec->class_index, sm.spec->index});
1844  }
1845  }
1846  }
1847 
1848  static WaypointPickerCallbacks instance;
1849 };
1850 /* static */ WaypointPickerCallbacks WaypointPickerCallbacks::instance;
1851 
1853  BuildRailWaypointWindow(WindowDesc &desc, Window *parent) : PickerWindow(desc, parent, TRANSPORT_RAIL, WaypointPickerCallbacks::instance)
1854  {
1855  this->ConstructWindow();
1856  this->InvalidateData();
1857  }
1858 
1859  static inline HotkeyList hotkeys{"buildrailwaypoint", {
1860  Hotkey('F', "focus_filter_box", PCWHK_FOCUS_FILTER_BOX),
1861  }};
1862 };
1863 
1867  NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
1868  NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_WAYPOINT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1869  NWidget(WWT_SHADEBOX, COLOUR_DARK_GREEN),
1870  NWidget(WWT_DEFSIZEBOX, COLOUR_DARK_GREEN),
1871  EndContainer(),
1875  EndContainer(),
1876 };
1877 
1878 static WindowDesc _build_waypoint_desc(
1879  WDP_AUTO, "build_waypoint", 0, 0,
1883  &BuildRailWaypointWindow::hotkeys
1884 );
1885 
1886 static void ShowBuildWaypointPicker(Window *parent)
1887 {
1888  if (!WaypointPickerCallbacks::instance.IsActive()) return;
1889  new BuildRailWaypointWindow(_build_waypoint_desc, parent);
1890 }
1891 
1896 {
1899  _station_gui.sel_type = 0;
1901  _waypoint_gui.sel_type = 0;
1902 }
1903 
1908 void ReinitGuiAfterToggleElrail(bool disable)
1909 {
1910  extern RailType _last_built_railtype;
1911  if (disable && _last_built_railtype == RAILTYPE_ELECTRIC) {
1912  _last_built_railtype = _cur_railtype = RAILTYPE_RAIL;
1914  if (w != nullptr) w->ModifyRailType(_cur_railtype);
1915  }
1917 }
1918 
1920 static void SetDefaultRailGui()
1921 {
1923 
1924  extern RailType _last_built_railtype;
1925  RailType rt;
1927  case 2: {
1928  /* Find the most used rail type */
1929  uint count[RAILTYPE_END];
1930  memset(count, 0, sizeof(count));
1931  for (TileIndex t = 0; t < Map::Size(); t++) {
1934  count[GetRailType(t)]++;
1935  }
1936  }
1937 
1938  rt = static_cast<RailType>(std::max_element(count + RAILTYPE_BEGIN, count + RAILTYPE_END) - count);
1939  if (count[rt] > 0) break;
1940 
1941  /* No rail, just get the first available one */
1942  [[fallthrough]];
1943  }
1944  case 0: {
1945  /* Use first available type */
1946  std::vector<RailType>::const_iterator it = std::find_if(_sorted_railtypes.begin(), _sorted_railtypes.end(),
1947  [](RailType r) { return HasRailTypeAvail(_local_company, r); });
1948  rt = it != _sorted_railtypes.end() ? *it : RAILTYPE_BEGIN;
1949  break;
1950  }
1951  case 1: {
1952  /* Use last available type */
1953  std::vector<RailType>::const_reverse_iterator it = std::find_if(_sorted_railtypes.rbegin(), _sorted_railtypes.rend(),
1954  [](RailType r){ return HasRailTypeAvail(_local_company, r); });
1955  rt = it != _sorted_railtypes.rend() ? *it : RAILTYPE_BEGIN;
1956  break;
1957  }
1958  default:
1959  NOT_REACHED();
1960  }
1961 
1962  _last_built_railtype = _cur_railtype = rt;
1964  if (w != nullptr) w->ModifyRailType(_cur_railtype);
1965 }
1966 
1971 void ResetSignalVariant(int32_t)
1972 {
1974 
1975  if (new_variant != _cur_signal_variant) {
1977  if (w != nullptr) {
1978  w->SetDirty();
1980  }
1981  _cur_signal_variant = new_variant;
1982  }
1983 }
1984 
1985 static IntervalTimer<TimerGameCalendar> _check_reset_signal({TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE}, [](auto)
1986 {
1988 
1990 });
1991 
1997 {
1999 
2000  _convert_signal_button = false;
2003 }
2004 
2011 DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option)
2012 {
2013  RailTypes used_railtypes;
2014  RailTypes avail_railtypes;
2015 
2016  const Company *c = Company::Get(_local_company);
2017 
2018  /* Find the used railtypes. */
2019  if (for_replacement) {
2020  avail_railtypes = GetCompanyRailTypes(c->index, false);
2021  used_railtypes = GetRailTypes(false);
2022  } else {
2023  avail_railtypes = c->avail_railtypes;
2024  used_railtypes = GetRailTypes(true);
2025  }
2026 
2027  DropDownList list;
2028 
2029  if (all_option) {
2030  list.push_back(MakeDropDownListStringItem(STR_REPLACE_ALL_RAILTYPE, INVALID_RAILTYPE));
2031  }
2032 
2033  Dimension d = { 0, 0 };
2034  /* Get largest icon size, to ensure text is aligned on each menu item. */
2035  if (!for_replacement) {
2036  for (const auto &rt : _sorted_railtypes) {
2037  if (!HasBit(used_railtypes, rt)) continue;
2038  const RailTypeInfo *rti = GetRailTypeInfo(rt);
2040  }
2041  }
2042 
2043  for (const auto &rt : _sorted_railtypes) {
2044  /* If it's not used ever, don't show it to the user. */
2045  if (!HasBit(used_railtypes, rt)) continue;
2046 
2047  const RailTypeInfo *rti = GetRailTypeInfo(rt);
2048 
2049  SetDParam(0, rti->strings.menu_text);
2050  SetDParam(1, rti->max_speed);
2051  if (for_replacement) {
2052  list.push_back(MakeDropDownListStringItem(rti->strings.replace_text, rt, !HasBit(avail_railtypes, rt)));
2053  } else {
2054  StringID str = rti->max_speed > 0 ? STR_TOOLBAR_RAILTYPE_VELOCITY : STR_JUST_STRING;
2055  list.push_back(MakeDropDownListIconItem(d, rti->gui_sprites.build_x_rail, PAL_NONE, str, rt, !HasBit(avail_railtypes, rt)));
2056  }
2057  }
2058 
2059  if (list.empty()) {
2060  /* Empty dropdowns are not allowed */
2061  list.push_back(MakeDropDownListStringItem(STR_NONE, INVALID_RAILTYPE, true));
2062  }
2063 
2064  return list;
2065 }
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, uint8_t road_rail_type)
Prepare the data for the build a bridge window.
Definition: bridge_gui.cpp:354
bool IsBridgeTile(Tile t)
checks if there is a bridge on this tile
Definition: bridge_map.h:35
Common return value for all commands.
Definition: command_type.h:23
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:162
bool Failed() const
Did this command fail?
Definition: command_type.h:171
static std::span< NewGRFClass< Tspec, Tindex, Tmax > const > Classes()
Get read-only span of all classes of this type.
Definition: newgrf_class.h:64
static NewGRFClass * Get(Tindex class_index)
Get a particular class.
const Tspec * GetSpec(uint index) const
Get a spec from the class at a given index.
Helper for PickerCallbacks when the class system is based on NewGRFClass.
Definition: picker_gui.h:100
Base class for windows opened from a toolbar.
Definition: window_gui.h:986
void Close([[maybe_unused]] int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Definition: window.cpp:3519
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Definition: picker_gui.cpp:240
static const int PREVIEW_LEFT
Offset from left edge to draw preview.
Definition: picker_gui.h:165
@ PCWHK_FOCUS_FILTER_BOX
Focus the edit box for editing the filter string.
Definition: picker_gui.h:185
static const int PREVIEW_WIDTH
Width of each preview button.
Definition: picker_gui.h:163
static const int PREVIEW_BOTTOM
Offset from bottom edge to draw preview.
Definition: picker_gui.h:166
static const int PREVIEW_HEIGHT
Height of each preview button.
Definition: picker_gui.h:164
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:127
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition: rail.h:231
SpriteID build_tunnel
button for building a tunnel
Definition: rail.h:159
CursorID rail_swne
Cursor for building rail in X direction.
Definition: rail.h:166
SpriteID convert_rail
button for converting rail
Definition: rail.h:160
CursorID convert
Cursor for converting track.
Definition: rail.h:172
CursorID depot
Cursor for building a depot.
Definition: rail.h:170
struct RailTypeInfo::@26 strings
Strings associated with the rail type.
CursorID rail_nwse
Cursor for building rail in Y direction.
Definition: rail.h:168
SpriteID build_x_rail
button for building single rail in X direction
Definition: rail.h:154
CursorID rail_ew
Cursor for building rail in E-W direction.
Definition: rail.h:167
SpriteID auto_rail
button for the autorail construction
Definition: rail.h:157
CursorID autorail
Cursor for autorail tool.
Definition: rail.h:169
StringID menu_text
Name of this rail type in the main toolbar dropdown.
Definition: rail.h:178
StringID toolbar_caption
Caption in the construction toolbar GUI for this rail type.
Definition: rail.h:177
SpriteID signals[SIGTYPE_END][2][2]
signal GUI sprites (type, variant, state)
Definition: rail.h:161
SpriteID build_ew_rail
button for building single rail in E-W direction
Definition: rail.h:155
SpriteID build_y_rail
button for building single rail in Y direction
Definition: rail.h:156
StringID replace_text
Text used in the autoreplace GUI.
Definition: rail.h:180
SpriteID build_depot
button for building depots
Definition: rail.h:158
struct RailTypeInfo::@24 gui_sprites
struct containing the sprites for the rail GUI.
SpriteID build_ns_rail
button for building single rail in N-S direction
Definition: rail.h:153
CursorID rail_ns
Cursor for building rail in N-S direction.
Definition: rail.h:165
SpriteID tunnel
tunnel sprites base
Definition: rail.h:145
bool IsActive() const override
Should picker class/type selection be enabled?
Definition: rail_gui.cpp:975
bool HasClassChoice() const override
Are there multiple classes to chose from?
Definition: rail_gui.cpp:986
StringID GetTypeName(int cls_id, int id) const override
Get the item of a type.
Definition: rail_gui.cpp:1004
StringID GetClassTooltip() const override
Get the tooltip string for the class list.
Definition: rail_gui.cpp:972
void SetSelectedType(int id) const override
Set the selected type.
Definition: rail_gui.cpp:1002
void DrawType(int x, int y, int cls_id, int id) const override
Draw preview image of an item.
Definition: rail_gui.cpp:1015
StringID GetClassName(int id) const override
Get the name of a class.
Definition: rail_gui.cpp:994
StringID GetTypeTooltip() const override
Get the tooltip string for the type grid.
Definition: rail_gui.cpp:973
int GetSelectedClass() const override
Get the index of the selected class.
Definition: rail_gui.cpp:991
void SetSelectedClass(int id) const override
Set the selected class.
Definition: rail_gui.cpp:992
bool IsTypeAvailable(int cls_id, int id) const override
Test if an item is currently buildable.
Definition: rail_gui.cpp:1010
int GetSelectedType() const override
Get the selected type.
Definition: rail_gui.cpp:1001
void FillUsedItems(std::set< PickerItem > &items) override
Fill a set with all items that are used by the current player.
Definition: rail_gui.cpp:1022
Wrapper class to abstract away the way the tiles are stored.
Definition: map_func.h:25
static Year year
Current year, starting at 0.
int GetSelectedType() const override
Get the selected type.
Definition: rail_gui.cpp:1813
void SetSelectedClass(int id) const override
Set the selected class.
Definition: rail_gui.cpp:1804
StringID GetTypeTooltip() const override
Get the tooltip string for the type grid.
Definition: rail_gui.cpp:1784
void DrawType(int x, int y, int cls_id, int id) const override
Draw preview image of an item.
Definition: rail_gui.cpp:1827
bool IsTypeAvailable(int cls_id, int id) const override
Test if an item is currently buildable.
Definition: rail_gui.cpp:1822
int GetSelectedClass() const override
Get the index of the selected class.
Definition: rail_gui.cpp:1803
StringID GetTypeName(int cls_id, int id) const override
Get the item of a type.
Definition: rail_gui.cpp:1816
bool IsActive() const override
Should picker class/type selection be enabled?
Definition: rail_gui.cpp:1786
void SetSelectedType(int id) const override
Set the selected type.
Definition: rail_gui.cpp:1814
StringID GetClassName(int id) const override
Get the name of a class.
Definition: rail_gui.cpp:1806
StringID GetClassTooltip() const override
Get the tooltip string for the class list.
Definition: rail_gui.cpp:1783
void FillUsedItems(std::set< PickerItem > &items) override
Fill a set with all items that are used by the current player.
Definition: rail_gui.cpp:1832
bool HasClassChoice() const override
Are there multiple classes to chose from?
Definition: rail_gui.cpp:1797
RectPadding framerect
Standard padding inside many panels.
Definition: window_gui.h:42
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition: window_gui.h:68
int vsep_normal
Normal vertical spacing.
Definition: window_gui.h:60
RectPadding fullbevel
Always-scaled bevel thickness.
Definition: window_gui.h:41
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition: window_gui.h:67
Functions related to commands.
static constexpr DoCommandFlag CommandFlagsToDCFlags(CommandFlags cmd_flags)
Extracts the DC flags needed for DoCommand from the flags returned by GetCommandFlags.
Definition: command_func.h:58
@ DC_AUTO
don't allow building on structures
Definition: command_type.h:377
Commands
List of commands.
Definition: command_type.h:187
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
Functions related to companies.
@ COMPANY_SPECTATOR
The client is spectating.
Definition: company_type.h:35
bool IsValidAxis(Axis d)
Checks if an integer value is a valid Axis.
Axis
Allow incrementing of DiagDirDiff variables.
@ AXIS_X
The X axis.
@ AXIS_Y
The y axis.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_SW
Southwest.
Functions related to the drop down widget.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
Definition: dropdown_type.h:50
Base class for engines.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition: fontcache.cpp:77
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:922
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:38
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:988
uint8_t GetDigitWidth(FontSize size)
Return the maximum width of single digit.
Definition: gfx.cpp:1240
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
Definition: gfx.cpp:1548
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition: gfx_func.h:166
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:18
@ FS_NORMAL
Index of the normal font in the font tables.
Definition: gfx_type.h:209
@ WKC_GLOBAL_HOTKEY
Fake keycode bit to indicate global hotkeys.
Definition: gfx_type.h:34
constexpr NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
Obtain a nested widget (sub)tree from an external source.
Definition: widget_type.h:1330
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
Definition: widget_type.h:1181
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1260
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1228
constexpr NWidgetPart SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1202
constexpr NWidgetPart SetTextStyle(TextColour colour, FontSize size=FS_NORMAL)
Widget part function for setting the text style.
Definition: widget_type.h:1160
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
Definition: widget_type.h:1137
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
Definition: widget_type.h:1309
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
Definition: widget_type.h:1191
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:1149
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlags::ResizeX)
Widget part function for setting the aspect ratio.
Definition: widget_type.h:1295
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Definition: widget_type.h:1126
constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
Widget part function for setting a pre/inter/post ratio.
Definition: widget_type.h:1272
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:940
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp:1529
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:2057
GUI functions that shouldn't be here.
Hotkey related functions.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:554
bool HandlePlacePushButton(Window *w, WidgetID widget, CursorID cursor, HighLightStyle mode)
This code is shared for the majority of the pushbuttons.
Definition: main_gui.cpp:63
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:567
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition: map_func.h:404
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition: math_func.hpp:268
constexpr void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:283
void GuiShowTooltips(Window *parent, StringID str, TooltipCloseCondition close_tooltip, uint paramcount)
Shows a tooltip.
Definition: misc_gui.cpp:760
@ CBM_STATION_AVAIL
Availability of station in construction window.
@ CBID_STATION_AVAILABILITY
Determine whether a newstation should be made available to build.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
bool Convert8bitBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
Converts a callback result into a boolean.
bool IsWaypointClass(const RoadStopClass &cls)
Test if a RoadStopClass is the waypoint class.
bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station)
Draw representation of a station tile for GUI purposes.
Header file for NewGRF stations.
StationClassID
@ STAT_CLASS_DFLT
Default station class.
@ STAT_CLASS_WAYP
Waypoint class.
std::unique_ptr< NWidgetBase > MakePickerTypeWidgets()
Create nested widgets for the type picker widgets.
Definition: picker_gui.cpp:646
std::unique_ptr< NWidgetBase > MakePickerClassWidgets()
Create nested widgets for the class picker widgets.
Definition: picker_gui.cpp:623
Functions/types etc.
RailTypes GetCompanyRailTypes(CompanyID company, bool introduces)
Get the rail types the given company can build.
Definition: rail.cpp:251
RailTypes GetRailTypes(bool introduces)
Get list of rail types, regardless of company availability.
Definition: rail.cpp:282
bool ValParamRailType(const RailType rail)
Validate functions for rail building.
Definition: rail.cpp:206
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:307
Command definitions for rail.
static constexpr NWidgetPart _nested_signal_builder_widgets[]
Nested widget definition of the build signal window.
Definition: rail_gui.cpp:1620
static bool RailToolbar_CtrlChanged(Window *w)
Updates the Remove button because of Ctrl state change.
Definition: rail_gui.cpp:331
void ResetSignalVariant(int32_t)
Updates the current signal variant used in the signal GUI to the one adequate to current year.
Definition: rail_gui.cpp:1971
static void PlaceRail_Waypoint(TileIndex tile)
Place a rail waypoint.
Definition: rail_gui.cpp:165
static void SetDefaultRailGui()
Set the initial (default) railtype to use.
Definition: rail_gui.cpp:1920
static RailType _cur_railtype
Rail type of the current build-rail toolbar.
Definition: rail_gui.cpp:53
static constexpr NWidgetPart _nested_build_waypoint_widgets[]
Nested widget definition for the build NewGRF rail waypoint window.
Definition: rail_gui.cpp:1865
static constexpr NWidgetPart _nested_build_depot_widgets[]
Nested widget definition of the build rail depot window.
Definition: rail_gui.cpp:1748
static void HandleAutoSignalPlacement()
Build new signals or remove signals or (if only one tile marked) edit a signal.
Definition: rail_gui.cpp:410
static SignalVariant _cur_signal_variant
set the signal variant (for signal GUI)
Definition: rail_gui.cpp:57
Window * ShowBuildRailToolbar(RailType railtype)
Open the build rail toolbar window for a specific rail type.
Definition: rail_gui.cpp:918
static void PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Track track)
Try to add an additional rail-track at the entrance of a depot.
Definition: rail_gui.cpp:117
static void PlaceRail_Bridge(TileIndex tile, Window *w)
Start placing a rail bridge.
Definition: rail_gui.cpp:291
static void PlaceRail_Station(TileIndex tile)
Place a rail station.
Definition: rail_gui.cpp:197
static StationPickerSelection _station_gui
Settings of the station picker.
Definition: rail_gui.cpp:71
static SignalType _cur_signal_type
set the signal type (for signal GUI)
Definition: rail_gui.cpp:58
static void ToggleRailButton_Remove(Window *w)
Toggles state of the Remove button of Build rail toolbar.
Definition: rail_gui.cpp:317
DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option)
Create a drop down list for all the rail types of the local company.
Definition: rail_gui.cpp:2011
void CcBuildRailTunnel(Commands, const CommandCost &result, TileIndex tile)
Command callback for building a tunnel.
Definition: rail_gui.cpp:303
static void BuildRailClick_Remove(Window *w)
The "remove"-button click proc of the build-rail toolbar.
Definition: rail_gui.cpp:352
static bool IsStationAvailable(const StationSpec *statspec)
Check whether a station type can be build.
Definition: rail_gui.cpp:84
static Window * ShowStationBuilder(Window *parent)
Open station build window.
Definition: rail_gui.cpp:1439
static bool StationUsesDefaultType(const BaseStation *bst)
Test if a station/waypoint uses the default graphics.
Definition: rail_gui.cpp:960
static WindowDesc _station_builder_desc(WDP_AUTO, "build_station_rail", 0, 0, WC_BUILD_STATION, WC_BUILD_TOOLBAR, WDF_CONSTRUCTION, _nested_station_builder_widgets, &BuildRailStationWindow::hotkeys)
High level window description of the station-build window (default & newGRF)
static const Track _place_depot_extra_track[12]
Additional pieces of track to add at the entrance of a depot.
Definition: rail_gui.cpp:127
static WindowDesc _signal_builder_desc(WDP_AUTO, nullptr, 0, 0, WC_BUILD_SIGNAL, WC_BUILD_TOOLBAR, WDF_CONSTRUCTION, _nested_signal_builder_widgets)
Signal selection window description.
static DiagDirection _build_depot_direction
Currently selected depot direction.
Definition: rail_gui.cpp:55
void InitializeRailGui()
Initialize rail building GUI settings.
Definition: rail_gui.cpp:1895
static void ShowSignalBuilder(Window *parent)
Open the signal selection window.
Definition: rail_gui.cpp:1696
static bool _remove_button_clicked
Flag whether 'remove' toggle-button is currently enabled.
Definition: rail_gui.cpp:54
void ReinitGuiAfterToggleElrail(bool disable)
Re-initialize rail-build toolbar after toggling support for electric trains.
Definition: rail_gui.cpp:1908
static const DiagDirection _place_depot_extra_dir[12]
Direction to check for existing track pieces.
Definition: rail_gui.cpp:134
void InitializeRailGUI()
Resets the rail GUI - sets default railtype to build and resets the signal GUI.
Definition: rail_gui.cpp:1996
static bool _convert_signal_button
convert signal button in the signal GUI pressed
Definition: rail_gui.cpp:56
static void GenericPlaceSignals(TileIndex tile)
Build a new signal or edit/remove a present signal, use CmdBuildSingleSignal() or CmdRemoveSingleSign...
Definition: rail_gui.cpp:233
static WaypointPickerSelection _waypoint_gui
Settings of the waypoint picker.
Definition: rail_gui.cpp:64
Functions/types etc.
@ SIGNAL_GUI_ALL
Show all signals, including block and presignals.
Definition: rail_gui.h:25
@ SIGNAL_GUI_PATH
Show path signals only.
Definition: rail_gui.h:24
@ SIGNAL_CYCLE_ALL
Cycle through all signals visible to the player.
Definition: rail_gui.h:31
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition: rail_map.h:115
static debug_inline RailTileType GetRailTileType(Tile t)
Returns the RailTileType (normal with or without signals, waypoint or depot).
Definition: rail_map.h:36
TrackBits GetTrackBits(Tile tile)
Gets the track bits of the given tile.
Definition: rail_map.h:136
static debug_inline bool IsRailDepotTile(Tile t)
Is this tile rail tile and a rail depot?
Definition: rail_map.h:105
bool HasSignalOnTrack(Tile tile, Track track)
Checks for the presence of signals (either way) on the given track on the given rail tile.
Definition: rail_map.h:413
@ RAIL_TILE_DEPOT
Depot (one entrance)
Definition: rail_map.h:26
@ RAIL_TILE_SIGNALS
Normal rail tile with signals.
Definition: rail_map.h:25
static debug_inline bool IsPlainRailTile(Tile t)
Checks whether the tile is a rail tile or rail tile with signals.
Definition: rail_map.h:60
RailTypes
Allow incrementing of Track variables.
Definition: rail_type.h:44
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:27
@ RAILTYPE_BEGIN
Used for iterations.
Definition: rail_type.h:28
@ RAILTYPE_END
Used for iterations.
Definition: rail_type.h:33
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition: rail_type.h:34
@ RAILTYPE_ELECTRIC
Electric rails.
Definition: rail_type.h:30
@ RAILTYPE_RAIL
Standard non-electric rails.
Definition: rail_type.h:29
Types related to the rail widgets.
@ WID_RAT_BUILD_SIGNALS
Build signals.
Definition: rail_widget.h:26
@ WID_RAT_BUILD_NS
Build rail along the game view Y axis.
Definition: rail_widget.h:17
@ WID_RAT_CONVERT_RAIL
Convert other rail to this type.
Definition: rail_widget.h:30
@ WID_RAT_BUILD_Y
Build rail along the game grid Y axis.
Definition: rail_widget.h:20
@ WID_RAT_BUILD_EW
Build rail along the game view X axis.
Definition: rail_widget.h:19
@ WID_RAT_BUILD_BRIDGE
Build a bridge.
Definition: rail_widget.h:27
@ WID_RAT_REMOVE
Bulldozer to remove rail.
Definition: rail_widget.h:29
@ WID_RAT_CAPTION
Caption of the window.
Definition: rail_widget.h:16
@ WID_RAT_BUILD_WAYPOINT
Build a waypoint.
Definition: rail_widget.h:24
@ WID_RAT_BUILD_DEPOT
Build a depot.
Definition: rail_widget.h:23
@ WID_RAT_DEMOLISH
Destroy something with dynamite!
Definition: rail_widget.h:22
@ WID_RAT_BUILD_STATION
Build a station.
Definition: rail_widget.h:25
@ WID_RAT_BUILD_X
Build rail along the game grid X axis.
Definition: rail_widget.h:18
@ WID_RAT_BUILD_TUNNEL
Build a tunnel.
Definition: rail_widget.h:28
@ WID_RAT_AUTORAIL
Autorail tool.
Definition: rail_widget.h:21
@ WID_BRAS_HIGHLIGHT_OFF
Button for turning coverage highlighting off.
Definition: rail_widget.h:59
@ WID_BRAS_PLATFORM_NUM_4
Button to select stations with 4 platforms.
Definition: rail_widget.h:44
@ WID_BRAS_PLATFORM_NUM_7
Button to select stations with 7 platforms.
Definition: rail_widget.h:47
@ WID_BRAS_PLATFORM_DIR_X
Button to select '/' view.
Definition: rail_widget.h:38
@ WID_BRAS_PLATFORM_LEN_BEGIN
Helper for determining the chosen platform length.
Definition: rail_widget.h:64
@ WID_BRAS_PLATFORM_LEN_3
Button to select 3 tiles length station platforms.
Definition: rail_widget.h:51
@ WID_BRAS_PLATFORM_DIR_Y
Button to select '\' view.
Definition: rail_widget.h:39
@ WID_BRAS_PLATFORM_LEN_6
Button to select 6 tiles length station platforms.
Definition: rail_widget.h:54
@ WID_BRAS_PLATFORM_NUM_1
Button to select stations with a single platform.
Definition: rail_widget.h:41
@ WID_BRAS_PLATFORM_NUM_BEGIN
Helper for determining the chosen platform width.
Definition: rail_widget.h:63
@ WID_BRAS_PLATFORM_NUM_3
Button to select stations with 3 platforms.
Definition: rail_widget.h:43
@ WID_BRAS_PLATFORM_LEN_5
Button to select 5 tiles length station platforms.
Definition: rail_widget.h:53
@ WID_BRAS_PLATFORM_NUM_5
Button to select stations with 5 platforms.
Definition: rail_widget.h:45
@ WID_BRAS_COVERAGE_TEXTS
Empty space for the coverage texts.
Definition: rail_widget.h:61
@ WID_BRAS_PLATFORM_LEN_1
Button to select single tile length station platforms.
Definition: rail_widget.h:49
@ WID_BRAS_HIGHLIGHT_ON
Button for turning coverage highlighting on.
Definition: rail_widget.h:60
@ WID_BRAS_PLATFORM_DRAG_N_DROP
Button to enable drag and drop type station placement.
Definition: rail_widget.h:57
@ WID_BRAS_PLATFORM_LEN_7
Button to select 7 tiles length station platforms.
Definition: rail_widget.h:55
@ WID_BRAS_PLATFORM_NUM_6
Button to select stations with 6 platforms.
Definition: rail_widget.h:46
@ WID_BRAS_PLATFORM_NUM_2
Button to select stations with 2 platforms.
Definition: rail_widget.h:42
@ WID_BRAS_PLATFORM_LEN_4
Button to select 4 tiles length station platforms.
Definition: rail_widget.h:52
@ WID_BRAS_PLATFORM_LEN_2
Button to select 2 tiles length station platforms.
Definition: rail_widget.h:50
@ WID_BRAD_DEPOT_SE
Build a depot with the entrance in the south east.
Definition: rail_widget.h:95
@ WID_BRAD_DEPOT_NE
Build a depot with the entrance in the north east.
Definition: rail_widget.h:94
@ WID_BRAD_DEPOT_SW
Build a depot with the entrance in the south west.
Definition: rail_widget.h:96
@ WID_BRAD_DEPOT_NW
Build a depot with the entrance in the north west.
Definition: rail_widget.h:97
@ WID_BS_DRAG_SIGNALS_DENSITY_DECREASE
Decrease the signal density.
Definition: rail_widget.h:85
@ WID_BS_TOGGLE_SIZE
Toggle showing advanced signal types.
Definition: rail_widget.h:70
@ WID_BS_ELECTRIC_PBS
Build an electric path signal.
Definition: rail_widget.h:81
@ WID_BS_SEMAPHORE_NORM
Build a semaphore normal block signal.
Definition: rail_widget.h:71
@ WID_BS_ELECTRIC_NORM
Build an electric normal block signal.
Definition: rail_widget.h:77
@ WID_BS_ELECTRIC_EXIT
Build an electric exit block signal.
Definition: rail_widget.h:79
@ WID_BS_ELECTRIC_ENTRY
Build an electric entry block signal.
Definition: rail_widget.h:78
@ WID_BS_SEMAPHORE_ENTRY
Build a semaphore entry block signal.
Definition: rail_widget.h:72
@ WID_BS_BLOCK_SEL
Container for the block signal group, which can be hidden.
Definition: rail_widget.h:87
@ WID_BS_CAPTION
Caption for the Signal Selection window.
Definition: rail_widget.h:69
@ WID_BS_SEMAPHORE_COMBO
Build a semaphore combo block signal.
Definition: rail_widget.h:74
@ WID_BS_BLOCK_SPACER_SEL
Container for the spacer between block and path signal groups, which can be hidden.
Definition: rail_widget.h:88
@ WID_BS_SEMAPHORE_PBS
Build a semaphore path signal.
Definition: rail_widget.h:75
@ WID_BS_DRAG_SIGNALS_DENSITY_LABEL
The current signal density.
Definition: rail_widget.h:84
@ WID_BS_SEMAPHORE_EXIT
Build a semaphore exit block signal.
Definition: rail_widget.h:73
@ WID_BS_SEMAPHORE_PBS_OWAY
Build a semaphore one way path signal.
Definition: rail_widget.h:76
@ WID_BS_DRAG_SIGNALS_DENSITY_INCREASE
Increase the signal density.
Definition: rail_widget.h:86
@ WID_BS_CONVERT
Convert the signal.
Definition: rail_widget.h:83
@ WID_BS_ELECTRIC_COMBO
Build an electric combo block signal.
Definition: rail_widget.h:80
@ WID_BS_ELECTRIC_PBS_OWAY
Build an electric one way path signal.
Definition: rail_widget.h:82
bool IsLevelCrossingTile(Tile t)
Return whether a tile is a level crossing tile.
Definition: road_map.h:95
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition: road_type.h:30
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
SignalType
Type of signal, i.e.
Definition: signal_type.h:23
@ SIGTYPE_PBS
normal pbs signal
Definition: signal_type.h:28
@ SIGTYPE_BLOCK
block signal
Definition: signal_type.h:24
SignalVariant
Variant of the signal, i.e.
Definition: signal_type.h:16
@ SIG_SEMAPHORE
Old-fashioned semaphore signal.
Definition: signal_type.h:18
@ SIG_ELECTRIC
Light signal.
Definition: signal_type.h:17
Functions related to sound.
@ SND_15_BEEP
19 == 0x13 GUI button click
Definition: sound_type.h:58
@ SND_20_CONSTRUCTION_RAIL
30 == 0x1E Construction: rail infrastructure
Definition: sound_type.h:69
Functions to cache sprites in memory.
static const CursorID ANIMCURSOR_BUILDSIGNALS
1292 - 1293 - build signal
Definition: sprites.h:1512
static const CursorID ANIMCURSOR_DEMOLISH
704 - 707 - demolish dynamite
Definition: sprites.h:1508
Base classes/functions for stations.
Command definitions related to stations.
void ShowSelectStationIfNeeded(TileArea ta, StationPickerCmdProc proc)
Show the station selection window when needed.
void ShowSelectRailWaypointIfNeeded(TileArea ta, StationPickerCmdProc proc)
Show the rail waypoint selection window when needed.
void CheckRedrawStationCoverage(const Window *w)
Check whether we need to redraw the station coverage text.
int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageType sct, int rad, bool supplies)
Calculates and draws the accepted or supplied cargo around the selected tile(s)
Definition: station_gui.cpp:77
Contains enums and function declarations connected with stations GUI.
@ SCT_ALL
Draw all cargoes.
Definition: station_gui.h:23
Maps accessors for stations.
bool HasStationTileRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
Definition: station_map.h:146
uint GetCustomStationSpecIndex(Tile t)
Get the custom station spec for this tile.
Definition: station_map.h:642
bool HasStationRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
Definition: station_map.h:135
static constexpr uint CA_TRAIN
Catchment for train stations with "modified catchment" enabled.
Definition: station_type.h:80
static constexpr uint CA_UNMODIFIED
Catchment for all stations with "modified catchment" disabled.
Definition: station_type.h:83
Definition of base types and functions in a cross-platform compatible way.
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
Functions related to OTTD's strings.
int64_t PackVelocity(uint speed, VehicleType type)
Pack velocity and vehicle type for use with SCC_VELOCITY string parameter.
Definition: strings_func.h:75
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Base class for all station-ish types.
TileArea train_station
Tile area the train 'station' part covers.
virtual bool TileBelongsToRailStation(TileIndex tile) const =0
Check whether a specific tile belongs to this station.
void OnPaint() override
The window must be repainted.
Definition: rail_gui.cpp:1118
void OnRealtimeTick([[maybe_unused]] uint delta_ms) override
Called periodically.
Definition: rail_gui.cpp:1353
static EventState BuildRailStationGlobalHotkeys(int hotkey)
Handler for global hotkeys of the BuildRailStationWindow.
Definition: rail_gui.cpp:1363
uint coverage_height
Height of the coverage texts.
Definition: rail_gui.cpp:1044
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: rail_gui.cpp:1108
void CheckSelectedSize(const StationSpec *statspec)
Verify whether the currently selected station size is allowed after selecting a new station class/typ...
Definition: rail_gui.cpp:1051
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition: rail_gui.cpp:1087
Rail toolbar management class.
Definition: rail_gui.cpp:435
RailType railtype
Rail type to build.
Definition: rail_gui.cpp:436
void ModifyRailType(RailType railtype)
Switch to another rail type.
Definition: rail_gui.cpp:517
int last_user_action
Last started user action.
Definition: rail_gui.cpp:437
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition: rail_gui.cpp:499
EventState OnCTRLStateChange() override
The state of the control key has changed.
Definition: rail_gui.cpp:816
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
Definition: rail_gui.cpp:793
static EventState RailToolbarGlobalHotkeys(int hotkey)
Handler for global hotkeys of the BuildRailToolbarWindow.
Definition: rail_gui.cpp:833
void OnRealtimeTick([[maybe_unused]] uint delta_ms) override
Called periodically.
Definition: rail_gui.cpp:823
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: rail_gui.cpp:467
static const std::initializer_list< WidgetID > can_build_widgets
List of widgets to be disabled if infrastructure limit prevents building.
Definition: rail_gui.cpp:461
EventState OnHotkey(int hotkey) override
A hotkey has been pressed.
Definition: rail_gui.cpp:658
Dimension sig_sprite_size
Maximum size of signal GUI sprites.
Definition: rail_gui.cpp:1446
void DrawSignalSprite(const Rect &r, SpriteID image) const
Draw dynamic a signal-sprite in a button in the signal GUI.
Definition: rail_gui.cpp:1453
void SetSignalUIMode()
Show or hide buttons for non-path signals in the signal GUI.
Definition: rail_gui.cpp:1466
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: rail_gui.cpp:1607
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition: rail_gui.cpp:1489
int sig_sprite_bottom_offset
Maximum extent of signal GUI sprite from reference point towards bottom.
Definition: rail_gui.cpp:1447
SoundSettings sound
sound effect settings
GUISettings gui
settings related to the GUI
RailTypes avail_railtypes
Rail types available to this company.
Definition: company_base.h:137
Dimensions (a width and height) of a rectangle in 2D.
Data about how and where to blit pixels.
Definition: gfx_type.h:157
const struct GRFFile * grffile
grf file that introduced this entity
bool persistent_buildingtools
keep the building tools active after usage
SignalCycleSettings cycle_signal_types
Which signal types to cycle with the build signal tool.
uint8_t station_platlength
the platform length, in tiles, for rail stations
bool auto_remove_signals
automatically remove signals when in the way during rail construction
bool station_dragdrop
whether drag and drop is enabled for stations
bool station_show_coverage
whether to highlight coverage area
uint8_t default_rail_type
the default rail type for the rail GUI
uint8_t drag_signals_density
many signals density
uint8_t station_numtracks
the number of platforms to default on for rail stations
TimerGameCalendar::Year semaphore_build_before
build semaphore signals automatically before this year
SignalGUISettings signal_gui_mode
select which signal types are shown in the signal GUI
bool drag_signals_fixed_distance
keep fixed distance between signals when dragging
SignalType default_signal_type
The default signal type, which is set automatically by the last signal used. Not available in Setting...
bool link_terraform_toolbar
display terraform toolbar when displaying rail, road, water and airport toolbars
StationSettings station
settings related to station management
List of hotkeys for a window.
Definition: hotkeys.h:37
All data for a single hotkey.
Definition: hotkeys.h:21
static debug_inline uint Size()
Get the size of the map.
Definition: map_func.h:288
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:1075
Represents the covered area of e.g.
Definition: tilearea_type.h:18
Coordinates of a point in 2D.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
int Width() const
Get width of Rect.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
int Height() const
Get height of Rect.
bool click_beep
Beep on a random selection of buttons.
bool confirm
Play sound effect on successful constructions or other actions.
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
StationClassID sel_class
Selected station class.
Definition: rail_gui.cpp:67
uint16_t sel_type
Selected station type within the class.
Definition: rail_gui.cpp:68
Axis axis
Selected orientation of the station.
Definition: rail_gui.cpp:69
uint8_t station_spread
amount a station may spread
bool modified_catchment
different-size catchment areas
Station specification.
uint8_t callback_mask
Bitmask of station callbacks that have to be called.
uint8_t disallowed_lengths
Bitmask of platform lengths available for the station.
uint8_t disallowed_platforms
Bitmask of number of platforms available for the station.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
Station data structure.
Definition: station_base.h:439
Point selstart
The location where the dragging started.
HighLightStyle drawstyle
Lower bits 0-3 are reserved for detailed highlight information.
Point pos
Location, in tile "units", of the northern tile of the selected area.
Point selend
The location where the drag currently ends.
StationClassID sel_class
Selected station class.
Definition: rail_gui.cpp:61
uint16_t sel_type
Selected station type within the class.
Definition: rail_gui.cpp:62
Representation of a waypoint.
Definition: waypoint_base.h:23
High level window description.
Definition: window_gui.h:159
Data structure for an opened window.
Definition: window_gui.h:273
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition: window.cpp:952
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition: window.cpp:1047
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1733
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:733
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition: window.cpp:3154
Window * parent
Parent window.
Definition: window_gui.h:328
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition: window_gui.h:475
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition: window.cpp:551
ResizeInfo resize
Resize information.
Definition: window_gui.h:314
void DisableWidget(WidgetID widget_index)
Sets a widget to disabled.
Definition: window_gui.h:397
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1723
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition: window_gui.h:497
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
Definition: window_gui.h:416
virtual void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, [[maybe_unused]] ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, [[maybe_unused]] TileIndex start_tile, [[maybe_unused]] TileIndex end_tile)
The user has dragged over the map when the tile highlight mode has been set.
Definition: window_gui.h:836
void RaiseButtons(bool autoraise=false)
Raise the buttons of the window.
Definition: window.cpp:525
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:447
bool IsShaded() const
Is window shaded currently?
Definition: window_gui.h:563
int top
y position of top edge of the window
Definition: window_gui.h:310
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition: window_gui.h:466
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition: window.cpp:1746
virtual EventState OnHotkey(int hotkey)
A hotkey has been pressed.
Definition: window.cpp:565
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:387
virtual void OnInit()
Notification that the nested widget tree gets initialized.
Definition: window_gui.h:582
void ToggleWidgetLoweredState(WidgetID widget_index)
Invert the lowered/raised status of a widget.
Definition: window_gui.h:456
bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_tile, TileIndex end_tile)
A central place to handle all X_AND_Y dragged GUI functions.
void PlaceProc_DemolishArea(TileIndex tile)
Start a drag for demolishing an area.
Window * ShowTerraformToolbar(Window *link)
Show the toolbar for terraforming in the game.
GUI stuff related to terraforming.
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition: tile_map.h:161
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:95
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:57
@ MP_RAILWAY
A railway.
Definition: tile_type.h:49
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
Definition: viewport.cpp:3498
void VpSetPresizeRange(TileIndex from, TileIndex to)
Highlights all tiles between a set of two tiles.
Definition: viewport.cpp:2777
void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method)
Selects tiles while dragging.
Definition: viewport.cpp:3216
void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, ViewportDragDropSelectionProcess process)
highlighting tiles while only going over them with the mouse
Definition: viewport.cpp:2722
@ HT_LINE
used for autorail highlighting (longer stretches), lower bits: direction
@ HT_DIR_HL
horizontal lower
@ HT_DIR_X
X direction.
@ HT_DIAGONAL
Also allow 'diagonal rectangles'. Only usable in combination with HT_RECT or HT_POINT.
@ HT_RECT
rectangle (stations, depots, ...)
@ HT_DIR_MASK
masks the drag-direction
@ HT_RAIL
autorail (one piece), lower bits: direction
@ HT_DRAG_MASK
Mask for the tile drag-type modes.
@ HT_DIR_VL
vertical left
@ HT_SPECIAL
special mode used for highlighting while dragging (and for tunnels/docks)
@ HT_DIR_Y
Y direction.
Definition of Interval and OneShot timers.
Definition of the game-calendar-timer.
bool IsValidTrack(Track track)
Checks if a Track is valid.
Definition: track_func.h:28
Track FindFirstTrack(TrackBits tracks)
Returns first Track from TrackBits or INVALID_TRACK.
Definition: track_func.h:177
TrackBits DiagdirReachesTracks(DiagDirection diagdir)
Returns all tracks that can be reached when entering a tile from a given (diagonal) direction.
Definition: track_func.h:573
TrackBits TrackStatusToTrackBits(TrackStatus ts)
Returns the present-track-information of a TrackStatus.
Definition: track_func.h:363
TrackBits
Allow incrementing of Track variables.
Definition: track_type.h:35
@ TRACK_BIT_UPPER
Upper track.
Definition: track_type.h:39
@ TRACK_BIT_LEFT
Left track.
Definition: track_type.h:41
@ TRACK_BIT_HORZ
Upper and lower track.
Definition: track_type.h:44
@ TRACK_BIT_LOWER
Lower track.
Definition: track_type.h:40
@ TRACK_BIT_RIGHT
Right track.
Definition: track_type.h:42
@ TRACK_BIT_VERT
Left and right track.
Definition: track_type.h:45
Track
These are used to specify a single track.
Definition: track_type.h:19
@ TRACK_Y
Track along the y-axis (north-west to south-east)
Definition: track_type.h:22
@ TRACK_LOWER
Track in the lower corner of the tile (south)
Definition: track_type.h:24
@ TRACK_LEFT
Track in the left corner of the tile (west)
Definition: track_type.h:25
@ TRACK_RIGHT
Track in the right corner of the tile (east)
Definition: track_type.h:26
@ TRACK_X
Track along the x-axis (north-east to south-west)
Definition: track_type.h:21
@ TRACK_UPPER
Track in the upper corner of the tile (north)
Definition: track_type.h:23
@ TRANSPORT_RAIL
Transport by train.
Header file for things common for tunnels and bridges.
TileIndex _build_tunnel_endtile
The end of a tunnel; as hidden return from the tunnel build command for GUI purposes.
Command definitions related to tunnels and bridges.
Functions that have tunnels and bridges in common.
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
TileIndex GetOtherTunnelBridgeEnd(Tile t)
Determines type of the wormhole and returns its other end.
bool CanBuildVehicleInfrastructure(VehicleType type, uint8_t subtype)
Check whether we can build infrastructure for the given vehicle type.
Definition: vehicle.cpp:1922
Functions related to vehicles.
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
void SetTileSelectSize(int w, int h)
Highlight w by h tiles at the cursor.
Definition: viewport.cpp:2542
void SetViewportCatchmentWaypoint(const Waypoint *wp, bool sel)
Select or deselect waypoint for coverage area highlight.
Definition: viewport.cpp:3638
void SetRedErrorSquare(TileIndex tile)
Set a tile to display a red error square.
Definition: viewport.cpp:2524
void SetViewportCatchmentStation(const Station *st, bool sel)
Select or deselect station for coverage area highlight.
Definition: viewport.cpp:3618
Functions related to (drawing on) viewports.
ViewportDragDropSelectionProcess
Drag and drop selection process, or, what to do with an area of land when you've selected it.
@ DDSP_CONVERT_RAIL
Rail conversion.
@ DDSP_DEMOLISH_AREA
Clear area.
@ DDSP_BUILD_SIGNALS
Signal placement.
@ DDSP_REMOVE_STATION
Station removal.
@ DDSP_BUILD_STATION
Station placement.
@ DDSP_BUILD_BRIDGE
Bridge placement.
@ DDSP_PLACE_RAIL
Rail placement.
ViewportPlaceMethod
Viewport place method (type of highlighted area and placed objects)
Definition: viewport_type.h:92
@ VPM_FIX_Y
drag only in Y axis
Definition: viewport_type.h:95
@ VPM_Y_LIMITED
Drag only in Y axis with limited size.
@ VPM_X_AND_Y_LIMITED
area of land of limited size
Definition: viewport_type.h:97
@ VPM_FIX_VERTICAL
drag only in vertical direction
Definition: viewport_type.h:99
@ VPM_X_LIMITED
Drag only in X axis with limited size.
@ VPM_X_AND_Y
area of land in X and Y directions
Definition: viewport_type.h:96
@ VPM_FIX_HORIZONTAL
drag only in horizontal direction
Definition: viewport_type.h:98
@ VPM_FIX_X
drag only in X axis
Definition: viewport_type.h:94
@ VPM_SIGNALDIRS
similar to VMP_RAILDIRS, but with different cursor
@ VPM_X_OR_Y
drag in X or Y direction
Definition: viewport_type.h:93
@ VPM_RAILDIRS
all rail directions
void DrawWaypointSprite(int x, int y, StationClassID station_class, uint16_t station_type, RailType railtype)
Draw a waypoint.
Definition: waypoint.cpp:28
Base of waypoints.
@ WPF_ROAD
This is a road waypoint.
Definition: waypoint_base.h:19
Axis GetAxisForNewRailWaypoint(TileIndex tile)
Get the axis for a new rail waypoint.
Command definitions related to waypoints.
Functions related to waypoints.
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
Definition: widget_type.h:483
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:31
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:32
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:524
@ WWT_IMGBTN
(Toggle) Button with image
Definition: widget_type.h:52
@ WWT_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:114
@ WWT_LABEL
Centered label.
Definition: widget_type.h:57
@ NWID_HORIZONTAL
Horizontal container.
Definition: widget_type.h:75
@ WWT_TEXTBTN
(Toggle) Button with text
Definition: widget_type.h:55
@ WWT_PANEL
Simple depressed panel.
Definition: widget_type.h:50
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:66
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:64
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:61
@ NWID_VERTICAL
Vertical container.
Definition: widget_type.h:77
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition: widget_type.h:69
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition: widget_type.h:48
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition: widget_type.h:65
@ NWID_HORIZONTAL_LTR
Horizontal container that doesn't change the order of the widgets for RTL languages.
Definition: widget_type.h:76
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:80
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition: window.cpp:1140
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1098
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition: window.cpp:1152
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3096
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ WDF_CONSTRUCTION
This window is used for construction; close it whenever changing company.
Definition: window_gui.h:203
@ WDP_AUTO
Find a place automatically.
Definition: window_gui.h:147
@ WDP_ALIGN_TOOLBAR
Align toward the toolbar.
Definition: window_gui.h:149
int WidgetID
Widget ID.
Definition: window_type.h:18
@ WN_GAME_OPTIONS_GAME_SETTINGS
Game settings.
Definition: window_type.h:27
EventState
State of handling an event.
Definition: window_type.h:743
@ ES_HANDLED
The passed event is handled.
Definition: window_type.h:744
@ ES_NOT_HANDLED
The passed event is not handled.
Definition: window_type.h:745
@ WC_BUILD_STATION
Build station; Window numbers:
Definition: window_type.h:403
@ WC_BUILD_TOOLBAR
Build toolbar; Window numbers:
Definition: window_type.h:73
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:45
@ WC_SCEN_LAND_GEN
Landscape generation (in Scenario Editor); Window numbers:
Definition: window_type.h:455
@ WC_SELECT_STATION
Select station (when joining stations); Window numbers:
Definition: window_type.h:242
@ WC_BUILD_SIGNAL
Build signal toolbar; Window numbers:
Definition: window_type.h:98
@ WC_BUILD_DEPOT
Build depot; Window numbers:
Definition: window_type.h:423
@ WC_GAME_OPTIONS
Game options window; Window numbers:
Definition: window_type.h:624
@ WC_BUILD_WAYPOINT
Build waypoint; Window numbers:
Definition: window_type.h:429
@ WC_BUILD_BRIDGE
Build bridge; Window numbers:
Definition: window_type.h:395
Functions related to zooming.
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition: zoom_func.h:107
int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:117