using System.Collections.Generic; using Pathfinding.Util; namespace Pathfinding { /// /// Contains useful functions for updating graphs. /// This class works a lot with the GraphNode class, a useful function to get nodes is . /// /// See: /// See: /// /// \since Added in 3.1 /// /// \ingroup utils /// public static class GraphUpdateUtilities { /// /// Updates graphs and checks if all nodes are still reachable from each other. /// Graphs are updated, then a check is made to see if the nodes are still reachable from each other. /// If they are not, the graphs are reverted to before the update and false is returned.\n /// This is slower than a normal graph update. /// All queued graph updates and thread safe callbacks will be flushed during this function. /// /// Returns: True if the given nodes are still reachable from each other after the guo has been applied. False otherwise. /// /// /// var guo = new GraphUpdateObject(tower.GetComponent().bounds); /// var spawnPointNode = AstarPath.active.GetNearest(spawnPoint.position).node; /// var goalNode = AstarPath.active.GetNearest(goalPoint.position).node; /// /// if (GraphUpdateUtilities.UpdateGraphsNoBlock(guo, spawnPointNode, goalNode, false)) { /// // Valid tower position /// // Since the last parameter (which is called "alwaysRevert") in the method call was false /// // The graph is now updated and the game can just continue /// } else { /// // Invalid tower position. It blocks the path between the spawn point and the goal /// // The effect on the graph has been reverted /// Destroy(tower); /// } /// /// /// The GraphUpdateObject to update the graphs with /// Node which should have a valid path to node2. All nodes should be walkable or false will be returned. /// Node which should have a valid path to node1. All nodes should be walkable or false will be returned. /// If true, reverts the graphs to the old state even if no blocking occurred public static bool UpdateGraphsNoBlock (GraphUpdateObject guo, GraphNode node1, GraphNode node2, bool alwaysRevert = false) { List buffer = ListPool.Claim(); buffer.Add(node1); buffer.Add(node2); bool worked = UpdateGraphsNoBlock(guo, buffer, alwaysRevert); ListPool.Release(ref buffer); return worked; } /// /// Updates graphs and checks if all nodes are still reachable from each other. /// Graphs are updated, then a check is made to see if the nodes are still reachable from each other. /// If they are not, the graphs are reverted to before the update and false is returned. /// This is slower than a normal graph update. /// All queued graph updates will be flushed during this function. /// /// Returns: True if the given nodes are still reachable from each other after the guo has been applied. False otherwise. /// /// The GraphUpdateObject to update the graphs with /// Nodes which should have valid paths between them. All nodes should be walkable or false will be returned. /// If true, reverts the graphs to the old state even if no blocking occurred public static bool UpdateGraphsNoBlock (GraphUpdateObject guo, List nodes, bool alwaysRevert = false) { bool worked; // Pause pathfinding while modifying the graphs var graphLock = AstarPath.active.PausePathfinding(); try { // Make sure any pending graph updates have been done before we start AstarPath.active.FlushGraphUpdates(); // Make sure all nodes are walkable for (int i = 0; i < nodes.Count; i++) if (!nodes[i].Walkable) return false; // Track changed nodes to enable reversion of the guo guo.trackChangedNodes = true; AstarPath.active.UpdateGraphs(guo); // Update the graphs immediately AstarPath.active.FlushGraphUpdates(); // Check if all nodes are in the same area and that they are walkable, i.e that there are paths between all of them worked = PathUtilities.IsPathPossible(nodes); // If it did not work, revert the GUO if (!worked || alwaysRevert) { guo.RevertFromBackup(); // Recalculate connected components AstarPath.active.hierarchicalGraph.RecalculateIfNecessary(); } } finally { graphLock.Release(); } // Disable tracking nodes, not strictly necessary, but will slightly reduce the cance that some user causes errors guo.trackChangedNodes = false; return worked; } } }