Build preview for road stations
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
131
src/road_gui.cpp
131
src/road_gui.cpp
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user