|
@@ -37,281 +37,282 @@
|
|
|
#include "rail_map.h"
|
|
|
#include "road_map.h"
|
|
|
#include "station_map.h"
|
|
|
#include "tunnel_map.h"
|
|
|
#include "tunnelbridge_map.h"
|
|
|
|
|
|
#include "table/sprites.h"
|
|
|
#include "table/strings.h"
|
|
|
|
|
|
static RailType _cur_railtype; ///< Rail type of the current build-rail toolbar.
|
|
|
static bool _remove_button_clicked; ///< Flag whether 'remove' toggle-button is currently enabled
|
|
|
static DiagDirection _build_depot_direction; ///< Currently selected depot direction
|
|
|
static byte _waypoint_count = 1; ///< Number of waypoint types
|
|
|
static byte _cur_waypoint_type; ///< Currently selected waypoint type
|
|
|
static bool _convert_signal_button; ///< convert signal button in the signal GUI pressed
|
|
|
static SignalVariant _cur_signal_variant; ///< set the signal variant (for signal GUI)
|
|
|
static SignalType _cur_signal_type; ///< set the signal type (for signal GUI)
|
|
|
|
|
|
/* Map _patches.default_signal_type to the corresponding signal type */
|
|
|
static const SignalType _default_signal_type[] = {SIGTYPE_NORMAL, SIGTYPE_PBS, SIGTYPE_PBS_ONEWAY};
|
|
|
|
|
|
struct RailStationGUISettings {
|
|
|
Axis orientation; ///< Currently selected rail station orientation
|
|
|
byte numtracks; ///< Currently selected number of tracks in station (if not \c dragdrop )
|
|
|
byte platlength; ///< Currently selected platform length of station (if not \c dragdrop )
|
|
|
bool dragdrop; ///< Use drag & drop to place a station
|
|
|
|
|
|
bool newstations; ///< Are custom station definitions available?
|
|
|
StationClassIDByte station_class; ///< Currently selected custom station class (if newstations is \c true )
|
|
|
byte station_type; ///< Station type within the currently selected custom station class (if newstations is \c true )
|
|
|
byte station_count; ///< Number of custom stations (if newstations is \c true )
|
|
|
};
|
|
|
static RailStationGUISettings _railstation; ///< Settings of the station builder GUI
|
|
|
|
|
|
|
|
|
static void HandleStationPlacement(TileIndex start, TileIndex end);
|
|
|
static void ShowBuildTrainDepotPicker(Window *parent);
|
|
|
static void ShowBuildWaypointPicker(Window *parent);
|
|
|
static void ShowStationBuilder(Window *parent);
|
|
|
static void ShowSignalBuilder(Window *parent);
|
|
|
|
|
|
void CcPlaySound1E(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
if (success) SndPlayTileFx(SND_20_SPLAT_2, tile);
|
|
|
}
|
|
|
|
|
|
static void GenericPlaceRail(TileIndex tile, int cmd)
|
|
|
{
|
|
|
DoCommandP(tile, _cur_railtype, cmd, CcPlaySound1E,
|
|
|
DoCommandP(tile, _cur_railtype, cmd,
|
|
|
_remove_button_clicked ?
|
|
|
CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_1012_CAN_T_REMOVE_RAILROAD_TRACK) | CMD_NO_WATER :
|
|
|
CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_1011_CAN_T_BUILD_RAILROAD_TRACK) | CMD_NO_WATER
|
|
|
CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_1011_CAN_T_BUILD_RAILROAD_TRACK) | CMD_NO_WATER,
|
|
|
CcPlaySound1E
|
|
|
);
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_N(TileIndex tile)
|
|
|
{
|
|
|
int cmd = _tile_fract_coords.x > _tile_fract_coords.y ? 4 : 5;
|
|
|
GenericPlaceRail(tile, cmd);
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_NE(TileIndex tile)
|
|
|
{
|
|
|
VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_RAIL_NE);
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_E(TileIndex tile)
|
|
|
{
|
|
|
int cmd = _tile_fract_coords.x + _tile_fract_coords.y <= 15 ? 2 : 3;
|
|
|
GenericPlaceRail(tile, cmd);
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_NW(TileIndex tile)
|
|
|
{
|
|
|
VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_RAIL_NW);
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_AutoRail(TileIndex tile)
|
|
|
{
|
|
|
VpStartPlaceSizing(tile, VPM_RAILDIRS, DDSP_PLACE_AUTORAIL);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Try to add an additional rail-track at the entrance of a depot
|
|
|
* @param tile Tile to use for adding the rail-track
|
|
|
* @param extra Track to add
|
|
|
* @see CcRailDepot()
|
|
|
*/
|
|
|
static void PlaceExtraDepotRail(TileIndex tile, uint16 extra)
|
|
|
{
|
|
|
if (GetRailTileType(tile) != RAIL_TILE_NORMAL) return;
|
|
|
if ((GetTrackBits(tile) & GB(extra, 8, 8)) == 0) return;
|
|
|
|
|
|
DoCommandP(tile, _cur_railtype, extra & 0xFF, NULL, CMD_BUILD_SINGLE_RAIL | CMD_NO_WATER);
|
|
|
DoCommandP(tile, _cur_railtype, extra & 0xFF, CMD_BUILD_SINGLE_RAIL | CMD_NO_WATER);
|
|
|
}
|
|
|
|
|
|
/** Additional pieces of track to add at the entrance of a depot. */
|
|
|
static const uint16 _place_depot_extra[12] = {
|
|
|
0x0604, 0x2102, 0x1202, 0x0505, // First additional track for directions 0..3
|
|
|
0x2400, 0x2801, 0x1800, 0x1401, // Second additional track
|
|
|
0x2203, 0x0904, 0x0A05, 0x1103, // Third additional track
|
|
|
};
|
|
|
|
|
|
|
|
|
void CcRailDepot(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
if (success) {
|
|
|
DiagDirection dir = (DiagDirection)p2;
|
|
|
|
|
|
SndPlayTileFx(SND_20_SPLAT_2, tile);
|
|
|
ResetObjectToPlace();
|
|
|
|
|
|
tile += TileOffsByDiagDir(dir);
|
|
|
|
|
|
if (IsTileType(tile, MP_RAILWAY)) {
|
|
|
PlaceExtraDepotRail(tile, _place_depot_extra[dir]);
|
|
|
PlaceExtraDepotRail(tile, _place_depot_extra[dir + 4]);
|
|
|
PlaceExtraDepotRail(tile, _place_depot_extra[dir + 8]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_Depot(TileIndex tile)
|
|
|
{
|
|
|
DoCommandP(tile, _cur_railtype, _build_depot_direction, CcRailDepot,
|
|
|
CMD_BUILD_TRAIN_DEPOT | CMD_NO_WATER | CMD_MSG(STR_100E_CAN_T_BUILD_TRAIN_DEPOT));
|
|
|
DoCommandP(tile, _cur_railtype, _build_depot_direction,
|
|
|
CMD_BUILD_TRAIN_DEPOT | CMD_NO_WATER | CMD_MSG(STR_100E_CAN_T_BUILD_TRAIN_DEPOT),
|
|
|
CcRailDepot);
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_Waypoint(TileIndex tile)
|
|
|
{
|
|
|
if (_remove_button_clicked) {
|
|
|
DoCommandP(tile, 0, 0, CcPlaySound1E, CMD_REMOVE_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_REMOVE_TRAIN_WAYPOINT));
|
|
|
DoCommandP(tile, 0, 0, CMD_REMOVE_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_REMOVE_TRAIN_WAYPOINT), CcPlaySound1E);
|
|
|
} else {
|
|
|
DoCommandP(tile, _cur_waypoint_type, 0, CcPlaySound1E, CMD_BUILD_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_BUILD_TRAIN_WAYPOINT));
|
|
|
DoCommandP(tile, _cur_waypoint_type, 0, CMD_BUILD_TRAIN_WAYPOINT | CMD_MSG(STR_CANT_BUILD_TRAIN_WAYPOINT), CcPlaySound1E);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void CcStation(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
if (success) {
|
|
|
SndPlayTileFx(SND_20_SPLAT_2, tile);
|
|
|
/* Only close the station builder window if the default station is chosen. */
|
|
|
if (_railstation.station_class == STAT_CLASS_DFLT && _railstation.station_type == 0) ResetObjectToPlace();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_Station(TileIndex tile)
|
|
|
{
|
|
|
if (_remove_button_clicked) {
|
|
|
VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_REMOVE_STATION);
|
|
|
VpSetPlaceSizingLimit(-1);
|
|
|
} else if (_railstation.dragdrop) {
|
|
|
VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_STATION);
|
|
|
VpSetPlaceSizingLimit(_settings_game.station.station_spread);
|
|
|
} else {
|
|
|
DoCommandP(tile,
|
|
|
_railstation.orientation | (_railstation.numtracks << 8) | (_railstation.platlength << 16) | (_ctrl_pressed << 24),
|
|
|
_cur_railtype | (_railstation.station_class << 8) | (_railstation.station_type << 16), CcStation,
|
|
|
CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION));
|
|
|
_cur_railtype | (_railstation.station_class << 8) | (_railstation.station_type << 16),
|
|
|
CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION), CcStation);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Build a new signal or edit/remove a present signal, use CmdBuildSingleSignal() or CmdRemoveSingleSignal() in rail_cmd.cpp
|
|
|
*
|
|
|
* @param tile The tile where the signal will build or edit
|
|
|
*/
|
|
|
static void GenericPlaceSignals(TileIndex tile)
|
|
|
{
|
|
|
TrackBits trackbits = TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0));
|
|
|
|
|
|
if (trackbits & TRACK_BIT_VERT) { // N-S direction
|
|
|
trackbits = (_tile_fract_coords.x <= _tile_fract_coords.y) ? TRACK_BIT_RIGHT : TRACK_BIT_LEFT;
|
|
|
}
|
|
|
|
|
|
if (trackbits & TRACK_BIT_HORZ) { // E-W direction
|
|
|
trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? TRACK_BIT_UPPER : TRACK_BIT_LOWER;
|
|
|
}
|
|
|
|
|
|
Track track = FindFirstTrack(trackbits);
|
|
|
|
|
|
if (_remove_button_clicked) {
|
|
|
DoCommandP(tile, track, 0, CcPlaySound1E,
|
|
|
CMD_REMOVE_SIGNALS | CMD_MSG(STR_1013_CAN_T_REMOVE_SIGNALS_FROM));
|
|
|
DoCommandP(tile, track, 0, CMD_REMOVE_SIGNALS | CMD_MSG(STR_1013_CAN_T_REMOVE_SIGNALS_FROM), CcPlaySound1E);
|
|
|
} else {
|
|
|
const Window *w = FindWindowById(WC_BUILD_SIGNAL, 0);
|
|
|
|
|
|
/* Map _patches.cycle_signal_types to the lower and upper allowed signal type. */
|
|
|
static const uint cycle_bounds[] = {SIGTYPE_NORMAL | (SIGTYPE_LAST_NOPBS << 3), SIGTYPE_PBS | (SIGTYPE_LAST << 3), SIGTYPE_NORMAL | (SIGTYPE_LAST << 3)};
|
|
|
|
|
|
/* various bitstuffed elements for CmdBuildSingleSignal() */
|
|
|
uint32 p1 = track;
|
|
|
|
|
|
if (w != NULL) {
|
|
|
/* signal GUI is used */
|
|
|
SB(p1, 3, 1, _ctrl_pressed);
|
|
|
SB(p1, 4, 1, _cur_signal_variant);
|
|
|
SB(p1, 5, 3, _cur_signal_type);
|
|
|
SB(p1, 8, 1, _convert_signal_button);
|
|
|
SB(p1, 9, 6, cycle_bounds[_settings_client.gui.cycle_signal_types]);
|
|
|
} else {
|
|
|
SB(p1, 3, 1, _ctrl_pressed);
|
|
|
SB(p1, 4, 1, (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
|
|
|
SB(p1, 5, 3, _default_signal_type[_settings_client.gui.default_signal_type]);
|
|
|
SB(p1, 8, 1, 0);
|
|
|
SB(p1, 9, 6, cycle_bounds[_settings_client.gui.cycle_signal_types]);
|
|
|
}
|
|
|
|
|
|
DoCommandP(tile, p1, 0, CcPlaySound1E, CMD_BUILD_SIGNALS |
|
|
|
CMD_MSG((w != NULL && _convert_signal_button) ? STR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE : STR_1010_CAN_T_BUILD_SIGNALS_HERE));
|
|
|
DoCommandP(tile, p1, 0, CMD_BUILD_SIGNALS |
|
|
|
CMD_MSG((w != NULL && _convert_signal_button) ? STR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE : STR_1010_CAN_T_BUILD_SIGNALS_HERE),
|
|
|
CcPlaySound1E);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_Bridge(TileIndex tile)
|
|
|
{
|
|
|
VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
|
|
|
}
|
|
|
|
|
|
/** Command callback for building a tunnel */
|
|
|
void CcBuildRailTunnel(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
if (success) {
|
|
|
SndPlayTileFx(SND_20_SPLAT_2, tile);
|
|
|
ResetObjectToPlace();
|
|
|
} else {
|
|
|
SetRedErrorSquare(_build_tunnel_endtile);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_Tunnel(TileIndex tile)
|
|
|
{
|
|
|
DoCommandP(tile, _cur_railtype, 0, CcBuildRailTunnel,
|
|
|
CMD_BUILD_TUNNEL | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE));
|
|
|
DoCommandP(tile, _cur_railtype, 0, CMD_BUILD_TUNNEL | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE), CcBuildRailTunnel);
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_ConvertRail(TileIndex tile)
|
|
|
{
|
|
|
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CONVERT_RAIL);
|
|
|
}
|
|
|
|
|
|
static void PlaceRail_AutoSignals(TileIndex tile)
|
|
|
{
|
|
|
VpStartPlaceSizing(tile, VPM_SIGNALDIRS, DDSP_BUILD_SIGNALS);
|
|
|
}
|
|
|
|
|
|
|
|
|
/** Enum referring to the widgets of the build rail toolbar */
|
|
|
enum RailToolbarWidgets {
|
|
|
RTW_CLOSEBOX = 0,
|
|
|
RTW_CAPTION,
|
|
|
RTW_STICKY,
|
|
|
RTW_SPACER,
|
|
|
RTW_BUILD_NS,
|
|
|
RTW_BUILD_X,
|
|
|
RTW_BUILD_EW,
|
|
|
RTW_BUILD_Y,
|
|
|
RTW_AUTORAIL,
|
|
|
RTW_DEMOLISH,
|
|
|
RTW_BUILD_DEPOT,
|
|
|
RTW_BUILD_WAYPOINT,
|
|
|
RTW_BUILD_STATION,
|
|
|
RTW_BUILD_SIGNALS,
|
|
|
RTW_BUILD_BRIDGE,
|
|
|
RTW_BUILD_TUNNEL,
|
|
|
RTW_REMOVE,
|
|
|
RTW_CONVERT_RAIL,
|
|
|
};
|
|
|
|
|
|
|
|
|
/** Toggles state of the Remove button of Build rail toolbar
|
|
|
* @param w window the button belongs to
|
|
|
*/
|
|
|
static void ToggleRailButton_Remove(Window *w)
|
|
|
{
|
|
|
w->ToggleWidgetLoweredState(RTW_REMOVE);
|
|
|
w->InvalidateWidget(RTW_REMOVE);
|
|
|
_remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE);
|
|
|
SetSelectionRed(_remove_button_clicked);
|
|
|
}
|
|
|
|
|
|
/** Updates the Remove button because of Ctrl state change
|
|
@@ -469,160 +470,159 @@ static void BuildRailClick_Tunnel(Window
|
|
|
/**
|
|
|
* The "remove"-button click proc of the build-rail toolbar.
|
|
|
* @param w Build-rail toolbar window
|
|
|
* @see BuildRailToolbWndProc()
|
|
|
*/
|
|
|
static void BuildRailClick_Remove(Window *w)
|
|
|
{
|
|
|
if (w->IsWidgetDisabled(RTW_REMOVE)) return;
|
|
|
ToggleRailButton_Remove(w);
|
|
|
SndPlayFx(SND_15_BEEP);
|
|
|
|
|
|
/* handle station builder */
|
|
|
if (w->IsWidgetLowered(RTW_BUILD_STATION)) {
|
|
|
if (_remove_button_clicked) {
|
|
|
/* starting drag & drop remove */
|
|
|
if (!_railstation.dragdrop) {
|
|
|
SetTileSelectSize(1, 1);
|
|
|
} else {
|
|
|
VpSetPlaceSizingLimit(-1);
|
|
|
}
|
|
|
} else {
|
|
|
/* starting station build mode */
|
|
|
if (!_railstation.dragdrop) {
|
|
|
int x = _railstation.numtracks;
|
|
|
int y = _railstation.platlength;
|
|
|
if (_railstation.orientation == 0) Swap(x, y);
|
|
|
SetTileSelectSize(x, y);
|
|
|
} else {
|
|
|
VpSetPlaceSizingLimit(_settings_game.station.station_spread);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* The "convert-rail"-button click proc of the build-rail toolbar.
|
|
|
* Switches to 'convert-rail' mode
|
|
|
* @param w Build-rail toolbar window
|
|
|
* @see BuildRailToolbWndProc()
|
|
|
*/
|
|
|
static void BuildRailClick_Convert(Window *w)
|
|
|
{
|
|
|
HandlePlacePushButton(w, RTW_CONVERT_RAIL, GetRailTypeInfo(_cur_railtype)->cursor.convert, VHM_RECT, PlaceRail_ConvertRail);
|
|
|
}
|
|
|
|
|
|
|
|
|
static void DoRailroadTrack(int mode)
|
|
|
{
|
|
|
DoCommandP(TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), _cur_railtype | (mode << 4), NULL,
|
|
|
DoCommandP(TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), _cur_railtype | (mode << 4),
|
|
|
_remove_button_clicked ?
|
|
|
CMD_REMOVE_RAILROAD_TRACK | CMD_NO_WATER | CMD_MSG(STR_1012_CAN_T_REMOVE_RAILROAD_TRACK) :
|
|
|
CMD_BUILD_RAILROAD_TRACK | CMD_NO_WATER | CMD_MSG(STR_1011_CAN_T_BUILD_RAILROAD_TRACK)
|
|
|
);
|
|
|
}
|
|
|
|
|
|
static void HandleAutodirPlacement()
|
|
|
{
|
|
|
TileHighlightData *thd = &_thd;
|
|
|
int trackstat = thd->drawstyle & 0xF; // 0..5
|
|
|
|
|
|
if (thd->drawstyle & HT_RAIL) { // one tile case
|
|
|
GenericPlaceRail(TileVirtXY(thd->selend.x, thd->selend.y), trackstat);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
DoRailroadTrack(trackstat);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Build new signals or remove signals or (if only one tile marked) edit a signal.
|
|
|
*
|
|
|
* If one tile marked abort and use GenericPlaceSignals()
|
|
|
* else use CmdBuildSingleSignal() or CmdRemoveSingleSignal() in rail_cmd.cpp to build many signals
|
|
|
*/
|
|
|
static void HandleAutoSignalPlacement()
|
|
|
{
|
|
|
TileHighlightData *thd = &_thd;
|
|
|
uint32 p2 = GB(thd->drawstyle, 0, 3); // 0..5
|
|
|
|
|
|
if (thd->drawstyle == HT_RECT) { // one tile case
|
|
|
GenericPlaceSignals(TileVirtXY(thd->selend.x, thd->selend.y));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
const Window *w = FindWindowById(WC_BUILD_SIGNAL, 0);
|
|
|
|
|
|
if (w != NULL) {
|
|
|
/* signal GUI is used */
|
|
|
SB(p2, 3, 1, 0);
|
|
|
SB(p2, 4, 1, _cur_signal_variant);
|
|
|
SB(p2, 6, 1, _ctrl_pressed);
|
|
|
SB(p2, 7, 3, _cur_signal_type);
|
|
|
SB(p2, 24, 8, _settings_client.gui.drag_signals_density);
|
|
|
} else {
|
|
|
SB(p2, 3, 1, 0);
|
|
|
SB(p2, 4, 1, (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
|
|
|
SB(p2, 6, 1, _ctrl_pressed);
|
|
|
SB(p2, 7, 3, _default_signal_type[_settings_client.gui.default_signal_type]);
|
|
|
SB(p2, 24, 8, _settings_client.gui.drag_signals_density);
|
|
|
}
|
|
|
|
|
|
/* _settings_client.gui.drag_signals_density is given as a parameter such that each user
|
|
|
* in a network game can specify his/her own signal density */
|
|
|
DoCommandP(
|
|
|
TileVirtXY(thd->selstart.x, thd->selstart.y),
|
|
|
TileVirtXY(thd->selend.x, thd->selend.y),
|
|
|
p2,
|
|
|
CcPlaySound1E,
|
|
|
_remove_button_clicked ?
|
|
|
CMD_REMOVE_SIGNAL_TRACK | CMD_NO_WATER | CMD_MSG(STR_1013_CAN_T_REMOVE_SIGNALS_FROM) :
|
|
|
CMD_BUILD_SIGNAL_TRACK | CMD_NO_WATER | CMD_MSG(STR_1010_CAN_T_BUILD_SIGNALS_HERE)
|
|
|
);
|
|
|
CMD_BUILD_SIGNAL_TRACK | CMD_NO_WATER | CMD_MSG(STR_1010_CAN_T_BUILD_SIGNALS_HERE),
|
|
|
CcPlaySound1E);
|
|
|
}
|
|
|
|
|
|
|
|
|
typedef void OnButtonClick(Window *w);
|
|
|
|
|
|
/** Data associated with a push button in the build rail toolbar window */
|
|
|
struct RailBuildingGUIButtonData {
|
|
|
uint16 keycode; ///< Keycode associated with the button
|
|
|
OnButtonClick *click_proc; ///< Procedure to call when button is clicked
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* GUI rail-building button data constants.
|
|
|
* Offsets match widget order, starting at RTW_BUILD_NS
|
|
|
*/
|
|
|
static const RailBuildingGUIButtonData _rail_build_button_data[] = {
|
|
|
{'1', BuildRailClick_N },
|
|
|
{'2', BuildRailClick_NE },
|
|
|
{'3', BuildRailClick_E },
|
|
|
{'4', BuildRailClick_NW },
|
|
|
{'5', BuildRailClick_AutoRail },
|
|
|
{'6', BuildRailClick_Demolish },
|
|
|
{'7', BuildRailClick_Depot },
|
|
|
{'8', BuildRailClick_Waypoint },
|
|
|
{'9', BuildRailClick_Station },
|
|
|
{'S', BuildRailClick_AutoSignals},
|
|
|
{'B', BuildRailClick_Bridge },
|
|
|
{'T', BuildRailClick_Tunnel },
|
|
|
{'R', BuildRailClick_Remove },
|
|
|
{'C', BuildRailClick_Convert }
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* Based on the widget clicked, update the status of the 'remove' button.
|
|
|
* @param w Rail toolbar window
|
|
|
* @param clicked_widget Widget clicked in the toolbar
|
|
|
*/
|
|
|
struct BuildRailToolbarWindow : Window {
|
|
|
BuildRailToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
|
|
|
{
|
|
|
this->DisableWidget(RTW_REMOVE);
|
|
|
|
|
|
this->FindWindowPlacementAndResize(desc);
|
|
|
if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
|
|
|
}
|
|
|
|
|
|
~BuildRailToolbarWindow()
|
|
|
{
|
|
@@ -682,103 +682,103 @@ struct BuildRailToolbarWindow : Window {
|
|
|
_remove_button_clicked = false;
|
|
|
_rail_build_button_data[i].click_proc(this);
|
|
|
this->UpdateRemoveWidgetStatus(i + RTW_BUILD_NS);
|
|
|
if (_ctrl_pressed) RailToolbar_CtrlChanged(this);
|
|
|
state = ES_HANDLED;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection
|
|
|
return state;
|
|
|
}
|
|
|
|
|
|
virtual void OnPlaceObject(Point pt, TileIndex tile)
|
|
|
{
|
|
|
_place_proc(tile);
|
|
|
}
|
|
|
|
|
|
virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
|
|
|
{
|
|
|
/* no dragging if you have pressed the convert button */
|
|
|
if (FindWindowById(WC_BUILD_SIGNAL, 0) != NULL && _convert_signal_button && this->IsWidgetLowered(RTW_BUILD_SIGNALS)) return;
|
|
|
|
|
|
VpSelectTilesWithMethod(pt.x, pt.y, select_method);
|
|
|
}
|
|
|
|
|
|
virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
|
|
|
{
|
|
|
if (pt.x != -1) {
|
|
|
switch (select_proc) {
|
|
|
default: NOT_REACHED();
|
|
|
case DDSP_BUILD_BRIDGE:
|
|
|
ResetObjectToPlace();
|
|
|
ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype);
|
|
|
break;
|
|
|
|
|
|
case DDSP_PLACE_AUTORAIL:
|
|
|
HandleAutodirPlacement();
|
|
|
break;
|
|
|
|
|
|
case DDSP_BUILD_SIGNALS:
|
|
|
HandleAutoSignalPlacement();
|
|
|
break;
|
|
|
|
|
|
case DDSP_DEMOLISH_AREA:
|
|
|
GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
|
|
|
break;
|
|
|
|
|
|
case DDSP_CONVERT_RAIL:
|
|
|
DoCommandP(end_tile, start_tile, _cur_railtype, CcPlaySound10, CMD_CONVERT_RAIL | CMD_MSG(STR_CANT_CONVERT_RAIL));
|
|
|
DoCommandP(end_tile, start_tile, _cur_railtype, CMD_CONVERT_RAIL | CMD_MSG(STR_CANT_CONVERT_RAIL), CcPlaySound10);
|
|
|
break;
|
|
|
|
|
|
case DDSP_REMOVE_STATION:
|
|
|
case DDSP_BUILD_STATION:
|
|
|
if (_remove_button_clicked) {
|
|
|
DoCommandP(end_tile, start_tile, 0, CcPlaySound1E, CMD_REMOVE_FROM_RAILROAD_STATION | CMD_MSG(STR_CANT_REMOVE_PART_OF_STATION));
|
|
|
DoCommandP(end_tile, start_tile, 0, CMD_REMOVE_FROM_RAILROAD_STATION | CMD_MSG(STR_CANT_REMOVE_PART_OF_STATION), CcPlaySound1E);
|
|
|
break;
|
|
|
}
|
|
|
HandleStationPlacement(start_tile, end_tile);
|
|
|
break;
|
|
|
|
|
|
case DDSP_PLACE_RAIL_NE:
|
|
|
case DDSP_PLACE_RAIL_NW:
|
|
|
DoRailroadTrack(select_proc == DDSP_PLACE_RAIL_NE ? TRACK_X : TRACK_Y);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
virtual void OnPlaceObjectAbort()
|
|
|
{
|
|
|
this->RaiseButtons();
|
|
|
this->DisableWidget(RTW_REMOVE);
|
|
|
this->InvalidateWidget(RTW_REMOVE);
|
|
|
|
|
|
delete FindWindowById(WC_BUILD_SIGNAL, 0);
|
|
|
delete FindWindowById(WC_BUILD_STATION, 0);
|
|
|
delete FindWindowById(WC_BUILD_DEPOT, 0);
|
|
|
}
|
|
|
|
|
|
virtual void OnPlacePresize(Point pt, TileIndex tile)
|
|
|
{
|
|
|
DoCommand(tile, 0, 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
|
|
VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
|
|
|
}
|
|
|
|
|
|
virtual EventState OnCTRLStateChange()
|
|
|
{
|
|
|
/* do not toggle Remove button by Ctrl when placing station */
|
|
|
if (!this->IsWidgetLowered(RTW_BUILD_STATION) && RailToolbar_CtrlChanged(this)) return ES_HANDLED;
|
|
|
return ES_NOT_HANDLED;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
/** Widget definition for the rail toolbar */
|
|
|
static const Widget _build_rail_widgets[] = {
|
|
|
{ WWT_CLOSEBOX, RESIZE_NONE, COLOUR_DARK_GREEN, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // RTW_CLOSEBOX
|
|
|
{ WWT_CAPTION, RESIZE_NONE, COLOUR_DARK_GREEN, 11, 337, 0, 13, STR_100A_RAILROAD_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // RTW_CAPTION
|
|
|
{ WWT_STICKYBOX, RESIZE_NONE, COLOUR_DARK_GREEN, 338, 349, 0, 13, 0x0, STR_STICKY_BUTTON}, // RTW_STICKY
|
|
|
|
|
|
{ WWT_PANEL, RESIZE_NONE, COLOUR_DARK_GREEN, 110, 113, 14, 35, 0x0, STR_NULL}, // RTW_SPACER
|
|
|
|
|
|
{ WWT_IMGBTN, RESIZE_NONE, COLOUR_DARK_GREEN, 0, 21, 14, 35, SPR_IMG_RAIL_NS, STR_1018_BUILD_RAILROAD_TRACK}, // RTW_BUILD_NS
|
|
|
{ WWT_IMGBTN, RESIZE_NONE, COLOUR_DARK_GREEN, 22, 43, 14, 35, SPR_IMG_RAIL_NE, STR_1018_BUILD_RAILROAD_TRACK}, // RTW_BUILD_X
|
|
@@ -835,98 +835,98 @@ static void SetupRailToolbar(RailType ra
|
|
|
* toolbar. In the latter case, the corresponding widget is also selected.
|
|
|
*
|
|
|
* If the terraform toolbar is linked to the toolbar, that window is also opened.
|
|
|
*
|
|
|
* @param railtype Rail type to open the window for
|
|
|
* @param button Widget clicked (\c -1 means no button clicked)
|
|
|
*/
|
|
|
void ShowBuildRailToolbar(RailType railtype, int button)
|
|
|
{
|
|
|
BuildRailToolbarWindow *w;
|
|
|
|
|
|
if (!IsValidCompanyID(_current_company)) return;
|
|
|
if (!ValParamRailtype(railtype)) return;
|
|
|
|
|
|
// don't recreate the window if we're clicking on a button and the window exists.
|
|
|
if (button < 0 || !(w = dynamic_cast<BuildRailToolbarWindow*>(FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_RAIL)))) {
|
|
|
DeleteWindowByClass(WC_BUILD_TOOLBAR);
|
|
|
_cur_railtype = railtype;
|
|
|
w = AllocateWindowDescFront<BuildRailToolbarWindow>(&_build_rail_desc, TRANSPORT_RAIL);
|
|
|
SetupRailToolbar(railtype, w);
|
|
|
}
|
|
|
|
|
|
_remove_button_clicked = false;
|
|
|
if (w != NULL && button >= RTW_CLOSEBOX) {
|
|
|
_rail_build_button_data[button].click_proc(w);
|
|
|
w->UpdateRemoveWidgetStatus(button + RTW_BUILD_NS);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* TODO: For custom stations, respect their allowed platforms/lengths bitmasks!
|
|
|
* --pasky */
|
|
|
|
|
|
static void HandleStationPlacement(TileIndex start, TileIndex end)
|
|
|
{
|
|
|
uint sx = TileX(start);
|
|
|
uint sy = TileY(start);
|
|
|
uint ex = TileX(end);
|
|
|
uint ey = TileY(end);
|
|
|
uint w,h;
|
|
|
|
|
|
if (sx > ex) Swap(sx, ex);
|
|
|
if (sy > ey) Swap(sy, ey);
|
|
|
w = ex - sx + 1;
|
|
|
h = ey - sy + 1;
|
|
|
if (_railstation.orientation == AXIS_X) Swap(w, h);
|
|
|
|
|
|
DoCommandP(TileXY(sx, sy),
|
|
|
_railstation.orientation | (w << 8) | (h << 16) | (_ctrl_pressed << 24),
|
|
|
_cur_railtype | (_railstation.station_class << 8) | (_railstation.station_type << 16), CcStation,
|
|
|
CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION));
|
|
|
_cur_railtype | (_railstation.station_class << 8) | (_railstation.station_type << 16),
|
|
|
CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION), CcStation);
|
|
|
}
|
|
|
|
|
|
struct BuildRailStationWindow : public PickerWindowBase {
|
|
|
private:
|
|
|
/** Enum referring to the widgets of the rail stations window */
|
|
|
enum BuildRailStationWidgets {
|
|
|
BRSW_CLOSEBOX = 0,
|
|
|
BRSW_CAPTION,
|
|
|
BRSW_BACKGROUND,
|
|
|
|
|
|
BRSW_PLATFORM_DIR_X,
|
|
|
BRSW_PLATFORM_DIR_Y,
|
|
|
|
|
|
BRSW_PLATFORM_NUM_BEGIN = BRSW_PLATFORM_DIR_Y,
|
|
|
BRSW_PLATFORM_NUM_1,
|
|
|
BRSW_PLATFORM_NUM_2,
|
|
|
BRSW_PLATFORM_NUM_3,
|
|
|
BRSW_PLATFORM_NUM_4,
|
|
|
BRSW_PLATFORM_NUM_5,
|
|
|
BRSW_PLATFORM_NUM_6,
|
|
|
BRSW_PLATFORM_NUM_7,
|
|
|
|
|
|
BRSW_PLATFORM_LEN_BEGIN = BRSW_PLATFORM_NUM_7,
|
|
|
BRSW_PLATFORM_LEN_1,
|
|
|
BRSW_PLATFORM_LEN_2,
|
|
|
BRSW_PLATFORM_LEN_3,
|
|
|
BRSW_PLATFORM_LEN_4,
|
|
|
BRSW_PLATFORM_LEN_5,
|
|
|
BRSW_PLATFORM_LEN_6,
|
|
|
BRSW_PLATFORM_LEN_7,
|
|
|
|
|
|
BRSW_PLATFORM_DRAG_N_DROP,
|
|
|
|
|
|
BRSW_HIGHLIGHT_OFF,
|
|
|
BRSW_HIGHLIGHT_ON,
|
|
|
|
|
|
BRSW_NEWST_DROPDOWN,
|
|
|
BRSW_NEWST_LIST,
|
|
|
BRSW_NEWST_SCROLL
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* Verify whether the currently selected station size is allowed after selecting a new station class/type.
|
|
|
* If not, change the station size variables ( _railstation.numtracks and _railstation.platlength ).
|
|
|
* @param statspec Specification of the new station class/type
|
|
|
*/
|
|
|
void CheckSelectedSize(const StationSpec *statspec)
|
|
|
{
|