polyline update applied
--HG-- branch : novattd150
This commit is contained in:
@@ -110,7 +110,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
|
||||
InitializeEconomy();
|
||||
|
||||
ResetObjectToPlace();
|
||||
ClearRailPlacementEndpoints();
|
||||
ResetRailPlacementSnapping();
|
||||
|
||||
GamelogReset();
|
||||
GamelogStartAction(GLAT_START);
|
||||
|
||||
@@ -417,6 +417,8 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
||||
Track track = Extract<Track, 0, 3>(p2);
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION);
|
||||
|
||||
_rail_track_endtile = INVALID_TILE;
|
||||
|
||||
if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
|
||||
|
||||
Slope tileh = GetTileSlope(tile);
|
||||
@@ -433,7 +435,10 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
||||
|
||||
ret = CheckTrackCombination(tile, trackbit, flags);
|
||||
if (ret.Succeeded()) ret = EnsureNoTrainOnTrack(tile, track);
|
||||
if (ret.Failed()) return ret;
|
||||
if (ret.Failed()) {
|
||||
if (ret.GetErrorMessage() == STR_ERROR_ALREADY_BUILT) _rail_track_endtile = tile;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile);
|
||||
if (ret.Failed()) return ret;
|
||||
@@ -522,6 +527,7 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
||||
}
|
||||
|
||||
if (IsLevelCrossing(tile) && GetCrossingRailBits(tile) == trackbit) {
|
||||
_rail_track_endtile = tile;
|
||||
return_cmd_error(STR_ERROR_ALREADY_BUILT);
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
@@ -580,6 +586,8 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION);
|
||||
bool crossing = false;
|
||||
|
||||
_rail_track_endtile = INVALID_TILE;
|
||||
|
||||
if (!ValParamTrackOrientation(track)) return CMD_ERROR;
|
||||
TrackBits trackbit = TrackToTrackBits(track);
|
||||
|
||||
@@ -840,6 +848,8 @@ static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint3
|
||||
bool remove = HasBit(p2, 7);
|
||||
RailType railtype = Extract<RailType, 0, 4>(p2);
|
||||
|
||||
_rail_track_endtile = INVALID_TILE;
|
||||
|
||||
if ((!remove && !ValParamRailtype(railtype)) || !ValParamTrackOrientation(track)) return CMD_ERROR;
|
||||
if (p1 >= MapSize()) return CMD_ERROR;
|
||||
TileIndex end_tile = p1;
|
||||
@@ -851,10 +861,12 @@ static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint3
|
||||
bool had_success = false;
|
||||
CommandCost last_error = CMD_ERROR;
|
||||
for (;;) {
|
||||
TileIndex last_endtile = _rail_track_endtile;
|
||||
CommandCost ret = DoCommand(tile, remove ? 0 : railtype, TrackdirToTrack(trackdir), flags, remove ? CMD_REMOVE_SINGLE_RAIL : CMD_BUILD_SINGLE_RAIL);
|
||||
|
||||
if (ret.Failed()) {
|
||||
last_error = ret;
|
||||
if (_rail_track_endtile == INVALID_TILE) _rail_track_endtile = last_endtile;
|
||||
if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT && !remove) {
|
||||
if (HasBit(p2, 8)) return last_error;
|
||||
break;
|
||||
|
||||
115
src/rail_gui.cpp
115
src/rail_gui.cpp
@@ -57,6 +57,9 @@ extern TileIndex _rail_track_endtile; // rail_cmd.cpp
|
||||
/* Map the setting: default_signal_type to the corresponding signal type */
|
||||
static const SignalType _default_signal_type[] = {SIGTYPE_NORMAL, SIGTYPE_PBS, SIGTYPE_PBS_ONEWAY};
|
||||
|
||||
static const int HOTKEY_POLYRAIL = 0x1000;
|
||||
static const int HOTKEY_NEW_POLYRAIL = 0x1001;
|
||||
|
||||
struct RailStationGUISettings {
|
||||
Axis orientation; ///< Currently selected rail station orientation
|
||||
|
||||
@@ -93,13 +96,20 @@ void CcPlaySound1E(const CommandCost &result, TileIndex tile, uint32 p1, uint32
|
||||
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile);
|
||||
}
|
||||
|
||||
static bool GenericPlaceRail(TileIndex tile, Track track)
|
||||
static CommandContainer GenericPlaceRailCmd(TileIndex tile, Track track)
|
||||
{
|
||||
return DoCommandP(tile, _cur_railtype, track,
|
||||
_remove_button_clicked ?
|
||||
CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
|
||||
CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK),
|
||||
CcPlaySound1E);
|
||||
CommandContainer ret = {
|
||||
tile, // tile
|
||||
_cur_railtype, // p1
|
||||
track, // p2
|
||||
_remove_button_clicked ?
|
||||
CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
|
||||
CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK), // cmd
|
||||
CcPlaySound1E, // callback
|
||||
"" // text
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,13 +362,20 @@ static void BuildRailClick_Remove(Window *w)
|
||||
}
|
||||
}
|
||||
|
||||
static bool DoRailroadTrack(TileIndex start_tile, TileIndex end_tile, Track track)
|
||||
static CommandContainer DoRailroadTrackCmd(TileIndex start_tile, TileIndex end_tile, Track track)
|
||||
{
|
||||
return DoCommandP(start_tile, end_tile, _cur_railtype | (track << 4),
|
||||
_remove_button_clicked ?
|
||||
CMD_REMOVE_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
|
||||
CMD_BUILD_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK),
|
||||
CcPlaySound1E);
|
||||
CommandContainer ret = {
|
||||
start_tile, // tile
|
||||
end_tile, // p1
|
||||
_cur_railtype | (track << 4), // p2
|
||||
_remove_button_clicked ?
|
||||
CMD_REMOVE_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
|
||||
CMD_BUILD_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK), // cmd
|
||||
CcPlaySound1E, // callback
|
||||
"" // text
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void HandleAutodirPlacement()
|
||||
@@ -367,8 +384,21 @@ static void HandleAutodirPlacement()
|
||||
TileIndex start_tile = TileVirtXY(_thd.selstart.x, _thd.selstart.y);
|
||||
TileIndex end_tile = TileVirtXY(_thd.selend.x, _thd.selend.y);
|
||||
|
||||
if ((_thd.drawstyle & HT_RAIL ? GenericPlaceRail(end_tile, track) : DoRailroadTrack(start_tile, end_tile, track))
|
||||
&& !_shift_pressed) {
|
||||
CommandContainer cmd = (_thd.drawstyle & HT_RAIL) ?
|
||||
GenericPlaceRailCmd(end_tile, track) : // one tile case
|
||||
DoRailroadTrackCmd(start_tile, end_tile, track); // multitile selection
|
||||
|
||||
/* When overbuilding existing tracks in polyline mode we just want to move the
|
||||
* snap point without altering the user with the "already built" error. Don't
|
||||
* execute the command right away, firstly check if tracks are being overbuilt. */
|
||||
if (!(_thd.place_mode & HT_POLY) || _shift_pressed ||
|
||||
DoCommand(&cmd, DC_AUTO | DC_NO_WATER).GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
|
||||
/* place tracks */
|
||||
if (!DoCommandP(&cmd)) return;
|
||||
}
|
||||
|
||||
/* save new snap points for the polyline tool */
|
||||
if (!_shift_pressed && _rail_track_endtile != INVALID_TILE) {
|
||||
StoreRailPlacementEndpoints(start_tile, _rail_track_endtile, track, true);
|
||||
}
|
||||
}
|
||||
@@ -632,10 +662,39 @@ struct BuildRailToolbarWindow : Window {
|
||||
this->last_user_action = widget;
|
||||
break;
|
||||
|
||||
case WID_RAT_POLYRAIL:
|
||||
HandlePlacePushButton(this, WID_RAT_POLYRAIL, GetRailTypeInfo(railtype)->cursor.autorail, HT_RAIL | HT_POLY);
|
||||
this->last_user_action = widget;
|
||||
case WID_RAT_POLYRAIL: {
|
||||
bool was_snap = CurrentlySnappingRailPlacement();
|
||||
bool was_open = this->IsWidgetLowered(WID_RAT_POLYRAIL);
|
||||
bool do_snap;
|
||||
bool do_open;
|
||||
/* "polyrail" hotkey - activate polyline tool in snapping mode, close the tool if snapping mode is already active
|
||||
* "new_polyrail" hotkey - activate polyline tool in non-snapping (new line) mode, close the tool if non-snapping mode is already active
|
||||
* button ctrl-clicking - switch between snapping and non-snapping modes, open the tool in non-snapping mode if it is closed
|
||||
* button clicking - open the tool in non-snapping mode, close the tool if it is opened */
|
||||
if (this->last_user_action == HOTKEY_POLYRAIL) {
|
||||
do_snap = true;
|
||||
do_open = !was_open || !was_snap;
|
||||
} else if (this->last_user_action == HOTKEY_NEW_POLYRAIL) {
|
||||
do_snap = false;
|
||||
do_open = !was_open || was_snap;
|
||||
} else if (_ctrl_pressed) {
|
||||
do_snap = !was_open || !was_snap;
|
||||
do_open = true;
|
||||
} else {
|
||||
do_snap = false;
|
||||
do_open = !was_open;
|
||||
}
|
||||
/* close the tool explicitly so it can be re-opened in different snapping mode */
|
||||
if (was_open) ResetObjectToPlace();
|
||||
/* open the tool in desired mode */
|
||||
if (do_open && HandlePlacePushButton(this, WID_RAT_POLYRAIL, GetRailTypeInfo(railtype)->cursor.autorail, do_snap ? (HT_RAIL | HT_POLY) : (HT_RAIL | HT_NEW_POLY))) {
|
||||
/* if we are re-opening the tool but we couldn't switch the snapping
|
||||
* then close the tool instead of appearing to be doing nothing */
|
||||
if (was_open && do_snap != CurrentlySnappingRailPlacement()) ResetObjectToPlace();
|
||||
}
|
||||
this->last_user_action = WID_RAT_POLYRAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_RAT_DEMOLISH:
|
||||
HandlePlacePushButton(this, WID_RAT_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
|
||||
@@ -701,7 +760,15 @@ struct BuildRailToolbarWindow : Window {
|
||||
virtual EventState OnHotkey(int hotkey)
|
||||
{
|
||||
MarkTileDirtyByTile(TileVirtXY(_thd.pos.x, _thd.pos.y)); // redraw tile selection
|
||||
return Window::OnHotkey(hotkey);
|
||||
|
||||
if (hotkey == HOTKEY_POLYRAIL || hotkey == HOTKEY_NEW_POLYRAIL) {
|
||||
/* Indicate to the OnClick that the action comes from a hotkey rather
|
||||
* then from a click and that the CTRL state should be ignored. */
|
||||
this->last_user_action = hotkey;
|
||||
hotkey = WID_RAT_POLYRAIL;
|
||||
}
|
||||
|
||||
return this->Window::OnHotkey(hotkey);
|
||||
}
|
||||
|
||||
virtual void OnPlaceObject(Point pt, TileIndex tile)
|
||||
@@ -877,7 +944,8 @@ static EventState RailToolbarGlobalHotkeys(int hotkey)
|
||||
}
|
||||
|
||||
const uint16 _railtoolbar_autorail_keys[] = {'5', 'A' | WKC_GLOBAL_HOTKEY, 0};
|
||||
const uint16 _railtoolbar_polyrail_keys[] = {'5' | WKC_CTRL, 'A' | WKC_GLOBAL_HOTKEY | WKC_CTRL, 0};
|
||||
const uint16 _railtoolbar_polyrail_keys[] = {'5' | WKC_CTRL, 'A' | WKC_CTRL | WKC_GLOBAL_HOTKEY, 0};
|
||||
const uint16 _railtoolbar_new_poly_keys[] = {'5' | WKC_CTRL | WKC_SHIFT, 'A' | WKC_CTRL | WKC_SHIFT | WKC_GLOBAL_HOTKEY, 0};
|
||||
|
||||
static Hotkey railtoolbar_hotkeys[] = {
|
||||
Hotkey('1', "build_ns", WID_RAT_BUILD_NS),
|
||||
@@ -885,7 +953,8 @@ static Hotkey railtoolbar_hotkeys[] = {
|
||||
Hotkey('3', "build_ew", WID_RAT_BUILD_EW),
|
||||
Hotkey('4', "build_y", WID_RAT_BUILD_Y),
|
||||
Hotkey(_railtoolbar_autorail_keys, "autorail", WID_RAT_AUTORAIL),
|
||||
Hotkey(_railtoolbar_polyrail_keys, "polyrail", WID_RAT_POLYRAIL),
|
||||
Hotkey(_railtoolbar_polyrail_keys, "polyrail", HOTKEY_POLYRAIL),
|
||||
Hotkey(_railtoolbar_new_poly_keys, "new_polyrail", HOTKEY_NEW_POLYRAIL),
|
||||
Hotkey('6', "demolish", WID_RAT_DEMOLISH),
|
||||
Hotkey('7', "depot", WID_RAT_BUILD_DEPOT),
|
||||
Hotkey('8', "waypoint", WID_RAT_BUILD_WAYPOINT),
|
||||
@@ -1819,7 +1888,6 @@ 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);
|
||||
@@ -1857,9 +1925,6 @@ static const NWidgetPart _nested_build_depot_widgets[] = {
|
||||
EndContainer(),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(3, 0), SetFill(1, 0),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL), SetPIP(2, 2, 2),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BRAD_DEPOT_AUTO), SetMinimalSize(134, 12), SetDataTip(STR_STATION_BUILD_ORIENTATION_AUTO, STR_BUILD_DEPOT_TRAIN_ORIENTATION_AUTO_TOOLTIP),
|
||||
EndContainer(),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
|
||||
EndContainer(),
|
||||
};
|
||||
@@ -1980,7 +2045,7 @@ static void ShowBuildWaypointPicker(Window *parent)
|
||||
*/
|
||||
void InitializeRailGui()
|
||||
{
|
||||
_build_depot_direction = (DiagDirection)(DIAGDIR_NW + 1);
|
||||
_build_depot_direction = DIAGDIR_NW;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: rev.cpp.in 26482 2014-04-23 20:13:33Z rubidium $ */
|
||||
/* $Id: rev.cpp.in 26440 2014-04-01 18:33:16Z frosch $ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
@@ -39,7 +39,7 @@ bool IsReleasedVersion()
|
||||
* norev000 is for non-releases that are made on systems without
|
||||
* subversion or sources that are not a checkout of subversion.
|
||||
*/
|
||||
const char _openttd_revision[] = "1.5.0-beta2";
|
||||
const char _openttd_revision[] = "1.4.0";
|
||||
|
||||
/**
|
||||
* The text version of OpenTTD's build date.
|
||||
@@ -72,11 +72,11 @@ const byte _openttd_revision_modified = 0;
|
||||
* final release will always have a lower version number than the released
|
||||
* version, thus making comparisons on specific revisions easy.
|
||||
*/
|
||||
const uint32 _openttd_newgrf_version = 1 << 28 | 5 << 24 | 0 << 20 | 0 << 19 | (27170 & ((1 << 19) - 1));
|
||||
const uint32 _openttd_newgrf_version = 1 << 28 | 4 << 24 | 0 << 20 | 1 << 19 | (26440 & ((1 << 19) - 1));
|
||||
|
||||
#ifdef __MORPHOS__
|
||||
/**
|
||||
* Variable used by MorphOS to show the version.
|
||||
*/
|
||||
extern const char morphos_versions_tag[] = "$VER: OpenTTD 1.5.0-beta2 (16.03.15) OpenTTD Team [MorphOS, PowerPC]";
|
||||
extern const char morphos_versions_tag[] = "$VER: OpenTTD 1.4.0 (02.04.14) OpenTTD Team [MorphOS, PowerPC]";
|
||||
#endif
|
||||
|
||||
@@ -904,6 +904,7 @@ void SQGSWindow_Register(Squirrel *engine)
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RAT_BUILD_EW, "WID_RAT_BUILD_EW");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RAT_BUILD_Y, "WID_RAT_BUILD_Y");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RAT_AUTORAIL, "WID_RAT_AUTORAIL");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RAT_POLYRAIL, "WID_RAT_POLYRAIL");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RAT_DEMOLISH, "WID_RAT_DEMOLISH");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RAT_BUILD_DEPOT, "WID_RAT_BUILD_DEPOT");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RAT_BUILD_WAYPOINT, "WID_RAT_BUILD_WAYPOINT");
|
||||
|
||||
@@ -1982,6 +1982,7 @@ public:
|
||||
WID_RAT_BUILD_EW = ::WID_RAT_BUILD_EW, ///< Build rail along the game view X axis.
|
||||
WID_RAT_BUILD_Y = ::WID_RAT_BUILD_Y, ///< Build rail along the game grid Y axis.
|
||||
WID_RAT_AUTORAIL = ::WID_RAT_AUTORAIL, ///< Autorail tool.
|
||||
WID_RAT_POLYRAIL = ::WID_RAT_POLYRAIL, ///< Polyline rail tool.
|
||||
WID_RAT_DEMOLISH = ::WID_RAT_DEMOLISH, ///< Destroy something with dynamite!
|
||||
WID_RAT_BUILD_DEPOT = ::WID_RAT_BUILD_DEPOT, ///< Build a depot.
|
||||
WID_RAT_BUILD_WAYPOINT = ::WID_RAT_BUILD_WAYPOINT, ///< Build a waypoint.
|
||||
|
||||
@@ -32,7 +32,8 @@ void VpSetPlaceSizingLimit(int limit);
|
||||
void UpdateTileSelection();
|
||||
|
||||
void StoreRailPlacementEndpoints(TileIndex start_tile, TileIndex end_tile, Track start_track, bool bidirectional = true);
|
||||
void ClearRailPlacementEndpoints();
|
||||
void ResetRailPlacementSnapping();
|
||||
bool CurrentlySnappingRailPlacement();
|
||||
|
||||
extern TileHighlightData _thd;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ enum HighLightStyle {
|
||||
HT_VEHICLE = 0x100, ///< vehicle is accepted as target as well (bitmask)
|
||||
HT_DIAGONAL = 0x200, ///< Also allow 'diagonal rectangles'. Only usable in combination with #HT_RECT or #HT_POINT.
|
||||
HT_POLY = 0x400, ///< polyline mode; connect highlighted track with previous one
|
||||
HT_NEW_POLY = 0xC00, ///< start completly new polyline; implies #HT_POLY
|
||||
HT_DRAG_MASK = 0x0F8, ///< Mask for the tile drag-type modes.
|
||||
|
||||
/* lower bits (used with HT_LINE and HT_RAIL):
|
||||
@@ -63,7 +64,7 @@ struct TileHighlightData {
|
||||
Point selend; ///< The location where the drag currently ends.
|
||||
Point selstart2; ///< The location where the second segment of a polyline track starts.
|
||||
Point selend2; ///< The location where the second segment of a polyline track ends.
|
||||
HighLightStyle dir2; ///< Direction of the second segment of a polyline track, HT_DIR_END if second segment is not selected.
|
||||
HighLightStyle dir2; ///< Direction of the second segment of a polyline track, HT_DIR_END if second segment is not selected. HT_LINE drawstyle.
|
||||
byte sizelimit; ///< Whether the selection is limited in length, and what the maximum length is.
|
||||
|
||||
HighLightStyle drawstyle; ///< Lower bits 0-3 are reserved for detailed highlight information.
|
||||
|
||||
390
src/viewport.cpp
390
src/viewport.cpp
@@ -152,6 +152,12 @@ typedef SmallVector<StringSpriteToDraw, 4> StringSpriteToDrawVector;
|
||||
typedef SmallVector<ParentSpriteToDraw, 64> ParentSpriteToDrawVector;
|
||||
typedef SmallVector<ChildScreenSpriteToDraw, 16> ChildScreenSpriteToDrawVector;
|
||||
|
||||
enum RailSnapMode {
|
||||
RSM_NO_SNAP,
|
||||
RSM_SNAP_TO_TILE,
|
||||
RSM_SNAP_TO_RAIL,
|
||||
};
|
||||
|
||||
/**
|
||||
* Snapping point for a track.
|
||||
*
|
||||
@@ -199,14 +205,22 @@ static void MarkViewportDirty(const ViewPort *vp, int left, int top, int right,
|
||||
static ViewportDrawer _vd;
|
||||
|
||||
TileHighlightData _thd;
|
||||
static LineSnapPoints _rail_snap_points; ///< Set of points where a rail track will be snapped to (polyline tool).
|
||||
static LineSnapPoint _current_snap_lock; ///< Start point and direction at which selected track is locked on currently (while dragging in polyline mode).
|
||||
static TileInfo *_cur_ti;
|
||||
bool _draw_bounding_boxes = false;
|
||||
bool _draw_dirty_blocks = false;
|
||||
uint _dirty_block_colour = 0;
|
||||
static VpSpriteSorter _vp_sprite_sorter = NULL;
|
||||
|
||||
static RailSnapMode _rail_snap_mode = RSM_NO_SNAP; ///< Type of rail track snapping (polyline tool).
|
||||
static LineSnapPoints _tile_snap_points; ///< Tile to which a rail track will be snapped to (polyline tool).
|
||||
static LineSnapPoints _rail_snap_points; ///< Set of points where a rail track will be snapped to (polyline tool).
|
||||
static LineSnapPoint _current_snap_lock; ///< Start point and direction at which selected track is locked on currently (while dragging in polyline mode).
|
||||
|
||||
static RailSnapMode GetRailSnapMode();
|
||||
static void SetRailSnapMode(RailSnapMode mode);
|
||||
static TileIndex GetRailSnapTile();
|
||||
static void SetRailSnapTile(TileIndex tile);
|
||||
|
||||
static Point MapXYZToViewport(const ViewPort *vp, int x, int y, int z)
|
||||
{
|
||||
Point p = RemapCoords(x, y, z);
|
||||
@@ -1052,27 +1066,27 @@ static void DrawTileSelection(const TileInfo *ti)
|
||||
/* Draw a blue rect. */
|
||||
DrawTileSelectionRect(ti, PALETTE_SEL_TILE_BLUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HT_POINT:
|
||||
if (IsInsideSelectedRectangle(ti->x, ti->y)) {
|
||||
/* Figure out the Z coordinate for the single dot. */
|
||||
int z = 0;
|
||||
FoundationPart foundation_part = FOUNDATION_PART_NORMAL;
|
||||
if (ti->tileh & SLOPE_N) {
|
||||
z += TILE_HEIGHT;
|
||||
if (RemoveHalftileSlope(ti->tileh) == SLOPE_STEEP_N) z += TILE_HEIGHT;
|
||||
}
|
||||
if (IsHalftileSlope(ti->tileh)) {
|
||||
Corner halftile_corner = GetHalftileSlopeCorner(ti->tileh);
|
||||
if ((halftile_corner == CORNER_W) || (halftile_corner == CORNER_E)) z += TILE_HEIGHT;
|
||||
if (halftile_corner != CORNER_S) {
|
||||
foundation_part = FOUNDATION_PART_HALFTILE;
|
||||
if (IsSteepSlope(ti->tileh)) z -= TILE_HEIGHT;
|
||||
/* Figure out the Z coordinate for the single dot. */
|
||||
int z = 0;
|
||||
FoundationPart foundation_part = FOUNDATION_PART_NORMAL;
|
||||
if (ti->tileh & SLOPE_N) {
|
||||
z += TILE_HEIGHT;
|
||||
if (RemoveHalftileSlope(ti->tileh) == SLOPE_STEEP_N) z += TILE_HEIGHT;
|
||||
}
|
||||
}
|
||||
DrawSelectionSprite(_cur_dpi->zoom <= ZOOM_LVL_DETAIL ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti, z, foundation_part);
|
||||
if (IsHalftileSlope(ti->tileh)) {
|
||||
Corner halftile_corner = GetHalftileSlopeCorner(ti->tileh);
|
||||
if ((halftile_corner == CORNER_W) || (halftile_corner == CORNER_E)) z += TILE_HEIGHT;
|
||||
if (halftile_corner != CORNER_S) {
|
||||
foundation_part = FOUNDATION_PART_HALFTILE;
|
||||
if (IsSteepSlope(ti->tileh)) z -= TILE_HEIGHT;
|
||||
}
|
||||
}
|
||||
DrawSelectionSprite(_cur_dpi->zoom <= ZOOM_LVL_DETAIL ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti, z, foundation_part);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1087,12 +1101,13 @@ static void DrawTileSelection(const TileInfo *ti)
|
||||
HighLightStyle type = GetPartOfAutoLine(ti->x, ti->y, _thd.selstart, _thd.selend, _thd.drawstyle & HT_DIR_MASK);
|
||||
if (type < HT_DIR_END) {
|
||||
DrawAutorailSelection(ti, type);
|
||||
} else if ((_thd.drawstyle & HT_POLY) && _thd.dir2 < HT_DIR_END) {
|
||||
} else if (_thd.dir2 < HT_DIR_END) {
|
||||
/* FIXME mb missing condition (_thd.drawstyle & HT_POLY) */
|
||||
type = GetPartOfAutoLine(ti->x, ti->y, _thd.selstart2, _thd.selend2, _thd.dir2);
|
||||
if (type < HT_DIR_END) DrawAutorailSelection(ti, type, PALETTE_SEL_TILE_BLUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1277,9 +1292,8 @@ static void ViewportAddTownNames(DrawPixelInfo *dpi)
|
||||
const Town *t;
|
||||
FOR_ALL_TOWNS(t) {
|
||||
ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &t->cache.sign,
|
||||
//_settings_client.gui.population_in_label ? STR_VIEWPORT_TOWN_POP : STR_VIEWPORT_TOWN,
|
||||
//STR_VIEWPORT_TOWN_TINY_WHITE, STR_VIEWPORT_TOWN_TINY_BLACK,
|
||||
t->Label(), t->SmallLabel(), STR_VIEWPORT_TOWN_TINY_BLACK,
|
||||
_settings_client.gui.population_in_label ? STR_VIEWPORT_TOWN_POP : STR_VIEWPORT_TOWN,
|
||||
STR_VIEWPORT_TOWN_TINY_WHITE, STR_VIEWPORT_TOWN_TINY_BLACK,
|
||||
t->index, t->cache.population);
|
||||
}
|
||||
}
|
||||
@@ -2098,8 +2112,7 @@ static bool CheckClickOnTown(const ViewPort *vp, int x, int y)
|
||||
const Town *t;
|
||||
FOR_ALL_TOWNS(t) {
|
||||
if (CheckClickOnViewportSign(vp, x, y, &t->cache.sign)) {
|
||||
if(_ctrl_pressed) TownExecuteAction(t, 4); //build statue
|
||||
else ShowTownViewWindow(t->index);
|
||||
ShowTownViewWindow(t->index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2194,15 +2207,21 @@ bool HandleViewportClicked(const ViewPort *vp, int x, int y, bool double_click)
|
||||
if (v != NULL && VehicleClicked(v)) return true;
|
||||
}
|
||||
|
||||
/* Double-clicking finishes current polyline and starts new one. */
|
||||
if (double_click && _settings_client.gui.polyrail_double_click && (_thd.place_mode & HT_POLY)) {
|
||||
ClearRailPlacementEndpoints();
|
||||
SetTileSelectSize(1, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Vehicle placement mode already handled above. */
|
||||
if ((_thd.place_mode & HT_DRAG_MASK) != HT_NONE) {
|
||||
if (_thd.place_mode & HT_POLY) {
|
||||
/* In polyline mode double-clicking on a single white line, finishes current polyline.
|
||||
* If however the user double-clicks on a line that has a white and a blue section,
|
||||
* both lines (white and blue) will be constructed consecutively. */
|
||||
static bool stop_snap_on_double_click = false;
|
||||
/* FIXME _settings_client.gui.polyrail_double_click */
|
||||
if (double_click && stop_snap_on_double_click) {
|
||||
SetRailSnapMode(RSM_NO_SNAP);
|
||||
return true;
|
||||
}
|
||||
stop_snap_on_double_click = !(_thd.drawstyle & HT_LINE) || (_thd.dir2 == HT_DIR_END);
|
||||
}
|
||||
|
||||
PlaceObject();
|
||||
return true;
|
||||
}
|
||||
@@ -2218,7 +2237,7 @@ bool HandleViewportClicked(const ViewPort *vp, int x, int y, bool double_click)
|
||||
v = v->First();
|
||||
if (_ctrl_pressed && v->owner == _local_company) {
|
||||
if (_settings_client.gui.enable_ctrl_click_start_stop)
|
||||
StartStopVehicle(v, true);
|
||||
StartStopVehicle(v, true);
|
||||
} else {
|
||||
ShowVehicleViewWindow(v);
|
||||
}
|
||||
@@ -2440,9 +2459,6 @@ void UpdateTileSelection()
|
||||
_thd.new_size.x += TILE_SIZE;
|
||||
_thd.new_size.y += TILE_SIZE;
|
||||
}
|
||||
if (_thd.place_mode & HT_POLY) {
|
||||
CalcNewPolylineOutersize();
|
||||
}
|
||||
new_drawstyle = _thd.next_drawstyle;
|
||||
}
|
||||
} else if ((_thd.place_mode & HT_DRAG_MASK) != HT_NONE) {
|
||||
@@ -2463,7 +2479,16 @@ void UpdateTileSelection()
|
||||
case HT_LINE:
|
||||
/* HT_POLY */
|
||||
if (_thd.place_mode & HT_POLY) {
|
||||
if (_rail_snap_points.Length() > 0) {
|
||||
RailSnapMode snap_mode = GetRailSnapMode();
|
||||
if (snap_mode == RSM_NO_SNAP ||
|
||||
(snap_mode == RSM_SNAP_TO_TILE && GetRailSnapTile() == TileVirtXY(pt.x, pt.y))) {
|
||||
new_drawstyle = GetAutorailHT(pt.x, pt.y);
|
||||
_thd.new_offs.x = 0;
|
||||
_thd.new_offs.y = 0;
|
||||
_thd.new_outersize.x = 0;
|
||||
_thd.new_outersize.y = 0;
|
||||
_thd.dir2 = HT_DIR_END;
|
||||
} else {
|
||||
new_drawstyle = CalcPolyrailDrawstyle(pt, false);
|
||||
if (new_drawstyle != HT_NONE) {
|
||||
x1 = _thd.selstart.x & ~TILE_UNIT_MASK;
|
||||
@@ -2476,21 +2501,15 @@ void UpdateTileSelection()
|
||||
_thd.new_pos.y = y1;
|
||||
_thd.new_size.x = x2 - x1 + TILE_SIZE;
|
||||
_thd.new_size.y = y2 - y1 + TILE_SIZE;
|
||||
CalcNewPolylineOutersize();
|
||||
}
|
||||
break;
|
||||
}
|
||||
_thd.new_offs.x = 0;
|
||||
_thd.new_offs.y = 0;
|
||||
_thd.new_outersize.x = 0;
|
||||
_thd.new_outersize.y = 0;
|
||||
_thd.dir2 = HT_DIR_END;
|
||||
break;
|
||||
}
|
||||
/* HT_RAIL */
|
||||
if (_thd.place_mode & HT_RAIL) {
|
||||
/* Draw one highlighted tile in any direction */
|
||||
new_drawstyle = GetAutorailHT(pt.x, pt.y);
|
||||
break;
|
||||
/* Draw one highlighted tile in any direction */
|
||||
new_drawstyle = GetAutorailHT(pt.x, pt.y);
|
||||
break;
|
||||
}
|
||||
/* HT_LINE */
|
||||
switch (_thd.place_mode & HT_DIR_MASK) {
|
||||
@@ -2523,6 +2542,8 @@ void UpdateTileSelection()
|
||||
}
|
||||
}
|
||||
|
||||
if (new_drawstyle & HT_LINE) CalcNewPolylineOutersize();
|
||||
|
||||
/* redraw selection */
|
||||
if (_thd.drawstyle != new_drawstyle ||
|
||||
_thd.pos.x != _thd.new_pos.x || _thd.pos.y != _thd.new_pos.y ||
|
||||
@@ -2588,6 +2609,10 @@ void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, ViewportDrag
|
||||
_thd.place_mode = HT_SPECIAL | others;
|
||||
_thd.next_drawstyle = _thd.drawstyle | others;
|
||||
_current_snap_lock.x = -1;
|
||||
if ((_thd.place_mode & HT_POLY) != 0 && GetRailSnapMode() == RSM_NO_SNAP) {
|
||||
SetRailSnapMode(RSM_SNAP_TO_TILE);
|
||||
SetRailSnapTile(tile);
|
||||
}
|
||||
} else {
|
||||
_thd.place_mode = HT_SPECIAL | others;
|
||||
_thd.next_drawstyle = HT_POINT | others;
|
||||
@@ -2968,26 +2993,34 @@ static inline uint SqrDist(const Point &a, const Point &b)
|
||||
|
||||
static LineSnapPoint *FindBestPolyline(const Point &pt, LineSnapPoint *snap_points, uint num_points, Polyline *ret)
|
||||
{
|
||||
while (num_points > 0) {
|
||||
/* run a single bubble sort loop to find the closest snap point (push it to the and of the array) */
|
||||
uint prev_dist = SqrDist(snap_points[0], pt);
|
||||
for (uint i = 1; i < num_points; i++) {
|
||||
uint next_dist = SqrDist(snap_points[i], pt);
|
||||
if (prev_dist < next_dist) {
|
||||
Swap(snap_points[i], snap_points[i - 1]);
|
||||
} else {
|
||||
prev_dist = next_dist;
|
||||
}
|
||||
/* Find the best polyline (a pair of two lines - the white one and the blue
|
||||
* one) led from any of saved snap points to the mouse cursor. */
|
||||
|
||||
LineSnapPoint *best_snap_point = NULL; // the best polyline we found so far is led from this snap point
|
||||
|
||||
for (int i = 0; i < (int)num_points; i++) {
|
||||
/* try to fit a polyline */
|
||||
Polyline polyline;
|
||||
if (!FindPolyline(pt, snap_points[i], &polyline)) continue; // skip non-matching snap points
|
||||
/* check whether we've found a better polyline */
|
||||
if (best_snap_point != NULL) {
|
||||
/* firstly choose shorter polyline (the one with smaller amount of
|
||||
* track pieces composing booth the white and the blue line) */
|
||||
uint cur_len = polyline.first_len + polyline.second_len;
|
||||
uint best_len = ret->first_len + ret->second_len;
|
||||
if (cur_len > best_len) continue;
|
||||
/* secondly choose that polyline which has longer first (white) line */
|
||||
if (cur_len == best_len && polyline.first_len < ret->first_len) continue;
|
||||
/* finally check euclidean distance to snap points and choose the
|
||||
* one which is closer */
|
||||
if (cur_len == best_len && polyline.first_len == ret->first_len && SqrDist(pt, snap_points[i]) >= SqrDist(pt, *best_snap_point)) continue;
|
||||
}
|
||||
|
||||
/* try to fit a line */
|
||||
if (FindPolyline(pt, snap_points[num_points - 1], ret)) return &snap_points[num_points - 1];
|
||||
|
||||
/* repeat procedure for the rest of snap points */
|
||||
--num_points;
|
||||
/* save the found polyline */
|
||||
*ret = polyline;
|
||||
best_snap_point = &snap_points[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return best_snap_point;
|
||||
}
|
||||
|
||||
/** while dragging */
|
||||
@@ -3178,6 +3211,7 @@ static void CalcRaildirsDrawstyle(int x, int y, int method)
|
||||
|
||||
_thd.selend.x = x;
|
||||
_thd.selend.y = y;
|
||||
_thd.dir2 = HT_DIR_END;
|
||||
_thd.next_drawstyle = b;
|
||||
|
||||
ShowLengthMeasurement(b, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y));
|
||||
@@ -3185,33 +3219,37 @@ static void CalcRaildirsDrawstyle(int x, int y, int method)
|
||||
|
||||
static HighLightStyle CalcPolyrailDrawstyle(Point pt, bool dragging)
|
||||
{
|
||||
RailSnapMode snap_mode = GetRailSnapMode();
|
||||
|
||||
/* are we only within one tile? */
|
||||
if (snap_mode == RSM_SNAP_TO_TILE && GetRailSnapTile() == TileVirtXY(pt.x, pt.y)) {
|
||||
_thd.selend.x = pt.x;
|
||||
_thd.selend.y = pt.y;
|
||||
return GetAutorailHT(pt.x, pt.y);
|
||||
}
|
||||
|
||||
/* find the best track */
|
||||
Polyline line;
|
||||
|
||||
HighLightStyle ret = HT_LINE | HT_POLY;
|
||||
bool lock_snapping = dragging && snap_mode == RSM_SNAP_TO_RAIL;
|
||||
if (!lock_snapping) _current_snap_lock.x = -1;
|
||||
|
||||
if (!dragging) {
|
||||
_current_snap_lock.x = -1;
|
||||
if (FindBestPolyline(pt, _rail_snap_points.Begin(), _rail_snap_points.Length(), &line) == NULL) ret = HT_NONE; // no match
|
||||
} else if (_current_snap_lock.x != -1) {
|
||||
if (FindBestPolyline(pt, &_current_snap_lock, 1, &line) == NULL) ret = HT_NONE; // no match
|
||||
const LineSnapPoint *snap_point;
|
||||
if (_current_snap_lock.x != -1) {
|
||||
snap_point = FindBestPolyline(pt, &_current_snap_lock, 1, &line);
|
||||
} else if (snap_mode == RSM_SNAP_TO_TILE) {
|
||||
snap_point = FindBestPolyline(pt, _tile_snap_points.Begin(), _tile_snap_points.Length(), &line);
|
||||
} else {
|
||||
const LineSnapPoint *snap_point = FindBestPolyline(pt, _rail_snap_points.Begin(), _rail_snap_points.Length(), &line);
|
||||
if (snap_point == NULL) {
|
||||
ret = HT_NONE; // no match
|
||||
} else {
|
||||
_current_snap_lock = *snap_point;
|
||||
_current_snap_lock.dirs &= (1 << line.first_dir) | (1 << ReverseDir(line.first_dir)); // lock direction
|
||||
}
|
||||
}
|
||||
assert(snap_mode == RSM_SNAP_TO_RAIL);
|
||||
snap_point = FindBestPolyline(pt, _rail_snap_points.Begin(), _rail_snap_points.Length(), &line);
|
||||
}
|
||||
|
||||
if (ret == HT_NONE) {
|
||||
_thd.selstart.x = -1;
|
||||
_thd.selend.x = -1;
|
||||
_thd.selstart2.x = -1;
|
||||
_thd.selend2.x = -1;
|
||||
_thd.dir2 = HT_DIR_END;
|
||||
return ret;
|
||||
if (snap_point == NULL) return HT_NONE; // no match
|
||||
|
||||
if (lock_snapping && _current_snap_lock.x == -1) {
|
||||
/* lock down the snap point */
|
||||
_current_snap_lock = *snap_point;
|
||||
_current_snap_lock.dirs &= (1 << line.first_dir) | (1 << ReverseDir(line.first_dir));
|
||||
}
|
||||
|
||||
TileIndexDiffC first_dir = TileIndexDiffCByDir(line.first_dir);
|
||||
@@ -3228,7 +3266,6 @@ static HighLightStyle CalcPolyrailDrawstyle(Point pt, bool dragging)
|
||||
Trackdir seldir = PointDirToTrackdir(_thd.selstart, line.first_dir);
|
||||
_thd.selstart.x &= ~TILE_UNIT_MASK;
|
||||
_thd.selstart.y &= ~TILE_UNIT_MASK;
|
||||
ret |= (HighLightStyle)TrackdirToTrack(seldir);
|
||||
|
||||
if (line.second_len != 0) {
|
||||
TileIndexDiffC second_dir = TileIndexDiffCByDir(line.second_dir);
|
||||
@@ -3246,6 +3283,7 @@ static HighLightStyle CalcPolyrailDrawstyle(Point pt, bool dragging)
|
||||
_thd.dir2 = HT_DIR_END;
|
||||
}
|
||||
|
||||
HighLightStyle ret = HT_LINE | (HighLightStyle)TrackdirToTrack(seldir);
|
||||
ShowLengthMeasurement(ret, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), TCC_HOVER, true);
|
||||
return ret;
|
||||
}
|
||||
@@ -3267,7 +3305,7 @@ void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((_thd.place_mode & HT_POLY) && _rail_snap_points.Length() > 0) {
|
||||
if ((_thd.place_mode & HT_POLY) && GetRailSnapMode() != RSM_NO_SNAP) {
|
||||
Point pt = { x, y };
|
||||
_thd.next_drawstyle = CalcPolyrailDrawstyle(pt, true);
|
||||
return;
|
||||
@@ -3325,11 +3363,11 @@ calc_heightdiff_single_direction:;
|
||||
x = sx + Clamp(x - sx, -limit, limit);
|
||||
y = sy + Clamp(y - sy, -limit, limit);
|
||||
}
|
||||
/* With current code passing a HT_LINE style to calculate the height
|
||||
* difference is enough. However if/when a point-tool is created
|
||||
* with this method, function should be called with new_style (below)
|
||||
* instead of HT_LINE | style case HT_POINT is handled specially
|
||||
* new_style := (_thd.next_drawstyle & HT_RECT) ? HT_LINE | style : _thd.next_drawstyle; */
|
||||
/* With current code passing a HT_LINE style to calculate the height
|
||||
* difference is enough. However if/when a point-tool is created
|
||||
* with this method, function should be called with new_style (below)
|
||||
* instead of HT_LINE | style case HT_POINT is handled specially
|
||||
* new_style := (_thd.next_drawstyle & HT_RECT) ? HT_LINE | style : _thd.next_drawstyle; */
|
||||
ShowLengthMeasurement(HT_LINE | style, TileVirtXY(sx, sy), TileVirtXY(x, y));
|
||||
break;
|
||||
|
||||
@@ -3409,6 +3447,7 @@ calc_heightdiff_single_direction:;
|
||||
|
||||
_thd.selend.x = x;
|
||||
_thd.selend.y = y;
|
||||
_thd.dir2 = HT_DIR_END;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3426,11 +3465,10 @@ EventState VpHandlePlaceSizingDrag()
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
/* while dragging execute the drag procedure of the corresponding window (mostly VpSelectTilesWithMethod() ) */
|
||||
if (_left_button_down) {
|
||||
w->OnPlaceDrag(_thd.select_method, _thd.select_proc, GetTileBelowCursor());
|
||||
return ES_HANDLED;
|
||||
}
|
||||
/* While dragging execute the drag procedure of the corresponding window (mostly VpSelectTilesWithMethod() ).
|
||||
* Do it even if the button is no longer pressed to make sure that OnPlaceDrag was called at least once. */
|
||||
w->OnPlaceDrag(_thd.select_method, _thd.select_proc, GetTileBelowCursor());
|
||||
if (_left_button_down) return ES_HANDLED;
|
||||
|
||||
/* mouse button released..
|
||||
* keep the selected tool, but reset it to the original mode. */
|
||||
@@ -3447,8 +3485,12 @@ EventState VpHandlePlaceSizingDrag()
|
||||
}
|
||||
SetTileSelectSize(1, 1);
|
||||
|
||||
w->OnPlaceMouseUp(_thd.select_method, _thd.select_proc, _thd.selend, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y));
|
||||
if (_thd.place_mode & HT_POLY) {
|
||||
if (GetRailSnapMode() == RSM_SNAP_TO_TILE) SetRailSnapMode(RSM_NO_SNAP);
|
||||
if (_thd.drawstyle == HT_NONE) return ES_HANDLED;
|
||||
}
|
||||
|
||||
w->OnPlaceMouseUp(_thd.select_method, _thd.select_proc, _thd.selend, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y));
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
@@ -3495,6 +3537,10 @@ void SetObjectToPlace(CursorID icon, PaletteID pal, HighLightStyle mode, WindowC
|
||||
VpStartPreSizing();
|
||||
}
|
||||
|
||||
if (mode & HT_POLY) {
|
||||
SetRailSnapMode((mode & HT_NEW_POLY) == HT_NEW_POLY ? RSM_NO_SNAP : RSM_SNAP_TO_RAIL);
|
||||
}
|
||||
|
||||
if ((icon & ANIMCURSOR_FLAG) != 0) {
|
||||
SetAnimatedMouseCursor(_animcursors[icon & ~ANIMCURSOR_FLAG]);
|
||||
} else {
|
||||
@@ -3508,6 +3554,44 @@ void ResetObjectToPlace()
|
||||
SetObjectToPlace(SPR_CURSOR_MOUSE, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0);
|
||||
}
|
||||
|
||||
Point GetViewportStationMiddle(const ViewPort *vp, const Station *st)
|
||||
{
|
||||
int x = TileX(st->xy) * TILE_SIZE;
|
||||
int y = TileY(st->xy) * TILE_SIZE;
|
||||
int z = GetSlopePixelZ(Clamp(x, 0, MapSizeX() * TILE_SIZE - 1), Clamp(y, 0, MapSizeY() * TILE_SIZE - 1));
|
||||
|
||||
Point p = RemapCoords(x, y, z);
|
||||
p.x = UnScaleByZoom(p.x - vp->virtual_left, vp->zoom) + vp->left;
|
||||
p.y = UnScaleByZoom(p.y - vp->virtual_top, vp->zoom) + vp->top;
|
||||
return p;
|
||||
}
|
||||
|
||||
/** Helper class for getting the best sprite sorter. */
|
||||
struct ViewportSSCSS {
|
||||
VpSorterChecker fct_checker; ///< The check function.
|
||||
VpSpriteSorter fct_sorter; ///< The sorting function.
|
||||
};
|
||||
|
||||
/** List of sorters ordered from best to worst. */
|
||||
static ViewportSSCSS _vp_sprite_sorters[] = {
|
||||
#ifdef WITH_SSE
|
||||
{ &ViewportSortParentSpritesSSE41Checker, &ViewportSortParentSpritesSSE41 },
|
||||
#endif
|
||||
{ &ViewportSortParentSpritesChecker, &ViewportSortParentSprites }
|
||||
};
|
||||
|
||||
/** Choose the "best" sprite sorter and set _vp_sprite_sorter. */
|
||||
void InitializeSpriteSorter()
|
||||
{
|
||||
for (uint i = 0; i < lengthof(_vp_sprite_sorters); i++) {
|
||||
if (_vp_sprite_sorters[i].fct_checker()) {
|
||||
_vp_sprite_sorter = _vp_sprite_sorters[i].fct_sorter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(_vp_sprite_sorter != NULL);
|
||||
}
|
||||
|
||||
static LineSnapPoint LineSnapPointAtRailTrackEndpoint(TileIndex tile, DiagDirection exit_dir, bool bidirectional)
|
||||
{
|
||||
LineSnapPoint ret;
|
||||
@@ -3554,57 +3638,69 @@ void StoreRailPlacementEndpoints(TileIndex start_tile, TileIndex end_tile, Track
|
||||
LineSnapPoint snap_end = LineSnapPointAtRailTrackEndpoint(end_tile, TrackdirToExitdir(exit_trackdir_at_end), bidirectional_exit);
|
||||
/* Find if we already had these coordinates before. */
|
||||
LineSnapPoint *snap;
|
||||
bool had_start = false;
|
||||
bool had_end = false;
|
||||
for (snap = _rail_snap_points.Begin(); snap != _rail_snap_points.End(); snap++) {
|
||||
/* Coordinates found - remove the snap point as it was already used. */
|
||||
if (snap->x == snap_start.x && snap->y == snap_start.y) snap_start.dirs = 0;
|
||||
if (snap->x == snap_end.x && snap->y == snap_end.y) snap_end.dirs = 0;
|
||||
had_start |= (snap->x == snap_start.x && snap->y == snap_start.y);
|
||||
had_end |= (snap->x == snap_end.x && snap->y == snap_end.y);
|
||||
}
|
||||
/* Create new snap point set. */
|
||||
_rail_snap_points.Clear();
|
||||
if (snap_start.dirs != 0) *_rail_snap_points.Append() = snap_start;
|
||||
if (snap_end.dirs != 0) *_rail_snap_points.Append() = snap_end;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearRailPlacementEndpoints()
|
||||
{
|
||||
_rail_snap_points.Clear();
|
||||
}
|
||||
|
||||
Point GetViewportStationMiddle(const ViewPort *vp, const Station *st)
|
||||
{
|
||||
int x = TileX(st->xy) * TILE_SIZE;
|
||||
int y = TileY(st->xy) * TILE_SIZE;
|
||||
int z = GetSlopePixelZ(Clamp(x, 0, MapSizeX() * TILE_SIZE - 1), Clamp(y, 0, MapSizeY() * TILE_SIZE - 1));
|
||||
|
||||
Point p = RemapCoords(x, y, z);
|
||||
p.x = UnScaleByZoom(p.x - vp->virtual_left, vp->zoom) + vp->left;
|
||||
p.y = UnScaleByZoom(p.y - vp->virtual_top, vp->zoom) + vp->top;
|
||||
return p;
|
||||
}
|
||||
|
||||
/** Helper class for getting the best sprite sorter. */
|
||||
struct ViewportSSCSS {
|
||||
VpSorterChecker fct_checker; ///< The check function.
|
||||
VpSpriteSorter fct_sorter; ///< The sorting function.
|
||||
};
|
||||
|
||||
/** List of sorters ordered from best to worst. */
|
||||
static ViewportSSCSS _vp_sprite_sorters[] = {
|
||||
#ifdef WITH_SSE
|
||||
{ &ViewportSortParentSpritesSSE41Checker, &ViewportSortParentSpritesSSE41 },
|
||||
#endif
|
||||
{ &ViewportSortParentSpritesChecker, &ViewportSortParentSprites }
|
||||
};
|
||||
|
||||
/** Choose the "best" sprite sorter and set _vp_sprite_sorter. */
|
||||
void InitializeSpriteSorter()
|
||||
{
|
||||
for (uint i = 0; i < lengthof(_vp_sprite_sorters); i++) {
|
||||
if (_vp_sprite_sorters[i].fct_checker()) {
|
||||
_vp_sprite_sorter = _vp_sprite_sorters[i].fct_sorter;
|
||||
break;
|
||||
if (had_start && had_end) {
|
||||
/* just stop snaping, don't forget snap points */
|
||||
SetRailSnapMode(RSM_NO_SNAP);
|
||||
} else {
|
||||
/* include only new points */
|
||||
_rail_snap_points.Clear();
|
||||
if (!had_start) *_rail_snap_points.Append() = snap_start;
|
||||
if (!had_end) *_rail_snap_points.Append() = snap_end;
|
||||
SetRailSnapMode(RSM_SNAP_TO_RAIL);
|
||||
}
|
||||
}
|
||||
assert(_vp_sprite_sorter != NULL);
|
||||
}
|
||||
|
||||
bool CurrentlySnappingRailPlacement()
|
||||
{
|
||||
return (_thd.place_mode & HT_POLY) && GetRailSnapMode() == RSM_SNAP_TO_RAIL;
|
||||
}
|
||||
|
||||
static RailSnapMode GetRailSnapMode()
|
||||
{
|
||||
if (_rail_snap_mode == RSM_SNAP_TO_TILE && _tile_snap_points.Length() == 0) return RSM_NO_SNAP;
|
||||
if (_rail_snap_mode == RSM_SNAP_TO_RAIL && _rail_snap_points.Length() == 0) return RSM_NO_SNAP;
|
||||
return _rail_snap_mode;
|
||||
}
|
||||
|
||||
static void SetRailSnapMode(RailSnapMode mode)
|
||||
{
|
||||
_rail_snap_mode = mode;
|
||||
|
||||
if ((_thd.place_mode & HT_POLY) && (GetRailSnapMode() == RSM_NO_SNAP)) {
|
||||
SetTileSelectSize(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static TileIndex GetRailSnapTile()
|
||||
{
|
||||
if (_tile_snap_points.Length() == 0) return INVALID_TILE;
|
||||
return TileVirtXY(_tile_snap_points[DIAGDIR_NE].x, _tile_snap_points[DIAGDIR_NE].y);
|
||||
}
|
||||
|
||||
static void SetRailSnapTile(TileIndex tile)
|
||||
{
|
||||
_tile_snap_points.Clear();
|
||||
if (tile == INVALID_TILE) return;
|
||||
|
||||
for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
|
||||
LineSnapPoint *point = _tile_snap_points.Append();
|
||||
*point = LineSnapPointAtRailTrackEndpoint(tile, dir, false);
|
||||
point->dirs = ROR<uint8>(point->dirs, DIRDIFF_REVERSE);
|
||||
}
|
||||
}
|
||||
|
||||
void ResetRailPlacementSnapping()
|
||||
{
|
||||
_rail_snap_mode = RSM_NO_SNAP;
|
||||
_tile_snap_points.Clear();
|
||||
_rail_snap_points.Clear();
|
||||
_current_snap_lock.x = -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user