/// <summary> /// Scans for and applies reductions if specified anchor tile contains a collider. /// </summary> /// <remarks> /// <para>This method searches from left-to-right from specified anchor tile to /// find furthest tile horizontally that it can be reduced with. Once the initial /// horizontal sequence is known this method proceeds to scan vertically for other /// sequences of colliders that can further reduce the initial horizontal sequence.</para> /// </remarks> /// <param name="anchor">Index of anchor tile.</param> /// <returns></returns> private int Scan(TileIndex anchor) { ColliderInfo anchorInfo = null; this.GetColliderInfo(ref anchorInfo, anchor); if (anchorInfo == null) { return(anchor.column); } ColliderInfo info = null, firstInfo = null, lastInfo = null; // Begin tracking list of collider components which will be combined. this.ResetReducedColliderTracking(); this.TrackReducedCollider(anchorInfo.Row, anchorInfo.Column, anchorInfo.Collider); try { TileIndex target = anchor; BoxBounds reducedBounds = anchorInfo.Bounds; // Scan rightwards for colliders which can be combined with anchor. for (int column = anchor.column + 1; column < this.system.ColumnCount; ++column) { if (this.markedTiles[anchor.row, column]) { break; } this.GetColliderInfo(ref info, anchor.row, column); if (!this.CanReduce(info, anchorInfo)) { break; } // Can candidate collider be combined with anchor? if (!reducedBounds.Encapsulate(info.Bounds)) { break; } target.column = column; this.TrackReducedCollider(info.Row, info.Column, info.Collider); } this.GetColliderInfo(ref info, target); var prevFirstBounds = anchorInfo.Bounds; var prevLastBounds = info.Bounds; // Extend downwards if possible, though avoid crossing T-junctions since splitting // a T-junction will often cause more colliders to occur in result. for (int row = anchor.row + 1; row < this.system.RowCount; ++row) { this.GetColliderInfo(ref firstInfo, row, anchor.column); this.GetColliderInfo(ref lastInfo, row, target.column); if (firstInfo == null || lastInfo == null || !this.CanReduce(firstInfo, anchorInfo) || this.CheckForTJunction(firstInfo, lastInfo)) { goto FinishedExtendingDownards; } // Does first and last tile from previous row extend downwards? if (!prevFirstBounds.Encapsulate(firstInfo.Bounds) || !prevLastBounds.Encapsulate(lastInfo.Bounds)) { goto FinishedExtendingDownards; } // No need to track collider from `lastInfo` since it will be included // within the following loop. this.candidateColliders.Clear(); this.candidateColliders.Add(firstInfo.Collider); // Reduce bounds for strip. BoxBounds stripBounds = firstInfo.Bounds; for (int column = anchor.column + 1; column <= target.column; ++column) { this.GetColliderInfo(ref info, row, column); if (!this.CanReduce(info, anchorInfo) || !stripBounds.Encapsulate(info.Bounds)) { goto FinishedExtendingDownards; } this.candidateColliders.Add(info.Collider); } // The following should not fail, but let's just be safe! if (!reducedBounds.Encapsulate(stripBounds)) { Debug.LogWarning("Unable to encapsulate collider on reduce."); goto FinishedExtendingDownards; } target.row = row; // Accept and track candidate colliders! for (int i = 0; i < this.candidateColliders.Count; ++i) { this.TrackReducedCollider(row, anchor.column + i, this.candidateColliders[i]); } prevFirstBounds = firstInfo.Bounds; prevLastBounds = lastInfo.Bounds; } FinishedExtendingDownards: ; bool hasManyColliders = (this.reducedColliderCount > 1); bool hasOneHypotheticalCollider = (this.reducedColliderCount == 1 && this.reducedColliderComponents.Count == 0); if (hasManyColliders || hasOneHypotheticalCollider) { this.Reduce(anchorInfo, reducedBounds); } return(target.column); } finally { ColliderInfo.Despawn(anchorInfo); ColliderInfo.Despawn(info); ColliderInfo.Despawn(firstInfo); ColliderInfo.Despawn(lastInfo); } }
/// <inheritdoc cref="this.GetColliderInfo(ref ColliderInfo, int, int)"/> /// <param name="index">Index of tile.</param> private void GetColliderInfo(ref ColliderInfo info, TileIndex index) { this.GetColliderInfo(ref info, index.row, index.column); }