//Good Game //Vector3 Snap (ABPath path, Exactness mode, bool start, out bool forceAddPoint) { VInt3 Snap(ABPath path, Exactness mode, bool start, out bool forceAddPoint) { var index = start ? 0 : path.path.Count - 1; var node = path.path[index]; //Good Game //var nodePos = (Vector3)node.position; var nodePos = node.position; forceAddPoint = false; switch (mode) { case Exactness.ClosestOnNode: return(start ? path.startPoint : path.endPoint); case Exactness.SnapToNode: return(nodePos); case Exactness.Original: case Exactness.Interpolate: case Exactness.NodeConnection: //Good Game //Vector3 relevantPoint; VInt3 relevantPoint; if (start) { relevantPoint = adjustStartPoint != null?adjustStartPoint() : path.originalStartPoint; } else { relevantPoint = path.originalEndPoint; } switch (mode) { case Exactness.Original: return(GetClampedPoint(nodePos, relevantPoint, node)); case Exactness.Interpolate: // Adjacent node to either the start node or the end node in the path var adjacentNode = path.path[Mathf.Clamp(index + (start ? 1 : -1), 0, path.path.Count - 1)]; //Good Game //return VectorMath.ClosestPointOnSegment(nodePos, (Vector3)adjacentNode.position, relevantPoint); return(IntMath.NearestPointStrict(nodePos, adjacentNode.position, relevantPoint)); case Exactness.NodeConnection: // This code uses some tricks to avoid allocations // even though it uses delegates heavily // The connectionBufferAddDelegate delegate simply adds whatever node // it is called with to the connectionBuffer connectionBuffer = connectionBuffer ?? new List <GraphNode>(); connectionBufferAddDelegate = connectionBufferAddDelegate ?? (System.Action <GraphNode>)connectionBuffer.Add; // Adjacent node to either the start node or the end node in the path adjacentNode = path.path[Mathf.Clamp(index + (start ? 1 : -1), 0, path.path.Count - 1)]; // Add all neighbours of #node to the connectionBuffer node.GetConnections(connectionBufferAddDelegate); var bestPos = nodePos; var bestDist = float.PositiveInfinity; // Loop through all neighbours // Do it in reverse order because the length of the connectionBuffer // will change during iteration for (int i = connectionBuffer.Count - 1; i >= 0; i--) { var neighbour = connectionBuffer[i]; // Find the closest point on the connection between the nodes // and check if the distance to that point is lower than the previous best //Good Game //var closest = VectorMath.ClosestPointOnSegment(nodePos, (Vector3)neighbour.position, relevantPoint); var closest = IntMath.NearestPointStrict(nodePos, neighbour.position, relevantPoint); var dist = (closest - relevantPoint).sqrMagnitude; if (dist < bestDist) { bestPos = closest; bestDist = dist; // If this node is not the adjacent node // then the path should go through the start node as well forceAddPoint = neighbour != adjacentNode; } } connectionBuffer.Clear(); return(bestPos); default: throw new System.ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that."); } default: throw new System.ArgumentException("Invalid mode"); } }