diff --git a/cm_changelog.txt b/cm_changelog.txt index b6c7eb0131..ea40f78d54 100644 --- a/cm_changelog.txt +++ b/cm_changelog.txt @@ -73,6 +73,16 @@ This is usable for any OpenTTD servers == CHANGELOG == +*** 14.1 *** +- Fixed polyrail endpoint update when removing rail. +- Fixed industry blinking rate on minimap. +- Fixed APM and average APM counters. +- Fixed cargo ID in industry chains window and make it use newgrf_developer_tools setting. +- Reimplemented all station building tools hopefully fixing all the old bugs. +- Made industries on the minimap blink with color similar to the industry colour instead of just white. +- Added settings to configure modifier keys for depot orders. +- Added no unload option to station order modifier hotkey actions. + *** 14.0 *** - Fixed graphs with cargo selection. - Fixed measurement tooltips. diff --git a/src/citymania/cm_blueprint.cpp b/src/citymania/cm_blueprint.cpp index 438b6ddbc1..85559ec89f 100644 --- a/src/citymania/cm_blueprint.cpp +++ b/src/citymania/cm_blueprint.cpp @@ -4,13 +4,14 @@ #include "cm_commands.hpp" #include "cm_highlight.hpp" +#include "cm_station_gui.hpp" // RailStationGUISettings, IterateStation #include "../console_func.h" #include "../command_func.h" #include "../error.h" #include "../debug.h" #include "../direction_type.h" -#include "../map_func.h" + #include "../rail_map.h" #include "../station_cmd.h" #include "../station_map.h" @@ -27,12 +28,6 @@ extern TileHighlightData _thd; extern RailType _cur_railtype; -// from rail_gui.cpp -struct StationPickerSelection { - StationClassID sel_class; ///< Selected station class. - uint16_t sel_type; ///< Selected station type within the class. - Axis axis; ///< Selected orientation of the station. -}; extern StationPickerSelection _station_gui; ///< Settings of the station picker. namespace citymania { @@ -55,22 +50,6 @@ bool operator!=(const TileIndexDiffC &a, const TileIndexDiffC &b) { return a.x != b.x || a.y != b.y; } -template -void IterateStation(TileIndex start_tile, Axis axis, uint8_t numtracks, uint8_t plat_len, Func visitor) { - auto plat_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); - auto track_delta = (axis == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); - TileIndex tile_track = start_tile; - do { - TileIndex tile = tile_track; - int w = plat_len; - do { - visitor(tile); - tile += plat_delta; - } while (--w); - tile_track += track_delta; - } while (--numtracks); -} - void Blueprint::Add(TileIndex source_tile, Blueprint::Item item) { this->items.push_back(item); switch (item.type) { @@ -85,7 +64,7 @@ void Blueprint::Add(TileIndex source_tile, Blueprint::Item item) { } case Item::Type::RAIL_STATION_PART: IterateStation(source_tile, item.u.rail.station_part.axis, item.u.rail.station_part.numtracks, item.u.rail.station_part.plat_len, - [&](TileIndex tile) { + [&](TileIndex tile, int, int) { this->source_tiles.insert(tile); } ); @@ -257,12 +236,14 @@ std::multimap Blueprint::GetTiles(TileIndex tile case Item::Type::RAIL_STATION_PART: { RailStationTileLayout stl{nullptr, o.u.rail.station_part.numtracks, o.u.rail.station_part.plat_len}; // TODO statspec auto it = stl.begin(); + TileArea area{tile, o.u.rail.station_part.numtracks, o.u.rail.station_part.plat_len}; + if (o.u.rail.station_part.axis == AXIS_X) std::swap(area.w, area.h); if (palette == CM_PALETTE_TINT_WHITE && can_build_station_sign.find(o.u.rail.station_part.id) == can_build_station_sign.end()) palette = CM_PALETTE_TINT_ORANGE_DEEP; IterateStation(otile, o.u.rail.station_part.axis, o.u.rail.station_part.numtracks, o.u.rail.station_part.plat_len, - [&](TileIndex tile) { - add_tile(tile, ObjectTileHighlight::make_rail_station(palette, o.u.rail.station_part.axis, *it++)); + [&](TileIndex tile, int, int) { + add_tile(tile, ObjectTileHighlight::make_rail_station(palette, o.u.rail.station_part.axis, *it++, STAT_CLASS_DFLT, 0, area)); } ); break; diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index d0254f3b8f..2ce17d3d09 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -19,6 +19,7 @@ #include "../industry.h" #include "../landscape.h" #include "../newgrf_airporttiles.h" +#include "../newgrf_cargo.h" // SpriteGroupCargo #include "../newgrf_railtype.h" #include "../newgrf_roadtype.h" #include "../newgrf_station.h" @@ -79,20 +80,8 @@ extern IndustryType _cm_funding_type; extern void IndustryDrawTileLayout(const TileInfo *ti, const DrawTileSpriteSpan &dts, Colours rnd_colour, uint8_t stage); extern void SetSelectionTilesDirty(); -struct RoadStopPickerSelection { - RoadStopClassID sel_class; ///< Selected road stop class. - uint16_t sel_type; ///< Selected road stop type within the class. - DiagDirection orientation; ///< Selected orientation of the road stop. -}; - -extern RoadStopPickerSelection _roadstop_gui; - -struct StationPickerSelection { - StationClassID sel_class; ///< Selected station class. - uint16_t sel_type; ///< Selected station type within the class. - Axis axis; ///< Selected orientation of the station. -}; extern StationPickerSelection _station_gui; ///< Settings of the station picker. +extern RoadStopPickerSelection _roadstop_gui; template <> struct std::hash { @@ -220,10 +209,15 @@ ObjectTileHighlight ObjectTileHighlight::make_rail_track(SpriteID palette, Track return oh; } -ObjectTileHighlight ObjectTileHighlight::make_rail_station(SpriteID palette, Axis axis, uint8_t section) { +ObjectTileHighlight ObjectTileHighlight::make_rail_station(SpriteID palette, Axis axis, uint8_t section, StationClassID spec_class, uint16_t spec_index, TileArea whole_area) { auto oh = ObjectTileHighlight(Type::RAIL_STATION, palette); oh.u.rail.station.axis = axis; oh.u.rail.station.section = section; + oh.u.rail.station.spec_class = spec_class; + oh.u.rail.station.spec_index = spec_index; + oh.u.rail.station.base_tile = whole_area.tile.base(); + oh.u.rail.station.w = whole_area.w; + oh.u.rail.station.h = whole_area.h; return oh; } @@ -333,7 +327,12 @@ bool ObjectTileHighlight::operator==(const ObjectTileHighlight &oh) const { return this->u.rail.track == oh.u.rail.track; case ObjectTileHighlight::Type::RAIL_STATION: return this->u.rail.station.axis == oh.u.rail.station.axis - && this->u.rail.station.section == oh.u.rail.station.section; + && this->u.rail.station.section == oh.u.rail.station.section + && this->u.rail.station.spec_class == oh.u.rail.station.spec_class + && this->u.rail.station.spec_index == oh.u.rail.station.spec_index + && this->u.rail.station.base_tile == oh.u.rail.station.base_tile + && this->u.rail.station.w == oh.u.rail.station.w + && this->u.rail.station.h == oh.u.rail.station.h; case ObjectTileHighlight::Type::RAIL_SIGNAL: return this->u.rail.signal.pos == oh.u.rail.signal.pos && this->u.rail.signal.type == oh.u.rail.signal.type @@ -438,11 +437,13 @@ ObjectHighlight ObjectHighlight::make_rail_depot(TileIndex tile, DiagDirection d return oh; } -ObjectHighlight ObjectHighlight::make_rail_station(TileIndex start_tile, TileIndex end_tile, Axis axis) { +ObjectHighlight ObjectHighlight::make_rail_station(TileIndex start_tile, TileIndex end_tile, Axis axis, StationClassID station_class, uint16_t station_type) { auto oh = ObjectHighlight{ObjectHighlight::Type::RAIL_STATION}; oh.tile = start_tile; oh.end_tile = end_tile; oh.axis = axis; + oh.rail_station_class = station_class; + oh.rail_station_type = station_type; return oh; } @@ -542,6 +543,48 @@ void ObjectHighlight::AddTile(TileIndex tile, ObjectTileHighlight &&oh) { this->tiles.insert(std::make_pair(tile, std::move(oh))); } +uint16_t GetPreviewStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, TileIndex tile, TileArea area, StationGfx gfx, Axis axis); +uint16_t GetPurchaseStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, TileIndex tile, TileArea area); + +std::map, std::vector> _station_layout_cache; +std::vector &GetPreviewStationLayout(const StationSpec *statspec, Axis axis, TileArea area) { + std::tuple key{statspec, axis, area.tile, area.w, area.h}; + auto it = _station_layout_cache.find(key); + if (it != _station_layout_cache.end()) return it->second; + uint8_t numtracks = area.w; + uint8_t plat_len = area.h; + if (axis == AXIS_X) std::swap(numtracks, plat_len); + + + // std::vector res_layout(numtracks * plat_len); + it = _station_layout_cache.insert(it, {key, std::vector(area.w * area.h)}); + auto &res_layout = it->second; + + RailStationTileLayout stl{statspec, numtracks, plat_len}; + auto sit = stl.begin(); + IterateStation(area.tile, axis, numtracks, plat_len, + [&](TileIndex tile, int platform, int position) { + auto gfx = *sit++ + axis; + + if (statspec != nullptr) { + /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */ + uint32_t platinfo = GetPlatformInfo(AXIS_X, gfx, plat_len, numtracks, position, platform, false); + + /* As the station is not yet completely finished, the station does not yet exist. */ + uint16_t callback = GetPurchaseStationCallback(CBID_STATION_BUILD_TILE_LAYOUT, platinfo, 0, statspec, tile, area); + if (callback != CALLBACK_FAILED && callback < 8) { + gfx = (callback & -1) + axis; + } + } + + auto diff = TileIndexToTileIndexDiffC(tile, area.tile); + res_layout[diff.y * area.w + diff.x] = gfx; + } + ); + + return res_layout; +} + void ObjectHighlight::UpdateTiles() { this->tiles.clear(); this->sprites.clear(); @@ -581,27 +624,26 @@ void ObjectHighlight::UpdateTiles() { this->axis, numtracks, plat_len, - _station_gui.sel_class, - _station_gui.sel_type, + this->rail_station_class, + this->rail_station_type, NEW_STATION, true ).test(); auto palette = (this->cost.Succeeded() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP); - RailStationTileLayout stl{nullptr, numtracks, plat_len}; // TODO statspec - auto it = stl.begin(); - - auto tile_delta = (this->axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); - TileIndex tile_track = this->tile; - do { - TileIndex tile = tile_track; - int w = plat_len; - do { - this->AddTile(tile, ObjectTileHighlight::make_rail_station(palette, this->axis, *it++)); - tile += tile_delta; - } while (--w); - tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta - } while (--numtracks); + const StationSpec *statspec = StationClass::Get(this->rail_station_class)->GetSpec(this->rail_station_type); + auto layout = GetPreviewStationLayout(statspec, this->axis, ta); + auto it = layout.begin(); + for (auto tile : ta) { + this->AddTile(tile, ObjectTileHighlight::make_rail_station( + palette, + this->axis, + *it++, + this->rail_station_class, + this->rail_station_type, + ta + )); + } break; } @@ -997,87 +1039,325 @@ void DrawTrainDepotSprite(SpriteID palette, const TileInfo *ti, RailType railtyp DrawRailTileSeq(ti, dts, TO_INVALID, offset, 0, palette); } -void DrawTrainStationSprite(SpriteID palette, const TileInfo *ti, RailType railtype, Axis axis, uint8_t section) { +void AddGroundAsSortableSprite(const TileInfo *ti, SpriteID image, PaletteID pal /*, const SubSprite *sub = nullptr, int extra_offs_x = 0, int extra_offs_y = 0 */) { + AddSortableSpriteToDraw(image, pal, *ti, {{}, {1, 1, BB_HEIGHT_UNDER_BRIDGE}, {}}); +} + +struct PreviewStationScopeResolver : public StationScopeResolver { + TileArea area; + StationGfx gfx; + Axis axis; + bool purchase; // Running in purchase mode (fake vars) + + PreviewStationScopeResolver(ResolverObject &ro, const StationSpec *statspec, TileIndex tile, TileArea area, StationGfx gfx, Axis axis, bool purchase) + : StationScopeResolver(ro, statspec, nullptr, tile), area{area}, gfx{gfx}, axis{axis}, purchase{purchase} {} + + uint32_t GetRandomBits() const override { return 574740206; /* It's random, I promise ;) */ }; + uint32_t GetRandomTriggers() const override { return 0; }; + + TileIndex FindRailStationEnd(TileIndex tile, TileIndexDiff delta, bool check_type, bool check_axis) const + { + for (;;) { + TileIndex new_tile = TileAdd(tile, delta); + if (!this->area.Contains(new_tile)) { + // Only run checks for tiles outside preview area + // TODO check station index + // if (!IsTileType(new_tile, MP_STATION) || GetStationIndex(new_tile) != sid) break; + if (!IsTileType(new_tile, MP_STATION)) break; + if (!HasStationRail(new_tile)) break; + if (check_type && GetStationSpec(new_tile) != this->statspec) break; + if (check_axis && GetRailStationAxis(new_tile) != this->axis) break; + } + + tile = new_tile; + } + return tile; + } + + uint32_t GetPlatformInfoHelper(bool check_type, bool check_axis, bool centred) const { + int tx = TileX(this->tile); + int ty = TileY(this->tile); + int sx = TileX(this->FindRailStationEnd(this->tile, TileDiffXY(-1, 0), check_type, check_axis)); + int sy = TileY(this->FindRailStationEnd(this->tile, TileDiffXY( 0, -1), check_type, check_axis)); + int ex = TileX(this->FindRailStationEnd(this->tile, TileDiffXY( 1, 0), check_type, check_axis)) + 1; + int ey = TileY(this->FindRailStationEnd(this->tile, TileDiffXY( 0, 1), check_type, check_axis)) + 1; + + tx -= sx; ex -= sx; + ty -= sy; ey -= sy; + + // Debug(misc, 0, "GetPlatformInfoHelper ofs = {},{} t = {},{} e = {},{}", + // TileX(this->tile) - TileX(this->area.tile), + // TileY(this->tile) - TileY(this->area.tile), + // tx, ty, + // ex, ey + // ); + + return GetPlatformInfo(this->axis, this->gfx, ex, ey, tx, ty, centred); + } + + uint32_t GetVariable(uint8_t variable, uint32_t parameter, bool &available) const override { + // Debug(misc, 0, "Var {:x}({}) requested", variable, parameter); + + if (this->purchase) { + // Don't try to be smart with faking wars, we actually need the dumb way. + return StationScopeResolver::GetVariable(variable, parameter, available); + } + + switch (variable) { + case 0x40: return this->GetPlatformInfoHelper(false, false, false); + case 0x41: return this->GetPlatformInfoHelper(true, false, false); + case 0x42: return GetTerrainType(tile) | (GetReverseRailTypeTranslation(_cur_railtype, this->statspec->grf_prop.grffile) << 8); // use current railtype but real tile type + case 0x43: return GetCompanyInfo(_current_company); // Station owner - current company + case 0x44: return 4; // PBS status - no reservation + // case 0x45: return 0; TODO rail continuation info + case 0x46: return this->GetPlatformInfoHelper(false, false, true); + case 0x47: return this->GetPlatformInfoHelper(true, false, true); + case 0x49: return this->GetPlatformInfoHelper(false, true, false); + + case 0x67: { // Land info of nearby tile + auto tile = this->tile; + if (parameter != 0) tile = GetNearbyTile(parameter, tile, true, this->axis); // only perform if it is required + + Slope tileh = GetTileSlope(tile); + bool swap = (this->axis == AXIS_Y && HasBit(tileh, CORNER_W) != HasBit(tileh, CORNER_E)); + + return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8) ^ (swap ? SLOPE_EW : 0); + } + + case 0x68: { // Station info of nearby tiles + TileIndex tile = GetNearbyTile(parameter, this->tile, true, this->axis); + // auto diff = TileIndexToTileIndexDiffC(tile, this->tile); + // Debug(misc, 0, "Var68 tile={},{} area={},{} contains={}", diff.x, diff.y, this->area.w, this->area.h, this->area.Contains(tile)); + if (!this->area.Contains(tile)) return 0xFFFFFFFF; + + // Restore gfx from offset by quirying station layout + auto layout = GetPreviewStationLayout(this->statspec, this->axis, this->area); + auto ofs = TileIndexToTileIndexDiffC(tile, this->area.tile); + auto gfx = layout[ofs.x + ofs.y * this->area.w]; + + bool perpendicular = false; + bool same_station = true; + uint32_t res = GB(gfx, 1, 2) << 12 | !!perpendicular << 11 | !!same_station << 10; + auto local_id = ClampTo(statspec->grf_prop.local_id); + // Debug(misc, 0, "Var68 gfx={} local_id={} ofs={},{} layout={} this->gfx={}", gfx, local_id, ofs.x, ofs.y, ofs.y * this->area.w + ofs.x, this->gfx); + res |= 1 << 8 | local_id; + return res; + } + + case 0xFA: return ClampTo(TimerGameCalendar::date - CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // Build date, clamped to a 16 bit value + } + + available = false; + return UINT_MAX; + } +}; + +struct StationPreivewResolverObject : public StationResolverObject { + PreviewStationScopeResolver preview_station_scope; + TileIndex tile; + TileIndexDiffC offset; + + StationPreivewResolverObject(const StationSpec *statspec, TileIndex tile, TileArea area, StationGfx gfx, Axis axis, bool purchase, + CallbackID callback = CBID_NO_CALLBACK, uint32_t callback_param1 = 0, uint32_t callback_param2 = 0) + : StationResolverObject(statspec, nullptr, tile, callback, callback_param1, callback_param2), + preview_station_scope{*this, statspec, tile, area, gfx, axis, purchase}, + tile{tile}, offset{offset} { + + CargoType ctype = (purchase ? CargoGRFFileProps::SG_PURCHASE : CargoGRFFileProps::SG_DEFAULT_NA); + this->root_spritegroup = statspec->grf_prop.GetSpriteGroup(ctype); + if (!purchase && this->root_spritegroup == nullptr) { + CargoType ctype = CargoGRFFileProps::SG_DEFAULT; + this->root_spritegroup = statspec->grf_prop.GetSpriteGroup(ctype); + } + this->preview_station_scope.cargo_type = this->station_scope.cargo_type = ctype; + } + + ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, uint8_t relative = 0) override + { + switch (scope) { + case VSG_SCOPE_SELF: + return &this->preview_station_scope; + + case VSG_SCOPE_PARENT: { + if (!this->town_scope.has_value()) { + auto t = ClosestTownFromTile(this->tile, UINT_MAX); + this->town_scope.emplace(*this, t, true); + } + return &*this->town_scope; + } + + default: + return ResolverObject::GetScope(scope, relative); + } + } + + const SpriteGroup *ResolveReal(const RealSpriteGroup &group) const override + { + if (!this->preview_station_scope.purchase && !group.loaded.empty()) { + return group.loaded[0]; + } + return group.loading[0]; + } +}; + +uint16_t GetPreviewStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, TileIndex tile, TileArea area, StationGfx gfx, Axis axis) +{ + StationPreivewResolverObject object(statspec, tile, area, gfx, axis, false, callback, param1, param2); + return object.ResolveCallback({}); +} + +uint16_t GetPurchaseStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, TileIndex tile, TileArea area) +{ + StationPreivewResolverObject object(statspec, tile, area, 0, INVALID_AXIS, true, callback, param1, param2); + return object.ResolveCallback({}); +} + +SpriteID GetCustomPreviewStationRelocation(const StationSpec *statspec, uint32_t var10, TileIndex tile, TileArea area, StationGfx gfx, Axis axis) +{ + StationPreivewResolverObject object(statspec, tile, area, gfx, axis, false, CBID_NO_CALLBACK, var10); + const auto *group = object.Resolve(); + if (group == nullptr || group->num_sprites == 0) return 0; + return group->sprite - SPR_RAIL_PLATFORM_Y_FRONT; +} + +void DrawTrainStationSprite(SpriteID palette, const TileInfo *ti, RailType railtype, Axis axis, uint8_t section, StationClassID spec_class, uint16_t spec_index, TileArea area) { int32 total_offset = 0; - const DrawTileSprites *t = GetStationTileLayout(StationType::Rail, section + (axis == AXIS_X ? 0 : 1)); + StationGfx gfx = section + (axis == AXIS_X ? 0 : 1); + const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index); + const NewGRFSpriteLayout *layout = nullptr; + const DrawTileSprites *t = nullptr; const RailTypeInfo *rti = nullptr; + BaseStation *st = nullptr; + + // Debug(misc, 0, "DrawTrainStationSprite {} {} {}", spec_class, spec_index, statspec == nullptr); + + if (statspec != nullptr) { + uint tile_layout = gfx; + if (statspec->callback_mask.Test(StationCallbackMask::DrawTileLayout)) { + uint16_t callback = GetPreviewStationCallback(CBID_STATION_DRAW_TILE_LAYOUT, 0, 0, statspec, ti->tile, area, gfx, axis); + if (callback != CALLBACK_FAILED) tile_layout = (callback & ~1) + axis; + } + + // Debug(misc, 0, "DrawTrainStationSprite layout={}", tile_layout); + + /* Ensure the chosen tile layout is valid for this custom station */ + if (!statspec->renderdata.empty()) { + layout = &statspec->renderdata[tile_layout < statspec->renderdata.size() ? tile_layout : (uint)axis]; + if (!layout->NeedsPreprocessing()) { + t = layout; + layout = nullptr; + } + } + } + + // Debug(misc, 0, "DrawTrainStationSprite get default? {} {} {}", layout == nullptr, t == nullptr, t == nullptr || t->seq == nullptr); + + if (layout == nullptr && (t == nullptr || t->GetSequence().empty())) t = GetStationTileLayout(StationType::Rail, gfx); if (railtype != INVALID_RAILTYPE) { rti = GetRailTypeInfo(railtype); total_offset = rti->GetRailtypeSpriteOffset(); } - DrawAutorailSelection(ti, (axis == AXIS_X ? HT_DIR_X : HT_DIR_Y), GetSelectionColourByTint(palette)); - - // if (roadtype != INVALID_ROADTYPE) { - // const RoadTypeInfo* rti = GetRoadTypeInfo(roadtype); - // if (image >= 4) { - // /* Drive-through stop */ - // uint sprite_offset = 5 - image; - - // /* Road underlay takes precedence over tram */ - // if (rti->UsesOverlay()) { - // SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_GROUND); - // DrawSprite(ground + sprite_offset, PAL_NONE, x, y); - - // SpriteID overlay = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_OVERLAY); - // if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y); - // } else if (RoadTypeIsTram(roadtype)) { - // DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y); - // } - // } else { - // /* Drive-in stop */ - // if (RoadTypeIsRoad(roadtype) && rti->UsesOverlay()) { - // SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_ROADSTOP); - // DrawSprite(ground + image, PAL_NONE, x, y); - // } - // } - // } - - /* Default waypoint has no railtype specific sprites */ - // DrawRailTileSeq(ti, t, TO_INVALID, (st == STATION_WAYPOINT ? 0 : total_offset), 0, PALETTE_TINT_WHITE); - DrawRailTileSeq(ti, t, TO_INVALID, total_offset, 0, palette); -} - -void AddSortableStationSprite(SpriteID sprite, SpriteID palette, const TileInfo *ti) { - AddSortableSpriteToDraw(sprite, palette, *ti, {{}, {1, 1, BB_HEIGHT_UNDER_BRIDGE}, {}}); -} - -void DrawRoadStop(SpriteID palette, const TileInfo *ti, RoadType roadtype, DiagDirection orientation, bool is_truck) { - int32 total_offset = 0; - const RoadTypeInfo* rti = GetRoadTypeInfo(roadtype); - - uint image = (uint)orientation; - if (image >= 4) { - /* Drive-through stop */ - uint sprite_offset = 5 - image; - - /* Road underlay takes precedence over tram */ - if (rti->UsesOverlay()) { - SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_GROUND); - DrawSprite(ground + sprite_offset, PAL_NONE, ti->x, ti->y); - - SpriteID overlay = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_OVERLAY); - // if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y); - if (overlay) AddSortableStationSprite(overlay + sprite_offset, palette, ti); - } else if (RoadTypeIsTram(roadtype)) { - // DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y); - AddSortableStationSprite(SPR_TRAMWAY_TRAM + sprite_offset, palette, ti); + uint32_t ground_relocation = 0; + uint32_t relocation = 0; + DrawTileSpriteSpan tmp_layout; + if (layout != nullptr) { + /* Sprite layout which needs preprocessing */ + bool separate_ground = statspec->flags.Test(StationSpecFlag::SeparateGround); + auto processor = SpriteLayoutProcessor(*layout, total_offset, rti->fallback_railtype, 0, 0, separate_ground); + GetCustomStationRelocation(processor, statspec, st, ti->tile); + tmp_layout = processor.GetLayout(); + t = &tmp_layout; + total_offset = 0; + } else if (statspec != nullptr) { + /* Simple sprite layout */ + ground_relocation = relocation = GetCustomStationRelocation(statspec, st, ti->tile, 0); + if (statspec->flags.Test(StationSpecFlag::SeparateGround)) { + ground_relocation = GetCustomStationRelocation(statspec, st, ti->tile, 1); } - } else { - /* Drive-in stop */ - if (RoadTypeIsRoad(roadtype) && rti->UsesOverlay()) { - SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_ROADSTOP); - // DrawSprite(, PAL_NONE, x, y); - AddSortableStationSprite(ground + image, palette, ti); + if (rti != nullptr) { + ground_relocation += rti->fallback_railtype; } } - const DrawTileSprites *t = GetStationTileLayout(is_truck ? StationType::Truck : StationType::Bus, image); - AddSortableStationSprite(t->ground.sprite, palette, ti); - DrawRailTileSeq(ti, t, TO_INVALID, total_offset, 0, palette); - /* Draw road, tram catenary */ - // DrawRoadCatenary(ti); + // Debug(misc, 0, "DrawTrainStationSprite ground {}", t->ground.sprite); + // const DrawTileSeqStruct *dtss; + // foreach_draw_tile_seq(dtss, t->seq) Debug(misc, 0, " seq {} {}", GB(dtss->image.sprite, 0, SPRITE_WIDTH), HasBit(dtss->image.sprite, CUSTOM_BIT)); + + SpriteID image = t->ground.sprite; + // PaletteID pal = t->ground.pal; + RailTrackOffset overlay_offset; + if (rti != nullptr && rti->UsesOverlay() && SplitGroundSpriteForOverlay(ti, &image, &overlay_offset)) { + SpriteID ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND); + AddGroundAsSortableSprite(ti, image, palette); + AddGroundAsSortableSprite(ti, ground + overlay_offset, palette); + } else { + image += HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE) ? ground_relocation : total_offset; + // if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += ground_relocation; + AddGroundAsSortableSprite(ti, image, palette); + } + + // DrawAutorailSelection(ti, (axis == AXIS_X ? HT_DIR_X : HT_DIR_Y), GetSelectionColourByTint(palette)); + + /* Default waypoint has no railtype specific sprites */ + // DrawRailTileSeq(ti, t, TO_INVALID, (st == STATION_WAYPOINT ? 0 : total_offset), 0, PALETTE_TINT_WHITE); + DrawRailTileSeq(ti, t, TO_INVALID, total_offset, relocation, palette); +} + +void DrawRoadStop(SpriteID palette, const TileInfo *ti, RoadType roadtype, DiagDirection orientation, bool is_truck, RoadStopClassID spec_class, uint16_t spec_index) { + // TODO this is based on preview drawing code, not map one, is it right? + int32 total_offset = 0; + const RoadTypeInfo* rti = GetRoadTypeInfo(roadtype); + const RoadStopSpec *spec = RoadStopClass::Get(spec_class)->GetSpec(spec_index); + uint view = (uint)orientation; + StationType type = (is_truck ? StationType::Truck : StationType::Bus); + + const DrawTileSprites *dts; + if (spec != nullptr) { + RoadStopResolverObject object(spec, nullptr, INVALID_TILE, roadtype, type, view); + const auto *group = object.Resolve(); + if (group == nullptr) return; + auto processor = group->ProcessRegisters(object, nullptr); + auto dts = processor.GetLayout(); + } else { + dts = GetStationTileLayout(type, view); + } + + SpriteID image = dts->ground.sprite; + if (GB(image, 0, SPRITE_WIDTH) != 0) { + AddGroundAsSortableSprite(ti, image, palette); + } + + if (view >= 4) { + /* Drive-through stop */ + uint sprite_offset = 5 - view; + + /* Road underlay takes precedence over tram */ + if (!spec || spec->draw_mode.Test(RoadStopDrawMode::Overlay)) { + if (rti->UsesOverlay()) { + SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_GROUND); + DrawSprite(ground + sprite_offset, PAL_NONE, ti->x, ti->y); + + SpriteID overlay = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_OVERLAY); + // if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y); + if (overlay) AddGroundAsSortableSprite(ti, overlay + sprite_offset, palette); + } else if (RoadTypeIsTram(roadtype)) { + // DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y); + AddGroundAsSortableSprite(ti, SPR_TRAMWAY_TRAM + sprite_offset, palette); + } + } + } else { + /* Bay stop */ + bool draw_mode_road = (spec != nullptr ? spec->draw_mode.Test(RoadStopDrawMode::Road) : RoadTypeIsRoad(roadtype)); + if (draw_mode_road && rti->UsesOverlay()) { + SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_ROADSTOP); + // DrawSprite(, PAL_NONE, x, y); + AddGroundAsSortableSprite(ti, ground + view, palette); + } + } + + DrawRailTileSeq(ti, dts, TO_INVALID, total_offset, 0, palette); } void DrawDockSlope(SpriteID palette, const TileInfo *ti, DiagDirection ddir) { @@ -1144,15 +1424,15 @@ void DrawRoadDepot(SpriteID palette, const TileInfo *ti, RoadType roadtype, Diag } const DrawTileSprites *dts = &_road_depot[orientation]; - AddSortableStationSprite(dts->ground.sprite, palette, ti); + AddGroundAsSortableSprite(ti, dts->ground.sprite, palette); if (default_gfx) { uint offset = GetRoadSpriteOffset(SLOPE_FLAT, DiagDirToRoadBits(orientation)); if (rti->UsesOverlay()) { SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_OVERLAY); - if (ground != 0) AddSortableStationSprite(ground + offset, palette, ti); + if (ground != 0) AddGroundAsSortableSprite(ti, ground + offset, palette); } else if (RoadTypeIsTram(roadtype)) { - AddSortableStationSprite(SPR_TRAMWAY_OVERLAY + offset, palette, ti); + AddGroundAsSortableSprite(ti, SPR_TRAMWAY_OVERLAY + offset, palette); } } @@ -1194,7 +1474,7 @@ void DrawAirportTile(SpriteID palette, const TileInfo *ti, StationGfx gfx) { } if (t == nullptr || t->GetSequence().empty()) t = GetStationTileLayout(StationType::Airport, gfx); if (t) { - AddSortableStationSprite(t->ground.sprite, palette, ti); + AddGroundAsSortableSprite(ti, t->ground.sprite, palette); DrawRailTileSeq(ti, t, TO_INVALID, total_offset, 0, palette); } } @@ -1488,7 +1768,7 @@ void DrawBridgeHead(SpriteID palette, const TileInfo *ti, RailType railtype, Dia if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head psid = &GetBridgeSpriteTable(type, BRIDGE_PIECE_HEAD)[base_offset]; - AddSortableSpriteToDraw(psid->sprite, palette, ti->x, ti->y, ti->z, {{}, {16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8}, {}}); + AddSortableSpriteToDraw(psid->sprite, palette, ti->x, ti->y, ti->z, {{}, {16, 16, (uint8_t)(ti->tileh == SLOPE_FLAT ? 0 : 8)}, {}}); // DrawAutorailSelection(ti, (ddir == DIAGDIR_SW || ddir == DIAGDIR_NE ? HT_DIR_X : HT_DIR_Y), PAL_NONE); } @@ -1599,9 +1879,20 @@ static void DrawObjectTileHighlight(const TileInfo *ti, const ObjectTileHighligh DrawAutorailSelection(ti, (HighLightStyle)oth.u.rail.track, GetSelectionColourByTint(oth.palette)); break; } - case ObjectTileHighlight::Type::RAIL_STATION: - DrawTrainStationSprite(oth.palette, ti, _cur_railtype, oth.u.rail.station.axis, oth.u.rail.station.section); + case ObjectTileHighlight::Type::RAIL_STATION: { + TileArea area{TileIndex(oth.u.rail.station.base_tile), oth.u.rail.station.w, oth.u.rail.station.h}; + DrawTrainStationSprite( + oth.palette, + ti, + _cur_railtype, + oth.u.rail.station.axis, + oth.u.rail.station.section, + oth.u.rail.station.spec_class, + oth.u.rail.station.spec_index, + area + ); break; + } case ObjectTileHighlight::Type::RAIL_SIGNAL: DrawSignal(oth.palette, ti, _cur_railtype, oth.u.rail.signal.pos, oth.u.rail.signal.type, oth.u.rail.signal.variant); break; @@ -1612,7 +1903,7 @@ static void DrawObjectTileHighlight(const TileInfo *ti, const ObjectTileHighligh DrawTunnelHead(oth.palette, ti, _cur_railtype, oth.u.rail.tunnel_head.ddir); break; case ObjectTileHighlight::Type::ROAD_STOP: - DrawRoadStop(oth.palette, ti, oth.u.road.stop.roadtype, oth.u.road.stop.ddir, oth.u.road.stop.is_truck); + DrawRoadStop(oth.palette, ti, oth.u.road.stop.roadtype, oth.u.road.stop.ddir, oth.u.road.stop.is_truck, oth.u.road.stop.spec_class, oth.u.road.stop.spec_index); break; case ObjectTileHighlight::Type::ROAD_DEPOT: DrawRoadDepot(oth.palette, ti, oth.u.road.depot.roadtype, oth.u.road.depot.ddir); @@ -2109,7 +2400,13 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) { std::min((_thd.new_pos.y + _thd.new_size.y) / TILE_SIZE, Map::SizeY()) - 1 ); if (_thd.select_proc == DDSP_BUILD_STATION) - _thd.cm_new = ObjectHighlight::make_rail_station(start_tile, end_tile, _station_gui.axis); + _thd.cm_new = ObjectHighlight::make_rail_station( + start_tile, + end_tile, + _station_gui.axis, + _station_gui.sel_class, + _station_gui.sel_type + ); else if (_thd.select_proc == DDSP_BUILD_BUSSTOP || _thd.select_proc == DDSP_BUILD_TRUCKSTOP) { auto ddir = _roadstop_gui.orientation; auto ta = TileArea(start_tile, end_tile); diff --git a/src/citymania/cm_highlight_type.hpp b/src/citymania/cm_highlight_type.hpp index b9869c2050..0787e49e68 100644 --- a/src/citymania/cm_highlight_type.hpp +++ b/src/citymania/cm_highlight_type.hpp @@ -111,6 +111,11 @@ public: struct { Axis axis; uint8_t section; + StationClassID spec_class; + uint16_t spec_index; + uint32_t base_tile; // TODO should be TileArea but TileIndex can't go into union + uint16_t w; + uint16_t h; } station; struct { uint pos; @@ -164,7 +169,7 @@ public: static ObjectTileHighlight make_rail_depot(SpriteID palette, DiagDirection ddir); static ObjectTileHighlight make_rail_track(SpriteID palette, Track track); - static ObjectTileHighlight make_rail_station(SpriteID palette, Axis axis, uint8_t section); + static ObjectTileHighlight make_rail_station(SpriteID palette, Axis axis, uint8_t section, StationClassID spec_class, uint16_t spec_index, TileArea whole_area); static ObjectTileHighlight make_rail_signal(SpriteID palette, uint pos, SignalType type, SignalVariant variant); static ObjectTileHighlight make_rail_bridge_head(SpriteID palette, DiagDirection ddir, BridgeType type); static ObjectTileHighlight make_rail_tunnel_head(SpriteID palette, DiagDirection ddir); @@ -346,6 +351,8 @@ public: bool is_truck = false; RoadStopClassID road_stop_spec_class; uint16_t road_stop_spec_index; + StationClassID rail_station_class; + uint16_t rail_station_type; int airport_type = 0; uint8_t airport_layout = 0; sp blueprint = nullptr; @@ -370,7 +377,7 @@ public: bool operator!=(const ObjectHighlight& oh) const; 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_rail_station(TileIndex start_tile, TileIndex end_tile, Axis axis, StationClassID station_class, uint16_t station_type); static ObjectHighlight make_road_stop(TileIndex start_tile, TileIndex end_tile, RoadType roadtype, DiagDirection orientation, bool is_truck, RoadStopClassID spec_class, uint16_t spec_index); static ObjectHighlight make_road_depot(TileIndex tile, RoadType roadtype, DiagDirection orientation); static ObjectHighlight make_airport(TileIndex start_tile, int airport_type, uint8_t airport_layout); @@ -412,7 +419,7 @@ public: class Tool { protected: - up action = nullptr; + sp action = nullptr; public: virtual ~Tool() = default; virtual void Update(Point pt, TileIndex tile) = 0; diff --git a/src/citymania/cm_hotkeys.cpp b/src/citymania/cm_hotkeys.cpp index ed6767cfc2..799d2baf3c 100644 --- a/src/citymania/cm_hotkeys.cpp +++ b/src/citymania/cm_hotkeys.cpp @@ -2,12 +2,14 @@ #include "cm_hotkeys.hpp" #include "cm_settings.hpp" +#include "cm_station_gui.hpp" // StationPickerSelection #include "../newgrf_station.h" #include "../settings_type.h" #include "../sound_func.h" #include "../tilehighlight_func.h" #include "../viewport_func.h" +#include "../vehicle_base.h" #include "../window_func.h" #include "../window_gui.h" #include "../window_type.h" @@ -19,11 +21,6 @@ #include "../safeguards.h" -struct StationPickerSelection { - StationClassID sel_class; ///< Selected station class. - uint16_t sel_type; ///< Selected station type within the class. - Axis axis; ///< Selected orientation of the station. -}; extern StationPickerSelection _station_gui; ///< Settings of the station picker. extern bool _generating_world; @@ -78,11 +75,11 @@ bool HasSeparateRemoveMod() { } void UpdateModKeys(bool shift_pressed, bool ctrl_pressed, bool alt_pressed, bool command_pressed) { - bool mod_pressed[(size_t)ModKey::END] = {false}; - if (shift_pressed) mod_pressed[(size_t)ModKey::SHIFT] = true; - if (ctrl_pressed) mod_pressed[(size_t)ModKey::CTRL] = true; - if (alt_pressed) mod_pressed[(size_t)ModKey::ALT] = true; - if (command_pressed) mod_pressed[(size_t)ModKey::COMMAND] = true; + bool mod_pressed[(size_t)ModKey::End] = {false}; + if (shift_pressed) mod_pressed[(size_t)ModKey::Shift] = true; + if (ctrl_pressed) mod_pressed[(size_t)ModKey::Ctrl] = true; + if (alt_pressed) mod_pressed[(size_t)ModKey::Alt] = true; + if (command_pressed) mod_pressed[(size_t)ModKey::Command] = true; bool fn_mod_prev = _fn_mod; bool remove_mod_prev = _remove_mod; _fn_mod = mod_pressed[(size_t)_settings_client.gui.cm_fn_mod]; @@ -284,4 +281,86 @@ void CountHotkeyStats(const HotkeyList *list, int hotkey) { _game_session_stats.cm.hotkeys[key]++; } +static StationOrderModAction GetStationOrderModAction() +{ + if (_ctrl_pressed) { + if (_shift_pressed) + return (StationOrderModAction)_settings_client.gui.cm_ctrl_shift_station_mod; + else if (_alt_pressed) + return (StationOrderModAction)_settings_client.gui.cm_alt_ctrl_station_mod; + else + return (StationOrderModAction)_settings_client.gui.cm_ctrl_station_mod; + } else if (_shift_pressed) { + if (_alt_pressed) + return (StationOrderModAction)_settings_client.gui.cm_alt_shift_station_mod; + else + return (StationOrderModAction)_settings_client.gui.cm_shift_station_mod; + } else if (_alt_pressed) + return (StationOrderModAction)_settings_client.gui.cm_alt_station_mod; + return StationOrderModAction::None; +} + +DepotOrderModAction GetDepotOrderModAction() { + if (_ctrl_pressed) { + if (_shift_pressed) return (DepotOrderModAction)_settings_client.gui.cm_ctrl_shift_depot_mod; + else return (DepotOrderModAction)_settings_client.gui.cm_ctrl_depot_mod; + } else if (_shift_pressed) { + return (DepotOrderModAction)_settings_client.gui.cm_shift_depot_mod; + } + return DepotOrderModAction::None; +} + +StationModOrders GetStationModOrders(const Vehicle *v) +{ + StationModOrders res = { + OLF_LOAD_IF_POSSIBLE, + OUF_UNLOAD_IF_POSSIBLE, + FeederOrderMod::None, + }; + + switch(GetStationOrderModAction()) { + case StationOrderModAction::None: + break; + + case StationOrderModAction::FullLoad: + res.load = OLF_FULL_LOAD_ANY; + break; + + case StationOrderModAction::Transfer: + res.unload = OUFB_TRANSFER; + if (_settings_client.gui.cm_no_loading_on_transfer_order) + res.load = OLFB_NO_LOAD; + break; + + case StationOrderModAction::UnloadAll: + res.unload = OUFB_UNLOAD; + if (_settings_client.gui.cm_no_loading_on_unload_order) + res.load = OLFB_NO_LOAD; + break; + + case StationOrderModAction::FeederLoad: + if (v->GetNumOrders() > 0) res.mod = FeederOrderMod::Load; + res.unload = OUFB_NO_UNLOAD; + res.load = OLF_FULL_LOAD_ANY; + break; + + case StationOrderModAction::FeederUnload: + if (v->GetNumOrders() > 0) res.mod = FeederOrderMod::Unload; + res.unload = OUFB_TRANSFER; + res.load = OLFB_NO_LOAD; + break; + + case StationOrderModAction::NoLoad: + res.load = OLFB_NO_LOAD; + break; + + case StationOrderModAction::NoUnload: + res.unload = OUFB_NO_UNLOAD; + break; + + default: NOT_REACHED(); + } + return res; +} + } // namespace citymania diff --git a/src/citymania/cm_hotkeys.hpp b/src/citymania/cm_hotkeys.hpp index 0132208297..27addd8945 100644 --- a/src/citymania/cm_hotkeys.hpp +++ b/src/citymania/cm_hotkeys.hpp @@ -2,8 +2,11 @@ #define CMEXT_HOTKEYS_HPP #include "../hotkeys.h" +#include "../order_type.h" #include "../window_type.h" +struct Vehicle; + namespace citymania { extern bool _fn_mod; @@ -32,6 +35,40 @@ std::pair GetEPM(); bool ChooseSignalDragBehaviour(); void CountHotkeyStats(const HotkeyList *list, int hotkey); + +enum class FeederOrderMod { + None, + Load, + Unload, +}; + +enum class StationOrderModAction : uint8_t { + None = 0, + FullLoad, + Transfer, + UnloadAll, + FeederLoad, + FeederUnload, + NoLoad, + NoUnload, +}; + +enum class DepotOrderModAction : uint8_t { + None = 0, + Service, + Stop, + Unbunch, +}; + +struct StationModOrders { + OrderLoadFlags load; + OrderUnloadFlags unload; + FeederOrderMod mod; +}; + +DepotOrderModAction GetDepotOrderModAction(); +StationModOrders GetStationModOrders(const Vehicle *v); + } // namespace citymania #endif diff --git a/src/citymania/cm_settings.hpp b/src/citymania/cm_settings.hpp index c294faa74d..0656e754d6 100644 --- a/src/citymania/cm_settings.hpp +++ b/src/citymania/cm_settings.hpp @@ -11,13 +11,13 @@ namespace citymania { -enum class ModKey : uint8 { - NONE = 0, - SHIFT = 1, - CTRL = 2, - ALT = 3, - COMMAND = 4, - END, +enum class ModKey : uint8_t { + None = 0, + Shift = 1, + Ctrl = 2, + Alt = 3, + Command = 4, + End, }; struct EconomySettings { diff --git a/src/citymania/cm_station_gui.cpp b/src/citymania/cm_station_gui.cpp index 3b586ddfd9..a8dcc78f66 100644 --- a/src/citymania/cm_station_gui.cpp +++ b/src/citymania/cm_station_gui.cpp @@ -61,18 +61,7 @@ extern RailType _cur_railtype; // rail_gui.cpp extern RoadType _cur_roadtype; // road_gui.cpp extern void GetStationLayout(uint8_t *layout, uint numtracks, uint plat_len, const StationSpec *statspec); -struct StationPickerSelection { - StationClassID sel_class; ///< Selected station class. - uint16_t sel_type; ///< Selected station type within the class. - Axis axis; ///< Selected orientation of the station. -}; extern StationPickerSelection _station_gui; ///< Settings of the station picker. - -struct RoadStopPickerSelection { - RoadStopClassID sel_class; ///< Selected road stop class. - uint16_t sel_type; ///< Selected road stop type within the class. - DiagDirection orientation; ///< Selected orientation of the road stop. -}; extern RoadStopPickerSelection _roadstop_gui; extern AirportClassID _selected_airport_class; ///< the currently visible airport class @@ -732,52 +721,50 @@ ToolGUIInfo GetSelectedStationGUIInfo() { } // --- Action base class --- + void Action::OnStationRemoved(const Station *) {} // --- RemoveAction --- -template -void RemoveAction::Update(Point, TileIndex tile) { + +void RemoveAction::Update(Point, TileIndex tile) { this->cur_tile = tile; } -template -bool RemoveAction::HandleMousePress() { +bool RemoveAction::HandleMousePress() { if (!IsValidTile(this->cur_tile)) return false; this->start_tile = this->cur_tile; return true; } -template -void RemoveAction::HandleMouseRelease() { +void RemoveAction::HandleMouseRelease() { auto area = this->GetArea(); if (!area.has_value()) return; - this->handler.Execute(area.value()); + this->Execute(area.value()); this->start_tile = INVALID_TILE; } -template -std::optional RemoveAction::GetArea() const { +std::optional RemoveAction::GetArea() const { if (!IsValidTile(this->cur_tile)) return std::nullopt; if (!IsValidTile(this->start_tile)) return TileArea{this->cur_tile, this->cur_tile}; return TileArea{this->start_tile, this->cur_tile}; } -template -ToolGUIInfo RemoveAction::GetGUIInfo() { +ToolGUIInfo RemoveAction::GetGUIInfo() { HighlightMap hlmap; BuildInfoOverlayData data; auto area = this->GetArea(); CommandCost cost; if (area.has_value()) { hlmap.AddTileAreaWithBorder(area.value(), CM_PALETTE_TINT_RED_DEEP); - auto cmd = this->handler.GetCommand(area.value()); + auto cmd = this->GetCommand(area.value()); if (cmd) cost = cmd->test(); } return {hlmap, data, cost}; } -template -void RemoveAction::OnStationRemoved(const Station *) {} +void RemoveAction::OnStationRemoved(const Station *) {} + +// --- PlacementAction --- ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional ohl, up cmd, StationCoverageType sct, uint rad) { if (!cmd || !ohl.has_value()) return {}; @@ -911,8 +898,8 @@ ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional ohl, } // --- SizedPlacementAction --- -template -void SizedPlacementAction::Update(Point, TileIndex tile) { + +void SizedPlacementAction::Update(Point, TileIndex tile) { this->cur_tile = tile; if (UseImprovedStationJoin()) return; @@ -920,7 +907,7 @@ void SizedPlacementAction::Update(Point, TileIndex tile) { auto area = this->GetArea(); if (!area.has_value()) return; - auto cmdptr = this->handler.GetCommand(tile, StationID::Invalid()); + auto cmdptr = this->GetCommand(tile, StationID::Invalid()); auto cmd = dynamic_cast(cmdptr.get()); if (cmd == nullptr) return; @@ -967,88 +954,80 @@ void SizedPlacementAction::Update(Point, TileIndex tile) { // } } -template -bool SizedPlacementAction::HandleMousePress() { +bool SizedPlacementAction::HandleMousePress() { return IsValidTile(this->cur_tile); } -template -void SizedPlacementAction::HandleMouseRelease() { +void SizedPlacementAction::HandleMouseRelease() { if (!IsValidTile(this->cur_tile)) return; - this->handler.Execute(this->cur_tile); + this->Execute(this->cur_tile); } -template -ToolGUIInfo SizedPlacementAction::GetGUIInfo() { +ToolGUIInfo SizedPlacementAction::GetGUIInfo() { if (!IsValidTile(this->cur_tile)) return {}; - auto [sct, rad] = this->handler.GetCatchmentParams(); + auto [sct, rad] = this->GetCatchmentParams(); return this->PrepareGUIInfo( - this->handler.GetObjectHighlight(this->cur_tile), - this->handler.GetCommand(this->cur_tile, StationID::Invalid()), + this->GetObjectHighlight(this->cur_tile), + this->GetCommand(this->cur_tile, StationID::Invalid()), sct, rad ); } -template -void SizedPlacementAction::OnStationRemoved(const Station *) {} +void SizedPlacementAction::OnStationRemoved(const Station *) {} // --- DragNDropPlacementAction --- -template -std::optional DragNDropPlacementAction::GetArea() const { +std::optional DragNDropPlacementAction::GetArea() const { // TODO separate common fuctions with RemoveAction into base class if (!IsValidTile(this->cur_tile)) return std::nullopt; if (!IsValidTile(this->start_tile)) return TileArea{this->cur_tile, this->cur_tile}; return TileArea{this->start_tile, this->cur_tile}; } -template -void DragNDropPlacementAction::Update(Point, TileIndex tile) { +void DragNDropPlacementAction::Update(Point, TileIndex tile) { this->cur_tile = tile; } -template -bool DragNDropPlacementAction::HandleMousePress() { +bool DragNDropPlacementAction::HandleMousePress() { if (!IsValidTile(this->cur_tile)) return false; this->start_tile = this->cur_tile; return true; } -template -void DragNDropPlacementAction::HandleMouseRelease() { +void DragNDropPlacementAction::HandleMouseRelease() { auto area = this->GetArea(); if (!area.has_value()) return; - this->handler.Execute(area.value()); + this->Execute(area.value()); this->start_tile = INVALID_TILE; } -template -ToolGUIInfo DragNDropPlacementAction::GetGUIInfo() { +ToolGUIInfo DragNDropPlacementAction::GetGUIInfo() { auto area = this->GetArea(); if (!area.has_value()) return {}; - auto ohl = this->handler.GetObjectHighlight(area.value()); - auto [sct, rad] = this->handler.GetCatchmentParams(); + auto ohl = this->GetObjectHighlight(area.value()); + auto [sct, rad] = this->GetCatchmentParams(); return this->PrepareGUIInfo( - this->handler.GetObjectHighlight(area.value()), - this->handler.GetCommand(area.value(), StationID::Invalid()), + this->GetObjectHighlight(area.value()), + this->GetCommand(area.value(), StationID::Invalid()), sct, rad ); } -template -void DragNDropPlacementAction::OnStationRemoved(const Station *) {} +void DragNDropPlacementAction::OnStationRemoved(const Station *) {} // --- StationSelectAction --- -template -void StationSelectAction::Update(Point, TileIndex tile) { this->cur_tile = tile; } -template -bool StationSelectAction::HandleMousePress() { return true; } +void StationSelectAction::Update(Point, TileIndex tile) { + this->cur_tile = tile; +} -template -void StationSelectAction::HandleMouseRelease() { +bool StationSelectAction::HandleMousePress() { + return true; +} + +void StationSelectAction::HandleMouseRelease() { // TODO station sign click if (!IsValidTile(this->cur_tile)) return; _station_action = StationAction::Create{}; @@ -1058,8 +1037,7 @@ void StationSelectAction::HandleMouseRelease() { } } -template -ToolGUIInfo StationSelectAction::GetGUIInfo() { +ToolGUIInfo StationSelectAction::GetGUIInfo() { if (!IsValidTile(this->cur_tile)) return {}; HighlightMap hlmap; hlmap.Add(this->cur_tile, ObjectTileHighlight::make_border(CM_PALETTE_TINT_BLUE, ZoningBorder::FULL)); @@ -1073,12 +1051,11 @@ ToolGUIInfo StationSelectAction::GetGUIInfo() { return {hlmap, data, {}}; } -template -void StationSelectAction::OnStationRemoved(const Station *station) { +void StationSelectAction::OnStationRemoved(const Station *station) { // if (this->selected_station == station->index) this->selected_station = INVALID_STATION; } -// --- StationBuildTool --- +// --- Misc functions --- TileArea GetCommandArea(const up &cmd) { if (auto rail_cmd = dynamic_cast(cmd.get())) { @@ -1105,41 +1082,54 @@ StationBuildTool::StationBuildTool() { ResetHighlightCoverageStation(); } -template -bool StationBuildTool::ExecuteBuildCommand(Thandler *handler, Tcallback callback, Targ arg) { - if (auto mode = std::get_if(&_station_action)) { - auto cmd = handler->GetCommand(arg, mode->station); - return cmd ? cmd->post(callback) : false; - } +extern void ShowSelectStationWindow(TileArea ta, StationPickerCmdProc&& proc); - // Vanilla joining behaviour - auto cmd = handler->GetCommand(arg, StationID::Invalid()); - auto proc = [cmd=sp{std::move(cmd)}, callback](bool test, StationID to_join) -> bool { - if (!cmd) return false; - auto station_cmd = dynamic_cast(cmd.get()); - if (station_cmd == nullptr) return false; - station_cmd->station_to_join = to_join; - if (test) { - return cmd->test().Succeeded(); - } else { - ResetSelectedStationToJoin(); - return cmd->post(callback); +template +bool ExecuteBuildCommand(Taction *action, Tcallback callback, Targ arg) { + std::visit(Overload{ + [&](StationAction::Join &a) { + Debug(misc, 0, "Join to {}", a.station); + auto cmd = action->GetCommand(arg, a.station); + return cmd ? cmd->post(callback) : false; + }, + [&](StationAction::Create &) { + Debug(misc, 0, "Create new station"); + auto cmd = action->GetCommand(arg, NEW_STATION); + return cmd ? cmd->post(callback) : false; + }, + [&](StationAction::Picker &) { + Debug(misc, 0, "Show picker"); + auto cmd = action->GetCommand(arg, StationID::Invalid()); + auto proc = [cmd=sp{std::move(cmd)}, callback](bool test, StationID to_join) -> bool { + if (!cmd) return false; + auto station_cmd = dynamic_cast(cmd.get()); + if (station_cmd == nullptr) return false; + station_cmd->station_to_join = to_join; + if (test) { + return cmd->test().Succeeded(); + } else { + ResetSelectedStationToJoin(); + return cmd->post(callback); + } + }; + + auto ohl = action->GetObjectHighlight(arg); + if (!ohl.has_value()) return false; + auto area = ohl->GetArea(); + if (!area.has_value()) return false; + // SetActiveHighlightObject(ohl); + ShowSelectStationWindow(*area, std::move(proc)); + return true; } - }; + }, _station_action); - auto ohl = handler->GetObjectHighlight(arg); - if (!ohl.has_value()) return false; - auto area = ohl->GetArea(); - if (!area.has_value()) return false; - SetActiveHighlightObject(ohl); - ShowSelectStationIfNeeded(area.value(), proc); return true; } -// --- RailStationBuildTool --- +// --- RailStationBuildTool::RemoveAction --- -up RailStationBuildTool::RemoveHandler::GetCommand(TileArea area) { +up RailStationBuildTool::RemoveAction::GetCommand(TileArea area) { auto cmd = make_up( area.tile, area.CMGetEndTile(), @@ -1149,20 +1139,23 @@ up RailStationBuildTool::RemoveHandler::GetCommand(TileArea area) { return cmd; } -bool RailStationBuildTool::RemoveHandler::Execute(TileArea area) { +bool RailStationBuildTool::RemoveAction::Execute(TileArea area) { auto cmd = this->GetCommand(area); return cmd->post(&CcPlaySound_CONSTRUCTION_RAIL); } -std::optional RailStationBuildTool::SizedPlacementHandler::GetArea(TileIndex tile) const { - if (!IsValidTile(tile)) return std::nullopt; + +// --- RailStationBuildTool::SizedPlacementAction --- + +std::optional RailStationBuildTool::SizedPlacementAction::GetArea() const { + if (!IsValidTile(this->cur_tile)) return std::nullopt; auto w = _settings_client.gui.station_numtracks; auto h = _settings_client.gui.station_platlength; if (_station_gui.axis == AXIS_X) std::swap(w, h); - return TileArea{tile, w, h}; + return TileArea{this->cur_tile, w, h}; } -up RailStationBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) { +up RailStationBuildTool::SizedPlacementAction::GetCommand(TileIndex tile, StationID to_join) { // TODO mostly same as DragNDropPlacement auto cmd = make_up( tile, @@ -1173,17 +1166,19 @@ up RailStationBuildTool::SizedPlacementHandler::GetCommand(TileIndex ti _station_gui.sel_class, _station_gui.sel_type, to_join, - _fn_mod + true ); cmd->with_error(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION); return cmd; } -bool RailStationBuildTool::SizedPlacementHandler::Execute(TileIndex tile) { - return this->tool.ExecuteBuildCommand(this, &CcStation, tile); +bool RailStationBuildTool::SizedPlacementAction::Execute(TileIndex tile) { + return ExecuteBuildCommand(this, &CcStation, tile); } -up RailStationBuildTool::DragNDropPlacementHandler::GetCommand(TileArea area, StationID to_join) { +// --- RailStationBuildTool::DragNDropPlacementAction --- + +up RailStationBuildTool::DragNDropPlacementAction::GetCommand(TileArea area, StationID to_join) { uint numtracks = area.w; uint platlength = area.h; @@ -1198,26 +1193,34 @@ up RailStationBuildTool::DragNDropPlacementHandler::GetCommand(TileArea _station_gui.sel_class, _station_gui.sel_type, to_join, - _fn_mod + true ); cmd->with_error(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION); return cmd; } -bool RailStationBuildTool::DragNDropPlacementHandler::Execute(TileArea area) { - return this->tool.ExecuteBuildCommand(this, &CcStation, area); +bool RailStationBuildTool::DragNDropPlacementAction::Execute(TileArea area) { + return ExecuteBuildCommand(this, &CcStation, area); } -std::optional RailStationBuildTool::DragNDropPlacementHandler::GetObjectHighlight(TileArea area) { - return this->tool.GetStationObjectHighlight(area.tile, area.CMGetEndTile()); +std::optional RailStationBuildTool::DragNDropPlacementAction::GetObjectHighlight(TileArea area) { + // Debug(misc, 0, "GetObjectHighlight {} {} ", _railstation.station_class, _railstation.station_type); + return ObjectHighlight::make_rail_station(area.tile, area.CMGetEndTile(), _station_gui.axis, _station_gui.sel_class, _station_gui.sel_type); } -std::optional RailStationBuildTool::SizedPlacementHandler::GetObjectHighlight(TileIndex tile) { - return this->tool.GetStationObjectHighlight(tile, INVALID_TILE); +std::optional RailStationBuildTool::SizedPlacementAction::GetObjectHighlight(TileIndex tile) { + TileIndex end_tile; + if (_station_gui.axis == AXIS_X) + end_tile = TileAddXY(tile, _settings_client.gui.station_platlength - 1, _settings_client.gui.station_numtracks - 1); + else + end_tile = TileAddXY(tile, _settings_client.gui.station_numtracks - 1, _settings_client.gui.station_platlength - 1); + return ObjectHighlight::make_rail_station(tile, end_tile, _station_gui.axis, _station_gui.sel_class, _station_gui.sel_type); } +// --- RailStationBuildTool implementation --- + RailStationBuildTool::RailStationBuildTool() : mode(Mode::SIZED) { - this->action = make_up>(SizedPlacementHandler(*this)); + this->action = make_sp(); } void RailStationBuildTool::Update(Point pt, TileIndex tile) { @@ -1234,16 +1237,16 @@ void RailStationBuildTool::Update(Point pt, TileIndex tile) { if (new_mode != this->mode) { switch (new_mode) { case Mode::REMOVE: - this->action = make_up>(*this); + this->action = make_sp(); break; case Mode::SELECT: - this->action = make_up>(*this); + this->action = make_sp(); break; case Mode::DRAGDROP: - this->action = make_up>(*this); + this->action = make_sp(); break; case Mode::SIZED: - this->action = make_up>(*this); + this->action = make_sp(); break; default: NOT_REACHED(); @@ -1253,86 +1256,96 @@ void RailStationBuildTool::Update(Point pt, TileIndex tile) { this->action->Update(pt, tile); } -std::optional RailStationBuildTool::GetStationObjectHighlight(TileIndex start_tile, TileIndex end_tile) const { - assert(IsValidTile(start_tile)); - assert(!IsValidTile(end_tile) || (TileX(start_tile) <= TileX(end_tile) && TileY(start_tile) <= TileY(end_tile))); - if (!IsValidTile(end_tile)) { - // Sized placement mode - if (_station_gui.axis == AXIS_X) - end_tile = TileAddXY(start_tile, _settings_client.gui.station_platlength - 1, _settings_client.gui.station_numtracks - 1); - else - end_tile = TileAddXY(start_tile, _settings_client.gui.station_numtracks - 1, _settings_client.gui.station_platlength - 1); - } else { - - } - return ObjectHighlight::make_rail_station(start_tile, end_tile, _station_gui.axis); -} - CursorID RailStationBuildTool::GetCursor() { return SPR_CURSOR_RAIL_STATION; } -// --- RoadStopBuildTool Handler Implementations --- +// --- RoadStopBuildTool::RemoveAction --- -up RoadStopBuildTool::RemoveHandler::GetCommand(TileArea area) { +up RoadStopBuildTool::RemoveAction::GetCommand(TileArea area) { auto cmd = make_up( area.tile, area.w, area.h, - this->tool.stop_type, + this->stop_type, _fn_mod ); auto rti = GetRoadTypeInfo(_cur_roadtype); - cmd->with_error(rti->strings.err_remove_station[to_underlying(this->tool.stop_type)]); + cmd->with_error(rti->strings.err_remove_station[to_underlying(this->stop_type)]); return cmd; } -bool RoadStopBuildTool::RemoveHandler::Execute(TileArea area) { +bool RoadStopBuildTool::RemoveAction::Execute(TileArea area) { auto cmd = this->GetCommand(area); return cmd->post(&CcPlaySound_CONSTRUCTION_OTHER); } -up RoadStopBuildTool::DragNDropPlacementHandler::GetCommand(TileArea area, StationID to_join) { - DiagDirection ddir = this->tool.ddir; - bool drive_through = this->tool.ddir >= DIAGDIR_END; - if (drive_through) ddir = static_cast(this->tool.ddir - DIAGDIR_END); // Adjust picker result to actual direction. +up RoadStopBuildTool::DragNDropPlacementAction::GetCommand(TileArea area, StationID to_join) { + DiagDirection ddir = this->ddir; + bool drive_through = this->ddir >= DIAGDIR_END; + if (drive_through) ddir = static_cast(this->ddir - DIAGDIR_END); // Adjust picker result to actual direction. auto res = make_up( area.tile, area.w, area.h, - this->tool.stop_type, + this->stop_type, drive_through, ddir, - _cur_roadtype, + this->road_type, _roadstop_gui.sel_class, _roadstop_gui.sel_type, to_join, - _fn_mod + true ); return res; } -bool RoadStopBuildTool::DragNDropPlacementHandler::Execute(TileArea area) { - return this->tool.ExecuteBuildCommand(this, &CcRoadStop, area); +bool RoadStopBuildTool::DragNDropPlacementAction::Execute(TileArea area) { + return ExecuteBuildCommand(this, &CcRoadStop, area); } -std::optional RoadStopBuildTool::DragNDropPlacementHandler::GetObjectHighlight(TileArea area) { +std::optional RoadStopBuildTool::DragNDropPlacementAction::GetObjectHighlight(TileArea area) { return ObjectHighlight::make_road_stop( area.tile, area.CMGetEndTile(), - _cur_roadtype, - this->tool.ddir, - this->tool.stop_type == RoadStopType::Truck, + this->road_type, + this->ddir, + this->stop_type == RoadStopType::Truck, _roadstop_gui.sel_class, _roadstop_gui.sel_type ); } -// --- RoadStopBuildTool Implementation --- +// --- RoadStopBuildTool implementation --- RoadStopBuildTool::RoadStopBuildTool(RoadStopType stop_type) : mode(Mode::DRAGDROP), stop_type(stop_type) { - this->action = make_up>(*this); + this->action = make_sp(_cur_roadtype, this->stop_type); +} + +void RoadStopBuildTool::DragNDropPlacementAction::Update(Point pt, TileIndex tile) { + citymania::DragNDropPlacementAction::Update(pt, tile); + this->ddir = DIAGDIR_NE; + auto area = this->GetArea(); + if (pt.x != -1 && area.has_value()) { + auto ddir = _roadstop_gui.orientation; + + if (ddir >= DIAGDIR_END && ddir < STATIONDIR_AUTO) { + // When placed on road autorotate anyway + if (ddir == STATIONDIR_X) { + if (!CheckDriveThroughRoadStopDirection(area.value(), ROAD_X)) + ddir = STATIONDIR_Y; + } else { + if (!CheckDriveThroughRoadStopDirection(area.value(), ROAD_Y)) + ddir = STATIONDIR_X; + } + } else if (ddir == STATIONDIR_AUTO) { + ddir = AddAutodetectionRotation(AutodetectRoadObjectDirection(tile, pt, this->road_type)); + } else if (ddir == STATIONDIR_AUTO_XY) { + ddir = AddAutodetectionRotation(AutodetectDriveThroughRoadStopDirection(area.value(), pt, this->road_type)); + } + this->ddir = ddir; + } } void RoadStopBuildTool::Update(Point pt, TileIndex tile) { @@ -1348,89 +1361,73 @@ void RoadStopBuildTool::Update(Point pt, TileIndex tile) { if (new_mode != this->mode) { switch (new_mode) { case Mode::REMOVE: - this->action = make_up>(*this); + this->action = make_sp(this->stop_type); break; case Mode::SELECT: - this->action = make_up>(*this); + this->action = make_sp(); break; case Mode::DRAGDROP: - this->action = make_up>(*this); + this->action = make_sp(_cur_roadtype, this->stop_type); break; } this->mode = new_mode; } this->action->Update(pt, tile); - - this->ddir = DIAGDIR_NE; - auto area = this->action->GetArea(); - if (pt.x != -1 && this->mode == Mode::DRAGDROP && area.has_value()) { - auto ddir = _roadstop_gui.orientation; - - if (ddir >= DIAGDIR_END && ddir < STATIONDIR_AUTO) { - // When placed on road autorotate anyway - if (ddir == STATIONDIR_X) { - if (!CheckDriveThroughRoadStopDirection(area.value(), ROAD_X)) - ddir = STATIONDIR_Y; - } else { - if (!CheckDriveThroughRoadStopDirection(area.value(), ROAD_Y)) - ddir = STATIONDIR_X; - } - } else if (ddir == STATIONDIR_AUTO) { - ddir = AddAutodetectionRotation(AutodetectRoadObjectDirection(tile, pt, _cur_roadtype)); - } else if (ddir == STATIONDIR_AUTO_XY) { - ddir = AddAutodetectionRotation(AutodetectDriveThroughRoadStopDirection(area.value(), pt, _cur_roadtype)); - } - this->ddir = ddir; - } } CursorID RoadStopBuildTool::GetCursor() { return this->stop_type == RoadStopType::Truck ? SPR_CURSOR_TRUCK_STATION : SPR_CURSOR_BUS_STATION; } -// --- DockBuildTool Handler Implementations --- +// --- DockBuildTool::RemoveAction --- -// RemoveHandler -up DockBuildTool::RemoveHandler::GetCommand(TileArea area) { +up DockBuildTool::RemoveAction::GetCommand(TileArea area) { // TODO: Implement dock removal command if available return nullptr; } -bool DockBuildTool::RemoveHandler::Execute(TileArea area) { +bool DockBuildTool::RemoveAction::Execute(TileArea area) { // TODO: Implement dock removal execution if available return false; } -// SizedPlacementHandler +// --- DockBuildTool::SizedPlacementAction --- -std::optional DockBuildTool::SizedPlacementHandler::GetArea(TileIndex tile) const { - if (!IsValidTile(tile)) return std::nullopt; - DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile)); - TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile, ReverseDiagDir(dir)) : tile); - return TileArea{tile, tile_to}; +std::optional DockBuildTool::SizedPlacementAction::GetArea() const { + auto ddir = this->GetDirection(this->cur_tile); + if (!ddir.has_value()) return std::nullopt; + return TileArea{this->cur_tile, TileAddByDiagDir(this->cur_tile, *ddir)}; } -up DockBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) { +up DockBuildTool::SizedPlacementAction::GetCommand(TileIndex tile, StationID to_join) { return make_up( tile, to_join, - _fn_mod + true ); } -bool DockBuildTool::SizedPlacementHandler::Execute(TileIndex tile) { - return this->tool.ExecuteBuildCommand(this, &CcBuildDocks, tile); +bool DockBuildTool::SizedPlacementAction::Execute(TileIndex tile) { + return ExecuteBuildCommand(this, &CcBuildDocks, tile); } -std::optional DockBuildTool::SizedPlacementHandler::GetObjectHighlight(TileIndex tile) { - return ObjectHighlight::make_dock(tile, this->tool.ddir); +std::optional DockBuildTool::SizedPlacementAction::GetObjectHighlight(TileIndex tile) { + return ObjectHighlight::make_dock(tile, this->GetDirection(tile).value_or(DIAGDIR_SE)); } +std::optional DockBuildTool::SizedPlacementAction::GetDirection(TileIndex tile) const { + if (!IsValidTile(tile)) return std::nullopt; + auto slope_dir = GetInclinedSlopeDirection(GetTileSlope(tile)); + if (slope_dir == INVALID_DIAGDIR) return std::nullopt; + return ReverseDiagDir(slope_dir); +}; + + // --- DockBuildTool Implementation --- DockBuildTool::DockBuildTool() : mode(Mode::SIZED) { - this->action = make_up>(*this); + this->action = make_sp(); } void DockBuildTool::Update(Point pt, TileIndex tile) { @@ -1445,13 +1442,13 @@ void DockBuildTool::Update(Point pt, TileIndex tile) { if (new_mode != this->mode) { switch (new_mode) { case Mode::REMOVE: - this->action = make_up>(*this); + this->action = make_up(); break; case Mode::SELECT: - this->action = make_up>(*this); + this->action = make_up(); break; case Mode::SIZED: - this->action = make_up>(*this); + this->action = make_up(); break; default: NOT_REACHED(); @@ -1459,41 +1456,34 @@ void DockBuildTool::Update(Point pt, TileIndex tile) { this->mode = new_mode; } this->action->Update(pt, tile); - this->ddir = DIAGDIR_SE; - if (pt.x != -1 && this->mode == Mode::SIZED) { - auto slope_dir = GetInclinedSlopeDirection(GetTileSlope(tile)); - if (slope_dir != INVALID_DIAGDIR) - this->ddir = ReverseDiagDir(slope_dir); - } - } +} CursorID DockBuildTool::GetCursor() { return SPR_CURSOR_DOCK; } -// --- AirportBuildTool Handler Implementations --- +// --- AirportBuildTool::RemoveAction --- -// RemoveHandler -up AirportBuildTool::RemoveHandler::GetCommand(TileArea area) { +up AirportBuildTool::RemoveAction::GetCommand(TileArea area) { // TODO: Implement aiport removal command if available return nullptr; } -bool AirportBuildTool::RemoveHandler::Execute(TileArea area) { +bool AirportBuildTool::RemoveAction::Execute(TileArea area) { // TODO: Implement airport removal execution if available return false; } -// SizedPlacementHandler +// --- AirportBuildTool::SizedPlacementAction --- -std::optional AirportBuildTool::SizedPlacementHandler::GetArea(TileIndex tile) const { - if (!IsValidTile(tile)) return std::nullopt; +std::optional AirportBuildTool::SizedPlacementAction::GetArea() const { + if (!IsValidTile(this->cur_tile)) return std::nullopt; auto as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index); if (as == nullptr) return std::nullopt; - return TileArea{tile, as->size_x, as->size_y}; + return TileArea{this->cur_tile, as->size_x, as->size_y}; } -up AirportBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) { +up AirportBuildTool::SizedPlacementAction::GetCommand(TileIndex tile, StationID to_join) { auto as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index); if (as == nullptr) return nullptr; auto airport_type = as->GetIndex(); @@ -1503,32 +1493,32 @@ up AirportBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, airport_type, layout, to_join, - _fn_mod + true ); cmd->with_error(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE); return cmd; } -bool AirportBuildTool::SizedPlacementHandler::Execute(TileIndex tile) { - this->tool.ExecuteBuildCommand(this, &CcBuildAirport, tile); +bool AirportBuildTool::SizedPlacementAction::Execute(TileIndex tile) { + return ExecuteBuildCommand(this, &CcBuildAirport, tile); } -std::optional AirportBuildTool::SizedPlacementHandler::GetObjectHighlight(TileIndex tile) { +std::optional AirportBuildTool::SizedPlacementAction::GetObjectHighlight(TileIndex tile) { auto airport_type = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex(); auto layout = _selected_airport_layout; return ObjectHighlight::make_airport(tile, airport_type, layout); } -std::pair AirportBuildTool::SizedPlacementHandler::GetCatchmentParams() { +std::pair AirportBuildTool::SizedPlacementAction::GetCatchmentParams() { auto rad = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->catchment; return {SCT_ALL, rad}; } -// --- AirportBuildTool Implementation --- +// --- AirportBuildTool implementation --- AirportBuildTool::AirportBuildTool() : mode(Mode::SIZED) { - this->action = make_up>(*this); + this->action = make_sp(); } void AirportBuildTool::Update(Point pt, TileIndex tile) { @@ -1543,13 +1533,13 @@ void AirportBuildTool::Update(Point pt, TileIndex tile) { if (new_mode != this->mode) { switch (new_mode) { case Mode::REMOVE: - this->action = make_up>(*this); + this->action = make_sp(); break; case Mode::SELECT: - this->action = make_up>(*this); + this->action = make_sp(); break; case Mode::SIZED: - this->action = make_up>(*this); + this->action = make_sp(); break; default: NOT_REACHED(); @@ -1563,17 +1553,4 @@ CursorID AirportBuildTool::GetCursor() { return SPR_CURSOR_AIRPORT; } -// --- Explicit template instantiations for handlers --- -template class StationSelectAction; - -template class DragNDropPlacementAction; -template class RemoveAction; -template class SizedPlacementAction; - -template class RemoveAction; -template class DragNDropPlacementAction; - -template class RemoveAction; -template class SizedPlacementAction; - } // namespace citymania diff --git a/src/citymania/cm_station_gui.hpp b/src/citymania/cm_station_gui.hpp index 8668ae174a..729c8614a3 100644 --- a/src/citymania/cm_station_gui.hpp +++ b/src/citymania/cm_station_gui.hpp @@ -13,9 +13,19 @@ #include #include -namespace citymania { +struct StationPickerSelection { + StationClassID sel_class; ///< Selected station class. + uint16_t sel_type; ///< Selected station type within the class. + Axis axis; ///< Selected orientation of the station. +}; -std::pair GetOrderDistances(VehicleOrderID prev, VehicleOrderID cur, const Vehicle *v, int conditional_depth = 0); +struct RoadStopPickerSelection { + RoadStopClassID sel_class; ///< Selected road stop class. + uint16_t sel_type; ///< Selected road stop type within the class. + DiagDirection orientation; ///< Selected orientation of the road stop. +}; + +namespace citymania { const DiagDirection DEPOTDIR_AUTO = DIAGDIR_END; const DiagDirection STATIONDIR_X = DIAGDIR_END; @@ -23,15 +33,6 @@ const DiagDirection STATIONDIR_Y = (DiagDirection)((uint)DIAGDIR_END + 1); const DiagDirection STATIONDIR_AUTO = (DiagDirection)((uint)DIAGDIR_END + 2); const DiagDirection STATIONDIR_AUTO_XY = (DiagDirection)((uint)DIAGDIR_END + 3); -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 ) - uint16_t station_type; ///< %Station type within the currently selected custom station class (if newstations is \c true ) - uint16_t station_count; ///< Number of custom stations (if newstations is \c true ) -}; - // void SetStationTileSelectSize(int w, int h, int catchment); bool UseImprovedStationJoin(); void OnStationTileSetChange(const Station *station, bool adding, StationType type); @@ -58,6 +59,23 @@ bool IsHighlightCoverageStation(const Station *station); bool HasSelectedStationHighlight(); ToolGUIInfo GetSelectedStationGUIInfo(); +std::pair GetOrderDistances(VehicleOrderID prev, VehicleOrderID cur, const Vehicle *v, int conditional_depth = 0); + +template +void IterateStation(TileIndex start_tile, Axis axis, uint8_t numtracks, uint8_t plat_len, Func visitor) { + TileIndexDiff tile_delta = TileOffsByAxis(axis); // offset to go to the next platform tile + TileIndexDiff track_delta = TileOffsByAxis(OtherAxis(axis)); // offset to go to the next track + + TileIndex tile_track = start_tile; + for (uint i = 0; i != numtracks; ++i) { + TileIndex tile = tile_track; + for (uint j = 0; j != plat_len; ++j) { + visitor(tile, i, j); + tile += tile_delta; + } + tile_track += track_delta; + } +} struct OverlayParams { TileArea area; @@ -65,24 +83,11 @@ struct OverlayParams { StationCoverageType coverage_type; }; -// Remove action classes -class RemoveHandler { -public: - virtual ~RemoveHandler() = default; - virtual up GetCommand(TileArea area) = 0; - virtual bool Execute(TileArea area) = 0; -}; -template -concept ImplementsRemoveHandler = std::derived_from; - -template class RemoveAction : public Action { -private: - Handler handler; +protected: TileIndex start_tile = INVALID_TILE; TileIndex cur_tile = INVALID_TILE; public: - RemoveAction(const Handler &handler) : handler{handler} {} ~RemoveAction() override = default; void Update(Point pt, TileIndex tile) override; std::optional GetArea() const override; @@ -90,24 +95,14 @@ public: void HandleMouseRelease() override; ToolGUIInfo GetGUIInfo() override; void OnStationRemoved(const Station *) override; + virtual up GetCommand(TileArea area) = 0; + virtual bool Execute(TileArea area) = 0; }; - -// StationSelect classes -class StationSelectHandler { -public: - virtual ~StationSelectHandler() = default; -}; -template -concept ImplementsStationSelectHandler = std::derived_from; - -template class StationSelectAction : public Action { -private: - Handler handler; +protected: TileIndex cur_tile = INVALID_TILE; public: - StationSelectAction(const Handler &handler) : handler{handler} {} ~StationSelectAction() override = default; void Update(Point pt, TileIndex tile) override; bool HandleMousePress() override; @@ -123,55 +118,27 @@ public: ToolGUIInfo PrepareGUIInfo(std::optional ohl, up cmd, StationCoverageType sct, uint rad); }; -// SizedPlacement classes -class SizedPlacementHandler { -public: - virtual ~SizedPlacementHandler() = default; - virtual up GetCommand(TileIndex tile, StationID to_join) = 0; - virtual bool Execute(TileIndex tile) = 0; - virtual std::optional GetObjectHighlight(TileIndex tile) = 0; - virtual std::pair GetCatchmentParams() = 0; - virtual std::optional GetArea(TileIndex tile) const = 0; -}; -template -concept ImplementsSizedPlacementHandler = std::derived_from; - -template class SizedPlacementAction : public PlacementAction { -private: - Handler handler; +protected: TileIndex cur_tile = INVALID_TILE; public: - SizedPlacementAction(const Handler &handler) : handler{handler} {} ~SizedPlacementAction() override = default; void Update(Point pt, TileIndex tile) override; - std::optional GetArea() const override { return this->handler.GetArea(this->cur_tile); } bool HandleMousePress() override; void HandleMouseRelease() override; ToolGUIInfo GetGUIInfo() override; void OnStationRemoved(const Station *) override; -}; - -// DragNDropPlacement classes -class DragNDropPlacementHandler { -public: - virtual ~DragNDropPlacementHandler() = default; - virtual up GetCommand(TileArea area, StationID to_join) = 0; - virtual bool Execute(TileArea area) = 0; - virtual std::optional GetObjectHighlight(TileArea area) = 0; + virtual up GetCommand(TileIndex tile, StationID to_join) = 0; + virtual bool Execute(TileIndex tile) = 0; + virtual std::optional GetObjectHighlight(TileIndex tile) = 0; virtual std::pair GetCatchmentParams() = 0; }; -template -concept ImplementsDragNDropPlacementHandler = std::derived_from; -template class DragNDropPlacementAction : public PlacementAction { -private: +protected: TileIndex start_tile = INVALID_TILE; TileIndex cur_tile = INVALID_TILE; - Handler handler; public: - DragNDropPlacementAction(const Handler &handler) :handler{handler} {}; ~DragNDropPlacementAction() override = default; void Update(Point pt, TileIndex tile) override; std::optional GetArea() const override; @@ -179,20 +146,14 @@ public: void HandleMouseRelease() override; ToolGUIInfo GetGUIInfo() override; void OnStationRemoved(const Station *) override; + virtual up GetCommand(TileArea area, StationID to_join) = 0; + virtual bool Execute(TileArea area) = 0; + virtual std::optional GetObjectHighlight(TileArea area) = 0; + virtual std::pair GetCatchmentParams() = 0; }; class StationBuildTool : public Tool { public: - // static StationID station_to_join; - // static bool ambigous_join; - - class StationSelectHandler : public citymania::StationSelectHandler { - public: - StationBuildTool &tool; - StationSelectHandler(StationBuildTool &tool) : tool(tool) {} - ~StationSelectHandler() {} - }; - StationBuildTool(); ~StationBuildTool() override = default; ToolGUIInfo GetGUIInfo() override { @@ -203,48 +164,37 @@ public: if (this->action) this->action->OnStationRemoved(station); } protected: - template - bool ExecuteBuildCommand(Thandler *handler, Tcallback callback, Targ arg); }; // RailStationBuildTool class RailStationBuildTool : public StationBuildTool { private: - class RemoveHandler : public citymania::RemoveHandler { + class RemoveAction : public citymania::RemoveAction { public: - RailStationBuildTool &tool; - RemoveHandler(RailStationBuildTool &tool) : tool(tool) {} - ~RemoveHandler() override = default; + ~RemoveAction() override = default; up GetCommand(TileArea area) override; bool Execute(TileArea area) override; }; - class SizedPlacementHandler : public citymania::SizedPlacementHandler { + class SizedPlacementAction : public citymania::SizedPlacementAction { public: - RailStationBuildTool &tool; - SizedPlacementHandler(RailStationBuildTool &tool) : tool(tool) {} - ~SizedPlacementHandler() override = default; + ~SizedPlacementAction() override = default; up GetCommand(TileIndex tile, StationID to_join) override; bool Execute(TileIndex tile) override; std::optional GetObjectHighlight(TileIndex tile) override; - std::pair GetCatchmentParams() override { return {this->tool.GetCatchmentParams()}; }; - std::optional GetArea(TileIndex tile) const override; + std::pair GetCatchmentParams() override { return {SCT_ALL, CA_TRAIN}; }; + std::optional GetArea() const override; }; - class DragNDropPlacementHandler: public citymania::DragNDropPlacementHandler { + class DragNDropPlacementAction: public citymania::DragNDropPlacementAction { public: - RailStationBuildTool &tool; - DragNDropPlacementHandler(RailStationBuildTool &tool) :tool{tool} {} - ~DragNDropPlacementHandler() override = default; + ~DragNDropPlacementAction() override = default; up GetCommand(TileArea area, StationID to_join) override; bool Execute(TileArea area) override; std::optional GetObjectHighlight(TileArea area) override; - std::pair GetCatchmentParams() override { return {this->tool.GetCatchmentParams()}; }; + std::pair GetCatchmentParams() override { return {SCT_ALL, CA_TRAIN}; }; }; - std::optional GetStationObjectHighlight(TileIndex start_tile, TileIndex end_tile) const; - std::pair GetCatchmentParams() { return {SCT_ALL, CA_TRAIN}; }; - public: RailStationBuildTool(); ~RailStationBuildTool() override = default; @@ -258,30 +208,38 @@ private: // RoadStopBuildTool class RoadStopBuildTool : public StationBuildTool { private: - class RemoveHandler : public citymania::RemoveHandler { + class RemoveAction : public citymania::RemoveAction { public: - RoadStopBuildTool &tool; - RemoveHandler(RoadStopBuildTool &tool) : tool(tool) {} - ~RemoveHandler() override = default; + RoadStopType stop_type; + RemoveAction(RoadStopType stop_type) : stop_type{stop_type} {} + ~RemoveAction() override = default; up GetCommand(TileArea area) override; bool Execute(TileArea area) override; }; - class DragNDropPlacementHandler: public citymania::DragNDropPlacementHandler { + class DragNDropPlacementAction: public citymania::DragNDropPlacementAction { public: - RoadStopBuildTool &tool; - DragNDropPlacementHandler(RoadStopBuildTool &tool) :tool{tool} {} - ~DragNDropPlacementHandler() override = default; + RoadType road_type; + RoadStopType stop_type; + DiagDirection ddir = DIAGDIR_NE; + // RoadStopClassID spec_class; + // uint16_t spec_index; + + DragNDropPlacementAction(RoadType road_type, RoadStopType stop_type) + :road_type{road_type}, stop_type{stop_type} {} + // DragNDropPlacementHandler(DiagDirection ddir, RoadStopType stop_type, RoadStopClassID spec_class, uint16_t spec_index;) + // :ddir{ddir}, stop_type{stop_type}, spec_class{spec_class}, spec_index{spec_index} {} + ~DragNDropPlacementAction() override = default; + void Update(Point pt, TileIndex tile) override; up GetCommand(TileArea area, StationID to_join) override; bool Execute(TileArea area) override; std::optional GetObjectHighlight(TileArea area) override; - std::pair GetCatchmentParams() override { return this->tool.GetCatchmentParams(); }; + std::pair GetCatchmentParams() override { + if (this->stop_type == RoadStopType::Bus) return {SCT_PASSENGERS_ONLY, CA_BUS}; + else return {SCT_NON_PASSENGERS_ONLY, CA_TRUCK}; + } }; - std::pair GetCatchmentParams() { - if (this->stop_type == RoadStopType::Bus) return {SCT_PASSENGERS_ONLY, CA_BUS}; - else return {SCT_NON_PASSENGERS_ONLY, CA_TRUCK}; - }; public: RoadStopBuildTool(RoadStopType stop_type); ~RoadStopBuildTool() override = default; @@ -291,31 +249,27 @@ private: enum class Mode { REMOVE, SELECT, DRAGDROP }; Mode mode; RoadStopType stop_type; - DiagDirection ddir = DIAGDIR_NE; }; // --- DockBuildTool --- class DockBuildTool : public StationBuildTool { private: - class RemoveHandler : public citymania::RemoveHandler { + class RemoveAction : public citymania::RemoveAction { public: - DockBuildTool &tool; - RemoveHandler(DockBuildTool &tool) : tool(tool) {} - ~RemoveHandler() override = default; + ~RemoveAction() override = default; up GetCommand(TileArea area) override; bool Execute(TileArea area) override; }; - class SizedPlacementHandler : public citymania::SizedPlacementHandler { + class SizedPlacementAction : public citymania::SizedPlacementAction { public: - DockBuildTool &tool; - SizedPlacementHandler(DockBuildTool &tool) : tool(tool) {} - ~SizedPlacementHandler() override = default; + ~SizedPlacementAction() override = default; up GetCommand(TileIndex tile, StationID to_join) override; bool Execute(TileIndex tile) override; std::optional GetObjectHighlight(TileIndex tile) override; std::pair GetCatchmentParams() override { return {SCT_ALL, CA_DOCK}; }; - std::optional GetArea(TileIndex tile) const override; + std::optional GetArea() const override; + std::optional GetDirection(TileIndex tile) const; }; public: @@ -326,31 +280,26 @@ public: private: enum class Mode { REMOVE, SELECT, SIZED }; Mode mode; - DiagDirection ddir; }; // --- AirportBuildTool --- class AirportBuildTool : public StationBuildTool { private: - class RemoveHandler : public citymania::RemoveHandler { + class RemoveAction : public citymania::RemoveAction { public: - AirportBuildTool &tool; - RemoveHandler(AirportBuildTool &tool) : tool(tool) {} - ~RemoveHandler() override = default; + ~RemoveAction() override = default; up GetCommand(TileArea area) override; bool Execute(TileArea area) override; }; - class SizedPlacementHandler : public citymania::SizedPlacementHandler { + class SizedPlacementAction : public citymania::SizedPlacementAction { public: - AirportBuildTool &tool; - SizedPlacementHandler(AirportBuildTool &tool) : tool(tool) {} - ~SizedPlacementHandler() override = default; + ~SizedPlacementAction() override = default; up GetCommand(TileIndex tile, StationID to_join) override; bool Execute(TileIndex tile) override; std::optional GetObjectHighlight(TileIndex tile) override; std::pair GetCatchmentParams() override; - std::optional GetArea(TileIndex tile) const override; + std::optional GetArea() const override; }; public: diff --git a/src/citymania/cm_type.hpp b/src/citymania/cm_type.hpp index 4ee075e909..d824fbb3ce 100644 --- a/src/citymania/cm_type.hpp +++ b/src/citymania/cm_type.hpp @@ -17,39 +17,17 @@ template using up=std::unique_ptr; template using sp=std::shared_ptr; template using wp=std::weak_ptr; -/* C++14 implementation of make_unique */ -template struct _Unique_if { - typedef std::unique_ptr _Single_object; -}; +template +constexpr auto make_up(Args&&... args) { + return std::make_unique(std::forward(args)...); +} -template struct _Unique_if { - typedef std::unique_ptr _Unknown_bound; -}; +template +constexpr auto make_sp(Args&&... args) { + return std::make_shared(std::forward(args)...); +} -template struct _Unique_if { - typedef void _Known_bound; -}; - -template - typename _Unique_if::_Single_object - make_up(Args&&... args) { - return std::unique_ptr(new T(std::forward(args)...)); - } - -template - typename _Unique_if::_Unknown_bound - make_up(size_t n) { - typedef typename std::remove_extent::type U; - return std::unique_ptr(new U[n]()); - } - -template - typename _Unique_if::_Known_bound - make_up(Args&&...) = delete; - -// template const auto make_up = std::make_unique; -// template const auto make_sp = std::make_shared; -template const auto make_sp = std::make_shared; +// template constexpr auto make_sp = std::make_shared; enum class GameType: uint8_t { @@ -73,6 +51,15 @@ enum class ControllerType: uint8_t { TOWN_DEFENCE = 6, }; + +// For use with std::visit +template +struct Overload : Ts ... { + using Ts::operator() ...; +}; +template Overload(Ts...) -> Overload; + + // Some utility funcitons for strings namespace string { diff --git a/src/lang/english.txt b/src/lang/english.txt index 6181e3820f..71168d00a0 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -6330,6 +6330,7 @@ CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_UNLOAD_ALL :Force unload of CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FEEDER_LOAD :Feeder Load (replace first order) CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FEEDER_UNLOAD :Feeder Unload (replace last order) CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NO_LOAD :Do not load any cargo +CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NO_UNLOAD :Do not unload any cargo CM_STR_CONFIG_SETTING_DEPOT_MOD_CTRL :Ctrl+click depot: {STRING2} CM_STR_CONFIG_SETTING_DEPOT_MOD_SHIFT :Shift+click depot: {STRING2} diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 7dbddc150f..8819cbf520 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -181,82 +181,6 @@ static const StringID _order_conditional_condition[] = { STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE, }; -enum class FeederOrderMod{ - NONE, - LOAD, - UNLOAD -}; - -struct OrdersFromSettings { - OrderLoadFlags load; - OrderUnloadFlags unload; - FeederOrderMod mod; -}; - -enum GetOrderFromSettingsTypes { - GOFS_NONE = 0, - GOFS_FULL, - GOFS_XFER, - GOFS_UNLOAD, - GOFS_FEEDLOAD, - GOFS_FEEDUNLOAD, - GOFS_NOLOAD -}; - -#define GOFSFEEDER_ORDERMOD_RESET gofsfeeder_ordermod = GOFS_FEEDER_NULL - - -/* fetch and compute orders set from settings */ - -static OrdersFromSettings GetOrdersFromSettings(const Vehicle *v, uint8 setting) -{ - OrdersFromSettings res = { - OLF_LOAD_IF_POSSIBLE, - OUF_UNLOAD_IF_POSSIBLE, - FeederOrderMod::NONE - }; - - switch(setting) { - - case GOFS_FEEDLOAD: - if (v->GetNumOrders() > 0) res.mod = FeederOrderMod::LOAD; - res.unload = OUFB_NO_UNLOAD; - res.load = OLF_FULL_LOAD_ANY; - break; - case GOFS_FULL: - res.load = OLF_FULL_LOAD_ANY; - break; - - case GOFS_UNLOAD: - res.unload = OUFB_UNLOAD; - if (_settings_client.gui.cm_no_loading_on_unload_order) - res.load = OLFB_NO_LOAD; - break; - - case GOFS_FEEDUNLOAD: - if (v->GetNumOrders() > 0) res.mod = FeederOrderMod::UNLOAD; - res.unload = OUFB_TRANSFER; - res.load = OLFB_NO_LOAD; - break; - - case GOFS_XFER: - res.unload = OUFB_TRANSFER; - if (_settings_client.gui.cm_no_loading_on_transfer_order) - res.load = OLFB_NO_LOAD; - break; - - case GOFS_NOLOAD: - res.load = OLFB_NO_LOAD; - break; - - case GOFS_NONE: - break; - - default: NOT_REACHED(); - } - return res; -} - extern uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type); extern uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type); @@ -454,7 +378,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, VehicleOrderID order_ * @param tile Tile being queried. * @return The order associated to vehicle v in given tile (or empty order if vehicle can do nothing in the tile). */ -static std::pair GetOrderCmdFromTile(const Vehicle *v, TileIndex tile) +static std::pair GetOrderCmdFromTile(const Vehicle *v, TileIndex tile) { Order order{}; @@ -464,18 +388,10 @@ static std::pair GetOrderCmdFromTile(const Vehicle *v, Ti ODTFB_PART_OF_ORDERS, (_settings_client.gui.new_nonstop && v->IsGroundVehicle()) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE); - uint8 os = 0; - if (_ctrl_pressed) { - if (_shift_pressed) os = _settings_client.gui.cm_ctrl_shift_depot_mod; - else os = _settings_client.gui.cm_ctrl_depot_mod; - } else if (_shift_pressed) { - os = _settings_client.gui.cm_shift_depot_mod; - } - - switch (os) { - case 1: order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() | ODTFB_SERVICE)); break; - case 2: order.SetDepotActionType(ODATFB_HALT); break; - case 3: order.SetDepotActionType(ODATFB_UNBUNCH); break; + switch (citymania::GetDepotOrderModAction()) { + case citymania::DepotOrderModAction::Service: order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() | ODTFB_SERVICE)); break; + case citymania::DepotOrderModAction::Stop: order.SetDepotActionType(ODATFB_HALT); break; + case citymania::DepotOrderModAction::Unbunch: order.SetDepotActionType(ODATFB_UNBUNCH); break; default: break; } @@ -499,14 +415,14 @@ static std::pair GetOrderCmdFromTile(const Vehicle *v, Ti /* Return an empty order to bail out. */ if (failed) { order.Free(); - return {order, FeederOrderMod::NONE};; + return {order, citymania::FeederOrderMod::None}; } /* Now we are allowed to set the action type. */ // order.SetDepotActionType(ODATFB_UNBUNCH); } - return {order, FeederOrderMod::NONE}; + return {order, citymania::FeederOrderMod::None}; } /* check rail waypoint */ @@ -515,7 +431,7 @@ static std::pair GetOrderCmdFromTile(const Vehicle *v, Ti IsTileOwner(tile, _local_company)) { order.MakeGoToWaypoint(GetStationIndex(tile)); if (_settings_client.gui.new_nonstop != citymania::_fn_mod) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION); - return std::make_pair(order, FeederOrderMod::NONE); + return {order, citymania::FeederOrderMod::None}; } /* check road waypoint */ @@ -524,13 +440,13 @@ static std::pair GetOrderCmdFromTile(const Vehicle *v, Ti IsTileOwner(tile, _local_company)) { order.MakeGoToWaypoint(GetStationIndex(tile)); if (_settings_client.gui.new_nonstop != _ctrl_pressed) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION); - return std::make_pair(order, FeederOrderMod::NONE); + return std::make_pair(order, citymania::FeederOrderMod::None); } /* check buoy (no ownership) */ if (IsBuoyTile(tile) && v->type == VEH_SHIP) { order.MakeGoToWaypoint(GetStationIndex(tile)); - return std::make_pair(order, FeederOrderMod::NONE); + return std::make_pair(order, citymania::FeederOrderMod::None); } /* check for station or industry with neutral station */ @@ -555,44 +471,22 @@ static std::pair GetOrderCmdFromTile(const Vehicle *v, Ti if (st->facilities.Any(facil)) { order.MakeGoToStation(st->index); - uint8 os = 0xff; - if (_ctrl_pressed) { - if (_shift_pressed) - os = _settings_client.gui.cm_ctrl_shift_station_mod; - else if (_alt_pressed) - os = _settings_client.gui.cm_alt_ctrl_station_mod; - else - os = _settings_client.gui.cm_ctrl_station_mod; - } - else if (_shift_pressed) { - if (_alt_pressed) - os = _settings_client.gui.cm_alt_shift_station_mod; - else - os = _settings_client.gui.cm_shift_station_mod; - } - else if (_alt_pressed) - os = _settings_client.gui.cm_alt_station_mod; - - auto feeder_mod = FeederOrderMod::NONE; - if (os != 0xff) { - auto ofs = GetOrdersFromSettings(v, os); - if (ofs.load != (enum OrderLoadFlags)-1) - order.SetLoadType(ofs.load); - if (ofs.unload != (enum OrderUnloadFlags)-1) - order.SetUnloadType(ofs.unload); - feeder_mod = ofs.mod; - } + auto feeder_mod = citymania::FeederOrderMod::None; + auto ofs = citymania::GetStationModOrders(v); + order.SetLoadType(ofs.load); + order.SetUnloadType(ofs.unload); + feeder_mod = ofs.mod; if (_settings_client.gui.new_nonstop && v->IsGroundVehicle()) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); order.SetStopLocation(v->type == VEH_TRAIN ? (OrderStopLocation)(_settings_client.gui.stop_location) : OSL_PLATFORM_FAR_END); - return std::make_pair(order, feeder_mod); + return {order, feeder_mod}; } } } /* not found */ order.Free(); - return std::make_pair(order, FeederOrderMod::NONE); + return {order, citymania::FeederOrderMod::None}; } /** Hotkeys for order window. */ @@ -1622,8 +1516,8 @@ public: auto feeder_mod = res.second; if (cmd.IsType(OT_NOTHING)) return; - if (feeder_mod != FeederOrderMod::NONE) { - if (feeder_mod == FeederOrderMod::LOAD) { + if (feeder_mod != citymania::FeederOrderMod::None) { + if (feeder_mod == citymania::FeederOrderMod::Load) { if (citymania::cmd::InsertOrder(this->vehicle->tile, this->vehicle->index, 1, cmd) .with_error(STR_ERROR_CAN_T_INSERT_NEW_ORDER) .set_auto() @@ -1634,7 +1528,7 @@ public: .post(); } - } else if (feeder_mod == FeederOrderMod::UNLOAD) { // still flushes the whole order table + } else if (feeder_mod == citymania::FeederOrderMod::Unload) { // still flushes the whole order table if (citymania::cmd::InsertOrder(this->vehicle->tile, this->vehicle->index, this->vehicle->GetNumOrders(), cmd) .with_error(STR_ERROR_CAN_T_INSERT_NEW_ORDER) .set_auto() diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 1fcd72cf37..bfcd83696b 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -7,7 +7,6 @@ /** @file rail_gui.cpp %File for dealing with rail construction user interface */ -#include "citymania/cm_highlight_type.hpp" #include "stdafx.h" #include "gui.h" #include "station_base.h" @@ -54,6 +53,7 @@ #include "citymania/cm_blueprint.hpp" #include "citymania/cm_commands.hpp" +#include "citymania/cm_highlight_type.hpp" #include "citymania/cm_hotkeys.hpp" #include "citymania/cm_highlight.hpp" #include "citymania/cm_station_gui.hpp" @@ -77,11 +77,12 @@ struct WaypointPickerSelection { }; static WaypointPickerSelection _waypoint_gui; ///< Settings of the waypoint picker. +/* Moved to cm_station_gui.hpp struct StationPickerSelection { StationClassID sel_class; ///< Selected station class. uint16_t sel_type; ///< Selected station type within the class. Axis axis; ///< Selected orientation of the station. -}; +}; */ /* CM static */ StationPickerSelection _station_gui; ///< Settings of the station picker. static const int HOTKEY_POLYRAIL = 0x1000; @@ -94,7 +95,6 @@ static const int HOTKEY_BLUEPRINT_LOAD_END = 0x1030; static const int HOTKEY_BLUEPRINT_SAVE = 0x1030; static const int HOTKEY_BLUEPRINT_SAVE_END = 0x1040; - static void HandleStationPlacement(TileIndex start, TileIndex end); static void ShowBuildTrainDepotPicker(Window *parent); static void ShowBuildWaypointPicker(Window *parent); @@ -1954,10 +1954,6 @@ public: size.width = ScaleGUITrad(64) + WidgetDimensions::scaled.fullbevel.Horizontal(); size.height = ScaleGUITrad(48) + WidgetDimensions::scaled.fullbevel.Vertical(); break; - - case WID_BRAD_DEPOT_AUTO: - size.width = ScaleGUITrad(128 + 2) + 2 * WidgetDimensions::scaled.fullbevel.Horizontal(); - break; } } @@ -1982,7 +1978,7 @@ public: case WID_BRAD_DEPOT_SE: case WID_BRAD_DEPOT_SW: case WID_BRAD_DEPOT_NW: - case WID_BRAD_DEPOT_AUTO: + case CM_WID_BRAD_DEPOT_AUTO: this->RaiseWidget(WID_BRAD_DEPOT_NE + _build_depot_direction); _build_depot_direction = (DiagDirection)(widget - WID_BRAD_DEPOT_NE); this->LowerWidget(WID_BRAD_DEPOT_NE + _build_depot_direction); @@ -2030,21 +2026,21 @@ static constexpr NWidgetPart _nested_build_depot_widgets[] = { NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), EndContainer(), NWidget(WWT_PANEL, COLOUR_DARK_GREEN), - NWidget(NWID_HORIZONTAL_LTR), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1), SetPadding(WidgetDimensions::unscaled.picker), - NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_NW), SetToolTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_SW), SetToolTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), + NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), SetPadding(WidgetDimensions::unscaled.picker), + NWidget(NWID_HORIZONTAL_LTR), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1), + NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_NW), SetMinimalSize(66, 50), SetToolTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_SW), SetMinimalSize(66, 50), SetToolTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), + EndContainer(), + NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_NE), SetMinimalSize(66, 50), SetToolTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_SE), SetMinimalSize(66, 50), SetToolTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), + EndContainer(), EndContainer(), - NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_NE), SetToolTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_SE), SetToolTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), + NWidget(NWID_HORIZONTAL), SetPIP(0, 0, 0), SetPIPRatio(1, 0, 1), + NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BRAD_DEPOT_AUTO), SetMinimalSize(2 * 66 + WidgetDimensions::unscaled.hsep_normal, 12), SetFill(0, 0), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_BUILD_DEPOT_TRAIN_ORIENTATION_AUTO_TOOLTIP), EndContainer(), EndContainer(), - NWidget(NWID_HORIZONTAL), SetPIP(2, 2, 2), - NWidget(NWID_SPACER), SetFill(1, 0), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_AUTO), SetMinimalSize(134, 12), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_BUILD_DEPOT_TRAIN_ORIENTATION_AUTO_TOOLTIP), - NWidget(NWID_SPACER), SetFill(1, 0), - EndContainer(), EndContainer(), }; diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 621fa691d7..5465900c84 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -7,9 +7,9 @@ /** @file road_gui.cpp GUI for building roads. */ -#include "station_type.h" #include "stdafx.h" #include "gui.h" +#include "widget_type.h" #include "window_gui.h" #include "station_gui.h" #include "terraform_gui.h" @@ -50,6 +50,9 @@ #include "table/strings.h" +// #include "direction_type.h" +// #include "gfx_type.h" +#include "station_type.h" #include "station_func.h" #include "industry.h" #include "citymania/cm_highlight.hpp" @@ -81,11 +84,12 @@ struct RoadWaypointPickerSelection { }; static RoadWaypointPickerSelection _waypoint_gui; ///< Settings of the road waypoint picker. +/* Moved to cm_station_gui.hpp struct RoadStopPickerSelection { RoadStopClassID sel_class; ///< Selected road stop class. uint16_t sel_type; ///< Selected road stop type within the class. DiagDirection orientation; ///< Selected orientation of the road stop. -}; +}; */ /* CM static */ RoadStopPickerSelection _roadstop_gui; static bool IsRoadStopEverAvailable(const RoadStopSpec *spec, StationType type) @@ -1238,8 +1242,8 @@ static constexpr NWidgetPart _nested_build_road_depot_widgets[] = { NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_BROD_CAPTION), SetStringTip(STR_BUILD_DEPOT_ROAD_ORIENTATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), EndContainer(), NWidget(WWT_PANEL, COLOUR_DARK_GREEN), - NWidget(NWID_VERTICAL), SetPIP(0, 0, 0), - NWidget(NWID_HORIZONTAL_LTR), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1), SetPadding(WidgetDimensions::unscaled.picker), + NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), SetPadding(WidgetDimensions::unscaled.picker), + NWidget(NWID_HORIZONTAL_LTR), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROD_DEPOT_NW), SetFill(0, 0), SetToolTip(STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROD_DEPOT_SW), SetFill(0, 0), SetToolTip(STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP), @@ -1249,7 +1253,9 @@ static constexpr NWidgetPart _nested_build_road_depot_widgets[] = { NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROD_DEPOT_SE), SetFill(0, 0), SetToolTip(STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP), EndContainer(), EndContainer(), - NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROD_DEPOT_AUTO), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_BUILD_DEPOT_ROAD_ORIENTATION_AUTO_TOOLTIP), + NWidget(NWID_HORIZONTAL), SetPIP(0, 0, 0), SetPIPRatio(1, 0, 1), + NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROD_DEPOT_AUTO), SetMinimalSize(2 * 66 + WidgetDimensions::unscaled.hsep_normal, 12), SetFill(0, 0), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_BUILD_DEPOT_ROAD_ORIENTATION_AUTO_TOOLTIP), + EndContainer(), EndContainer(), NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROD_DEPOT_AUTO), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_BUILD_DEPOT_ROAD_ORIENTATION_AUTO_TOOLTIP), EndContainer(), @@ -1521,22 +1527,6 @@ public: size.height = ScaleGUITrad(PREVIEW_HEIGHT) + WidgetDimensions::scaled.fullbevel.Vertical(); break; - /* CityMania code start */ - case CM_WID_BROS_STATION_AUTO: - size.width = ScaleGUITrad(128 + 2) + 2 * WidgetDimensions::scaled.fullbevel.Horizontal(); - break; - case CM_WID_BROS_STATION_XY_AUTO: - if (RoadTypeIsTram(_cur_roadtype)) - size.width = ScaleGUITrad(128 + 2) + 2 * WidgetDimensions::scaled.fullbevel.Horizontal(); - else - size.width = ScaleGUITrad(64) + WidgetDimensions::scaled.fullbevel.Horizontal(); - break; - /* CityMania code end */ - - case WID_BROS_ACCEPTANCE: - size.height = this->coverage_height; - break; - default: this->PickerWindow::UpdateWidgetSize(widget, size, padding, fill, resize); break; @@ -1674,16 +1664,19 @@ static constexpr NWidgetPart _nested_road_station_picker_widgets[] = { NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetFill(0, 0), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1), - NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROS_STATION_AUTO), SetMinimalSize(134, 12), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROS_STATION_AUTO), SetMinimalSize(2 * 66 + WidgetDimensions::unscaled.hsep_normal, 12), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP), NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROS_STATION_XY_AUTO), SetMinimalSize(66, 12), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP), EndContainer(), EndContainer(), /* 2-orientation plane. */ - NWidget(NWID_VERTICAL), SetPIPRatio(0, 0, 1), + NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), NWidget(NWID_HORIZONTAL_LTR), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1), NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_X), SetFill(0, 0), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetFill(0, 0), EndContainer(), EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1), + NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROS_STATION_XY_AUTO), SetMinimalSize(2 * 66 + WidgetDimensions::unscaled.hsep_normal, 12), SetFill(0, 0), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP), + EndContainer(), EndContainer(), EndContainer(), NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE), SetFill(1, 0), @@ -1726,7 +1719,9 @@ static constexpr NWidgetPart _nested_tram_station_picker_widgets[] = { NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_X), SetFill(0, 0), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetFill(0, 0), EndContainer(), EndContainer(), - NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROS_STATION_XY_AUTO), SetMinimalSize(274, 12), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP), + NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), SetPIPRatio(1, 0, 1), + NWidget(WWT_TEXTBTN, COLOUR_GREY, CM_WID_BROS_STATION_XY_AUTO), SetMinimalSize(2 * 66 + WidgetDimensions::unscaled.hsep_normal, 12), SetFill(0, 0), SetStringTip(CM_STR_STATION_BUILD_ORIENTATION_AUTO, CM_STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP), + EndContainer(), NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE), SetFill(1, 0), NWidget(NWID_HORIZONTAL), SetPIPRatio(1, 0, 1), NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROS_LT_OFF), SetMinimalSize(60, 12), diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 51f8117274..08154655e1 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -2548,3 +2548,10 @@ void ShowSelectRoadWaypointIfNeeded(TileArea ta, StationPickerCmdProc proc) { ShowSelectBaseStationIfNeeded(ta, std::move(proc)); } + +namespace citymania { + void ShowSelectStationWindow(TileArea ta, StationPickerCmdProc&& proc) { + if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace(); + new SelectStationWindow(_select_station_desc, ta, std::move(proc)); + } +} diff --git a/src/table/settings/cmclient_settings.ini b/src/table/settings/cmclient_settings.ini index a8f00d1796..b588dce0c6 100644 --- a/src/table/settings/cmclient_settings.ini +++ b/src/table/settings/cmclient_settings.ini @@ -2,7 +2,7 @@ static void cm_v_RedrawStatusBar(int32 new_value); static void cm_v_RedrawGraphs(int32 new_value); -static constexpr std::initializer_list _station_mod_actions{"nothing", "full_load", "transfer", "unload_all", "feeder_load", "feeder_unload", "no_load"}; +static constexpr std::initializer_list _station_mod_actions{"nothing", "full_load", "transfer", "unload_all", "feeder_load", "feeder_unload", "no_load", "no_unload"}; static constexpr std::initializer_list _depot_mod_actions{"nothing", "service", "stop", "unbunch"}; static constexpr std::initializer_list _mod_keys{"none", "shift", "ctrl", "alt", "command"}; static constexpr std::initializer_list _shaded_tree_options{"always_off", "always_on", "as_server"}; @@ -69,7 +69,7 @@ var = gui.cm_ctrl_station_mod type = SLE_UINT8 flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania def = 1 -max = 6 +max = 7 full = _station_mod_actions str = CM_STR_CONFIG_SETTING_STATION_MOD_CTRL strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE @@ -80,7 +80,7 @@ var = gui.cm_shift_station_mod type = SLE_UINT8 flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania def = 0 -max = 6 +max = 7 full = _station_mod_actions str = CM_STR_CONFIG_SETTING_STATION_MOD_SHIFT strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE @@ -91,7 +91,7 @@ var = gui.cm_ctrl_shift_station_mod type = SLE_UINT8 flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania def = 2 -max = 6 +max = 7 full = _station_mod_actions str = CM_STR_CONFIG_SETTING_STATION_MOD_CTRL_SHIFT strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE @@ -102,7 +102,7 @@ var = gui.cm_alt_station_mod type = SLE_UINT8 flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania def = 4 -max = 6 +max = 7 full = _station_mod_actions str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE @@ -113,7 +113,7 @@ var = gui.cm_alt_shift_station_mod type = SLE_UINT8 flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania def = 3 -max = 6 +max = 7 full = _station_mod_actions str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT_SHIFT strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE @@ -124,7 +124,7 @@ var = gui.cm_alt_ctrl_station_mod type = SLE_UINT8 flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania def = 5 -max = 6 +max = 7 full = _station_mod_actions str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT_CTRL strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE diff --git a/src/widgets/rail_widget.h b/src/widgets/rail_widget.h index 21de8eec15..7fbd552f33 100644 --- a/src/widgets/rail_widget.h +++ b/src/widgets/rail_widget.h @@ -100,7 +100,7 @@ enum BuildRailDepotWidgets : WidgetID { WID_BRAD_DEPOT_SE, ///< Build a depot with the entrance in the south east. WID_BRAD_DEPOT_SW, ///< Build a depot with the entrance in the south west. WID_BRAD_DEPOT_NW, ///< Build a depot with the entrance in the north west. - WID_BRAD_DEPOT_AUTO, ///< Build a depot, autoselect entrance. + CM_WID_BRAD_DEPOT_AUTO, ///< Build a depot, autoselect entrance. }; /** Widgets of the #BuildRailWaypointWindow class. */