diff options
Diffstat (limited to 'src/viewport.cpp')
-rw-r--r-- | src/viewport.cpp | 429 |
1 files changed, 362 insertions, 67 deletions
diff --git a/src/viewport.cpp b/src/viewport.cpp index bfcc8d9d1..10cc8f360 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -28,6 +28,8 @@ #include "stdafx.h" #include "landscape.h" +#include "layer_gui.h" +#include "layer_func.h" #include "viewport_func.h" #include "station_base.h" #include "waypoint_base.h" @@ -51,6 +53,13 @@ Point _tile_fract_coords; +struct RailTrackEndpoint { + TileIndex tile; + TrackdirBits dirs; +}; + +RailTrackEndpoint _rail_track_endpoints[4]; + struct StringSpriteToDraw { StringID string; Colours colour; @@ -1080,6 +1089,8 @@ static void ViewportAddLandscape() y_cur < MapMaxY() * TILE_SIZE) { TileIndex tile = TileVirtXY(x_cur, y_cur); + /* Валидны только клетки текущего слоя */ + if (LayerIndex(tile) == _vd.dpi.layer) if (!_settings_game.construction.freeform_edges || (TileX(tile) != 0 && TileY(tile) != 0)) { if (x_cur == ((int)MapMaxX() - 1) * TILE_SIZE || y_cur == ((int)MapMaxY() - 1) * TILE_SIZE) { uint maxh = max<uint>(TileHeight(tile), 1); @@ -1475,6 +1486,9 @@ void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom _vd.dpi.dst_ptr = BlitterFactoryBase::GetCurrentBlitter()->MoveTo(old_dpi->dst_ptr, x - old_dpi->left, y - old_dpi->top); + /* Определение слоя (который будем рисовать) */ + _vd.dpi.layer = calculateLayer(vp); + ViewportAddLandscape(); ViewportAddVehicles(&_vd.dpi); @@ -1953,7 +1967,7 @@ static void PlaceObject() } -bool HandleViewportClicked(const ViewPort *vp, int x, int y) +bool HandleViewportClicked(const ViewPort *vp, int x, int y, bool double_click) { const Vehicle *v = CheckClickOnVehicle(vp, x, y); @@ -1961,6 +1975,13 @@ bool HandleViewportClicked(const ViewPort *vp, int x, int y) if (v != NULL && VehicleClicked(v)) return true; } + /* Double-clicking finishes current polyline and starts new one. */ + if (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) { PlaceObject(); @@ -2113,7 +2134,7 @@ Window *TileHighlightData::GetCallbackWnd() return FindWindowById(this->window_class, this->window_number); } - +static HighLightStyle CalcPolyrailDrawstyle(Point pt); /** * Updates tile highlighting for all cases. @@ -2170,28 +2191,42 @@ void UpdateTileSelection() y1 += TILE_SIZE / 2; break; case HT_RAIL: - /* Draw one highlighted tile in any direction */ - new_drawstyle = GetAutorailHT(pt.x, pt.y); - break; case HT_LINE: - switch (_thd.place_mode & HT_DIR_MASK) { - case HT_DIR_X: new_drawstyle = HT_LINE | HT_DIR_X; break; - case HT_DIR_Y: new_drawstyle = HT_LINE | HT_DIR_Y; break; - - case HT_DIR_HU: - case HT_DIR_HL: - new_drawstyle = (pt.x & TILE_UNIT_MASK) + (pt.y & TILE_UNIT_MASK) <= TILE_SIZE ? HT_LINE | HT_DIR_HU : HT_LINE | HT_DIR_HL; - break; - - case HT_DIR_VL: - case HT_DIR_VR: - new_drawstyle = (pt.x & TILE_UNIT_MASK) > (pt.y & TILE_UNIT_MASK) ? HT_LINE | HT_DIR_VL : HT_LINE | HT_DIR_VR; + /* Handle polyline highlight */ + if (_thd.place_mode & HT_POLY) { + new_drawstyle = CalcPolyrailDrawstyle(pt); + if (new_drawstyle != HT_NONE) { + x1 = min(_thd.selstart.x, _thd.selend.x); + y1 = min(_thd.selstart.y, _thd.selend.y); + _thd.new_size.x = abs<int>(_thd.selstart.x - (_thd.selend.x & ~TILE_UNIT_MASK)) + TILE_SIZE; + _thd.new_size.y = abs<int>(_thd.selstart.y - (_thd.selend.y & ~TILE_UNIT_MASK)) + TILE_SIZE; break; - - default: NOT_REACHED(); + } + } + /* Handle regular (non-polyline) highlight */ + if (_thd.place_mode & HT_RAIL) { + /* Draw one highlighted tile in any direction */ + new_drawstyle = GetAutorailHT(pt.x, pt.y); + } else { // HT_LINE + switch (_thd.place_mode & HT_DIR_MASK) { + case HT_DIR_X: new_drawstyle = HT_LINE | HT_DIR_X; break; + case HT_DIR_Y: new_drawstyle = HT_LINE | HT_DIR_Y; break; + + case HT_DIR_HU: + case HT_DIR_HL: + new_drawstyle = (pt.x & TILE_UNIT_MASK) + (pt.y & TILE_UNIT_MASK) <= TILE_SIZE ? HT_LINE | HT_DIR_HU : HT_LINE | HT_DIR_HL; + break; + + case HT_DIR_VL: + case HT_DIR_VR: + new_drawstyle = (pt.x & TILE_UNIT_MASK) > (pt.y & TILE_UNIT_MASK) ? HT_LINE | HT_DIR_VL : HT_LINE | HT_DIR_VR; + break; + + default: NOT_REACHED(); + } + _thd.selstart.x = x1 & ~TILE_UNIT_MASK; + _thd.selstart.y = y1 & ~TILE_UNIT_MASK; } - _thd.selstart.x = x1 & ~TILE_UNIT_MASK; - _thd.selstart.y = y1 & ~TILE_UNIT_MASK; break; default: NOT_REACHED(); @@ -2455,7 +2490,31 @@ static int CalcHeightdiff(HighLightStyle style, uint distance, TileIndex start_t return (int)(h1 - h0) * TILE_HEIGHT_STEP; } -static const StringID measure_strings_length[] = {STR_NULL, STR_MEASURE_LENGTH, STR_MEASURE_LENGTH_HEIGHTDIFF}; +static void ShowLengthMeasurement(HighLightStyle style, TileIndex start_tile, TileIndex end_tile, TooltipCloseCondition close_cond = TCC_LEFT_CLICK, bool show_single_tile_length = false) +{ + static const StringID measure_strings_length[] = {STR_NULL, STR_MEASURE_LENGTH, STR_MEASURE_LENGTH_HEIGHTDIFF}; + + if (_settings_client.gui.measure_tooltip) { + uint distance = DistanceManhattan(start_tile, end_tile) + 1; + byte index = 0; + uint64 params[2]; + + if (show_single_tile_length || distance != 1) { + int heightdiff = CalcHeightdiff(style, distance, start_tile, end_tile); + /* If we are showing a tooltip for horizontal or vertical drags, + * 2 tiles have a length of 1. To bias towards the ceiling we add + * one before division. It feels more natural to count 3 lengths as 2 */ + if ((style & HT_DIR_MASK) != HT_DIR_X && (style & HT_DIR_MASK) != HT_DIR_Y) { + distance = CeilDiv(distance, 2); + } + + params[index++] = distance; + if (heightdiff != 0) params[index++] = heightdiff; + } + + ShowMeasurementTooltips(measure_strings_length[index], index, params, close_cond); + } +} /** * Check for underflowing the map. @@ -2486,8 +2545,178 @@ static void CheckOverflow(int &test, int &other, int max, int mult) test = max; } +static const struct { + Point start_point_offset; + Point direction; +} +_auto_line_by_trackdir[] = { + { { TILE_SIZE - 2, TILE_SIZE / 2 }, { -1, 0 } }, // TRACKDIR_X_NE + { { TILE_SIZE / 2, 0 }, { 0, +1 } }, // TRACKDIR_Y_SE + { { TILE_SIZE / 2 - 1, 0 }, { -1, +1 } }, // TRACKDIR_UPPER_E + { { TILE_SIZE - 1, TILE_SIZE / 2 }, { -1, +1 } }, // TRACKDIR_LOWER_E + { { TILE_SIZE / 2, 0 }, { +1, +1 } }, // TRACKDIR_LEFT_S + { { 0, TILE_SIZE / 2 }, { +1, +1 } }, // TRACKDIR_RIGHT_S + { { 0, 0 }, { 0, 0 } }, // TRACKDIR_RVREV_NE + { { 0, 0 }, { 0, 0 } }, // TRACKDIR_RVREV_SE + { { 0, TILE_SIZE / 2 }, { +1, 0 } }, // TRACKDIR_X_SW + { { TILE_SIZE / 2, TILE_SIZE - 1 }, { 0, -1 } }, // TRACKDIR_Y_NW + { { 0, TILE_SIZE / 2 - 1 }, { +1, -1 } }, // TRACKDIR_UPPER_W + { { TILE_SIZE / 2, TILE_SIZE - 1 }, { +1, -1 } }, // TRACKDIR_LOWER_W + { { TILE_SIZE - 1, TILE_SIZE / 2 - 1 }, { -1, -1 } }, // TRACKDIR_LEFT_N + { { TILE_SIZE / 2 - 1, TILE_SIZE - 1 }, { -1, -1 } } // TRACKDIR_RIGHT_N +}; + +/** + * Returns the distnce from a given point to a rail line. + * + * @param pt The point to get the distance from. + * @param start_tile Coordinates, in tile "units", of the tile where the line starts. + * @param trackdir The first trackdir of the line. + * @return X/Y coordinates of the vector that connects the 'pt' point with the line at the best path. + */ +static Point GetDistanceToAutoLine(Point pt, Point start_tile, Trackdir trackdir) +{ + assert(IsValidTrackdir(trackdir) && !IsReversingRoadTrackdir(trackdir)); + + /* calculate distance from the given point to the point where the line starts */ + Point d = { + start_tile.x + _auto_line_by_trackdir[trackdir].start_point_offset.x - pt.x, + start_tile.y + _auto_line_by_trackdir[trackdir].start_point_offset.y - pt.y + }; + /* get line direction */ + Point direction = _auto_line_by_trackdir[trackdir].direction; + /* correct the start point for "diagonal" dirs; there are two possible lines, choose the closer one */ + if (direction.x == 0) { // TRACKDIR_Y_SE and TRACKDIR_Y_NW trackdirs + d.x -= (int)(d.x > 0); + } else if (direction.y == 0) { // TRACKDIR_X_NE and TRACKDIR_X_SW trackdirs + d.y -= (int)(d.y > 0); + } + + /* calculate distance to the end of the line */ + int scale = direction.x * direction.x + direction.y * direction.y; + int length = d.x * direction.y - d.y * direction.x; + Point ret = { direction.y, -direction.x }; // 'direction' rotated 90 degree right + if (length > 0) { // is the 'p' point on the left side of the line ("up" is pointed by 'direction') + ret.x -= direction.x; + ret.y -= direction.y; + } else { + ret.x += direction.x; + ret.y += direction.y; + } + ret.x = length * ret.x / scale; + ret.y = length * ret.y / scale; + + /* test if the calculated end point is behind the start point; + * if not return the distance to the start point */ + if (((d.x < ret.x) == (direction.x < 0)) && ((d.y < ret.y) == (direction.y < 0))) return d; + + return ret; +} + +static void ClampAutoLineToMapBorders(Point *line_end, Track line_orientation) +{ + int padding = _settings_game.construction.freeform_edges ? TILE_SIZE : 0; + + Rect borders = { + padding, // left + padding, // top + MapSizeX() * TILE_SIZE - padding - 1, // right + MapSizeY() * TILE_SIZE - padding - 1 // bottom + }; + + switch (line_orientation) { + case TRACK_X: + line_end->y = Clamp(line_end->y, borders.top, borders.bottom); + break; + + case TRACK_Y: + line_end->x = Clamp(line_end->x, borders.left, borders.right); + break; + + case TRACK_UPPER: + case TRACK_LOWER: + if (line_end->x < borders.left) { + line_end->y += borders.left - line_end->x; + line_end->x += borders.left - line_end->x; + } else if (line_end->x > borders.right) { + line_end->y += borders.right - line_end->x; + line_end->x += borders.right - line_end->x; + } + if (line_end->y < borders.top) { + line_end->x += borders.top - line_end->y; + line_end->y += borders.top - line_end->y; + } else if (line_end->y > borders.bottom) { + line_end->x += borders.bottom - line_end->y; + line_end->y += borders.bottom - line_end->y; + } + break; + + case TRACK_LEFT: + case TRACK_RIGHT: + if (line_end->x < borders.left) { + line_end->y -= borders.left - line_end->x; + line_end->x += borders.left - line_end->x; + } else if (line_end->x > borders.right) { + line_end->y -= borders.right - line_end->x; + line_end->x += borders.right - line_end->x; + } + if (line_end->y < borders.top) { + line_end->x -= borders.top - line_end->y; + line_end->y += borders.top - line_end->y; + } else if (line_end->y > borders.bottom) { + line_end->x -= borders.bottom - line_end->y; + line_end->y += borders.bottom - line_end->y; + } + break; + + default: + NOT_REACHED(); + } + + assert(IsInsideMM(line_end->x, borders.left, borders.right + 1) && IsInsideMM(line_end->y, borders.top, borders.bottom + 1)); +} + +static const TrackdirBits _autoline_dirs_allowed_by_highlight_dir[] = { + TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW, // HT_DIR_X + TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE, // HT_DIR_Y + TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_LOWER_W, // HT_DIR_HU + TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_LOWER_W, // HT_DIR_HL + TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_RIGHT_S, // HT_DIR_VL + TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_RIGHT_S, // HT_DIR_VR +}; + +static Trackdir FindBestAutoLine(const Point &pt, RailTrackEndpoint *start_points, uint num_start_points, TrackdirBits allowed_trackdirs, Point *ret_start_tile, Point *ret_end_pos) +{ + Trackdir ret = INVALID_TRACKDIR; + uint best_distance = UINT_MAX; + + for (; num_start_points-- > 0; start_points++) { + /* skip invalid tiles */ + if (!IsValidTile(start_points->tile)) continue; + + Trackdir trackdir; + FOR_EACH_SET_TRACKDIR(trackdir, start_points->dirs & allowed_trackdirs) { + Point start_tile = { TileX(start_points->tile) * TILE_SIZE, TileY(start_points->tile) * TILE_SIZE }; + Point offset = GetDistanceToAutoLine(pt, start_tile, trackdir); + uint distance = (uint)(offset.x * offset.x + offset.y * offset.y); + if (distance < best_distance) { + *ret_start_tile = start_tile; + ret_end_pos->x = pt.x + offset.x; + ret_end_pos->y = pt.y + offset.y; + best_distance = distance; + ret = trackdir; + } + } + } + + /* cut the line at map borders */ + if (ret != INVALID_TRACKDIR) ClampAutoLineToMapBorders(ret_end_pos, TrackdirToTrack(ret)); + + return ret; +} + /** while dragging */ -static void CalcRaildirsDrawstyle(int x, int y, int method) +static void CalcRaildirsDrawstyle(int x, int y, ViewportPlaceMethod method) { HighLightStyle b; @@ -2672,32 +2901,31 @@ static void CalcRaildirsDrawstyle(int x, int y, int method) } } - if (_settings_client.gui.measure_tooltip) { - TileIndex t0 = TileVirtXY(_thd.selstart.x, _thd.selstart.y); - TileIndex t1 = TileVirtXY(x, y); - uint distance = DistanceManhattan(t0, t1) + 1; - byte index = 0; - uint64 params[2]; + _thd.selend.x = x; + _thd.selend.y = y; + _thd.next_drawstyle = b; - if (distance != 1) { - int heightdiff = CalcHeightdiff(b, distance, t0, t1); - /* If we are showing a tooltip for horizontal or vertical drags, - * 2 tiles have a length of 1. To bias towards the ceiling we add - * one before division. It feels more natural to count 3 lengths as 2 */ - if ((b & HT_DIR_MASK) != HT_DIR_X && (b & HT_DIR_MASK) != HT_DIR_Y) { - distance = CeilDiv(distance, 2); - } + ShowLengthMeasurement(b, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y)); +} - params[index++] = distance; - if (heightdiff != 0) params[index++] = heightdiff; - } +static HighLightStyle CalcPolyrailDrawstyle(Point pt) +{ + /* directions allowed by highlight method */ + TrackdirBits allowed_trackdirs = (_thd.place_mode & HT_RAIL) ? TRACKDIR_BIT_MASK : _autoline_dirs_allowed_by_highlight_dir[_thd.place_mode & HT_DIR_MASK]; - ShowMeasurementTooltips(measure_strings_length[index], index, params); - } + /* now find the best track */ + Trackdir best_trackdir = FindBestAutoLine(pt, _rail_track_endpoints, lengthof(_rail_track_endpoints), allowed_trackdirs, &_thd.selstart, &_thd.selend); + if (best_trackdir == INVALID_TRACKDIR) return HT_NONE; // no match - _thd.selend.x = x; - _thd.selend.y = y; - _thd.next_drawstyle = b; + TileIndex start_tile = TileVirtXY(_thd.selstart.x, _thd.selstart.y); + TileIndex end_tile = TileVirtXY(_thd.selend.x, _thd.selend.y); + + HighLightStyle ret = HT_POLY | + (HighLightStyle)TrackdirToTrack(best_trackdir) | // cast TRACK_XXX to HT_DIR_XXX + (start_tile == end_tile ? HT_RAIL : HT_LINE); // one tile case or multitile selection + + ShowLengthMeasurement(ret, start_tile, end_tile, TCC_HOVER, true); + return ret; } /** @@ -2769,27 +2997,12 @@ calc_heightdiff_single_direction:; x = sx + Clamp(x - sx, -limit, limit); y = sy + Clamp(y - sy, -limit, limit); } - if (_settings_client.gui.measure_tooltip) { - TileIndex t0 = TileVirtXY(sx, sy); - TileIndex t1 = TileVirtXY(x, y); - uint distance = DistanceManhattan(t0, t1) + 1; - byte index = 0; - uint64 params[2]; - - if (distance != 1) { - /* 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; */ - int heightdiff = CalcHeightdiff(HT_LINE | style, 0, t0, t1); - - params[index++] = distance; - if (heightdiff != 0) params[index++] = heightdiff; - } - - ShowMeasurementTooltips(measure_strings_length[index], index, params); - } + /* 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; case VPM_X_AND_Y_LIMITED: // Drag an X by Y constrained rect area. @@ -2900,7 +3113,7 @@ EventState VpHandlePlaceSizingDrag() } else if (_thd.select_method & VPM_SIGNALDIRS) { _thd.place_mode = HT_RECT | others; } else if (_thd.select_method & VPM_RAILDIRS) { - _thd.place_mode = (_thd.select_method & ~VPM_RAILDIRS) ? _thd.next_drawstyle : (HT_RAIL | others); + _thd.place_mode = (_thd.select_method & ~VPM_RAILDIRS ? _thd.next_drawstyle : HT_RAIL) | others; } else { _thd.place_mode = HT_POINT | others; } @@ -2966,3 +3179,85 @@ void ResetObjectToPlace() { SetObjectToPlace(SPR_CURSOR_MOUSE, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0); } + +void RemoveConnectedEndpointDirs(RailTrackEndpoint *a, const RailTrackEndpoint &b) +{ + if (IsValidTile(a->tile) && IsValidTile(b.tile)) { + for (DiagDirection test_dir = DIAGDIR_BEGIN; test_dir < DIAGDIR_END; test_dir++) { + TrackdirBits test_trackdirs = DiagdirReachesTrackdirs(test_dir); + if (test_trackdirs & a->dirs) { + if (a->tile == b.tile) { + if (b.dirs & test_trackdirs) a->dirs &= ~test_trackdirs; + } else if (a->tile - TileOffsByDiagDir(test_dir) == b.tile) { + if (b.dirs & DiagdirReachesTrackdirs(ReverseDiagDir(test_dir))) a->dirs &= ~test_trackdirs; + } + if (a->dirs == TRACKDIR_BIT_NONE) { + a->tile = INVALID_TILE; + return; + } + } + } + } +} + +/** + * Store the position of lastly built rail track; for highlighting purposes. + * + * In "polyline" highlighting mode, the stored end point of the track + * will be used as the start point of a being highlighted track. + * + * @param start_tile tile where the track starts + * @param end_tile tile where the track ends + * @param start_track track piece on the start_tile + * @param bidirectional whether to allow to highlight next track in any direction; otherwise new track will have to fallow the stored one (usefull when placing tunnels and bridges) + */ +void StoreRailPlacementEndpoints(TileIndex start_tile, TileIndex end_tile, Track start_track, bool bidirectional) +{ + const uint NUM_ENDPOINTS = lengthof(_rail_track_endpoints); + + RailTrackEndpoint new_endpoints[NUM_ENDPOINTS] = { + { INVALID_TILE, TRACKDIR_BIT_NONE }, + { INVALID_TILE, TRACKDIR_BIT_NONE }, + { INVALID_TILE, TRACKDIR_BIT_NONE }, + { INVALID_TILE, TRACKDIR_BIT_NONE }, + }; + + if (start_tile != INVALID_TILE && end_tile != INVALID_TILE) { + /* calculate trackdirs at booth ends of the track (pointing toward track middle) */ + Trackdir start_trackdir = TrackToTrackdir(start_track); + Trackdir end_trackdir = ReverseTrackdir(start_trackdir); + if (start_tile != end_tile) { // multi-tile case + /* determine proper direction (toward track middle) */ + uint distance = DistanceManhattan(start_tile, end_tile); + if (distance < DistanceManhattan(TileAddByDiagDir(start_tile, TrackdirToExitdir(start_trackdir)), end_tile)) { + Swap(start_trackdir, end_trackdir); + } + /* determine proper track on the end tile - switch between upper/lower or left/right based on the length */ + if (distance % 2 != 0) end_trackdir = NextTrackdir(end_trackdir); + } + + /* compute new endpoints */ + DiagDirection start_exit_dir = TrackdirToExitdir(ReverseTrackdir(start_trackdir)); + DiagDirection end_exit_dir = TrackdirToExitdir(ReverseTrackdir(end_trackdir)); + new_endpoints[0].tile = TileAddByDiagDir(start_tile, start_exit_dir); + new_endpoints[0].dirs = DiagdirReachesTrackdirs(start_exit_dir); + new_endpoints[1].tile = TileAddByDiagDir(end_tile, end_exit_dir); + new_endpoints[1].dirs = DiagdirReachesTrackdirs(end_exit_dir); + if (bidirectional) { + new_endpoints[2].tile = start_tile; + new_endpoints[2].dirs = DiagdirReachesTrackdirs(ReverseDiagDir(start_exit_dir)); + new_endpoints[3].tile = end_tile; + new_endpoints[3].dirs = DiagdirReachesTrackdirs(ReverseDiagDir(end_exit_dir)); + } + + /* exclude all endpoints stored previously */ + for (uint i = 0; i < NUM_ENDPOINTS; i++) { + for (uint j = 0; j < NUM_ENDPOINTS; j++) { + RemoveConnectedEndpointDirs(&new_endpoints[i], _rail_track_endpoints[j]); + } + } + } + + /* store endpoints */ + MemCpyT(_rail_track_endpoints, new_endpoints, NUM_ENDPOINTS); +} |