Merge branch 'v14'
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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<typename Func>
|
||||
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<TileIndex, ObjectTileHighlight> 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;
|
||||
|
||||
@@ -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<citymania::ObjectTileHighlight> {
|
||||
@@ -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::tuple<const StationSpec *, Axis, TileIndex, int16_t, int16_t>, std::vector<uint8_t>> _station_layout_cache;
|
||||
std::vector<uint8_t> &GetPreviewStationLayout(const StationSpec *statspec, Axis axis, TileArea area) {
|
||||
std::tuple<const StationSpec *, Axis, TileIndex, int16_t, int16_t> 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<byte> res_layout(numtracks * plat_len);
|
||||
it = _station_layout_cache.insert(it, {key, std::vector<uint8_t>(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<uint8_t>(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<uint16_t>(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<ResultSpriteGroup>();
|
||||
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<TileLayoutSpriteGroup>();
|
||||
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);
|
||||
|
||||
@@ -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> 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> action = nullptr;
|
||||
sp<Action> action = nullptr;
|
||||
public:
|
||||
virtual ~Tool() = default;
|
||||
virtual void Update(Point pt, TileIndex tile) = 0;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<uint32, uint32> 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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 <ImplementsRemoveHandler Handler>
|
||||
void RemoveAction<Handler>::Update(Point, TileIndex tile) {
|
||||
|
||||
void RemoveAction::Update(Point, TileIndex tile) {
|
||||
this->cur_tile = tile;
|
||||
}
|
||||
|
||||
template <ImplementsRemoveHandler Handler>
|
||||
bool RemoveAction<Handler>::HandleMousePress() {
|
||||
bool RemoveAction::HandleMousePress() {
|
||||
if (!IsValidTile(this->cur_tile)) return false;
|
||||
this->start_tile = this->cur_tile;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <ImplementsRemoveHandler Handler>
|
||||
void RemoveAction<Handler>::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 <ImplementsRemoveHandler Handler>
|
||||
std::optional<TileArea> RemoveAction<Handler>::GetArea() const {
|
||||
std::optional<TileArea> 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 <ImplementsRemoveHandler Handler>
|
||||
ToolGUIInfo RemoveAction<Handler>::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 <ImplementsRemoveHandler Handler>
|
||||
void RemoveAction<Handler>::OnStationRemoved(const Station *) {}
|
||||
void RemoveAction::OnStationRemoved(const Station *) {}
|
||||
|
||||
// --- PlacementAction ---
|
||||
|
||||
ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional<ObjectHighlight> ohl, up<Command> cmd, StationCoverageType sct, uint rad) {
|
||||
if (!cmd || !ohl.has_value()) return {};
|
||||
@@ -911,8 +898,8 @@ ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional<ObjectHighlight> ohl,
|
||||
}
|
||||
|
||||
// --- SizedPlacementAction ---
|
||||
template <ImplementsSizedPlacementHandler Handler>
|
||||
void SizedPlacementAction<Handler>::Update(Point, TileIndex tile) {
|
||||
|
||||
void SizedPlacementAction::Update(Point, TileIndex tile) {
|
||||
this->cur_tile = tile;
|
||||
if (UseImprovedStationJoin()) return;
|
||||
|
||||
@@ -920,7 +907,7 @@ void SizedPlacementAction<Handler>::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<cmd::BuildRailStation *>(cmdptr.get());
|
||||
if (cmd == nullptr) return;
|
||||
|
||||
@@ -967,88 +954,80 @@ void SizedPlacementAction<Handler>::Update(Point, TileIndex tile) {
|
||||
// }
|
||||
}
|
||||
|
||||
template <ImplementsSizedPlacementHandler Handler>
|
||||
bool SizedPlacementAction<Handler>::HandleMousePress() {
|
||||
bool SizedPlacementAction::HandleMousePress() {
|
||||
return IsValidTile(this->cur_tile);
|
||||
}
|
||||
|
||||
template <ImplementsSizedPlacementHandler Handler>
|
||||
void SizedPlacementAction<Handler>::HandleMouseRelease() {
|
||||
void SizedPlacementAction::HandleMouseRelease() {
|
||||
if (!IsValidTile(this->cur_tile)) return;
|
||||
this->handler.Execute(this->cur_tile);
|
||||
this->Execute(this->cur_tile);
|
||||
}
|
||||
|
||||
template <ImplementsSizedPlacementHandler Handler>
|
||||
ToolGUIInfo SizedPlacementAction<Handler>::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 <ImplementsSizedPlacementHandler Handler>
|
||||
void SizedPlacementAction<Handler>::OnStationRemoved(const Station *) {}
|
||||
void SizedPlacementAction::OnStationRemoved(const Station *) {}
|
||||
|
||||
// --- DragNDropPlacementAction ---
|
||||
|
||||
template <ImplementsDragNDropPlacementHandler Handler>
|
||||
std::optional<TileArea> DragNDropPlacementAction<Handler>::GetArea() const {
|
||||
std::optional<TileArea> 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 <ImplementsDragNDropPlacementHandler Handler>
|
||||
void DragNDropPlacementAction<Handler>::Update(Point, TileIndex tile) {
|
||||
void DragNDropPlacementAction::Update(Point, TileIndex tile) {
|
||||
this->cur_tile = tile;
|
||||
}
|
||||
|
||||
template <ImplementsDragNDropPlacementHandler Handler>
|
||||
bool DragNDropPlacementAction<Handler>::HandleMousePress() {
|
||||
bool DragNDropPlacementAction::HandleMousePress() {
|
||||
if (!IsValidTile(this->cur_tile)) return false;
|
||||
this->start_tile = this->cur_tile;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <ImplementsDragNDropPlacementHandler Handler>
|
||||
void DragNDropPlacementAction<Handler>::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 <ImplementsDragNDropPlacementHandler Handler>
|
||||
ToolGUIInfo DragNDropPlacementAction<Handler>::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 <ImplementsDragNDropPlacementHandler Handler>
|
||||
void DragNDropPlacementAction<Handler>::OnStationRemoved(const Station *) {}
|
||||
void DragNDropPlacementAction::OnStationRemoved(const Station *) {}
|
||||
|
||||
// --- StationSelectAction ---
|
||||
template <ImplementsStationSelectHandler Handler>
|
||||
void StationSelectAction<Handler>::Update(Point, TileIndex tile) { this->cur_tile = tile; }
|
||||
|
||||
template <ImplementsStationSelectHandler Handler>
|
||||
bool StationSelectAction<Handler>::HandleMousePress() { return true; }
|
||||
void StationSelectAction::Update(Point, TileIndex tile) {
|
||||
this->cur_tile = tile;
|
||||
}
|
||||
|
||||
template <ImplementsStationSelectHandler Handler>
|
||||
void StationSelectAction<Handler>::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<Handler>::HandleMouseRelease() {
|
||||
}
|
||||
}
|
||||
|
||||
template <ImplementsStationSelectHandler Handler>
|
||||
ToolGUIInfo StationSelectAction<Handler>::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<Handler>::GetGUIInfo() {
|
||||
return {hlmap, data, {}};
|
||||
}
|
||||
|
||||
template <ImplementsStationSelectHandler Handler>
|
||||
void StationSelectAction<Handler>::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<Command> &cmd) {
|
||||
if (auto rail_cmd = dynamic_cast<cmd::BuildRailStation *>(cmd.get())) {
|
||||
@@ -1105,41 +1082,54 @@ StationBuildTool::StationBuildTool() {
|
||||
ResetHighlightCoverageStation();
|
||||
}
|
||||
|
||||
template<typename Thandler, typename Tcallback, typename Targ>
|
||||
bool StationBuildTool::ExecuteBuildCommand(Thandler *handler, Tcallback callback, Targ arg) {
|
||||
if (auto mode = std::get_if<StationAction::Join>(&_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<Command>{std::move(cmd)}, callback](bool test, StationID to_join) -> bool {
|
||||
if (!cmd) return false;
|
||||
auto station_cmd = dynamic_cast<StationBuildCommand *>(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<typename Taction, typename Tcallback, typename Targ>
|
||||
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<Command>{std::move(cmd)}, callback](bool test, StationID to_join) -> bool {
|
||||
if (!cmd) return false;
|
||||
auto station_cmd = dynamic_cast<StationBuildCommand *>(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<Command> RailStationBuildTool::RemoveHandler::GetCommand(TileArea area) {
|
||||
up<Command> RailStationBuildTool::RemoveAction::GetCommand(TileArea area) {
|
||||
auto cmd = make_up<cmd::RemoveFromRailStation>(
|
||||
area.tile,
|
||||
area.CMGetEndTile(),
|
||||
@@ -1149,20 +1139,23 @@ up<Command> 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<TileArea> RailStationBuildTool::SizedPlacementHandler::GetArea(TileIndex tile) const {
|
||||
if (!IsValidTile(tile)) return std::nullopt;
|
||||
|
||||
// --- RailStationBuildTool::SizedPlacementAction ---
|
||||
|
||||
std::optional<TileArea> 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<Command> RailStationBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) {
|
||||
up<Command> RailStationBuildTool::SizedPlacementAction::GetCommand(TileIndex tile, StationID to_join) {
|
||||
// TODO mostly same as DragNDropPlacement
|
||||
auto cmd = make_up<cmd::BuildRailStation>(
|
||||
tile,
|
||||
@@ -1173,17 +1166,19 @@ up<Command> 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<Command> RailStationBuildTool::DragNDropPlacementHandler::GetCommand(TileArea area, StationID to_join) {
|
||||
// --- RailStationBuildTool::DragNDropPlacementAction ---
|
||||
|
||||
up<Command> RailStationBuildTool::DragNDropPlacementAction::GetCommand(TileArea area, StationID to_join) {
|
||||
uint numtracks = area.w;
|
||||
uint platlength = area.h;
|
||||
|
||||
@@ -1198,26 +1193,34 @@ up<Command> 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<ObjectHighlight> RailStationBuildTool::DragNDropPlacementHandler::GetObjectHighlight(TileArea area) {
|
||||
return this->tool.GetStationObjectHighlight(area.tile, area.CMGetEndTile());
|
||||
std::optional<ObjectHighlight> 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<ObjectHighlight> RailStationBuildTool::SizedPlacementHandler::GetObjectHighlight(TileIndex tile) {
|
||||
return this->tool.GetStationObjectHighlight(tile, INVALID_TILE);
|
||||
std::optional<ObjectHighlight> 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<SizedPlacementAction<SizedPlacementHandler>>(SizedPlacementHandler(*this));
|
||||
this->action = make_sp<RailStationBuildTool::SizedPlacementAction>();
|
||||
}
|
||||
|
||||
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<RemoveAction<RailStationBuildTool::RemoveHandler>>(*this);
|
||||
this->action = make_sp<RailStationBuildTool::RemoveAction>();
|
||||
break;
|
||||
case Mode::SELECT:
|
||||
this->action = make_up<StationSelectAction<StationBuildTool::StationSelectHandler>>(*this);
|
||||
this->action = make_sp<StationSelectAction>();
|
||||
break;
|
||||
case Mode::DRAGDROP:
|
||||
this->action = make_up<DragNDropPlacementAction<RailStationBuildTool::DragNDropPlacementHandler>>(*this);
|
||||
this->action = make_sp<RailStationBuildTool::DragNDropPlacementAction>();
|
||||
break;
|
||||
case Mode::SIZED:
|
||||
this->action = make_up<SizedPlacementAction<RailStationBuildTool::SizedPlacementHandler>>(*this);
|
||||
this->action = make_sp<RailStationBuildTool::SizedPlacementAction>();
|
||||
break;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
@@ -1253,86 +1256,96 @@ void RailStationBuildTool::Update(Point pt, TileIndex tile) {
|
||||
this->action->Update(pt, tile);
|
||||
}
|
||||
|
||||
std::optional<ObjectHighlight> 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<Command> RoadStopBuildTool::RemoveHandler::GetCommand(TileArea area) {
|
||||
up<Command> RoadStopBuildTool::RemoveAction::GetCommand(TileArea area) {
|
||||
auto cmd = make_up<cmd::RemoveRoadStop>(
|
||||
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<Command> 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<DiagDirection>(this->tool.ddir - DIAGDIR_END); // Adjust picker result to actual direction.
|
||||
up<Command> 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<DiagDirection>(this->ddir - DIAGDIR_END); // Adjust picker result to actual direction.
|
||||
|
||||
auto res = make_up<cmd::BuildRoadStop>(
|
||||
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<ObjectHighlight> RoadStopBuildTool::DragNDropPlacementHandler::GetObjectHighlight(TileArea area) {
|
||||
std::optional<ObjectHighlight> 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<DragNDropPlacementAction<RoadStopBuildTool::DragNDropPlacementHandler>>(*this);
|
||||
this->action = make_sp<RoadStopBuildTool::DragNDropPlacementAction>(_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<RemoveAction<RoadStopBuildTool::RemoveHandler>>(*this);
|
||||
this->action = make_sp<RoadStopBuildTool::RemoveAction>(this->stop_type);
|
||||
break;
|
||||
case Mode::SELECT:
|
||||
this->action = make_up<StationSelectAction<StationBuildTool::StationSelectHandler>>(*this);
|
||||
this->action = make_sp<StationSelectAction>();
|
||||
break;
|
||||
case Mode::DRAGDROP:
|
||||
this->action = make_up<DragNDropPlacementAction<RoadStopBuildTool::DragNDropPlacementHandler>>(*this);
|
||||
this->action = make_sp<RoadStopBuildTool::DragNDropPlacementAction>(_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<Command> DockBuildTool::RemoveHandler::GetCommand(TileArea area) {
|
||||
up<Command> 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<TileArea> 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<TileArea> 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<Command> DockBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) {
|
||||
up<Command> DockBuildTool::SizedPlacementAction::GetCommand(TileIndex tile, StationID to_join) {
|
||||
return make_up<cmd::BuildDock>(
|
||||
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<ObjectHighlight> DockBuildTool::SizedPlacementHandler::GetObjectHighlight(TileIndex tile) {
|
||||
return ObjectHighlight::make_dock(tile, this->tool.ddir);
|
||||
std::optional<ObjectHighlight> DockBuildTool::SizedPlacementAction::GetObjectHighlight(TileIndex tile) {
|
||||
return ObjectHighlight::make_dock(tile, this->GetDirection(tile).value_or(DIAGDIR_SE));
|
||||
}
|
||||
|
||||
std::optional<DiagDirection> 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<SizedPlacementAction<DockBuildTool::SizedPlacementHandler>>(*this);
|
||||
this->action = make_sp<DockBuildTool::SizedPlacementAction>();
|
||||
}
|
||||
|
||||
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<RemoveAction<DockBuildTool::RemoveHandler>>(*this);
|
||||
this->action = make_up<DockBuildTool::RemoveAction>();
|
||||
break;
|
||||
case Mode::SELECT:
|
||||
this->action = make_up<StationSelectAction<DockBuildTool::StationSelectHandler>>(*this);
|
||||
this->action = make_up<StationSelectAction>();
|
||||
break;
|
||||
case Mode::SIZED:
|
||||
this->action = make_up<SizedPlacementAction<DockBuildTool::SizedPlacementHandler>>(*this);
|
||||
this->action = make_up<DockBuildTool::SizedPlacementAction>();
|
||||
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<Command> AirportBuildTool::RemoveHandler::GetCommand(TileArea area) {
|
||||
up<Command> 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<TileArea> AirportBuildTool::SizedPlacementHandler::GetArea(TileIndex tile) const {
|
||||
if (!IsValidTile(tile)) return std::nullopt;
|
||||
std::optional<TileArea> 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<Command> AirportBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) {
|
||||
up<Command> 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<Command> 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<ObjectHighlight> AirportBuildTool::SizedPlacementHandler::GetObjectHighlight(TileIndex tile) {
|
||||
std::optional<ObjectHighlight> 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<StationCoverageType, uint> AirportBuildTool::SizedPlacementHandler::GetCatchmentParams() {
|
||||
std::pair<StationCoverageType, uint> 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<SizedPlacementAction<AirportBuildTool::SizedPlacementHandler>>(*this);
|
||||
this->action = make_sp<AirportBuildTool::SizedPlacementAction>();
|
||||
}
|
||||
|
||||
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<RemoveAction<AirportBuildTool::RemoveHandler>>(*this);
|
||||
this->action = make_sp<AirportBuildTool::RemoveAction>();
|
||||
break;
|
||||
case Mode::SELECT:
|
||||
this->action = make_up<StationSelectAction<AirportBuildTool::StationSelectHandler>>(*this);
|
||||
this->action = make_sp<StationSelectAction>();
|
||||
break;
|
||||
case Mode::SIZED:
|
||||
this->action = make_up<SizedPlacementAction<AirportBuildTool::SizedPlacementHandler>>(*this);
|
||||
this->action = make_sp<AirportBuildTool::SizedPlacementAction>();
|
||||
break;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
@@ -1563,17 +1553,4 @@ CursorID AirportBuildTool::GetCursor() {
|
||||
return SPR_CURSOR_AIRPORT;
|
||||
}
|
||||
|
||||
// --- Explicit template instantiations for handlers ---
|
||||
template class StationSelectAction<StationBuildTool::StationSelectHandler>;
|
||||
|
||||
template class DragNDropPlacementAction<RailStationBuildTool::DragNDropPlacementHandler>;
|
||||
template class RemoveAction<RailStationBuildTool::RemoveHandler>;
|
||||
template class SizedPlacementAction<RailStationBuildTool::SizedPlacementHandler>;
|
||||
|
||||
template class RemoveAction<RoadStopBuildTool::RemoveHandler>;
|
||||
template class DragNDropPlacementAction<RoadStopBuildTool::DragNDropPlacementHandler>;
|
||||
|
||||
template class RemoveAction<DockBuildTool::RemoveHandler>;
|
||||
template class SizedPlacementAction<DockBuildTool::SizedPlacementHandler>;
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
@@ -13,9 +13,19 @@
|
||||
#include <concepts>
|
||||
#include <optional>
|
||||
|
||||
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<uint, uint> 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<uint, uint> GetOrderDistances(VehicleOrderID prev, VehicleOrderID cur, const Vehicle *v, int conditional_depth = 0);
|
||||
|
||||
template<typename Func>
|
||||
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<Command> GetCommand(TileArea area) = 0;
|
||||
virtual bool Execute(TileArea area) = 0;
|
||||
};
|
||||
template<typename Handler>
|
||||
concept ImplementsRemoveHandler = std::derived_from<Handler, RemoveHandler>;
|
||||
|
||||
template<ImplementsRemoveHandler Handler>
|
||||
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<TileArea> GetArea() const override;
|
||||
@@ -90,24 +95,14 @@ public:
|
||||
void HandleMouseRelease() override;
|
||||
ToolGUIInfo GetGUIInfo() override;
|
||||
void OnStationRemoved(const Station *) override;
|
||||
virtual up<Command> GetCommand(TileArea area) = 0;
|
||||
virtual bool Execute(TileArea area) = 0;
|
||||
};
|
||||
|
||||
|
||||
// StationSelect classes
|
||||
class StationSelectHandler {
|
||||
public:
|
||||
virtual ~StationSelectHandler() = default;
|
||||
};
|
||||
template<typename Handler>
|
||||
concept ImplementsStationSelectHandler = std::derived_from<Handler, StationSelectHandler>;
|
||||
|
||||
template<ImplementsStationSelectHandler Handler>
|
||||
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<ObjectHighlight> ohl, up<Command> cmd, StationCoverageType sct, uint rad);
|
||||
};
|
||||
|
||||
// SizedPlacement classes
|
||||
class SizedPlacementHandler {
|
||||
public:
|
||||
virtual ~SizedPlacementHandler() = default;
|
||||
virtual up<Command> GetCommand(TileIndex tile, StationID to_join) = 0;
|
||||
virtual bool Execute(TileIndex tile) = 0;
|
||||
virtual std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) = 0;
|
||||
virtual std::pair<StationCoverageType, uint> GetCatchmentParams() = 0;
|
||||
virtual std::optional<TileArea> GetArea(TileIndex tile) const = 0;
|
||||
};
|
||||
template<typename Handler>
|
||||
concept ImplementsSizedPlacementHandler = std::derived_from<Handler, SizedPlacementHandler>;
|
||||
|
||||
template<ImplementsSizedPlacementHandler Handler>
|
||||
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<TileArea> 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<Command> GetCommand(TileArea area, StationID to_join) = 0;
|
||||
virtual bool Execute(TileArea area) = 0;
|
||||
virtual std::optional<ObjectHighlight> GetObjectHighlight(TileArea area) = 0;
|
||||
virtual up<Command> GetCommand(TileIndex tile, StationID to_join) = 0;
|
||||
virtual bool Execute(TileIndex tile) = 0;
|
||||
virtual std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) = 0;
|
||||
virtual std::pair<StationCoverageType, uint> GetCatchmentParams() = 0;
|
||||
};
|
||||
template<typename Handler>
|
||||
concept ImplementsDragNDropPlacementHandler = std::derived_from<Handler, DragNDropPlacementHandler>;
|
||||
|
||||
template<ImplementsDragNDropPlacementHandler Handler>
|
||||
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<TileArea> GetArea() const override;
|
||||
@@ -179,20 +146,14 @@ public:
|
||||
void HandleMouseRelease() override;
|
||||
ToolGUIInfo GetGUIInfo() override;
|
||||
void OnStationRemoved(const Station *) override;
|
||||
virtual up<Command> GetCommand(TileArea area, StationID to_join) = 0;
|
||||
virtual bool Execute(TileArea area) = 0;
|
||||
virtual std::optional<ObjectHighlight> GetObjectHighlight(TileArea area) = 0;
|
||||
virtual std::pair<StationCoverageType, uint> 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<typename Thandler, typename Tcallback, typename Targ>
|
||||
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<Command> 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<Command> GetCommand(TileIndex tile, StationID to_join) override;
|
||||
bool Execute(TileIndex tile) override;
|
||||
std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) override;
|
||||
std::pair<StationCoverageType, uint> GetCatchmentParams() override { return {this->tool.GetCatchmentParams()}; };
|
||||
std::optional<TileArea> GetArea(TileIndex tile) const override;
|
||||
std::pair<StationCoverageType, uint> GetCatchmentParams() override { return {SCT_ALL, CA_TRAIN}; };
|
||||
std::optional<TileArea> 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<Command> GetCommand(TileArea area, StationID to_join) override;
|
||||
bool Execute(TileArea area) override;
|
||||
std::optional<ObjectHighlight> GetObjectHighlight(TileArea area) override;
|
||||
std::pair<StationCoverageType, uint> GetCatchmentParams() override { return {this->tool.GetCatchmentParams()}; };
|
||||
std::pair<StationCoverageType, uint> GetCatchmentParams() override { return {SCT_ALL, CA_TRAIN}; };
|
||||
};
|
||||
|
||||
std::optional<ObjectHighlight> GetStationObjectHighlight(TileIndex start_tile, TileIndex end_tile) const;
|
||||
std::pair<StationCoverageType, uint> 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<Command> 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<Command> GetCommand(TileArea area, StationID to_join) override;
|
||||
bool Execute(TileArea area) override;
|
||||
std::optional<ObjectHighlight> GetObjectHighlight(TileArea area) override;
|
||||
std::pair<StationCoverageType, uint> GetCatchmentParams() override { return this->tool.GetCatchmentParams(); };
|
||||
std::pair<StationCoverageType, uint> GetCatchmentParams() override {
|
||||
if (this->stop_type == RoadStopType::Bus) return {SCT_PASSENGERS_ONLY, CA_BUS};
|
||||
else return {SCT_NON_PASSENGERS_ONLY, CA_TRUCK};
|
||||
}
|
||||
};
|
||||
|
||||
std::pair<StationCoverageType, uint> 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<Command> 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<Command> GetCommand(TileIndex tile, StationID to_join) override;
|
||||
bool Execute(TileIndex tile) override;
|
||||
std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) override;
|
||||
std::pair<StationCoverageType, uint> GetCatchmentParams() override { return {SCT_ALL, CA_DOCK}; };
|
||||
std::optional<TileArea> GetArea(TileIndex tile) const override;
|
||||
std::optional<TileArea> GetArea() const override;
|
||||
std::optional<DiagDirection> 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<Command> 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<Command> GetCommand(TileIndex tile, StationID to_join) override;
|
||||
bool Execute(TileIndex tile) override;
|
||||
std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) override;
|
||||
std::pair<StationCoverageType, uint> GetCatchmentParams() override;
|
||||
std::optional<TileArea> GetArea(TileIndex tile) const override;
|
||||
std::optional<TileArea> GetArea() const override;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
@@ -17,39 +17,17 @@ template<class T> using up=std::unique_ptr<T>;
|
||||
template<class T> using sp=std::shared_ptr<T>;
|
||||
template<class T> using wp=std::weak_ptr<T>;
|
||||
|
||||
/* C++14 implementation of make_unique */
|
||||
template<class T> struct _Unique_if {
|
||||
typedef std::unique_ptr<T> _Single_object;
|
||||
};
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto make_up(Args&&... args) {
|
||||
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class T> struct _Unique_if<T[]> {
|
||||
typedef std::unique_ptr<T[]> _Unknown_bound;
|
||||
};
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto make_sp(Args&&... args) {
|
||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class T, size_t N> struct _Unique_if<T[N]> {
|
||||
typedef void _Known_bound;
|
||||
};
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Single_object
|
||||
make_up(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename _Unique_if<T>::_Unknown_bound
|
||||
make_up(size_t n) {
|
||||
typedef typename std::remove_extent<T>::type U;
|
||||
return std::unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
make_up(Args&&...) = delete;
|
||||
|
||||
// template<typename T> const auto make_up = std::make_unique<T>;
|
||||
// template<typename T> const auto make_sp = std::make_shared<T>;
|
||||
template<typename T, class... Args> const auto make_sp = std::make_shared<T, Args...>;
|
||||
// template<typename T, class... Args> constexpr auto make_sp = std::make_shared<T, Args...>;
|
||||
|
||||
|
||||
enum class GameType: uint8_t {
|
||||
@@ -73,6 +51,15 @@ enum class ControllerType: uint8_t {
|
||||
TOWN_DEFENCE = 6,
|
||||
};
|
||||
|
||||
|
||||
// For use with std::visit
|
||||
template<typename ... Ts>
|
||||
struct Overload : Ts ... {
|
||||
using Ts::operator() ...;
|
||||
};
|
||||
template<class... Ts> Overload(Ts...) -> Overload<Ts...>;
|
||||
|
||||
|
||||
// Some utility funcitons for strings
|
||||
namespace string {
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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<Order, FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
|
||||
static std::pair<Order, citymania::FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
|
||||
{
|
||||
Order order{};
|
||||
|
||||
@@ -464,18 +388,10 @@ static std::pair<Order, FeederOrderMod> 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<Order, FeederOrderMod> 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<Order, FeederOrderMod> 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<Order, FeederOrderMod> 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<Order, FeederOrderMod> 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()
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -2548,3 +2548,10 @@ void ShowSelectRoadWaypointIfNeeded(TileArea ta, StationPickerCmdProc proc)
|
||||
{
|
||||
ShowSelectBaseStationIfNeeded<RoadWaypointTypeFilter>(ta, std::move(proc));
|
||||
}
|
||||
|
||||
namespace citymania {
|
||||
void ShowSelectStationWindow(TileArea ta, StationPickerCmdProc&& proc) {
|
||||
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
|
||||
new SelectStationWindow<StationTypeFilter>(_select_station_desc, ta, std::move(proc));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<std::string_view> _station_mod_actions{"nothing", "full_load", "transfer", "unload_all", "feeder_load", "feeder_unload", "no_load"};
|
||||
static constexpr std::initializer_list<std::string_view> _station_mod_actions{"nothing", "full_load", "transfer", "unload_all", "feeder_load", "feeder_unload", "no_load", "no_unload"};
|
||||
static constexpr std::initializer_list<std::string_view> _depot_mod_actions{"nothing", "service", "stop", "unbunch"};
|
||||
static constexpr std::initializer_list<std::string_view> _mod_keys{"none", "shift", "ctrl", "alt", "command"};
|
||||
static constexpr std::initializer_list<std::string_view> _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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user