diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index 0e5b477f9a..b960d4e6e2 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -14,6 +14,7 @@ #include "../town_kdtree.h" #include "../tilearea_type.h" #include "../tilehighlight_type.h" +#include "../tilehighlight_func.h" #include "../viewport_func.h" #include "../zoning.h" #include "../table/track_land.h" @@ -608,6 +609,38 @@ DiagDirection AutodetectRailObjectDirection(TileIndex tile, Point pt) { NOT_REACHED(); } +TileIndex _autodetection_tile = INVALID_TILE; +DiagDirDiff _autodetection_rotation = DIAGDIRDIFF_SAME; + +static DiagDirDiff GetAutodetectionRotation() { + auto pt = GetTileBelowCursor(); + auto tile = TileVirtXY(pt.x, pt.y); + + if (tile != _autodetection_tile) { + _autodetection_tile = tile; + _autodetection_rotation = DIAGDIRDIFF_SAME; + } + + return _autodetection_rotation; +} + +void RotateAutodetection() { + auto rotation = GetAutodetectionRotation(); + if (rotation == DIAGDIRDIFF_90LEFT) rotation = DIAGDIRDIFF_SAME; + else rotation++; + _autodetection_rotation = rotation; + ::UpdateTileSelection(); +} + +void ResetRotateAutodetection() { + _autodetection_tile = INVALID_TILE; + _autodetection_rotation = DIAGDIRDIFF_SAME; +} + +DiagDirection AddAutodetectionRotation(DiagDirection ddir) { + return ChangeDiagDir(ddir, GetAutodetectionRotation()); +} + HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) { _thd.cm_new = ObjectHighlight(ObjectHighlight::Type::NONE); if ((_thd.place_mode & HT_DRAG_MASK) == HT_RECT && @@ -616,8 +649,9 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) { auto pt = GetTileBelowCursor(); auto tile = TileVirtXY(pt.x, pt.y); if (pt.x != -1) { - if (dir >= DiagDirection::DIAGDIR_END) - dir = AutodetectRailObjectDirection(tile, pt); + if (dir >= DiagDirection::DIAGDIR_END) { + dir = AddAutodetectionRotation(AutodetectRailObjectDirection(tile, pt)); + } _thd.cm_new = ObjectHighlight::make_depot(tile, dir); } new_drawstyle = HT_RECT; diff --git a/src/citymania/cm_highlight.hpp b/src/citymania/cm_highlight.hpp index f3a5495f15..0ec66fa893 100644 --- a/src/citymania/cm_highlight.hpp +++ b/src/citymania/cm_highlight.hpp @@ -95,6 +95,9 @@ void SetIndustryForbiddenTilesHighlight(IndustryType type); PaletteID GetTreeShadePal(TileIndex tile); +void RotateAutodetection(); +void ResetRotateAutodetection(); + } // namespace citymania #endif diff --git a/src/citymania/cm_highlight_type.hpp b/src/citymania/cm_highlight_type.hpp index 81bbfb75ba..ba9f38be6e 100644 --- a/src/citymania/cm_highlight_type.hpp +++ b/src/citymania/cm_highlight_type.hpp @@ -40,7 +40,6 @@ public: RAIL_DEPOT = 1, }; -protected: Type type; union { struct { @@ -49,6 +48,7 @@ protected: } depot; } u; +protected: bool tiles_updated = false; std::multimap tiles; void UpdateTiles(); diff --git a/src/citymania/cm_hotkeys.cpp b/src/citymania/cm_hotkeys.cpp index d7c724f539..7b849973bb 100644 --- a/src/citymania/cm_hotkeys.cpp +++ b/src/citymania/cm_hotkeys.cpp @@ -35,6 +35,9 @@ bool _fn_mod = false; bool _remove_mod = false; bool _estimate_mod = false; +bool _middle_button_down; ///< Is middle mouse button pressed? +bool _middle_button_clicked; ///< Is middle mouse button clicked? + uint32 _effective_actions = 0; uint32 _first_effective_tick = 0; std::queue _last_actions; diff --git a/src/gfx_type.h b/src/gfx_type.h index 13afdfbd65..339d39d57c 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -105,13 +105,15 @@ enum WindowKeyCodes { WKC_L_BRACE = 154, ///< { Left brace WKC_R_BRACE = 155, ///< } Right brace - + WKC_L_PAREN = 157, ///< ( Left parentheses WKC_R_PAREN = 158, ///< ) Right parentheses WKC_PLUS = 159, ///< + Plus WKC_EXCLAIM = 160, ///< ! Exclamation mark WKC_ASTERISK = 161, ///< * Asterisk WKC_DOLLAR = 162, ///< $ Dollar sign + + CM_WKC_MOUSE_MIDDLE = 255, ///< CityMania special code for middle mouse button }; /** A single sprite of a list of animated cursors */ diff --git a/src/hotkeys.cpp b/src/hotkeys.cpp index a6e995b2a2..9d79fb5739 100644 --- a/src/hotkeys.cpp +++ b/src/hotkeys.cpp @@ -85,6 +85,7 @@ static const KeycodeNames _keycode_to_name[] = { {"R_PAREN", WKC_R_PAREN}, {"EXCLAIM", WKC_EXCLAIM}, {"ASTERISK", WKC_ASTERISK}, + {"MOUSE_MIDDLE", CM_WKC_MOUSE_MIDDLE}, }; /** diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 613e80c5f1..3100e2154d 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -39,6 +39,7 @@ #include "widgets/rail_widget.h" #include "citymania/cm_hotkeys.hpp" +#include "citymania/cm_highlight.hpp" #include "citymania/cm_station_gui.hpp" #include "safeguards.h" @@ -503,30 +504,6 @@ RoadBits FindRailsToConnect(TileIndex tile) { return passing; } -/* - * Selects orientation for rail object (depot) - */ -DiagDirection AutodetectRailObjectDirection(TileIndex tile) { - RoadBits bits = FindRailsToConnect(tile); - // FIXME after this point repeats road autodetection - if (HasExactlyOneBit(bits)) return RoadBitsToDiagDir(bits); - if (bits == ROAD_NONE) bits = ROAD_ALL; - RoadBits frac_bits = DiagDirToRoadBits(TileFractCoordsToDiagDir()); - if (HasExactlyOneBit(frac_bits & bits)) { - return RoadBitsToDiagDir(frac_bits & bits); - } - frac_bits |= MirrorRoadBits(frac_bits); - if (HasExactlyOneBit(frac_bits & bits)) { - return RoadBitsToDiagDir(frac_bits & bits); - } - for (DiagDirection ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) { - if (DiagDirToRoadBits(ddir) & bits) { - return ddir; - } - } - NOT_REACHED(); -} - /** Rail toolbar management class. */ struct BuildRailToolbarWindow : Window { RailType railtype; ///< Rail type to build. @@ -714,6 +691,7 @@ struct BuildRailToolbarWindow : Window { case WID_RAT_BUILD_DEPOT: if (HandlePlacePushButton(this, WID_RAT_BUILD_DEPOT, GetRailTypeInfo(_cur_railtype)->cursor.depot, HT_RECT | (HighLightStyle)_build_depot_direction)) { + citymania::ResetRotateAutodetection(); ShowBuildTrainDepotPicker(this); this->last_user_action = widget; } @@ -846,7 +824,8 @@ struct BuildRailToolbarWindow : Window { case WID_RAT_BUILD_DEPOT: ddir = _build_depot_direction; if (ddir == DIAGDIR_NW + 1) { - ddir = AutodetectRailObjectDirection(tile); + assert(_thd.cm.type == citymania::ObjectHighlight::Type::RAIL_DEPOT); + ddir = _thd.cm.u.depot.ddir; } DoCommandP(tile, _cur_railtype, ddir, CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT), @@ -1924,6 +1903,10 @@ static void ShowSignalBuilder(Window *parent) new BuildSignalWindow(&_signal_builder_desc, parent); } +enum class BuildRailDepotWindowHotkey : int { + ROTATE, +}; + struct BuildRailDepotWindow : public PickerWindowBase { BuildRailDepotWindow(WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) { @@ -1971,8 +1954,40 @@ struct BuildRailDepotWindow : public PickerWindowBase { break; } } + + + EventState OnHotkey(int hotkey) override + { + switch ((BuildRailDepotWindowHotkey)hotkey) { + /* Indicate to the OnClick that the action comes from a hotkey rather + * then from a click and that the CTRL state should be ignored. */ + case BuildRailDepotWindowHotkey::ROTATE: + if (_build_depot_direction < DIAGDIR_END) { + this->RaiseWidget(_build_depot_direction + WID_BRAD_DEPOT_NE); + _build_depot_direction = ChangeDiagDir(_build_depot_direction, DIAGDIRDIFF_90RIGHT); + this->LowerWidget(_build_depot_direction + WID_BRAD_DEPOT_NE); + } else { + citymania::RotateAutodetection(); + } + this->SetDirty(); + return ES_HANDLED; + + default: + return ES_NOT_HANDLED; + } + + return ES_NOT_HANDLED; + } + + static HotkeyList hotkeys; }; +static Hotkey build_depot_hotkeys[] = { + Hotkey(CM_WKC_MOUSE_MIDDLE, "rotate", (int)BuildRailDepotWindowHotkey::ROTATE), + HOTKEY_LIST_END +}; +HotkeyList BuildRailDepotWindow::hotkeys("cm_build_depot", build_depot_hotkeys); + /** Nested widget definition of the build rail depot window */ static const NWidgetPart _nested_build_depot_widgets[] = { NWidget(NWID_HORIZONTAL), @@ -2014,7 +2029,8 @@ static WindowDesc _build_depot_desc( WDP_AUTO, nullptr, 0, 0, WC_BUILD_DEPOT, WC_BUILD_TOOLBAR, WDF_CONSTRUCTION, - _nested_build_depot_widgets, lengthof(_nested_build_depot_widgets) + _nested_build_depot_widgets, lengthof(_nested_build_depot_widgets), + &BuildRailDepotWindow::hotkeys ); static void ShowBuildTrainDepotPicker(Window *parent) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 8f55734dc8..64fb51807c 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -544,6 +544,10 @@ int VideoDriver_SDL::PollEvent() break; case SDL_MOUSEBUTTONUP: + if (ev.button.button == SDL_BUTTON_MIDDLE) { + HandleKeypress(CM_WKC_MOUSE_MIDDLE, 0); + break; + } if (_rightclick_emulate) { _right_button_down = false; _left_button_down = false; diff --git a/src/window.cpp b/src/window.cpp index c0cd326e86..5728c878bf 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2974,6 +2974,7 @@ static void MouseLoop(MouseClick click, int mousewheel) case MC_HOVER: DispatchHoverEvent(w, x - w->left, y - w->top); break; + } }