merge stations autorotate branch

This commit is contained in:
Pavel Stupnikov
2014-04-17 17:13:55 +04:00
2 changed files with 244 additions and 39 deletions
+87 -18
View File
@@ -415,6 +415,68 @@ static void HandleAutoSignalPlacement()
}
// 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;
DiagDirection ddir;
for (ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
TileIndex cur_tile = TileAddByDiagDir(tile, ddir);
if (!IsTileType(cur_tile, MP_RAILWAY)) continue;
if (!IsPlainRail(cur_tile)) continue;
passing |= DiagDirToRoadBits(ddir);
if (GetTrackBits(cur_tile) & DiagdirReachesTracks(ddir)) {
directed |= DiagDirToRoadBits(ddir);
}
}
// Prioritize track bits that head in this direction
if (directed != ROAD_NONE) {
return directed;
}
return passing;
}
/*
* Selects orientation for rail object (depot)
*/
static DiagDirection AutodetectRailObjectDirection(TileIndex tile) {
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());
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();
}
/** Rail toolbar management class. */
struct BuildRailToolbarWindow : Window {
RailType railtype; ///< Rail type to build.
@@ -625,6 +687,7 @@ struct BuildRailToolbarWindow : Window {
virtual void OnPlaceObject(Point pt, TileIndex tile)
{
DiagDirection ddir;
switch (this->last_user_action) {
case WID_RAT_BUILD_NS:
VpStartPlaceSizing(tile, VPM_FIX_VERTICAL | VPM_RAILDIRS, DDSP_PLACE_RAIL);
@@ -652,7 +715,11 @@ struct BuildRailToolbarWindow : Window {
break;
case WID_RAT_BUILD_DEPOT:
DoCommandP(tile, _cur_railtype, _build_depot_direction,
ddir = _build_depot_direction;
if (ddir == DIAGDIR_NW + 1) {
ddir = AutodetectRailObjectDirection(tile);
}
DoCommandP(tile, _cur_railtype, ddir,
CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT),
CcRailDepot);
break;
@@ -1713,6 +1780,7 @@ struct BuildRailDepotWindow : public PickerWindowBase {
case WID_BRAD_DEPOT_SE:
case WID_BRAD_DEPOT_SW:
case WID_BRAD_DEPOT_NW:
case WID_BRAD_DEPOT_AUTO:
this->RaiseWidget(_build_depot_direction + WID_BRAD_DEPOT_NE);
_build_depot_direction = (DiagDirection)(widget - WID_BRAD_DEPOT_NE);
this->LowerWidget(_build_depot_direction + WID_BRAD_DEPOT_NE);
@@ -1731,23 +1799,24 @@ static const NWidgetPart _nested_build_depot_widgets[] = {
EndContainer(),
NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
NWidget(NWID_HORIZONTAL_LTR),
NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
NWidget(NWID_VERTICAL),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_NW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_SW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(2, 0),
NWidget(NWID_VERTICAL),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_NE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_SE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_NW), SetMinimalSize(66, 50), SetFill(0, 0), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_SW), SetMinimalSize(66, 50), SetFill(0, 0), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_NE), SetMinimalSize(66, 50), SetFill(0, 0), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BRAD_DEPOT_SE), SetMinimalSize(66, 50), SetFill(0, 0), SetDataTip(0x0, STR_BUILD_DEPOT_TRAIN_ORIENTATION_TOOLTIP), EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_AUTO), SetMinimalSize(134, 12),
SetDataTip(STR_STATION_BUILD_ORIENTATION_AUTO, STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
@@ -1865,7 +1934,7 @@ static void ShowBuildWaypointPicker(Window *parent)
*/
void InitializeRailGui()
{
_build_depot_direction = DIAGDIR_NW;
_build_depot_direction = (DiagDirection)(DIAGDIR_NW + 1);
}
/**
+157 -21
View File
@@ -11,7 +11,9 @@
#include "stdafx.h"
#include "gui.h"
#include "cmd_helper.h"
#include "window_gui.h"
#include "station_func.h"
#include "station_gui.h"
#include "terraform_gui.h"
#include "viewport_func.h"
@@ -208,6 +210,103 @@ void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
}
}
static RoadBits FindRoadsToConnect(TileIndex tile) {
RoadBits bits = ROAD_NONE;
DiagDirection ddir;
// 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, ROADTYPE_ROAD, 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 (HasTileRoadType(cur_tile, ROADTYPE_ROAD) && (GetTileType(cur_tile) == MP_ROAD) &&
(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)
*/
static 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();
}
static bool CheckDriveThroughRoadStopDirection(TileArea area, RoadBits r) {
TILE_AREA_LOOP(tile, area) {
if (!HasTileRoadType(tile, ROADTYPE_ROAD)) continue;
if (GetTileType(tile) != MP_ROAD) continue;
if (GetRoadTileType(tile) != ROAD_TILE_NORMAL) continue;
if (GetRoadBits(tile, ROADTYPE_ROAD) & ~r) return false;
}
return true;
}
/*
* Automaticaly selects direction to use for road stop.
* @param area road stop area
* @return selected direction
*/
static 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.
@@ -222,14 +321,21 @@ static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, u
{
uint8 ddir = _road_station_picker_orientation;
SB(p2, 16, 16, INVALID_STATION); // no station to join
TileArea ta(start_tile, end_tile);
if (ddir >= DIAGDIR_END) {
SetBit(p2, 1); // It's a drive-through stop.
ddir -= DIAGDIR_END; // Adjust picker result to actual direction.
if (ddir < DIAGDIR_END + 2) {
SetBit(p2, 1); // It's a drive-through stop.
ddir -= DIAGDIR_END; // Adjust picker result to actual direction.
} 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);
}
}
p2 |= ddir << 6; // Set the DiagDirecion into p2 bits 6 and 7.
TileArea ta(start_tile, end_tile);
CommandContainer cmdcont = { ta.tile, ta.w | ta.h << 8, p2, cmd, CcRoadStop, "" };
ShowSelectStationIfNeeded(cmdcont, ta);
}
@@ -497,6 +603,7 @@ struct BuildRoadToolbarWindow : Window {
virtual void OnPlaceObject(Point pt, TileIndex tile)
{
DiagDirection ddir;
_remove_button_clicked = this->IsWidgetLowered(WID_ROT_REMOVE);
_one_way_button_clicked = this->IsWidgetLowered(WID_ROT_ONE_WAY);
switch (this->last_started_action) {
@@ -529,7 +636,11 @@ struct BuildRoadToolbarWindow : Window {
break;
case WID_ROT_DEPOT:
DoCommandP(tile, _cur_roadtype << 2 | _road_depot_orientation, 0,
ddir = _road_depot_orientation;
if (ddir == DIAGDIR_NW + 1) {
ddir = AutodetectRoadObjectDirection(tile);
}
DoCommandP(tile, _cur_roadtype << 2 | ddir, 0,
CMD_BUILD_ROAD_DEPOT | CMD_MSG(_road_type_infos[_cur_roadtype].err_depot), CcRoadDepot);
break;
@@ -903,7 +1014,7 @@ struct BuildRoadDepotWindow : public PickerWindowBase {
this->LowerWidget(_road_depot_orientation + WID_BROD_DEPOT_NE);
if ( _cur_roadtype == ROADTYPE_TRAM) {
this->GetWidget<NWidgetCore>(WID_BROD_CAPTION)->widget_data = STR_BUILD_DEPOT_TRAM_ORIENTATION_CAPTION;
for (int i = WID_BROD_DEPOT_NE; i <= WID_BROD_DEPOT_NW; i++) this->GetWidget<NWidgetCore>(i)->tool_tip = STR_BUILD_DEPOT_TRAM_ORIENTATION_SELECT_TOOLTIP;
for (int i = WID_BROD_DEPOT_NE; i <= WID_BROD_DEPOT_AUTO; i++) this->GetWidget<NWidgetCore>(i)->tool_tip = STR_BUILD_DEPOT_TRAM_ORIENTATION_SELECT_TOOLTIP;
}
this->FinishInitNested(TRANSPORT_ROAD);
@@ -923,6 +1034,7 @@ struct BuildRoadDepotWindow : public PickerWindowBase {
case WID_BROD_DEPOT_NE:
case WID_BROD_DEPOT_SW:
case WID_BROD_DEPOT_SE:
case WID_BROD_DEPOT_AUTO:
this->RaiseWidget(_road_depot_orientation + WID_BROD_DEPOT_NE);
_road_depot_orientation = (DiagDirection)(widget - WID_BROD_DEPOT_NE);
this->LowerWidget(_road_depot_orientation + WID_BROD_DEPOT_NE);
@@ -943,25 +1055,38 @@ static const NWidgetPart _nested_build_road_depot_widgets[] = {
EndContainer(),
NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
NWidget(NWID_HORIZONTAL_LTR),
NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0), SetFill(0, 0),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
NWidget(NWID_VERTICAL),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SW), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NW), SetMinimalSize(66, 50),
SetFill(0, 0),
SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(2, 0),
NWidget(NWID_VERTICAL),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SE), SetMinimalSize(66, 50), SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_NE), SetMinimalSize(66, 50),
SetFill(0, 0),
SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0), SetFill(0, 0),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SW), SetMinimalSize(66, 50),
SetFill(0, 0),
SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROD_DEPOT_SE), SetMinimalSize(66, 50),
SetFill(0, 0),
SetDataTip(0x0, STR_BUILD_DEPOT_ROAD_ORIENTATION_SELECT_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROD_DEPOT_AUTO), SetMinimalSize(134, 12),
SetDataTip(STR_STATION_BUILD_ORIENTATION_AUTO, STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP),
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
EndContainer(),
};
@@ -1054,6 +1179,8 @@ struct BuildRoadStationWindow : public PickerWindowBase {
case WID_BROS_STATION_NW:
case WID_BROS_STATION_X:
case WID_BROS_STATION_Y:
case WID_BROS_STATION_AUTO:
case WID_BROS_STATION_XY_AUTO:
this->RaiseWidget(_road_station_picker_orientation + WID_BROS_STATION_NE);
_road_station_picker_orientation = (DiagDirection)(widget - WID_BROS_STATION_NE);
this->LowerWidget(_road_station_picker_orientation + WID_BROS_STATION_NE);
@@ -1105,6 +1232,15 @@ static const NWidgetPart _nested_rv_station_picker_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY, WID_BROS_STATION_Y), SetMinimalSize(66, 50), EndContainer(),
NWidget(NWID_SPACER), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2),
NWidget(NWID_HORIZONTAL), SetPIP(0, 2, 0),
NWidget(NWID_SPACER), SetFill(1, 0),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROS_STATION_AUTO), SetMinimalSize(134, 12),
SetDataTip(STR_STATION_BUILD_ORIENTATION_AUTO, STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BROS_STATION_XY_AUTO), SetMinimalSize(66, 12),
SetDataTip(STR_STATION_BUILD_ORIENTATION_AUTO, STR_STATION_BUILD_ORIENTATION_AUTO_TOOLTIP),
NWidget(NWID_SPACER), SetFill(1, 0),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 1),
NWidget(NWID_HORIZONTAL), SetPIP(2, 0, 2),
NWidget(WWT_LABEL, COLOUR_DARK_GREEN, WID_BROS_INFO), SetMinimalSize(140, 14), SetDataTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE, STR_NULL),
@@ -1136,6 +1272,6 @@ static void ShowRVStationPicker(Window *parent, RoadStopType rs)
void InitializeRoadGui()
{
_road_depot_orientation = DIAGDIR_NW;
_road_station_picker_orientation = DIAGDIR_NW;
_road_depot_orientation = (DiagDirection)(DIAGDIR_NW + 1);
_road_station_picker_orientation = (DiagDirection)(DIAGDIR_END + 3);
}