1
0
Fork 0

Codechange: Use (Diag)Directions when drawing catenary.

pull/14231/head
Peter Nelson 2025-05-06 20:37:49 +01:00 committed by Peter Nelson
parent 87544eff0c
commit 1ac9f24f38
2 changed files with 129 additions and 128 deletions

View File

@ -83,7 +83,7 @@ static inline TLG GetTLG(TileIndex t)
* @param override pointer to PCP override, can be nullptr
* @return trackbits of tile if it is electrified
*/
static TrackBits GetRailTrackBitsUniversal(TileIndex t, uint8_t *override)
static TrackBits GetRailTrackBitsUniversal(TileIndex t, DiagDirections *override)
{
switch (GetTileType(t)) {
case MP_RAILWAY:
@ -100,7 +100,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, uint8_t *override)
if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (override != nullptr && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) {
*override = 1 << GetTunnelBridgeDirection(t);
*override = GetTunnelBridgeDirection(t);
}
return DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t));
@ -295,10 +295,10 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
}
TLG tlg = GetTLG(ti->tile);
uint8_t pcp_status = 0;
uint8_t override_pcp = 0;
uint8_t ppp_preferred[DIAGDIR_END];
uint8_t ppp_allowed[DIAGDIR_END];
DiagDirections pcp_status{};
DiagDirections override_pcp{};
std::array<Directions, DIAGDIR_END> ppp_preferred{};
std::array<Directions, DIAGDIR_END> ppp_allowed{};
/* Find which rail bits are present, and select the override points.
* We don't draw a pylon:
@ -343,7 +343,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
isflat[TS_NEIGHBOUR] = ((trackconfig[TS_NEIGHBOUR] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
ppp_preferred[i] = 0xFF; // We start with preferring everything (end-of-line in any direction)
ppp_preferred[i] = DIRECTIONS_ALL; // We start with preferring everything (end-of-line in any direction)
ppp_allowed[i] = AllowedPPPonPCP[i];
/* We cycle through all the existing tracks at a PCP and see what
@ -363,19 +363,19 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
/* track found, if track is in the neighbour tile, adjust the number
* of the PCP for preferred/allowed determination*/
pcp_pos = (TrackSourceTile[i][k] == TS_HOME) ? i : ReverseDiagDir(i);
SetBit(pcp_status, i); // This PCP is in use
pcp_status.Set(i); // This PCP is in use
ppp_preferred[i] &= PreferredPPPofTrackAtPCP[TracksAtPCP[i][k]][pcp_pos];
}
if (HasBit(trackconfig[TrackSourceTile[i][k]], TracksAtPCP[i][k])) {
ppp_allowed[i] &= ~DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][pcp_pos];
ppp_allowed[i].Reset(DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][pcp_pos]);
}
}
/* Deactivate all PPPs if PCP is not used */
if (!HasBit(pcp_status, i)) {
ppp_preferred[i] = 0;
ppp_allowed[i] = 0;
if (!pcp_status.Test(i)) {
ppp_preferred[i].Reset();
ppp_allowed[i].Reset();
}
Foundation foundation = FOUNDATION_NONE;
@ -402,7 +402,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
* Level means that the slope is the same, or the track is flat */
if (tileh[TS_HOME] == tileh[TS_NEIGHBOUR] || (isflat[TS_HOME] && isflat[TS_NEIGHBOUR])) {
for (uint k = 0; k < NUM_IGNORE_GROUPS; k++) {
if (ppp_preferred[i] == IgnoredPCP[k][tlg][i]) ClrBit(pcp_status, i);
if (ppp_preferred[i] == IgnoredPCP[k][tlg][i]) pcp_status.Reset(i);
}
}
@ -410,7 +410,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
* In that case, we try the any of the allowed ones. if they don't exist either, don't draw
* anything. Note that the preferred PPPs still contain the end-of-line markers.
* Remove those (simply by ANDing with allowed, since these markers are never allowed) */
if ((ppp_allowed[i] & ppp_preferred[i]) != 0) ppp_allowed[i] &= ppp_preferred[i];
if (ppp_allowed[i].Any(ppp_preferred[i])) ppp_allowed[i] &= ppp_preferred[i];
if (IsBridgeAbove(ti->tile)) {
Track bridgetrack = GetBridgeAxis(ti->tile) == AXIS_X ? TRACK_X : TRACK_Y;
@ -418,21 +418,23 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
if ((height <= GetTileMaxZ(ti->tile) + 1) &&
(i == PCPpositions[bridgetrack][0] || i == PCPpositions[bridgetrack][1])) {
SetBit(override_pcp, i);
override_pcp.Set(i);
}
}
if (ppp_allowed[i] != 0 && HasBit(pcp_status, i) && !HasBit(override_pcp, i) &&
if (ppp_allowed[i].Any() && pcp_status.Test(i) && !override_pcp.Test(i) &&
(!IsRailStationTile(ti->tile) || CanStationTileHavePylons(ti->tile))) {
for (Direction k = DIR_BEGIN; k < DIR_END; k++) {
uint8_t temp = PPPorder[i][GetTLG(ti->tile)][k];
if (HasBit(ppp_allowed[i], temp)) {
uint x = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp];
uint y = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp];
const auto &ppp_orders = PPPorder[i][GetTLG(ti->tile)];
for (Direction k = DIR_BEGIN; k < DIR_END; k++) {
Direction temp = ppp_orders[k];
if (ppp_allowed[i].Test(temp)) {
uint x = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp];
uint y = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp];
/* Don't build the pylon if it would be outside the tile */
if (!HasBit(OwnedPPPonPCP[i], temp)) {
if (!OwnedPPPonPCP[i].Test(temp)) {
/* We have a neighbour that will draw it, bail out */
if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE) break;
continue; // No neighbour, go looking for a better position
@ -474,8 +476,8 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
/* Drawing of pylons is finished, now draw the wires */
for (Track t : SetTrackBitIterator(wireconfig[TS_HOME])) {
SpriteID wire_base = (t == halftile_track) ? wire_halftile : wire_normal;
uint8_t pcp_config = HasBit(pcp_status, PCPpositions[t][0]) +
(HasBit(pcp_status, PCPpositions[t][1]) << 1);
uint8_t pcp_config = pcp_status.Test(PCPpositions[t][0]) +
(pcp_status.Test(PCPpositions[t][1]) << 1);
const SortableSpriteStruct *sss;
int tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3; // tileh for the slopes, 0 otherwise

View File

@ -40,11 +40,11 @@ enum TileSource : uint8_t {
static const uint NUM_TRACKS_AT_PCP = 6;
/** Which PPPs are possible at all on a given PCP */
static const uint8_t AllowedPPPonPCP[DIAGDIR_END] = {
1 << DIR_N | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S | 1 << DIR_W | 1 << DIR_NW,
1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W,
1 << DIR_N | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S | 1 << DIR_W | 1 << DIR_NW,
1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W,
static const Directions AllowedPPPonPCP[DIAGDIR_END] = {
{DIR_N, DIR_E, DIR_SE, DIR_S, DIR_W, DIR_NW},
{DIR_N, DIR_NE, DIR_E, DIR_S, DIR_SW, DIR_W},
{DIR_N, DIR_E, DIR_SE, DIR_S, DIR_W, DIR_NW},
{DIR_N, DIR_NE, DIR_E, DIR_S, DIR_SW, DIR_W},
};
/**
@ -52,11 +52,11 @@ static const uint8_t AllowedPPPonPCP[DIAGDIR_END] = {
* the following system is used: if you rotate the PCP so that it is in the
* north, the eastern PPP belongs to the tile.
*/
static const uint8_t OwnedPPPonPCP[DIAGDIR_END] = {
1 << DIR_SE | 1 << DIR_S | 1 << DIR_SW | 1 << DIR_W,
1 << DIR_N | 1 << DIR_SW | 1 << DIR_W | 1 << DIR_NW,
1 << DIR_N | 1 << DIR_NE | 1 << DIR_E | 1 << DIR_NW,
1 << DIR_NE | 1 << DIR_E | 1 << DIR_SE | 1 << DIR_S
static const Directions OwnedPPPonPCP[DIAGDIR_END] = {
{DIR_SE, DIR_S, DIR_SW, DIR_W},
{DIR_N, DIR_SW, DIR_W, DIR_NW},
{DIR_N, DIR_NE, DIR_E, DIR_NW},
{DIR_NE, DIR_E, DIR_SE, DIR_S},
};
/** Maps a track bit onto two PCP positions */
@ -69,138 +69,137 @@ static const DiagDirection PCPpositions[TRACK_END][2] = {
{DIAGDIR_NE, DIAGDIR_SE}, // RIGHT
};
#define PCP_NOT_ON_TRACK 0xFF
/**
* Preferred points of each trackbit. Those are the ones perpendicular to the
* track, plus the point in extension of the track (to mark end-of-track). PCPs
* which are not on either end of the track are fully preferred.
* @see PCPpositions
*/
static const uint8_t PreferredPPPofTrackAtPCP[TRACK_END][DIAGDIR_END] = {
{ // X
1 << DIR_NE | 1 << DIR_SE | 1 << DIR_NW, // NE
PCP_NOT_ON_TRACK, // SE
1 << DIR_SE | 1 << DIR_SW | 1 << DIR_NW, // SW
PCP_NOT_ON_TRACK // NE
}, { // Y
PCP_NOT_ON_TRACK,
1 << DIR_NE | 1 << DIR_SE | 1 << DIR_SW,
PCP_NOT_ON_TRACK,
1 << DIR_SW | 1 << DIR_NW | 1 << DIR_NE
}, { // UPPER
1 << DIR_E | 1 << DIR_N | 1 << DIR_S,
PCP_NOT_ON_TRACK,
PCP_NOT_ON_TRACK,
1 << DIR_W | 1 << DIR_N | 1 << DIR_S
}, { // LOWER
PCP_NOT_ON_TRACK,
1 << DIR_E | 1 << DIR_N | 1 << DIR_S,
1 << DIR_W | 1 << DIR_N | 1 << DIR_S,
PCP_NOT_ON_TRACK
}, { // LEFT
PCP_NOT_ON_TRACK,
PCP_NOT_ON_TRACK,
1 << DIR_S | 1 << DIR_E | 1 << DIR_W,
1 << DIR_N | 1 << DIR_E | 1 << DIR_W
}, { // RIGHT
1 << DIR_N | 1 << DIR_E | 1 << DIR_W,
1 << DIR_S | 1 << DIR_E | 1 << DIR_W,
PCP_NOT_ON_TRACK,
PCP_NOT_ON_TRACK
}
static const Directions PreferredPPPofTrackAtPCP[TRACK_END][DIAGDIR_END] = {
{ // X
{DIR_NE, DIR_SE, DIR_NW}, // NE
DIRECTIONS_ALL, // SE
{DIR_SE, DIR_SW, DIR_NW}, // SW
DIRECTIONS_ALL // NE
},
{ // Y
DIRECTIONS_ALL,
{DIR_NE, DIR_SE, DIR_SW},
DIRECTIONS_ALL,
{DIR_SW, DIR_NW, DIR_NE},
},
{ // UPPER
{DIR_E, DIR_N, DIR_S},
DIRECTIONS_ALL,
DIRECTIONS_ALL,
{DIR_W, DIR_N, DIR_S},
},
{ // LOWER
DIRECTIONS_ALL,
{DIR_E, DIR_N, DIR_S},
{DIR_W, DIR_N, DIR_S},
DIRECTIONS_ALL,
},
{ // LEFT
DIRECTIONS_ALL,
DIRECTIONS_ALL,
{DIR_S, DIR_E, DIR_W},
{DIR_N, DIR_E, DIR_W},
},
{ // RIGHT
{DIR_N, DIR_E, DIR_W},
{DIR_S, DIR_E, DIR_W},
DIRECTIONS_ALL,
DIRECTIONS_ALL,
},
};
#undef PCP_NOT_ON_TRACK
#define NUM_IGNORE_GROUPS 3
#define IGNORE_NONE 0xFF
/**
* In case we have a straight line, we place pylon only every two tiles,
* so there are certain tiles which we ignore. A straight line is found if
* we have exactly two PPPs.
*/
static const uint8_t IgnoredPCP[NUM_IGNORE_GROUPS][TLG_END][DIAGDIR_END] = {
static const Directions IgnoredPCP[NUM_IGNORE_GROUPS][TLG_END][DIAGDIR_END] = {
{ // Ignore group 1, X and Y tracks
{ // X even, Y even
IGNORE_NONE,
1 << DIR_NE | 1 << DIR_SW,
1 << DIR_NW | 1 << DIR_SE,
IGNORE_NONE
DIRECTIONS_ALL,
{DIR_NE, DIR_SW},
{DIR_NW, DIR_SE},
DIRECTIONS_ALL,
}, { // X even, Y odd
IGNORE_NONE,
IGNORE_NONE,
1 << DIR_NW | 1 << DIR_SE,
1 << DIR_NE | 1 << DIR_SW
DIRECTIONS_ALL,
DIRECTIONS_ALL,
{DIR_NW, DIR_SE},
{DIR_NE, DIR_SW},
}, { // X odd, Y even
1 << DIR_NW | 1 << DIR_SE,
1 << DIR_NE | 1 << DIR_SW,
IGNORE_NONE,
IGNORE_NONE
{DIR_NW, DIR_SE},
{DIR_NE, DIR_SW},
DIRECTIONS_ALL,
DIRECTIONS_ALL,
}, { // X odd, Y odd
1 << DIR_NW | 1 << DIR_SE,
IGNORE_NONE,
IGNORE_NONE,
1 << DIR_NE | 1 << DIR_SW
{DIR_NW, DIR_SE},
DIRECTIONS_ALL,
DIRECTIONS_ALL,
{DIR_NE, DIR_SW},
}
},
{ // Ignore group 2, LEFT and RIGHT tracks
{
1 << DIR_E | 1 << DIR_W,
IGNORE_NONE,
IGNORE_NONE,
1 << DIR_E | 1 << DIR_W
{DIR_E, DIR_W},
DIRECTIONS_ALL,
DIRECTIONS_ALL,
{DIR_E, DIR_W},
}, {
IGNORE_NONE,
1 << DIR_E | 1 << DIR_W,
1 << DIR_E | 1 << DIR_W,
IGNORE_NONE
DIRECTIONS_ALL,
{DIR_E, DIR_W},
{DIR_E, DIR_W},
DIRECTIONS_ALL,
}, {
IGNORE_NONE,
1 << DIR_E | 1 << DIR_W,
1 << DIR_E | 1 << DIR_W,
IGNORE_NONE
DIRECTIONS_ALL,
{DIR_E, DIR_W},
{DIR_E, DIR_W},
DIRECTIONS_ALL,
}, {
1 << DIR_E | 1 << DIR_W,
IGNORE_NONE,
IGNORE_NONE,
1 << DIR_E | 1 << DIR_W
{DIR_E, DIR_W},
DIRECTIONS_ALL,
DIRECTIONS_ALL,
{DIR_E, DIR_W},
}
},
{ // Ignore group 3, UPPER and LOWER tracks
{
1 << DIR_N | 1 << DIR_S,
1 << DIR_N | 1 << DIR_S,
IGNORE_NONE,
IGNORE_NONE
{DIR_N, DIR_S},
{DIR_N, DIR_S},
DIRECTIONS_ALL,
DIRECTIONS_ALL,
}, {
IGNORE_NONE,
IGNORE_NONE,
1 << DIR_N | 1 << DIR_S,
1 << DIR_N | 1 << DIR_S
DIRECTIONS_ALL,
DIRECTIONS_ALL,
{DIR_N, DIR_S},
{DIR_N, DIR_S},
}, {
IGNORE_NONE,
IGNORE_NONE,
1 << DIR_N | 1 << DIR_S ,
1 << DIR_N | 1 << DIR_S
DIRECTIONS_ALL,
DIRECTIONS_ALL,
{DIR_N, DIR_S},
{DIR_N, DIR_S},
}, {
1 << DIR_N | 1 << DIR_S,
1 << DIR_N | 1 << DIR_S,
IGNORE_NONE,
IGNORE_NONE
{DIR_N, DIR_S},
{DIR_N, DIR_S},
DIRECTIONS_ALL,
DIRECTIONS_ALL,
}
}
};
#undef NO_IGNORE
/** Which pylons can definitely NOT be built */
static const uint8_t DisallowedPPPofTrackAtPCP[TRACK_END][DIAGDIR_END] = {
{1 << DIR_SW | 1 << DIR_NE, 0, 1 << DIR_SW | 1 << DIR_NE, 0 }, // X
{0, 1 << DIR_NW | 1 << DIR_SE, 0, 1 << DIR_NW | 1 << DIR_SE}, // Y
{1 << DIR_W | 1 << DIR_E, 0, 0, 1 << DIR_W | 1 << DIR_E }, // UPPER
{0, 1 << DIR_W | 1 << DIR_E, 1 << DIR_W | 1 << DIR_E, 0 }, // LOWER
{0, 0, 1 << DIR_S | 1 << DIR_N, 1 << DIR_N | 1 << DIR_S }, // LEFT
{1 << DIR_S | 1 << DIR_N, 1 << DIR_S | 1 << DIR_N, 0, 0, }, // RIGHT
static const Directions DisallowedPPPofTrackAtPCP[TRACK_END][DIAGDIR_END] = {
{{DIR_SW, DIR_NE}, {}, {DIR_SW, DIR_NE}, {} }, // X
{{}, {DIR_NW, DIR_SE}, {}, {DIR_NW, DIR_SE}}, // Y
{{DIR_W, DIR_E}, {}, {}, {DIR_W, DIR_E} }, // UPPER
{{}, {DIR_W, DIR_E}, {DIR_W, DIR_E}, {} }, // LOWER
{{}, {}, {DIR_S, DIR_N}, {DIR_N, DIR_S} }, // LEFT
{{DIR_S, DIR_N}, {DIR_S, DIR_N}, {}, {}, }, // RIGHT
};
/* This array stores which track bits can meet at a tile edge */