From 708d5b6712a213a91ac6c91c10da63dfddbef024 Mon Sep 17 00:00:00 2001 From: michi_cc Date: Tue, 17 Apr 2012 19:43:29 +0000 Subject: (svn r24129) -Feature [FS#3660]: Option to minimise signal distance when dragging over obstacles. (adf88) --- src/rail_cmd.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 10 deletions(-) (limited to 'src/rail_cmd.cpp') diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 1b60bfc6e..e8f92e51f 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1198,6 +1198,7 @@ static bool CheckSignalAutoFill(TileIndex &tile, Trackdir &trackdir, int &signal * - p2 = (bit 5) - 0 = build, 1 = remove signals * - p2 = (bit 6) - 0 = selected stretch, 1 = auto fill * - p2 = (bit 7- 9) - default signal type + * - p2 = (bit 10) - 0 = keep fixed distance, 1 = minimise gaps between signals * - p2 = (bit 24-31) - user defined signals_density * @param text unused * @return the cost of this operation or an error @@ -1212,6 +1213,7 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin bool semaphores = HasBit(p2, 4); bool remove = HasBit(p2, 5); bool autofill = HasBit(p2, 6); + bool minimise_gaps = HasBit(p2, 10); byte signal_density = GB(p2, 24, 8); if (p1 >= MapSize() || !ValParamTrackOrientation(track)) return CMD_ERROR; @@ -1258,7 +1260,11 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin if (signals & SignalAgainstTrackdir(trackdir)) SetBit(signal_dir, 1); /* signal_ctr - amount of tiles already processed + * last_used_ctr - amount of tiles before previously placed signal * signals_density - setting to put signal on every Nth tile (double space on |, -- tracks) + * last_suitable_ctr - amount of tiles before last possible signal place + * last_suitable_tile - last tile where it is possible to place a signal + * last_suitable_trackdir - trackdir of the last tile ********** * trackdir - trackdir to build with autorail * semaphores - semaphores or signals @@ -1266,11 +1272,15 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin * and convert all others to semaphore/signal * remove - 1 remove signals, 0 build signals */ int signal_ctr = 0; + int last_used_ctr = INT_MIN; // initially INT_MIN to force building/removing at the first tile + int last_suitable_ctr = 0; + TileIndex last_suitable_tile = INVALID_TILE; + Trackdir last_suitable_trackdir = INVALID_TRACKDIR; CommandCost last_error = CMD_ERROR; bool had_success = false; for (;;) { /* only build/remove signals with the specified density */ - if (remove || signal_ctr % signal_density == 0) { + if (remove || minimise_gaps || signal_ctr % signal_density == 0) { uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3); SB(p1, 3, 1, mode); SB(p1, 4, 1, semaphores); @@ -1282,17 +1292,42 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin if (HasBit(signal_dir, 0)) signals |= SignalAlongTrackdir(trackdir); if (HasBit(signal_dir, 1)) signals |= SignalAgainstTrackdir(trackdir); - CommandCost ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); + /* Test tiles in between for suitability as well if minimising gaps. */ + bool test_only = minimise_gaps && signal_ctr < (last_used_ctr + signal_density); + CommandCost ret = DoCommand(tile, p1, signals, test_only ? flags & ~DC_EXEC : flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); - /* Be user-friendly and try placing signals as much as possible */ if (ret.Succeeded()) { - had_success = true; - total_cost.AddCost(ret); - } else { - /* The "No railway" error is the least important one. */ - if (ret.GetErrorMessage() != STR_ERROR_THERE_IS_NO_RAILROAD_TRACK || - last_error.GetErrorMessage() == INVALID_STRING_ID) { - last_error = ret; + /* Remember last track piece where we can place a signal. */ + last_suitable_ctr = signal_ctr; + last_suitable_tile = tile; + last_suitable_trackdir = trackdir; + } else if (!test_only && last_suitable_tile != INVALID_TILE) { + /* If a signal can't be placed, place it at the last possible position. */ + SB(p1, 0, 3, TrackdirToTrack(last_suitable_trackdir)); + ClrBit(p1, 17); + + /* Pick the correct orientation for the track direction. */ + signals = 0; + if (HasBit(signal_dir, 0)) signals |= SignalAlongTrackdir(last_suitable_trackdir); + if (HasBit(signal_dir, 1)) signals |= SignalAgainstTrackdir(last_suitable_trackdir); + + ret = DoCommand(last_suitable_tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS); + } + + /* Collect cost. */ + if (!test_only) { + /* Be user-friendly and try placing signals as much as possible */ + if (ret.Succeeded()) { + had_success = true; + total_cost.AddCost(ret); + last_used_ctr = last_suitable_ctr; + last_suitable_tile = INVALID_TILE; + } else { + /* The "No railway" error is the least important one. */ + if (ret.GetErrorMessage() != STR_ERROR_THERE_IS_NO_RAILROAD_TRACK || + last_error.GetErrorMessage() == INVALID_STRING_ID) { + last_error = ret; + } } } } -- cgit v1.2.3-54-g00ecf