/** Draw gizmos for the graph */ public virtual void OnDrawGizmos(bool drawNodes) { if (!drawNodes) { return; } // This is the relatively slow default implementation // subclasses of the base graph class may override // this method to draw gizmos in a more optimized way PathHandler data = AstarPath.active.debugPathData; GraphNode node = null; // Use this delegate to draw connections // from the #node variable to #otherNode GraphNodeDelegate drawConnection = otherNode => Gizmos.DrawLine((Vector3)node.position, (Vector3)otherNode.position); GetNodes(_node => { // Set the #node variable so that #drawConnection can use it node = _node; Gizmos.color = NodeColor(node, AstarPath.active.debugPathData); if (AstarPath.active.showSearchTree && !InSearchTree(node, AstarPath.active.debugPath)) { return(true); } PathNode nodeR = data != null ? data.GetPathNode(node) : null; if (AstarPath.active.showSearchTree && nodeR != null && nodeR.parent != null) { Gizmos.DrawLine((Vector3)node.position, (Vector3)nodeR.parent.node.position); } else { node.GetConnections(drawConnection); } return(true); }); }
/** Draw gizmos for the graph */ public virtual void OnDrawGizmos(bool drawNodes) { if (!drawNodes) { return; } PathHandler data = AstarPath.active.debugPathData; GraphNode node = null; // Use this delegate to draw connections // from the #node variable to #otherNode GraphNodeDelegate drawConnection = otherNode => Gizmos.DrawLine((Vector3)node.position, (Vector3)otherNode.position); GetNodes(_node => { // Set the #node variable so that #drawConnection can use it node = _node; Gizmos.color = NodeColor(node, AstarPath.active.debugPathData); if (AstarPath.active.showSearchTree && !InSearchTree(node, AstarPath.active.debugPath)) { return(true); } PathNode nodeR = data != null ? data.GetPathNode(node) : null; if (AstarPath.active.showSearchTree && nodeR != null && nodeR.parent != null) { Gizmos.DrawLine((Vector3)node.position, (Vector3)nodeR.parent.node.position); } else { node.GetConnections(drawConnection); } return(true); }); }
public virtual void OnDrawGizmos(bool drawNodes) { if (!drawNodes) { return; } var data = AstarPath.active.debugPathData; GraphNode node = null; GraphNodeDelegate del = delegate(GraphNode o) { Gizmos.DrawLine((Vector3)node.position, (Vector3)o.position); }; GetNodes(delegate(GraphNode _node) { node = _node; Gizmos.color = NodeColor(node, AstarPath.active.debugPathData); if (AstarPath.active.showSearchTree && !InSearchTree(node, AstarPath.active.debugPath)) { return(true); } var nodeR = data != null ? data.GetPathNode(node) : null; if (AstarPath.active.showSearchTree && nodeR != null && nodeR.parent != null) { Gizmos.DrawLine((Vector3)node.position, (Vector3)nodeR.parent.node.position); } else { node.GetConnections(del); } return(true); }); }
// Token: 0x060027A0 RID: 10144 RVA: 0x001B3164 File Offset: 0x001B1364 public static List <GraphNode> BFS(GraphNode seed, int depth, int tagMask = -1, Func <GraphNode, bool> filter = null) { PathUtilities.BFSQueue = (PathUtilities.BFSQueue ?? new Queue <GraphNode>()); Queue <GraphNode> que = PathUtilities.BFSQueue; PathUtilities.BFSMap = (PathUtilities.BFSMap ?? new Dictionary <GraphNode, int>()); Dictionary <GraphNode, int> map = PathUtilities.BFSMap; que.Clear(); map.Clear(); List <GraphNode> result = ListPool <GraphNode> .Claim(); int currentDist = -1; Action <GraphNode> action; if (tagMask == -1) { action = delegate(GraphNode node) { if (node.Walkable && !map.ContainsKey(node)) { if (filter != null && !filter(node)) { return; } map.Add(node, currentDist + 1); result.Add(node); que.Enqueue(node); } }; } else { action = delegate(GraphNode node) { if (node.Walkable && (tagMask >> (int)node.Tag & 1) != 0 && !map.ContainsKey(node)) { if (filter != null && !filter(node)) { return; } map.Add(node, currentDist + 1); result.Add(node); que.Enqueue(node); } }; } action(seed); while (que.Count > 0) { GraphNode graphNode = que.Dequeue(); currentDist = map[graphNode]; if (currentDist >= depth) { break; } graphNode.GetConnections(action); } que.Clear(); map.Clear(); return(result); }
/** Returns all nodes up to a given node-distance from the seed node. * This function performs a BFS (breadth-first-search) or flood fill of the graph and returns all nodes within a specified node distance which can be reached from * the seed node. In almost all cases when \a depth is large enough this will be identical to returning all nodes which have the same area as the seed node. * In the editor areas are displayed as different colors of the nodes. * The only case where it will not be so is when there is a one way path from some part of the area to the seed node * but no path from the seed node to that part of the graph. * * The returned list is sorted by node distance from the seed node * i.e distance is measured in the number of nodes the shortest path from \a seed to that node would pass through. * Note that the distance measurement does not take heuristics, penalties or tag penalties. * * Depending on the number of nodes, this function can take quite some time to calculate * so don't use it too often or it might affect the framerate of your game. * * \param seed The node to start the search from. * \param depth The maximum node-distance from the seed node. * \param tagMask Optional mask for tags. This is a bitmask. * * \returns A List<Node> containing all nodes reachable up to a specified node distance from the seed node. * For better memory management the returned list should be pooled, see Pathfinding.Util.ListPool * * \warning This method is not thread safe. Only use it from the Unity thread (i.e normal game code). */ public static List <GraphNode> BFS(GraphNode seed, int depth, int tagMask = -1) { #if ASTAR_PROFILE System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); #endif BFSQueue = BFSQueue ?? new Queue <GraphNode>(); var que = BFSQueue; BFSMap = BFSMap ?? new Dictionary <GraphNode, int>(); var map = BFSMap; // Even though we clear at the end of this function, it is good to // do it here as well in case the previous invocation of the method // threw an exception for some reason // and didn't clear the que and map que.Clear(); map.Clear(); List <GraphNode> result = ListPool <GraphNode> .Claim(); int currentDist = -1; GraphNodeDelegate callback; if (tagMask == -1) { callback = node => { if (node.Walkable && !map.ContainsKey(node)) { map.Add(node, currentDist + 1); result.Add(node); que.Enqueue(node); } }; } else { callback = node => { if (node.Walkable && ((tagMask >> (int)node.Tag) & 0x1) != 0 && !map.ContainsKey(node)) { map.Add(node, currentDist + 1); result.Add(node); que.Enqueue(node); } }; } callback(seed); while (que.Count > 0) { GraphNode n = que.Dequeue(); currentDist = map[n]; if (currentDist >= depth) { break; } n.GetConnections(callback); } que.Clear(); map.Clear(); #if ASTAR_PROFILE watch.Stop(); Debug.Log((1000 * watch.Elapsed.TotalSeconds).ToString("0.0 ms")); #endif return(result); }
/** Returns all nodes up to a given node-distance from the seed node. * This function performs a BFS (breadth-first-search) or flood fill of the graph and returns all nodes within a specified node distance which can be reached from * the seed node. In almost all cases when \a depth is large enough this will be identical to returning all nodes which have the same area as the seed node. * In the editor areas are displayed as different colors of the nodes. * The only case where it will not be so is when there is a one way path from some part of the area to the seed node * but no path from the seed node to that part of the graph. * * The returned list is sorted by node distance from the seed node * i.e distance is measured in the number of nodes the shortest path from \a seed to that node would pass through. * Note that the distance measurement does not take heuristics, penalties or tag penalties. * * Depending on the number of nodes, this function can take quite some time to calculate * so don't use it too often or it might affect the framerate of your game. * * \param seed The node to start the search from. * \param depth The maximum node-distance from the seed node. * \param tagMask Optional mask for tags. This is a bitmask. * * \returns A List<Node> containing all nodes reachable up to a specified node distance from the seed node. * For better memory management the returned list should be pooled, see Pathfinding.Util.ListPool * * \warning This method is not thread safe. Only use it from the Unity thread (i.e normal game code). */ public static List <GraphNode> BFS(GraphNode seed, int depth, int tagMask = -1) { BFSQueue = BFSQueue ?? new Queue <GraphNode>(); var que = BFSQueue; BFSMap = BFSMap ?? new Dictionary <GraphNode, int>(); var map = BFSMap; // Even though we clear at the end of this function, it is good to // do it here as well in case the previous invocation of the method // threw an exception for some reason // and didn't clear the que and map que.Clear(); map.Clear(); List <GraphNode> result = ListPool <GraphNode> .Claim(); int currentDist = -1; GraphNodeDelegate callback; if (tagMask == -1) { callback = node => { if (node.Walkable && !map.ContainsKey(node)) { map.Add(node, currentDist + 1); result.Add(node); que.Enqueue(node); } }; } else { callback = node => { if (node.Walkable && ((tagMask >> (int)node.Tag) & 0x1) != 0 && !map.ContainsKey(node)) { map.Add(node, currentDist + 1); result.Add(node); que.Enqueue(node); } }; } callback(seed); while (que.Count > 0) { GraphNode n = que.Dequeue(); currentDist = map[n]; if (currentDist >= depth) { break; } n.GetConnections(callback); } que.Clear(); map.Clear(); return(result); }
private Vector3 Snap(ABPath path, StartEndModifier.Exactness mode, bool start, out bool forceAddPoint) { int num = start ? 0 : (path.path.Count - 1); GraphNode graphNode = path.path[num]; Vector3 vector = (Vector3)graphNode.position; forceAddPoint = false; switch (mode) { case StartEndModifier.Exactness.SnapToNode: return(vector); case StartEndModifier.Exactness.Original: case StartEndModifier.Exactness.Interpolate: case StartEndModifier.Exactness.NodeConnection: { Vector3 vector2; if (start) { vector2 = ((this.adjustStartPoint != null) ? this.adjustStartPoint() : path.originalStartPoint); } else { vector2 = path.originalEndPoint; } switch (mode) { case StartEndModifier.Exactness.Original: return(this.GetClampedPoint(vector, vector2, graphNode)); case StartEndModifier.Exactness.Interpolate: { Vector3 clampedPoint = this.GetClampedPoint(vector, vector2, graphNode); GraphNode graphNode2 = path.path[Mathf.Clamp(num + (start ? 1 : -1), 0, path.path.Count - 1)]; return(VectorMath.ClosestPointOnSegment(vector, (Vector3)graphNode2.position, clampedPoint)); } case StartEndModifier.Exactness.NodeConnection: { this.connectionBuffer = (this.connectionBuffer ?? new List <GraphNode>()); Action <GraphNode> action; if ((action = this.connectionBufferAddDelegate) == null) { action = new Action <GraphNode>(this.connectionBuffer.Add); } this.connectionBufferAddDelegate = action; GraphNode graphNode2 = path.path[Mathf.Clamp(num + (start ? 1 : -1), 0, path.path.Count - 1)]; graphNode.GetConnections(this.connectionBufferAddDelegate); Vector3 result = vector; float num2 = float.PositiveInfinity; for (int i = this.connectionBuffer.Count - 1; i >= 0; i--) { GraphNode graphNode3 = this.connectionBuffer[i]; Vector3 vector3 = VectorMath.ClosestPointOnSegment(vector, (Vector3)graphNode3.position, vector2); float sqrMagnitude = (vector3 - vector2).sqrMagnitude; if (sqrMagnitude < num2) { result = vector3; num2 = sqrMagnitude; forceAddPoint = (graphNode3 != graphNode2); } } this.connectionBuffer.Clear(); return(result); } } throw new ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that."); } case StartEndModifier.Exactness.ClosestOnNode: return(this.GetClampedPoint(vector, start ? path.startPoint : path.endPoint, graphNode)); default: throw new ArgumentException("Invalid mode"); } }
private Vector3 Snap(ABPath path, Exactness mode, bool start, out bool forceAddPoint) { Vector3 originalEndPoint; GraphNode node2; int num = !start ? (path.path.Count - 1) : 0; GraphNode hint = path.path[num]; Vector3 position = (Vector3)hint.position; forceAddPoint = false; switch (mode) { case Exactness.SnapToNode: return(position); case Exactness.Original: case Exactness.Interpolate: case Exactness.NodeConnection: if (!start) { originalEndPoint = path.originalEndPoint; break; } originalEndPoint = (this.adjustStartPoint == null) ? path.originalStartPoint : this.adjustStartPoint(); break; case Exactness.ClosestOnNode: return(this.GetClampedPoint(position, !start ? path.endPoint : path.startPoint, hint)); default: throw new ArgumentException("Invalid mode"); } switch (mode) { case Exactness.Original: return(this.GetClampedPoint(position, originalEndPoint, hint)); case Exactness.Interpolate: { Vector3 point = this.GetClampedPoint(position, originalEndPoint, hint); node2 = path.path[Mathf.Clamp(num + (!start ? -1 : 1), 0, path.path.Count - 1)]; return(VectorMath.ClosestPointOnSegment(position, (Vector3)node2.position, point)); } case Exactness.NodeConnection: { if (this.connectionBuffer == null) { } this.connectionBuffer = new List <GraphNode>(); if (this.connectionBufferAddDelegate == null) { } this.connectionBufferAddDelegate = new GraphNodeDelegate(this.connectionBuffer.Add); node2 = path.path[Mathf.Clamp(num + (!start ? -1 : 1), 0, path.path.Count - 1)]; hint.GetConnections(this.connectionBufferAddDelegate); Vector3 vector4 = position; float positiveInfinity = float.PositiveInfinity; for (int i = this.connectionBuffer.Count - 1; i >= 0; i--) { GraphNode node3 = this.connectionBuffer[i]; Vector3 vector5 = VectorMath.ClosestPointOnSegment(position, (Vector3)node3.position, originalEndPoint); Vector3 vector6 = vector5 - originalEndPoint; float sqrMagnitude = vector6.sqrMagnitude; if (sqrMagnitude < positiveInfinity) { vector4 = vector5; positiveInfinity = sqrMagnitude; forceAddPoint = node3 != node2; } } this.connectionBuffer.Clear(); return(vector4); } } throw new ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that."); }