diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index ed122b2c65..a6a36ea31e 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -13,10 +13,12 @@ #include "../industry.h" #include "../landscape.h" #include "../newgrf_railtype.h" +#include "../newgrf_station.h" #include "../town.h" #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" @@ -40,6 +42,16 @@ RoadBits FindRailsToConnect(TileIndex tile); extern DiagDirection _build_depot_direction; ///< Currently selected depot direction extern uint32 _realtime_tick; +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 { @@ -115,7 +127,11 @@ ObjectTileHighlight ObjectTileHighlight::make_rail_tunnel_head(DiagDirection ddi bool ObjectHighlight::operator==(const ObjectHighlight& oh) { if (this->type != oh.type) return false; - return (this->tile == oh.tile && this->ddir == oh.ddir && this->blueprint == oh.blueprint); + return (this->tile == oh.tile + && this->end_tile == oh.end_tile + && this->axis == oh.axis + && this->ddir == oh.ddir + && this->blueprint == oh.blueprint); // switch (this->type) { // case Type::RAIL_DEPOT: return this->tile == oh.tile && this->ddir == oh.ddir; // default: return true; @@ -128,13 +144,21 @@ bool ObjectHighlight::operator!=(const ObjectHighlight& oh) { } -ObjectHighlight ObjectHighlight::make_depot(TileIndex tile, DiagDirection ddir) { +ObjectHighlight ObjectHighlight::make_rail_depot(TileIndex tile, DiagDirection ddir) { auto oh = ObjectHighlight{ObjectHighlight::Type::RAIL_DEPOT}; oh.tile = tile; oh.ddir = ddir; return oh; } +ObjectHighlight ObjectHighlight::make_rail_station(TileIndex start_tile, TileIndex end_tile, Axis axis) { + auto oh = ObjectHighlight{ObjectHighlight::Type::RAIL_STATION}; + oh.tile = start_tile; + oh.end_tile = end_tile; + oh.axis = axis; + return oh; +} + ObjectHighlight ObjectHighlight::make_blueprint(TileIndex tile, sp blueprint) { auto oh = ObjectHighlight{ObjectHighlight::Type::BLUEPRINT}; oh.tile = tile; @@ -185,6 +209,13 @@ void ObjectHighlight::UpdateTiles() { } break; } + case Type::RAIL_STATION: { + auto ta = OrthogonalTileArea(this->tile, this->end_tile); + TILE_AREA_LOOP(tile, ta) { + this->tiles.insert({tile, ObjectTileHighlight::make_rail_station(this->axis)}); + } + break; + } case Type::BLUEPRINT: if (this->blueprint && this->tile != INVALID_TILE) this->tiles = this->blueprint->GetTiles(this->tile); @@ -533,21 +564,21 @@ static void SetStationSelectionHighlight(const TileInfo *ti, TileHighlight &th) if (_highlight_station_to_join) highlight_station = _highlight_station_to_join; - if (draw_selection) { - auto b = CalcTileBorders(ti->tile, [](TileIndex t) { - auto x = TileX(t) * TILE_SIZE, y = TileY(t) * TILE_SIZE; - return IsInsideSelectedRectangle(x, y); - }); - const SpriteID pal[] = {SPR_PALETTE_ZONING_RED, SPR_PALETTE_ZONING_YELLOW, SPR_PALETTE_ZONING_LIGHT_BLUE, SPR_PALETTE_ZONING_GREEN}; - auto color = pal[(int)_station_building_status]; - if (_thd.make_square_red) color = SPR_PALETTE_ZONING_RED; - if (b.first != ZoningBorder::NONE) - th.add_border(b.first, color); - if (IsInsideSelectedRectangle(TileX(ti->tile) * TILE_SIZE, TileY(ti->tile) * TILE_SIZE)) { - th.ground_pal = GetTintBySelectionColour(color); - return; - } - } + // if (draw_selection) { + // auto b = CalcTileBorders(ti->tile, [](TileIndex t) { + // auto x = TileX(t) * TILE_SIZE, y = TileY(t) * TILE_SIZE; + // return IsInsideSelectedRectangle(x, y); + // }); + // const SpriteID pal[] = {SPR_PALETTE_ZONING_RED, SPR_PALETTE_ZONING_YELLOW, SPR_PALETTE_ZONING_LIGHT_BLUE, SPR_PALETTE_ZONING_GREEN}; + // auto color = pal[(int)_station_building_status]; + // if (_thd.make_square_red) color = SPR_PALETTE_ZONING_RED; + // if (b.first != ZoningBorder::NONE) + // th.add_border(b.first, color); + // if (IsInsideSelectedRectangle(TileX(ti->tile) * TILE_SIZE, TileY(ti->tile) * TILE_SIZE)) { + // th.ground_pal = GetTintBySelectionColour(color); + // return; + // } + // } auto coverage_getter = [draw_selection, highlight_station](TileIndex t) { auto x = TileX(t) * TILE_SIZE, y = TileY(t) * TILE_SIZE; @@ -835,6 +866,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); auto pt = GetTileBelowCursor(); @@ -846,9 +909,20 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) { _cursor.sprite_seq[0].sprite == GetRailTypeInfo(_cur_railtype)->cursor.depot) { auto dir = _build_depot_direction; if (pt.x != -1) { - if (dir >= DiagDirection::DIAGDIR_END) - dir = AutodetectRailObjectDirection(tile, pt); - _thd.cm_new = ObjectHighlight::make_depot(tile, dir); + if (dir >= DiagDirection::DIAGDIR_END) { + dir = AddAutodetectionRotation(AutodetectRailObjectDirection(tile, pt)); + } + _thd.cm_new = ObjectHighlight::make_rail_depot(tile, dir); + } + new_drawstyle = HT_RECT; + } else if (_thd.outersize.x > 0) { // station + if (_thd.size.x >= (int)TILE_SIZE && _thd.size.y >= (int)TILE_SIZE) { + auto start_tile = TileXY(_thd.pos.x / TILE_SIZE, _thd.pos.y / TILE_SIZE); + auto end_tile = TileXY( + std::min((_thd.pos.x + _thd.size.x) / TILE_SIZE, MapSizeX()) - 1, + std::min((_thd.pos.y + _thd.size.y) / TILE_SIZE, MapSizeY()) - 1 + ); + _thd.cm_new = ObjectHighlight::make_rail_station(start_tile, end_tile, _railstation.orientation); } 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 5af02dd8a0..db3c63ff29 100644 --- a/src/citymania/cm_highlight_type.hpp +++ b/src/citymania/cm_highlight_type.hpp @@ -154,15 +154,18 @@ public: enum class Type { NONE = 0, RAIL_DEPOT = 1, - BLUEPRINT = 2, + RAIL_STATION = 2, + BLUEPRINT = 3, }; -protected: Type type; TileIndex tile = INVALID_TILE; + TileIndex end_tile = INVALID_TILE; + Axis axis = INVALID_AXIS; DiagDirection ddir = INVALID_DIAGDIR; sp blueprint = nullptr; +protected: bool tiles_updated = false; std::multimap tiles; void UpdateTiles(); @@ -173,7 +176,8 @@ public: bool operator==(const ObjectHighlight& oh); bool operator!=(const ObjectHighlight& oh); - static ObjectHighlight make_depot(TileIndex tile, DiagDirection ddir); + static ObjectHighlight make_rail_depot(TileIndex tile, DiagDirection ddir); + static ObjectHighlight make_rail_station(TileIndex start_tile, TileIndex end_tile, Axis axis); static ObjectHighlight make_blueprint(TileIndex tile, sp blueprint); void Draw(const TileInfo *ti); 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..73d8ce3f4b 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -105,13 +105,17 @@ 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 = 0x703, ///< CityMania: special code for middle mouse button + CM_WKC_MOUSE_OTHER_START = 0x704, ///< CityMania: start of the numbered buttons (whatever number driver reports), starts as MOUSE_4 hotkey + CM_WKC_MOUSE_OTHER_END = 0x71f, ///< CityMania: 30 buttons should be enough for any mouse, right? ;) }; /** A single sprite of a list of animated cursors */ diff --git a/src/hotkeys.cpp b/src/hotkeys.cpp index a6e995b2a2..298551d559 100644 --- a/src/hotkeys.cpp +++ b/src/hotkeys.cpp @@ -85,6 +85,35 @@ static const KeycodeNames _keycode_to_name[] = { {"R_PAREN", WKC_R_PAREN}, {"EXCLAIM", WKC_EXCLAIM}, {"ASTERISK", WKC_ASTERISK}, + + {"MOUSE_MIDDLE", CM_WKC_MOUSE_MIDDLE}, + {"MOUSE_4", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 0)}, + {"MOUSE_5", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 1)}, + {"MOUSE_6", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 2)}, + {"MOUSE_7", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 3)}, + {"MOUSE_8", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 4)}, + {"MOUSE_9", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 5)}, + {"MOUSE_10", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 6)}, + {"MOUSE_11", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 7)}, + {"MOUSE_12", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 8)}, + {"MOUSE_13", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 9)}, + {"MOUSE_14", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 10)}, + {"MOUSE_15", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 11)}, + {"MOUSE_16", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 12)}, + {"MOUSE_17", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 13)}, + {"MOUSE_18", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 14)}, + {"MOUSE_19", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 15)}, + {"MOUSE_20", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 16)}, + {"MOUSE_21", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 17)}, + {"MOUSE_22", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 18)}, + {"MOUSE_23", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 19)}, + {"MOUSE_24", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 20)}, + {"MOUSE_25", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 21)}, + {"MOUSE_26", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 22)}, + {"MOUSE_27", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 23)}, + {"MOUSE_28", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 24)}, + {"MOUSE_29", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 25)}, + {"MOUSE_30", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 26)}, }; /** diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index 5d36a39b96..0880c53efc 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -203,7 +203,7 @@ void NetworkExecuteLocalCommandQueue() if (_frame_counter > cp->frame) { /* If we reach here, it means for whatever reason, we've already executed * past the command we need to execute. */ - error("[net] Trying to execute a packet in the past!"); + error("[net] Trying to execute a packet in the past! (frame=%u cmd_frame=%u tile=%u p1=%u p2=%u cmd=%u)", (uint)_frame_counter, (uint)cp->frame, (uint)cp->tile, (uint)cp->p1, (uint)cp->p2, (uint)cp->cmd); } /* We can execute this command */ diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index a622c6f7b5..d66ef6ae88 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -40,6 +40,7 @@ #include "citymania/cm_blueprint.hpp" #include "citymania/cm_hotkeys.hpp" +#include "citymania/cm_highlight.hpp" #include "citymania/cm_station_gui.hpp" #include "safeguards.h" @@ -504,30 +505,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. @@ -715,6 +692,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; } @@ -852,7 +830,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.ddir; } DoCommandP(tile, _cur_railtype, ddir, CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT), @@ -1144,7 +1123,14 @@ static void HandleStationPlacement(TileIndex start, TileIndex end) ShowSelectStationIfNeeded(cmdcont, ta); } + struct BuildRailStationWindow : public PickerWindowBase { +/* CityMania code start */ +public: + enum class Hotkey : int { + ROTATE, + }; +/* CityMania code end */ private: uint line_height; ///< Height of a single line in the newstation selection matrix (#WID_BRAS_NEWST_LIST widget). uint coverage_height; ///< Height of the coverage texts. @@ -1628,8 +1614,40 @@ public: { CheckRedrawStationCoverage(this); } + + /* CityMania code start */ + EventState OnHotkey(int hotkey) override + { + switch ((BuildRailStationWindow::Hotkey)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 BuildRailStationWindow::Hotkey::ROTATE: + this->RaiseWidget(_railstation.orientation + WID_BRAS_PLATFORM_DIR_X); + _railstation.orientation = OtherAxis(_railstation.orientation); + this->LowerWidget(_railstation.orientation + WID_BRAS_PLATFORM_DIR_X); + this->SetDirty(); + DeleteWindowById(WC_SELECT_STATION, 0); + return ES_HANDLED; + + default: + NOT_REACHED(); + } + + return ES_NOT_HANDLED; + } + + static HotkeyList hotkeys; + /* CityMania code end */ }; +/* CityMania code start */ +static Hotkey build_station_hotkeys[] = { + Hotkey(CM_WKC_MOUSE_MIDDLE, "rotate", (int)BuildRailStationWindow::Hotkey::ROTATE), + HOTKEY_LIST_END +}; +HotkeyList BuildRailStationWindow::hotkeys("cm_build_rail_station", build_station_hotkeys); +/* CityMania code end */ + static const NWidgetPart _nested_station_builder_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), @@ -1729,7 +1747,8 @@ static WindowDesc _station_builder_desc( WDP_AUTO, "build_station_rail", 350, 0, WC_BUILD_STATION, WC_BUILD_TOOLBAR, WDF_CONSTRUCTION, - _nested_station_builder_widgets, lengthof(_nested_station_builder_widgets) + _nested_station_builder_widgets, lengthof(_nested_station_builder_widgets), + &BuildRailStationWindow::hotkeys // CityMania addition ); /** Open station build window */ @@ -1952,7 +1971,15 @@ static void ShowSignalBuilder(Window *parent) new BuildSignalWindow(&_signal_builder_desc, parent); } + struct BuildRailDepotWindow : public PickerWindowBase { +/* CityMania code start */ +public: + enum class Hotkey : int { + ROTATE, + }; +/* CityMania code end */ + BuildRailDepotWindow(WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) { this->InitNested(TRANSPORT_RAIL); @@ -1999,8 +2026,43 @@ struct BuildRailDepotWindow : public PickerWindowBase { break; } } + + /* CityMania code start */ + EventState OnHotkey(int hotkey) override + { + switch ((BuildRailDepotWindow::Hotkey)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 BuildRailDepotWindow::Hotkey::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: + NOT_REACHED(); + } + + return ES_NOT_HANDLED; + } + + static HotkeyList hotkeys; + /* CityMania code end */ }; +/* CityMania code start */ +static Hotkey build_depot_hotkeys[] = { + Hotkey(CM_WKC_MOUSE_MIDDLE, "rotate", (int)BuildRailDepotWindow::Hotkey::ROTATE), + HOTKEY_LIST_END +}; +HotkeyList BuildRailDepotWindow::hotkeys("cm_build_rail_depot", build_depot_hotkeys); +/* CityMania code end */ + /** Nested widget definition of the build rail depot window */ static const NWidgetPart _nested_build_depot_widgets[] = { NWidget(NWID_HORIZONTAL), @@ -2042,7 +2104,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 // CityMania addition ); static void ShowBuildTrainDepotPicker(Window *parent) diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index 193de584c1..5c4f76c9bf 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -370,7 +370,8 @@ static void QZ_MouseMovedEvent(int x, int y) } -static void QZ_MouseButtonEvent(int button, BOOL down) +static void +QZ_MouseButtonEvent(int button, BOOL down) { switch (button) { case 0: @@ -392,6 +393,18 @@ static void QZ_MouseButtonEvent(int button, BOOL down) } HandleMouseEvents(); break; + + case 2: + HandleKeypress(CM_WKC_MOUSE_MIDDLE, 0); + break; + + default: { + int button = CM_WKC_MOUSE_OTHER_START + ev.button.button - 3; + if (!down && button >= CM_WKC_MOUSE_OTHER_START && button < CM_WKC_MOUSE_OTHER_END) { + HandleKeypress(button, 0); + } + break + } } } @@ -501,11 +514,11 @@ static bool QZ_PollEvent() QZ_MouseButtonEvent(1, NO); break; -#if 0 +// #if 0 CityMania uses this! /* This is not needed since openttd currently only use two buttons */ case NSOtherMouseDown: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { + pt = _cocoa_subdriver->GetMouseLocation(event); + if (!_cocoa_subdriver->MouseIsInsideView(&pt)) { [ NSApp sendEvent:event ]; break; } @@ -515,8 +528,8 @@ static bool QZ_PollEvent() break; case NSOtherMouseUp: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { + pt = _cocoa_subdriver->GetMouseLocation(event); + if (!_cocoa_subdriver->MouseIsInsideView(&pt)) { [ NSApp sendEvent:event ]; break; } @@ -524,7 +537,7 @@ static bool QZ_PollEvent() QZ_MouseMovedEvent((int)pt.x, (int)pt.y); QZ_MouseButtonEvent([ event buttonNumber ], NO); break; -#endif +// #endif case NSKeyDown: { /* Quit, hide and minimize */ diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 8f55734dc8..c95e10d16a 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -524,7 +524,7 @@ int VideoDriver_SDL::PollEvent() break; case SDL_MOUSEBUTTONDOWN: - if (_rightclick_emulate && SDL_GetModState() & KMOD_CTRL) { + if (_rightclick_emulate && (SDL_GetModState() & KMOD_CTRL) && ev.button.button == SDL_BUTTON_LEFT) { ev.button.button = SDL_BUTTON_RIGHT; } @@ -544,6 +544,17 @@ int VideoDriver_SDL::PollEvent() break; case SDL_MOUSEBUTTONUP: + if (ev.button.button == SDL_BUTTON_MIDDLE) { + HandleKeypress(CM_WKC_MOUSE_MIDDLE, 0); + break; + } else if (ev.button.button > SDL_BUTTON_RIGHT) { + int button = CM_WKC_MOUSE_OTHER_START + ev.button.button - 4; + if (button >= CM_WKC_MOUSE_OTHER_START && button < CM_WKC_MOUSE_OTHER_END) { + HandleKeypress(button, 0); + } + break; + } + if (_rightclick_emulate) { _right_button_down = false; _left_button_down = false; diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp index 50ff5ff101..330c477662 100644 --- a/src/video/sdl_v.cpp +++ b/src/video/sdl_v.cpp @@ -27,7 +27,7 @@ #include #include -#include "../../citymania/cm_hotkeys.hpp" +#include "../citymania/cm_hotkeys.hpp" #include "../safeguards.h" @@ -527,7 +527,7 @@ int VideoDriver_SDL::PollEvent() break; case SDL_MOUSEBUTTONDOWN: - if (_rightclick_emulate && SDL_GetModState() & KMOD_CTRL) { + if (_rightclick_emulate && (SDL_GetModState() & KMOD_CTRL) && ev.button.button == SDL_BUTTON_LEFT) { ev.button.button = SDL_BUTTON_RIGHT; } @@ -550,6 +550,17 @@ int VideoDriver_SDL::PollEvent() break; case SDL_MOUSEBUTTONUP: + if (ev.button.button == SDL_BUTTON_MIDDLE) { + HandleKeypress(CM_WKC_MOUSE_MIDDLE, 0); + break; + } else if (ev.button.button > SDL_BUTTON_WHEELDOWN) { + int button = CM_WKC_MOUSE_OTHER_START + ev.button.button - 4; + if (button >= CM_WKC_MOUSE_OTHER_START && button < CM_WKC_MOUSE_OTHER_END) { + HandleKeypress(button, 0); + } + break; + } + if (_rightclick_emulate) { _right_button_down = false; _left_button_down = false; diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 037dfc6ebc..4d175b4923 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -715,6 +715,22 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP HandleMouseEvents(); return 0; + /* CityMania code start */ + case WM_MBUTTONUP: + ReleaseCapture(); + HandleKeypress(CM_WKC_MOUSE_MIDDLE); + return 0; + + case WM_XBUTTONUP: { + ReleaseCapture(); + int button = CM_WKC_MOUSE_OTHER_START + ev.button.button - 1; + if (button >= CM_WKC_MOUSE_OTHER_START && button < CM_WKC_MOUSE_OTHER_END) { + HandleKeypress(button, 0); + } + return 0; + } + /* CityMania code end */ + case WM_MOUSELEAVE: UndrawMouseCursor(); _cursor.in_window = false; diff --git a/src/viewport.cpp b/src/viewport.cpp index 4be4fdc4d0..21383150bf 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1831,32 +1831,6 @@ void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom _vd.child_screen_sprites_to_draw.clear(); } -/** - * Make sure we don't draw a too big area at a time. - * If we do, the sprite memory will overflow. - */ -static void ViewportDrawChk(const ViewPort *vp, int left, int top, int right, int bottom) -{ - if ((int64)ScaleByZoom(bottom - top, vp->zoom) * (int64)ScaleByZoom(right - left, vp->zoom) > (int64)(180000 * ZOOM_LVL_BASE * ZOOM_LVL_BASE)) { - if ((bottom - top) > (right - left)) { - int t = (top + bottom) >> 1; - ViewportDrawChk(vp, left, top, right, t); - ViewportDrawChk(vp, left, t, right, bottom); - } else { - int t = (left + right) >> 1; - ViewportDrawChk(vp, left, top, t, bottom); - ViewportDrawChk(vp, t, top, right, bottom); - } - } else { - ViewportDoDraw(vp, - ScaleByZoom(left - vp->left, vp->zoom) + vp->virtual_left, - ScaleByZoom(top - vp->top, vp->zoom) + vp->virtual_top, - ScaleByZoom(right - vp->left, vp->zoom) + vp->virtual_left, - ScaleByZoom(bottom - vp->top, vp->zoom) + vp->virtual_top - ); - } -} - static inline void ViewportDraw(const ViewPort *vp, int left, int top, int right, int bottom) { if (right <= vp->left || bottom <= vp->top) return; @@ -1871,7 +1845,12 @@ static inline void ViewportDraw(const ViewPort *vp, int left, int top, int right if (top < vp->top) top = vp->top; if (bottom > vp->top + vp->height) bottom = vp->top + vp->height; - ViewportDrawChk(vp, left, top, right, bottom); + ViewportDoDraw(vp, + ScaleByZoom(left - vp->left, vp->zoom) + vp->virtual_left, + ScaleByZoom(top - vp->top, vp->zoom) + vp->virtual_top, + ScaleByZoom(right - vp->left, vp->zoom) + vp->virtual_left, + ScaleByZoom(bottom - vp->top, vp->zoom) + vp->virtual_top + ); } /** 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; + } }