Build preview for road stations

This commit is contained in:
dP
2021-03-20 13:54:01 +03:00
parent 5d512a4445
commit 4b727dc447
6 changed files with 270 additions and 213 deletions

View File

@@ -13,6 +13,7 @@
#include "../industry.h"
#include "../landscape.h"
#include "../newgrf_railtype.h"
#include "../newgrf_roadtype.h"
#include "../newgrf_station.h"
#include "../town.h"
#include "../town_kdtree.h"
@@ -38,8 +39,9 @@ extern const Station *_viewport_highlight_station;
extern TileHighlightData _thd;
extern bool IsInsideSelectedRectangle(int x, int y);
extern RailType _cur_railtype;
RoadBits FindRailsToConnect(TileIndex tile);
extern RoadType _cur_roadtype;
extern DiagDirection _build_depot_direction; ///< Currently selected depot direction
extern DiagDirection _road_station_picker_orientation;
extern uint32 _realtime_tick;
extern void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec);
@@ -53,7 +55,6 @@ struct RailStationGUISettings {
};
extern RailStationGUISettings _railstation; ///< Settings of the station builder GUI
namespace citymania {
extern void (*DrawTileSelectionRect)(const TileInfo *ti, PaletteID pal);
@@ -75,7 +76,7 @@ extern const Station *_station_to_join;
extern const Station *_highlight_station_to_join;
extern TileArea _highlight_join_area;
std::set<std::pair<uint32, const Town*>, std::greater<std::pair<uint32, const Town*> > > _town_cache;
std::set<std::pair<uint32, const Town*>, std::greater<std::pair<uint32, const Town*>>> _town_cache;
// struct {
// int w;
// int h;
@@ -127,12 +128,22 @@ ObjectTileHighlight ObjectTileHighlight::make_rail_tunnel_head(SpriteID palette,
return oh;
}
ObjectTileHighlight ObjectTileHighlight::make_road_stop(SpriteID palette, RoadType roadtype, DiagDirection ddir, bool is_truck) {
auto oh = ObjectTileHighlight(Type::ROAD_STOP, palette);
oh.u.road.stop.roadtype = roadtype;
oh.u.road.stop.ddir = ddir;
oh.u.road.stop.is_truck = is_truck;
return oh;
}
bool ObjectHighlight::operator==(const ObjectHighlight& oh) {
if (this->type != oh.type) return false;
return (this->tile == oh.tile
&& this->end_tile == oh.end_tile
&& this->axis == oh.axis
&& this->ddir == oh.ddir
&& this->roadtype == oh.roadtype
&& this->is_truck == oh.is_truck
&& this->blueprint == oh.blueprint);
// switch (this->type) {
// case Type::RAIL_DEPOT: return this->tile == oh.tile && this->ddir == oh.ddir;
@@ -161,6 +172,17 @@ ObjectHighlight ObjectHighlight::make_rail_station(TileIndex start_tile, TileInd
return oh;
}
ObjectHighlight ObjectHighlight::make_road_stop(TileIndex start_tile, TileIndex end_tile, RoadType roadtype, DiagDirection orientation, bool is_truck) {
auto oh = ObjectHighlight{ObjectHighlight::Type::ROAD_STOP};
oh.tile = start_tile;
oh.end_tile = end_tile;
oh.ddir = orientation;
oh.roadtype = roadtype;
oh.is_truck = is_truck;
return oh;
}
// ObjectHighlight ObjectHighlight::make_blueprint(TileIndex tile, sp<Blueprint> blueprint) {
// auto oh = ObjectHighlight{ObjectHighlight::Type::BLUEPRINT};
// oh.tile = tile;
@@ -269,6 +291,20 @@ void ObjectHighlight::UpdateTiles() {
break;
}
case Type::ROAD_STOP: {
auto ta = OrthogonalTileArea(this->tile, this->end_tile);
auto palette = (CanBuild(
this->tile,
(uint32)(ta.w | ta.h << 8),
(this->is_truck ? 1 : 0) | (this->ddir >= DIAGDIR_END ? 2 : 0) | (((uint)this->ddir % 4) << 3) | (NEW_STATION << 16),
CMD_BUILD_ROAD_STOP
) ? PALETTE_TINT_WHITE : PALETTE_TINT_RED_DEEP);
TileIndex tile;
TILE_AREA_LOOP(tile, ta) {
this->tiles.insert(std::make_pair(tile, ObjectTileHighlight::make_road_stop(palette, this->roadtype, this->ddir, this->is_truck)));
}
break;
}
// case Type::BLUEPRINT:
// if (this->blueprint && this->tile != INVALID_TILE)
// this->tiles = this->blueprint->GetTiles(this->tile);
@@ -397,6 +433,42 @@ void DrawTrainStationSprite(SpriteID palette, const TileInfo *ti, RailType railt
DrawRailTileSeq(ti, t, TO_INVALID, total_offset, 0, palette);
}
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) AddSortableSpriteToDraw(overlay + sprite_offset, palette, ti->x, ti->y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, ti->z);
} else if (RoadTypeIsTram(roadtype)) {
// DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y);
AddSortableSpriteToDraw(SPR_TRAMWAY_TRAM + sprite_offset, palette, ti->x, ti->y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, ti->z);
}
} else {
/* Drive-in stop */
if (RoadTypeIsRoad(roadtype) && rti->UsesOverlay()) {
SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_ROADSTOP);
// DrawSprite(, PAL_NONE, x, y);
AddSortableSpriteToDraw(ground + image, palette, ti->x, ti->y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, ti->z);
}
}
const DrawTileSprites *t = GetStationTileLayout(is_truck ? STATION_TRUCK : STATION_BUS, image);
DrawRailTileSeq(ti, t, TO_INVALID, total_offset, 0, palette);
/* Draw road, tram catenary */
// DrawRoadCatenary(ti);
}
enum SignalOffsets { // from rail_cmd.cpp
SIGNAL_TO_SOUTHWEST,
SIGNAL_TO_NORTHEAST,
@@ -548,6 +620,9 @@ void ObjectHighlight::Draw(const TileInfo *ti) {
case ObjectTileHighlight::Type::RAIL_TUNNEL_HEAD:
DrawTunnelHead(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);
break;
default:
break;
}
@@ -880,7 +955,8 @@ bool DrawTileSelection(const TileInfo *ti, const TileHighlightType &tht) {
// if (_thd.drawstyle == CM_HT_BLUEPRINT_PLACE) return true;
// if ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT && _thd.outersize.x > 0) {
if (_thd.select_proc == DDSP_BUILD_STATION || _thd.select_proc == DDSP_BUILD_STATION) {
if (_thd.select_proc == DDSP_BUILD_STATION || _thd.select_proc == DDSP_BUILD_BUSSTOP
|| _thd.select_proc == DDSP_BUILD_TRUCKSTOP) {
// station selector, handled by DrawTileZoning
return true;
}
@@ -903,47 +979,6 @@ bool DrawTileSelection(const TileInfo *ti, const TileHighlightType &tht) {
return false;
}
// almost duplicate from road_gui.cpp
static DiagDirection TileFractCoordsToDiagDir(Point pt) {
auto x = pt.x & TILE_UNIT_MASK;
auto y = pt.y & TILE_UNIT_MASK;
bool diag = (x + y) < 16;
if (x < y) {
return diag ? DIAGDIR_NE : DIAGDIR_SE;
}
return diag ? DIAGDIR_NW : DIAGDIR_SW;
}
// FIXME duplicate from road_gui.cpp
static DiagDirection RoadBitsToDiagDir(RoadBits bits) {
if (bits < ROAD_SE) {
return bits == ROAD_NW ? DIAGDIR_NW : DIAGDIR_SW;
}
return bits == ROAD_SE ? DIAGDIR_SE : DIAGDIR_NE;
}
DiagDirection AutodetectRailObjectDirection(TileIndex tile, Point pt) {
RoadBits bits = FindRailsToConnect(tile);
// FIXME after this point repeats road autodetection
if (HasExactlyOneBit(bits)) return RoadBitsToDiagDir(bits);
if (bits == ROAD_NONE) bits = ROAD_ALL;
RoadBits frac_bits = DiagDirToRoadBits(TileFractCoordsToDiagDir(pt));
if (HasExactlyOneBit(frac_bits & bits)) {
return RoadBitsToDiagDir(frac_bits & bits);
}
frac_bits |= MirrorRoadBits(frac_bits);
if (HasExactlyOneBit(frac_bits & bits)) {
return RoadBitsToDiagDir(frac_bits & bits);
}
for (DiagDirection ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
if (DiagDirToRoadBits(ddir) & bits) {
return ddir;
}
}
NOT_REACHED();
}
TileIndex _autodetection_tile = INVALID_TILE;
DiagDirDiff _autodetection_rotation = DIAGDIRDIFF_SAME;
@@ -973,6 +1008,7 @@ void ResetRotateAutodetection() {
}
DiagDirection AddAutodetectionRotation(DiagDirection ddir) {
if (ddir >= DIAGDIR_END) return (DiagDirection)(((uint)ddir + (uint)GetAutodetectionRotation()) % 2 + DIAGDIR_END);
return ChangeDiagDir(ddir, GetAutodetectionRotation());
}
@@ -985,6 +1021,7 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) {
// UpdateBlueprintTileSelection(pt, tile);
// new_drawstyle = CM_HT_BLUEPRINT_PLACE;
// } else
if (_thd.select_proc == CM_DDSP_BUILD_RAIL_DEPOT) {
auto dir = _build_depot_direction;
if (pt.x != -1) {
@@ -995,14 +1032,37 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) {
}
new_drawstyle = HT_RECT;
// } else if (((_thd.place_mode & HT_DRAG_MASK) == HT_RECT || ((_thd.place_mode & HT_DRAG_MASK) == HT_SPECIAL && (_thd.next_drawstyle & HT_DRAG_MASK) == HT_RECT)) && _thd.new_outersize.x > 0 && !_thd.make_square_red) { // station
} else if (_thd.select_proc == DDSP_BUILD_STATION) { // station
} else if (_thd.select_proc == DDSP_BUILD_STATION || _thd.select_proc == DDSP_BUILD_BUSSTOP
|| _thd.select_proc == DDSP_BUILD_TRUCKSTOP) { // station
if (_thd.size.x >= (int)TILE_SIZE && _thd.size.y >= (int)TILE_SIZE) {
auto start_tile = TileXY(_thd.new_pos.x / TILE_SIZE, _thd.new_pos.y / TILE_SIZE);
auto end_tile = TileXY(
std::min((_thd.new_pos.x + _thd.new_size.x) / TILE_SIZE, MapSizeX()) - 1,
std::min((_thd.new_pos.y + _thd.new_size.y) / TILE_SIZE, MapSizeY()) - 1
);
_thd.cm_new = ObjectHighlight::make_rail_station(start_tile, end_tile, _railstation.orientation);
if (_thd.select_proc == DDSP_BUILD_STATION)
_thd.cm_new = ObjectHighlight::make_rail_station(start_tile, end_tile, _railstation.orientation);
else if (_thd.select_proc == DDSP_BUILD_BUSSTOP || _thd.select_proc == DDSP_BUILD_TRUCKSTOP) {
auto ddir = _road_station_picker_orientation;
auto ta = TileArea(start_tile, end_tile);
if (pt.x != -1) {
if (ddir >= DIAGDIR_END && ddir < STATIONDIR_AUTO) {
// When placed on road autorotate anyway
if (ddir == STATIONDIR_X) {
if (!CheckDriveThroughRoadStopDirection(ta, ROAD_X))
ddir = STATIONDIR_Y;
} else {
if (!CheckDriveThroughRoadStopDirection(ta, ROAD_Y))
ddir = STATIONDIR_X;
}
} else if (ddir == STATIONDIR_AUTO) {
ddir = AddAutodetectionRotation(AutodetectRoadObjectDirection(start_tile, pt, _cur_roadtype));
} else if (ddir == STATIONDIR_AUTO_XY) {
ddir = AddAutodetectionRotation(AutodetectDriveThroughRoadStopDirection(ta, pt, _cur_roadtype));
}
}
_thd.cm_new = ObjectHighlight::make_road_stop(start_tile, end_tile, _cur_roadtype, ddir, _thd.select_proc == DDSP_BUILD_TRUCKSTOP);
}
}
new_drawstyle = HT_RECT;
}

View File

@@ -4,6 +4,7 @@
#include "../bridge.h"
#include "../direction_type.h"
#include "../map_func.h"
#include "../road_type.h"
#include "../signal_type.h"
#include "../station_type.h"
#include "../tile_cmd.h"
@@ -27,6 +28,7 @@ public:
RAIL_SIGNAL,
RAIL_BRIDGE_HEAD,
RAIL_TUNNEL_HEAD,
ROAD_STOP,
END,
};
@@ -57,6 +59,13 @@ public:
DiagDirection ddir;
} tunnel_head;
} rail;
struct {
struct {
RoadType roadtype;
DiagDirection ddir;
bool is_truck;
} stop;
} road;
} u;
ObjectTileHighlight(Type type, SpriteID palette): type{type}, palette{palette} {}
@@ -66,6 +75,8 @@ public:
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);
static ObjectTileHighlight make_road_stop(SpriteID palette, RoadType roadtype, DiagDirection ddir, bool is_truck);
};
class TileIndexDiffCCompare{
@@ -165,6 +176,7 @@ public:
NONE = 0,
RAIL_DEPOT = 1,
RAIL_STATION = 2,
ROAD_STOP = 3,
// BLUEPRINT = 2,
};
@@ -173,6 +185,8 @@ public:
TileIndex end_tile = INVALID_TILE;
Axis axis = INVALID_AXIS;
DiagDirection ddir = INVALID_DIAGDIR;
RoadType roadtype = INVALID_ROADTYPE;
bool is_truck = false;
sp<Blueprint> blueprint = nullptr;
protected:
@@ -189,6 +203,7 @@ public:
static ObjectHighlight make_rail_depot(TileIndex tile, DiagDirection ddir);
static ObjectHighlight make_rail_station(TileIndex start_tile, TileIndex end_tile, Axis axis);
// static ObjectHighlight make_blueprint(TileIndex tile, sp<Blueprint> blueprint);
static ObjectHighlight make_road_stop(TileIndex start_tile, TileIndex end_tile, RoadType roadtype, DiagDirection orientation, bool is_truck);
void Draw(const TileInfo *ti);
void MarkDirty();

View File

@@ -35,11 +35,9 @@ extern TileHighlightData _thd;
extern void MarkCatchmentTilesDirty();
extern DiagDirection _road_station_picker_orientation;
extern bool CheckDriveThroughRoadStopDirection(TileArea area, RoadBits r);
extern DiagDirection AutodetectRoadObjectDirection(TileIndex tile);
extern DiagDirection AutodetectDriveThroughRoadStopDirection(TileArea area);
extern bool CheckClickOnViewportSign(const ViewPort *vp, int x, int y, const ViewportSign *sign);
extern Rect ExpandRectWithViewportSignMargins(Rect r, ZoomLevel zoom);
extern RoadBits FindRailsToConnect(TileIndex tile);
extern ViewportSignKdtree _viewport_sign_kdtree;
extern AirportClassID _selected_airport_class;
extern int _selected_airport_index;
@@ -225,33 +223,141 @@ void JoinAndBuild(CommandContainer cmdcont) {
DoCommandP(&cmdcont);
}
static DiagDirection TileFractCoordsToDiagDir(Point pt) {
auto x = pt.x & TILE_UNIT_MASK;
auto y = pt.y & TILE_UNIT_MASK;
bool diag = (x + y) < 16;
if (x < y) {
return diag ? DIAGDIR_NE : DIAGDIR_SE;
}
return diag ? DIAGDIR_NW : DIAGDIR_SW;
}
static DiagDirection RoadBitsToDiagDir(RoadBits bits) {
if (bits < ROAD_SE) {
return bits == ROAD_NW ? DIAGDIR_NW : DIAGDIR_SW;
}
return bits == ROAD_SE ? DIAGDIR_SE : DIAGDIR_NE;
}
DiagDirection AutodetectRailObjectDirection(TileIndex tile, Point pt) {
RoadBits bits = FindRailsToConnect(tile);
// FIXME after this point repeats road autodetection
if (HasExactlyOneBit(bits)) return RoadBitsToDiagDir(bits);
if (bits == ROAD_NONE) bits = ROAD_ALL;
RoadBits frac_bits = DiagDirToRoadBits(TileFractCoordsToDiagDir(pt));
if (HasExactlyOneBit(frac_bits & bits)) {
return RoadBitsToDiagDir(frac_bits & bits);
}
frac_bits |= MirrorRoadBits(frac_bits);
if (HasExactlyOneBit(frac_bits & bits)) {
return RoadBitsToDiagDir(frac_bits & bits);
}
for (DiagDirection ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
if (DiagDirToRoadBits(ddir) & bits) {
return ddir;
}
}
NOT_REACHED();
}
static RoadBits FindRoadsToConnect(TileIndex tile, RoadType roadtype) {
RoadBits bits = ROAD_NONE;
DiagDirection ddir;
auto cur_rtt = GetRoadTramType(roadtype);
// Prioritize roadbits that head in this direction
for (ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
TileIndex cur_tile = TileAddByDiagDir(tile, ddir);
if (GetAnyRoadBits(cur_tile, cur_rtt, true) &
DiagDirToRoadBits(ReverseDiagDir(ddir)))
{
bits |= DiagDirToRoadBits(ddir);
}
}
if (bits != ROAD_NONE) {
return bits;
}
// Try to connect to any road passing by
for (ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
TileIndex cur_tile = TileAddByDiagDir(tile, ddir);
if (GetTileType(cur_tile) == MP_ROAD && HasTileRoadType(cur_tile, cur_rtt) &&
(GetRoadTileType(cur_tile) == ROAD_TILE_NORMAL)) {
bits |= DiagDirToRoadBits(ddir);
}
}
return bits;
}
bool CheckDriveThroughRoadStopDirection(TileArea area, RoadBits r) {
TILE_AREA_LOOP(tile, area) {
if (GetTileType(tile) != MP_ROAD) continue;
if (GetRoadTileType(tile) != ROAD_TILE_NORMAL) continue;
if (GetAllRoadBits(tile) & ~r) return false;
}
return true;
}
/*
* Selects orientation for road object (depot, terminal station)
*/
DiagDirection AutodetectRoadObjectDirection(TileIndex tile, Point pt, RoadType roadtype) {
RoadBits bits = FindRoadsToConnect(tile, roadtype);
if (HasExactlyOneBit(bits)) {
return RoadBitsToDiagDir(bits);
}
if (bits == ROAD_NONE){
bits = ROAD_ALL;
}
RoadBits frac_bits = DiagDirToRoadBits(TileFractCoordsToDiagDir(pt));
if (HasExactlyOneBit(frac_bits & bits)) {
return RoadBitsToDiagDir(frac_bits & bits);
}
frac_bits |= MirrorRoadBits(frac_bits);
if (HasExactlyOneBit(frac_bits & bits)) {
return RoadBitsToDiagDir(frac_bits & bits);
}
for (DiagDirection ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
if (DiagDirToRoadBits(ddir) & bits) {
return ddir;
}
}
NOT_REACHED();
}
/*
* Automaticaly selects direction to use for road stop.
* @param area road stop area
* @return selected direction
*/
DiagDirection AutodetectDriveThroughRoadStopDirection(TileArea area, Point pt, RoadType roadtype) {
bool se_suits, ne_suits;
// Check which direction is available
// If both are not use SE, building will fail anyway
se_suits = CheckDriveThroughRoadStopDirection(area, ROAD_Y);
ne_suits = CheckDriveThroughRoadStopDirection(area, ROAD_X);
if (!ne_suits) return STATIONDIR_Y;
if (!se_suits) return STATIONDIR_X;
// Build station along the longer direction
if (area.w > area.h) return STATIONDIR_X;
if (area.w < area.h) return STATIONDIR_Y;
return DiagDirToAxis(AutodetectRoadObjectDirection(area.tile, pt, roadtype)) == AXIS_X ? STATIONDIR_X : STATIONDIR_Y;
}
void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, uint32 cmd) {
uint8 ddir = _road_station_picker_orientation;
assert(_thd.cm.type == citymania::ObjectHighlight::Type::ROAD_STOP);
uint8 ddir = _thd.cm.ddir;
SB(p2, 16, 16, INVALID_STATION); // no station to join
TileArea ta(start_tile, end_tile);
if (CheckStationJoin(start_tile, end_tile)) return;
if (ddir >= DIAGDIR_END) {
if (ddir < DIAGDIR_END + 2) {
SetBit(p2, 1); // It's a drive-through stop.
ddir -= DIAGDIR_END; // Adjust picker result to actual direction.
// When placed on road autorotate anyway
if (ddir == DIAGDIR_SE) {
if (!CheckDriveThroughRoadStopDirection(ta, ROAD_Y))
ddir = DIAGDIR_NE;
} else {
if (!CheckDriveThroughRoadStopDirection(ta, ROAD_X))
ddir = DIAGDIR_SE;
}
}
else if (ddir == DIAGDIR_END + 2) {
ddir = AutodetectRoadObjectDirection(start_tile);
}
else if (ddir == DIAGDIR_END + 3) {
SetBit(p2, 1); // It's a drive-through stop.
ddir = AutodetectDriveThroughRoadStopDirection(ta);
}
if (ddir >= DIAGDIR_END) { // drive-through stops
SetBit(p2, 1);
ddir -= DIAGDIR_END;
}
p2 |= ddir << 3; // Set the DiagDirecion into p2 bits 3 and 4.

View File

@@ -3,11 +3,17 @@
#include "../core/geometry_type.hpp"
#include "../command_type.h"
#include "../road_type.h"
#include "../station_gui.h"
#include "../station_type.h"
namespace citymania {
const DiagDirection STATIONDIR_X = DIAGDIR_END;
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);
enum class StationBuildingStatus {
IMPOSSIBLE = 0,
QUERY = 1,
@@ -34,6 +40,11 @@ void AbortStationPlacement();
std::string GetStationCoverageProductionText(TileIndex tile, int w, int h, int rad, StationCoverageType sct);
bool CheckDriveThroughRoadStopDirection(TileArea area, RoadBits r);
DiagDirection AutodetectRoadObjectDirection(TileIndex tile, Point pt, RoadType roadtype);
DiagDirection AutodetectDriveThroughRoadStopDirection(TileArea area, Point pt, RoadType roadtype);
DiagDirection AutodetectRailObjectDirection(TileIndex tile, Point pt);
} // namespace citymania
#endif

View File

@@ -460,24 +460,6 @@ static void HandleAutoSignalPlacement()
CcPlaySound_SPLAT_RAIL);
}
// FIXME duplicate from road_gui.cpp
static DiagDirection TileFractCoordsToDiagDir() {
bool diag = (_tile_fract_coords.x + _tile_fract_coords.y) < 16;
if (_tile_fract_coords.x < _tile_fract_coords.y) {
return diag ? DIAGDIR_NE : DIAGDIR_SE;
}
return diag ? DIAGDIR_NW : DIAGDIR_SW;
}
// FIXME duplicate from road_gui.cpp
static DiagDirection RoadBitsToDiagDir(RoadBits bits) {
if (bits < ROAD_SE) {
return bits == ROAD_NW ? DIAGDIR_NW : DIAGDIR_SW;
}
return bits == ROAD_SE ? DIAGDIR_SE : DIAGDIR_NE;
}
RoadBits FindRailsToConnect(TileIndex tile) {
RoadBits directed = ROAD_NONE;
RoadBits passing = ROAD_NONE;

View File

@@ -67,7 +67,7 @@ DECLARE_ENUM_AS_BIT_SET(RoadFlags)
static RoadFlags _place_road_flag;
static RoadType _cur_roadtype;
/* CM static */ RoadType _cur_roadtype;
static DiagDirection _road_depot_orientation;
DiagDirection _road_station_picker_orientation;
@@ -176,107 +176,6 @@ void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2,
}
}
static RoadBits FindRoadsToConnect(TileIndex tile) {
RoadBits bits = ROAD_NONE;
DiagDirection ddir;
auto cur_rtt = GetRoadTramType(_cur_roadtype);
// Prioritize roadbits that head in this direction
for (ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
TileIndex cur_tile = TileAddByDiagDir(tile, ddir);
if (GetAnyRoadBits(cur_tile, cur_rtt, true) &
DiagDirToRoadBits(ReverseDiagDir(ddir)))
{
bits |= DiagDirToRoadBits(ddir);
}
}
if (bits != ROAD_NONE) {
return bits;
}
// Try to connect to any road passing by
for (ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
TileIndex cur_tile = TileAddByDiagDir(tile, ddir);
if (GetTileType(cur_tile) == MP_ROAD && HasTileRoadType(cur_tile, cur_rtt) &&
(GetRoadTileType(cur_tile) == ROAD_TILE_NORMAL)) {
bits |= DiagDirToRoadBits(ddir);
}
}
return bits;
}
static DiagDirection RoadBitsToDiagDir(RoadBits bits) {
if (bits < ROAD_SE) {
return bits == ROAD_NW ? DIAGDIR_NW : DIAGDIR_SW;
}
return bits == ROAD_SE ? DIAGDIR_SE : DIAGDIR_NE;
}
static DiagDirection TileFractCoordsToDiagDir() {
bool diag = (_tile_fract_coords.x + _tile_fract_coords.y) < 16;
if (_tile_fract_coords.x < _tile_fract_coords.y) {
return diag ? DIAGDIR_NE : DIAGDIR_SE;
}
return diag ? DIAGDIR_NW : DIAGDIR_SW;
}
/*
* Selects orientation for road object (depot, terminal station)
*/
DiagDirection AutodetectRoadObjectDirection(TileIndex tile) {
RoadBits bits = FindRoadsToConnect(tile);
if (HasExactlyOneBit(bits)) {
return RoadBitsToDiagDir(bits);
}
if (bits == ROAD_NONE){
bits = ROAD_ALL;
}
RoadBits frac_bits = DiagDirToRoadBits(TileFractCoordsToDiagDir());
if (HasExactlyOneBit(frac_bits & bits)) {
return RoadBitsToDiagDir(frac_bits & bits);
}
frac_bits |= MirrorRoadBits(frac_bits);
if (HasExactlyOneBit(frac_bits & bits)) {
return RoadBitsToDiagDir(frac_bits & bits);
}
for (DiagDirection ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
if (DiagDirToRoadBits(ddir) & bits) {
return ddir;
}
}
NOT_REACHED();
}
bool CheckDriveThroughRoadStopDirection(TileArea area, RoadBits r) {
TILE_AREA_LOOP(tile, area) {
if (GetTileType(tile) != MP_ROAD) continue;
if (GetRoadTileType(tile) != ROAD_TILE_NORMAL) continue;
if (GetAllRoadBits(tile) & ~r) return false;
}
return true;
}
/*
* Automaticaly selects direction to use for road stop.
* @param area road stop area
* @return selected direction
*/
DiagDirection AutodetectDriveThroughRoadStopDirection(TileArea area) {
bool se_suits, ne_suits;
// Check which direction is available
// If both are not use SE, building will fail anyway
se_suits = CheckDriveThroughRoadStopDirection(area, ROAD_Y);
ne_suits = CheckDriveThroughRoadStopDirection(area, ROAD_X);
if (!ne_suits) return DIAGDIR_SE;
if (!se_suits) return DIAGDIR_NE;
// Build station along the longer direction
if (area.w > area.h) return DIAGDIR_NE;
if (area.w < area.h) return DIAGDIR_SE;
return AutodetectRoadObjectDirection(area.tile);
}
/**
* Place a new road stop.
* @param start_tile First tile of the area.
@@ -294,30 +193,14 @@ static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, u
return;
}
uint8 ddir = _road_station_picker_orientation;
assert(_thd.cm.type == citymania::ObjectHighlight::Type::ROAD_STOP);
uint8 ddir = _thd.cm.ddir;
SB(p2, 16, 16, INVALID_STATION); // no station to join
TileArea ta(start_tile, end_tile);
if (ddir >= DIAGDIR_END) {
if (ddir < DIAGDIR_END + 2) {
SetBit(p2, 1); // It's a drive-through stop.
ddir -= DIAGDIR_END; // Adjust picker result to actual direction.
// When placed on road autorotate anyway
if (ddir == DIAGDIR_SE) {
if (!CheckDriveThroughRoadStopDirection(ta, ROAD_Y))
ddir = DIAGDIR_NE;
} else {
if (!CheckDriveThroughRoadStopDirection(ta, ROAD_X))
ddir = DIAGDIR_SE;
}
}
else if (ddir == DIAGDIR_END + 2) {
ddir = AutodetectRoadObjectDirection(start_tile);
}
else if (ddir == DIAGDIR_END + 3) {
SetBit(p2, 1); // It's a drive-through stop.
ddir = AutodetectDriveThroughRoadStopDirection(ta);
}
if (ddir >= DIAGDIR_END) { // drive-through stops
SetBit(p2, 1);
ddir -= DIAGDIR_END;
}
p2 |= ddir << 3; // Set the DiagDirecion into p2 bits 3 and 4.
@@ -662,7 +545,7 @@ struct BuildRoadToolbarWindow : Window {
case WID_ROT_DEPOT:
ddir = _road_depot_orientation;
if (ddir == DIAGDIR_NW + 1) {
ddir = AutodetectRoadObjectDirection(tile);
ddir = citymania::AutodetectRoadObjectDirection(tile, GetTileBelowCursor(), _cur_roadtype);
}
DoCommandP(tile, _cur_roadtype << 2 | ddir, 0,
CMD_BUILD_ROAD_DEPOT | CMD_MSG(this->rti->strings.err_depot), CcRoadDepot);