diff --git a/src/citymania/cm_hotkeys.cpp b/src/citymania/cm_hotkeys.cpp index 396a49e43e..fc2909e6a2 100644 --- a/src/citymania/cm_hotkeys.cpp +++ b/src/citymania/cm_hotkeys.cpp @@ -3,12 +3,28 @@ #include "cm_hotkeys.hpp" #include "cm_settings.hpp" +#include "../newgrf_station.h" #include "../settings_type.h" +#include "../sound_func.h" +#include "../tilehighlight_func.h" +#include "../viewport_func.h" +#include "../window_func.h" #include "../window_gui.h" #include "../window_type.h" +#include "../widgets/rail_widget.h" #include "../safeguards.h" +struct RailStationGUISettings { + Axis orientation; ///< Currently selected rail station orientation + + bool newstations; ///< Are custom station definitions available? + StationClassID 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 ) +}; +extern RailStationGUISettings _railstation; ///< Settings of the station builder GUI + namespace citymania { bool _fn_mod = false; @@ -40,4 +56,93 @@ void UpdateModKeys(bool shift_pressed, bool ctrl_pressed, bool alt_pressed) { } } +bool HasSeparateRemoveMod() { + return (_settings_client.gui.cm_fn_mod != _settings_client.gui.cm_remove_mod); +} + +ToolRemoveMode RailToolbar_GetRemoveMode(int widget) { + switch(widget) { + case WID_RAT_BUILD_NS: + case WID_RAT_BUILD_X: + case WID_RAT_BUILD_EW: + case WID_RAT_BUILD_Y: + case WID_RAT_AUTORAIL: + case WID_RAT_POLYRAIL: + return ToolRemoveMode::MOD; + + case WID_RAT_BUILD_WAYPOINT: + case WID_RAT_BUILD_STATION: + case WID_RAT_BUILD_SIGNALS: + return HasSeparateRemoveMod() ? ToolRemoveMode::MOD : ToolRemoveMode::BUTTON; + + default: + return ToolRemoveMode::NONE; + } +} + +bool RailToolbar_IsRemoveInverted(int widget) { + return (RailToolbar_GetRemoveMode(widget) != ToolRemoveMode::NONE && citymania::_fn_mod); +} + +void RailToolbar_UpdateRemoveWidgetStatus(Window *w, int widget, bool remove_active) { + if (widget == WID_RAT_REMOVE) return; + + if (RailToolbar_GetRemoveMode(widget) == citymania::ToolRemoveMode::NONE || !w->IsWidgetLowered(widget)) { + w->DisableWidget(WID_RAT_REMOVE); + w->RaiseWidget(WID_RAT_REMOVE); + } else { + w->EnableWidget(WID_RAT_REMOVE); + w->SetWidgetLoweredState(WID_RAT_REMOVE, remove_active); + SetSelectionRed(remove_active); + } + w->SetWidgetDirty(WID_RAT_REMOVE); + + /* handle station builder */ + if (w->IsWidgetLowered(WID_RAT_BUILD_STATION)) { + if (remove_active) { + /* starting drag & drop remove */ + if (!_settings_client.gui.station_dragdrop) { + SetTileSelectSize(1, 1); + } else { + VpSetPlaceSizingLimit(-1); + } + } else { + /* starting station build mode */ + if (!_settings_client.gui.station_dragdrop) { + int x = _settings_client.gui.station_numtracks; + int y = _settings_client.gui.station_platlength; + if (_railstation.orientation == 0) Swap(x, y); + SetTileSelectSize(x, y); + } else { + VpSetPlaceSizingLimit(_settings_game.station.station_spread); + } + } + } +} + +bool RailToolbar_RemoveModChanged(Window *w, bool invert_remove, bool remove_active, bool button_clicked) { + if (w->IsWidgetDisabled(WID_RAT_REMOVE)) return false; + + DeleteWindowById(WC_SELECT_STATION, 0); + for (uint i = WID_RAT_BUILD_NS; i <= WID_RAT_BUILD_TUNNEL; i++) { + if (w->IsWidgetLowered(i)) { + auto old_active = remove_active; + switch (RailToolbar_GetRemoveMode(i)) { + case ToolRemoveMode::BUTTON: + if (button_clicked) remove_active = !w->IsWidgetLowered(WID_RAT_REMOVE); + break; + case ToolRemoveMode::MOD: + if (_remove_mod || !button_clicked) remove_active = (_remove_mod != invert_remove); + else remove_active = !w->IsWidgetLowered(WID_RAT_REMOVE); + break; + default: + break; + } + if (old_active != remove_active) RailToolbar_UpdateRemoveWidgetStatus(w, i, remove_active); + return remove_active; + } + } + return remove_active; +} + } // namespace citymania diff --git a/src/citymania/cm_hotkeys.hpp b/src/citymania/cm_hotkeys.hpp index 8f7d106c7b..e15f9996f2 100644 --- a/src/citymania/cm_hotkeys.hpp +++ b/src/citymania/cm_hotkeys.hpp @@ -1,14 +1,26 @@ #ifndef CMEXT_HOTKEYS_HPP #define CMEXT_HOTKEYS_HPP +#include "../window_type.h" + namespace citymania { extern bool _fn_mod; extern bool _estimate_mod; extern bool _remove_mod; +enum class ToolRemoveMode : uint8 { + NONE = 0, + BUTTON = 1, + MOD = 2, +}; + void UpdateModKeys(bool shift_pressed, bool ctrl_pressed, bool alt_pressed); +bool RailToolbar_IsRemoveInverted(int widget); +void RailToolbar_UpdateRemoveWidgetStatus(Window *w, int widged, bool remove_active); +bool RailToolbar_RemoveModChanged(Window *w, bool invert_remove, bool remove_active, bool button_clicked); + } // namespace citymania #endif diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index c2ec78e636..a8c2e5a214 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -46,6 +46,7 @@ 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 bool _cm_invert_remove; ///< Invert remove mode on tools (when fn-clicked) 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 @@ -58,6 +59,7 @@ extern TileIndex _rail_track_endtile; // rail_cmd.cpp /* Map the setting: default_signal_type to the corresponding signal type */ static const SignalType _default_signal_type[] = {SIGTYPE_NORMAL, SIGTYPE_PBS, SIGTYPE_PBS_ONEWAY}; +static const int HOTKEY_MASK = 0x1000; static const int HOTKEY_POLYRAIL = 0x1000; static const int HOTKEY_NEW_POLYRAIL = 0x1001; static const int HOTKEY_BUILD_STATION_SIZED = 0x1010; ///< Build a station in fixed size mode. @@ -646,9 +648,7 @@ struct BuildRailToolbarWindow : Window { void OnClick(Point pt, int widget, int click_count) override { if (widget < WID_RAT_BUILD_NS) return; - bool remove_on_ctrl = true; /* do not check ctrl for hotkeys */ - _remove_button_clicked = false; switch (widget) { case WID_RAT_BUILD_NS: HandlePlacePushButton(this, WID_RAT_BUILD_NS, GetRailTypeInfo(_cur_railtype)->cursor.rail_ns, HT_LINE | HT_DIR_VL); @@ -740,7 +740,6 @@ struct BuildRailToolbarWindow : Window { ShowStationBuilder(this); } this->last_user_action = WID_RAT_BUILD_STATION; - remove_on_ctrl = false; } else { /* button */ if (HandlePlacePushButton(this, WID_RAT_BUILD_STATION, SPR_CURSOR_RAIL_STATION, HT_RECT)) { ShowStationBuilder(this); @@ -770,7 +769,8 @@ struct BuildRailToolbarWindow : Window { break; case WID_RAT_REMOVE: - BuildRailClick_Remove(this); + _remove_button_clicked = citymania::RailToolbar_RemoveModChanged(this, _cm_invert_remove, _remove_button_clicked, true); + // BuildRailClick_Remove(this); break; case WID_RAT_CONVERT_RAIL: @@ -780,8 +780,16 @@ struct BuildRailToolbarWindow : Window { default: NOT_REACHED(); } - this->UpdateRemoveWidgetStatus(widget); - if (citymania::_remove_mod && remove_on_ctrl) RailToolbar_CtrlChanged(this); + + bool is_hotkey = (pt.x == 0 && pt.y == 0); + if (widget != WID_RAT_REMOVE) { + _cm_invert_remove = (!is_hotkey && citymania::RailToolbar_IsRemoveInverted(widget)); + _remove_button_clicked = _cm_invert_remove; + } + + citymania::RailToolbar_UpdateRemoveWidgetStatus(this, widget, _remove_button_clicked); + // this->UpdateRemoveWidgetStatus(widget); + // if (_ctrl_pressed) RailToolbar_CtrlChanged(this); } EventState OnHotkey(int hotkey) override @@ -962,8 +970,11 @@ struct BuildRailToolbarWindow : Window { EventState CM_OnRemoveModStateChange() override { - /* do not toggle Remove button by Ctrl when placing station */ - if (!this->IsWidgetLowered(WID_RAT_BUILD_STATION) && !this->IsWidgetLowered(WID_RAT_BUILD_WAYPOINT) && RailToolbar_CtrlChanged(this)) return ES_HANDLED; + auto new_remove = citymania::RailToolbar_RemoveModChanged(this, _cm_invert_remove, _remove_button_clicked, false); + if (new_remove != _remove_button_clicked) { + _remove_button_clicked = new_remove; + return ES_HANDLED; + } return ES_NOT_HANDLED; }