From e993c704ef07b8c0160ecc2d4a6d095aa4ca1b88 Mon Sep 17 00:00:00 2001 From: dP Date: Tue, 19 Nov 2024 19:51:19 +0500 Subject: [PATCH] Implement dock building preview --- src/citymania/cm_highlight.cpp | 42 +++++++++++++++++ src/citymania/cm_highlight_type.hpp | 13 +++++ src/citymania/cm_station_gui.cpp | 73 +++++++++++++++++++++++++++++ src/citymania/cm_station_gui.hpp | 19 +++++++- src/dock_gui.cpp | 6 ++- 5 files changed, 151 insertions(+), 2 deletions(-) diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index e5b69731..3df78790 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -138,6 +138,12 @@ struct std::hash { h ^= hash()(oh.u.road.depot.ddir); h ^= hash()(oh.u.road.depot.roadtype); break; + case citymania::ObjectTileHighlight::Type::DOCK_SLOPE: + h ^= hash()(oh.u.dock_slope.ddir); + break; + case citymania::ObjectTileHighlight::Type::DOCK_FLAT: + h ^= hash()(oh.u.dock_flat.axis); + break; case citymania::ObjectTileHighlight::Type::AIRPORT_TILE: h ^= hash()(oh.u.airport_tile.gfx); break; @@ -267,6 +273,18 @@ ObjectTileHighlight ObjectTileHighlight::make_road_depot(SpriteID palette, RoadT return oh; } +ObjectTileHighlight ObjectTileHighlight::make_dock_slope(SpriteID palette, DiagDirection ddir) { + auto oh = ObjectTileHighlight(Type::DOCK_SLOPE, palette); + oh.u.dock_slope.ddir = ddir; + return oh; +} + +ObjectTileHighlight ObjectTileHighlight::make_dock_flat(SpriteID palette, Axis axis) { + auto oh = ObjectTileHighlight(Type::DOCK_FLAT, palette); + oh.u.dock_flat.axis = axis; + return oh; +} + ObjectTileHighlight ObjectTileHighlight::make_airport_tile(SpriteID palette, StationGfx gfx) { auto oh = ObjectTileHighlight(Type::AIRPORT_TILE, palette); oh.u.airport_tile.gfx = gfx; @@ -354,6 +372,10 @@ bool ObjectTileHighlight::operator==(const ObjectTileHighlight &oh) const { return this->u.numbered_rect.number == oh.u.numbered_rect.number; case Type::BORDER: return this->u.border == oh.u.border; + case ObjectTileHighlight::Type::DOCK_SLOPE: + return this->u.dock_slope.ddir == oh.u.dock_slope.ddir; + case ObjectTileHighlight::Type::DOCK_FLAT: + return this->u.dock_flat.axis == oh.u.dock_flat.axis; case Type::POINT: case Type::RECT: case Type::END: @@ -376,6 +398,8 @@ bool ObjectTileHighlight::SetTileHighlight(TileHighlight &th, const TileInfo *) case ObjectTileHighlight::Type::ROAD_DEPOT: case ObjectTileHighlight::Type::AIRPORT_TILE: case ObjectTileHighlight::Type::INDUSTRY_TILE: + case ObjectTileHighlight::Type::DOCK_SLOPE: + case ObjectTileHighlight::Type::DOCK_FLAT: th.structure_pal = CM_PALETTE_HIDE_SPRITE; th.highlight_ground_pal = th.highlight_structure_pal = this->palette; return true; @@ -993,6 +1017,18 @@ void DrawRoadStop(SpriteID palette, const TileInfo *ti, RoadType roadtype, DiagD // DrawRoadCatenary(ti); } +void DrawDockSlope(SpriteID palette, const TileInfo *ti, DiagDirection ddir) { + uint image = (uint)ddir; + const DrawTileSprites *t = GetStationTileLayout(STATION_DOCK, image); + DrawRailTileSeq(ti, t, TO_INVALID, 0, 0, palette); +} + +void DrawDockFlat(SpriteID palette, const TileInfo *ti, Axis axis) { + uint image = GFX_DOCK_BASE_WATER_PART + (uint)axis; + const DrawTileSprites *t = GetStationTileLayout(STATION_DOCK, image); + DrawRailTileSeq(ti, t, TO_INVALID, 0, 0, palette); +} + struct DrawRoadTileStruct { uint16 image; @@ -1491,6 +1527,12 @@ static void DrawObjectTileHighlight(const TileInfo *ti, const ObjectTileHighligh case ObjectTileHighlight::Type::ROAD_DEPOT: DrawRoadDepot(oth.palette, ti, oth.u.road.depot.roadtype, oth.u.road.depot.ddir); break; + case ObjectTileHighlight::Type::DOCK_SLOPE: + DrawDockSlope(oth.palette, ti, oth.u.dock_slope.ddir); + break; + case ObjectTileHighlight::Type::DOCK_FLAT: + DrawDockFlat(oth.palette, ti, oth.u.dock_flat.axis); + break; case ObjectTileHighlight::Type::AIRPORT_TILE: DrawAirportTile(oth.palette, ti, oth.u.airport_tile.gfx); break; diff --git a/src/citymania/cm_highlight_type.hpp b/src/citymania/cm_highlight_type.hpp index 34ed8f1f..65884e28 100644 --- a/src/citymania/cm_highlight_type.hpp +++ b/src/citymania/cm_highlight_type.hpp @@ -98,6 +98,8 @@ class ObjectTileHighlight { RAIL_TUNNEL_HEAD, ROAD_STOP, ROAD_DEPOT, + DOCK_SLOPE, + DOCK_FLAT, AIRPORT_TILE, INDUSTRY_TILE, @@ -162,6 +164,12 @@ class ObjectTileHighlight { struct { uint32 number; } numbered_rect; + struct { + DiagDirection ddir; + } dock_slope; + struct { + Axis axis; + } dock_flat; ZoningBorder border; } u; @@ -176,7 +184,12 @@ class ObjectTileHighlight { static ObjectTileHighlight make_road_stop(SpriteID palette, RoadType roadtype, DiagDirection ddir, bool is_truck, RoadStopClassID spec_class, uint16_t spec_index); static ObjectTileHighlight make_road_depot(SpriteID palette, RoadType roadtype, DiagDirection ddir); + + static ObjectTileHighlight make_dock_slope(SpriteID palette, DiagDirection ddir); + static ObjectTileHighlight make_dock_flat(SpriteID palette, Axis axis); + static ObjectTileHighlight make_airport_tile(SpriteID palette, StationGfx gfx); + static ObjectTileHighlight make_industry_tile(SpriteID palette, IndustryType ind_type, byte ind_layout, TileIndexDiff tile_diff, IndustryGfx gfx); static ObjectTileHighlight make_point(SpriteID palette); static ObjectTileHighlight make_rect(SpriteID palette); diff --git a/src/citymania/cm_station_gui.cpp b/src/citymania/cm_station_gui.cpp index 71f3d20c..f9787d97 100644 --- a/src/citymania/cm_station_gui.cpp +++ b/src/citymania/cm_station_gui.cpp @@ -910,6 +910,79 @@ OverlayParams RoadStationPreview::GetOverlayParams() const { }; } +bool DockPreview::IsDragDrop() const { + return false; +} + +CursorID DockPreview::GetCursor() const { + return SPR_CURSOR_DOCK; +} + +TileArea DockPreview::GetArea(bool /* remove_mode */) const { + auto tile = this->GetStartTile(); + TileIndex tile_to = (this->ddir != INVALID_DIAGDIR ? TileAddByDiagDir(tile, ReverseDiagDir(this->ddir)) : tile); + return {tile, tile_to}; +} + +void DockPreview::Update(Point pt, TileIndex tile) { + if (pt.x == -1) return; + this->ddir = GetInclinedSlopeDirection(GetTileSlope(tile)); + if (this->ddir == INVALID_DIAGDIR) this->ddir = DIAGDIR_NE; + else this->ddir = ReverseDiagDir(this->ddir); +} + +up DockPreview::GetCommand(bool adjacent, StationID join_to) const { + // STR_ERROR_CAN_T_BUILD_DOCK_HERE + return make_up( + this->GetStartTile(), + join_to, + adjacent + ); +} + +up DockPreview::GetRemoveCommand() const { + return nullptr; +} + +bool DockPreview::Execute(up cmd, bool remove_mode) const { + cmd->post(&CcBuildDocks); +} + +void DockPreview::AddPreviewTiles(Preview::TileMap &tiles, SpriteID palette) const { + auto t = this->GetStartTile(); + tiles[t].push_back(ObjectTileHighlight::make_dock_slope(CM_PALETTE_TINT_WHITE, this->ddir)); + t += TileOffsByDiagDir(this->ddir); + tiles[t].push_back(ObjectTileHighlight::make_dock_flat(CM_PALETTE_TINT_WHITE, DiagDirToAxis(this->ddir))); + // TODO + // auto cmd = this->GetCommand(true, NEW_STATION); + // auto cmdt = dynamic_cast(cmd.get()); + // if (cmdt == nullptr) return; + + // if (palette == PAL_NONE) palette = cmd->test().Succeeded() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP; + + // for (TileIndex t : this->GetArea(false)) { + // auto ddir = cmdt->ddir; + // if (cmdt->is_drive_through) ddir = ddir + DIAGDIR_END; + // tiles[t].push_back(ObjectTileHighlight::make_road_stop( + // palette, + // cmdt->rt, + // ddir, + // cmdt->stop_type == ROADSTOP_TRUCK, + // cmdt->spec_class, + // cmdt->spec_index + // )); + // } +} + +OverlayParams DockPreview::GetOverlayParams() const { + return { + this->GetArea(false), + CA_DOCK, + SCT_ALL + }; +} + + void StationPreviewBase::AddAreaTiles(Preview::TileMap &tiles, bool add_current, bool show_join_area) { Station *st_join = Station::GetIfValid(this->station_to_join); std::set join_area; diff --git a/src/citymania/cm_station_gui.hpp b/src/citymania/cm_station_gui.hpp index 65da74a6..2443905e 100644 --- a/src/citymania/cm_station_gui.hpp +++ b/src/citymania/cm_station_gui.hpp @@ -111,7 +111,6 @@ class RoadStationPreview : public PreviewStationType { RoadStationPreview(RoadStopType stop_type) :stop_type{stop_type} {} virtual ~RoadStationPreview() {}; - // RailPreviewStation(RailStationGUISettings &settings) :settings{settings} {} bool IsDragDrop() const override; CursorID GetCursor() const override; TileArea GetArea(bool remove_mode) const override; @@ -123,6 +122,24 @@ class RoadStationPreview : public PreviewStationType { OverlayParams GetOverlayParams() const override; }; +class DockPreview : public PreviewStationType { +protected: + DiagDirection ddir; + +public: + DockPreview() {} + virtual ~DockPreview() {}; + + bool IsDragDrop() const override; + CursorID GetCursor() const override; + TileArea GetArea(bool remove_mode) const override; + void Update(Point pt, TileIndex tile) override; + up GetCommand(bool adjacent, StationID join_to) const override; + up GetRemoveCommand() const override; + void AddPreviewTiles(Preview::TileMap &tiles, SpriteID palette) const override; + bool Execute(up cmd, bool remove_mode) const override; + OverlayParams GetOverlayParams() const override; +}; class StationPreviewBase : public Preview { protected: diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index f8552e5e..428c62e7 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -171,7 +171,11 @@ struct BuildDocksToolbarWindow : Window { break; case WID_DT_STATION: // Build station button - if (HandlePlacePushButton(this, WID_DT_STATION, SPR_CURSOR_DOCK, HT_SPECIAL, CM_DDSP_BUILD_DOCK)) ShowBuildDockStationPicker(this); + // if (HandlePlacePushButton(this, WID_DT_STATION, SPR_CURSOR_DOCK, HT_SPECIAL, CM_DDSP_BUILD_DOCK)) ShowBuildDockStationPicker(this); + if (citymania::HandleStationPlacePushButton(this, WID_DT_STATION, std::make_shared())) { + ShowBuildDockStationPicker(this); + } + break; case WID_DT_BUOY: // Build buoy button