diff options
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RulePerLayerModifications.cs')
-rw-r--r-- | Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RulePerLayerModifications.cs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RulePerLayerModifications.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RulePerLayerModifications.cs new file mode 100644 index 0000000..1684b04 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RulePerLayerModifications.cs @@ -0,0 +1,79 @@ +using Pathfinding.Jobs; + +namespace Pathfinding.Graphs.Grid.Rules { + /// <summary> + /// Modifies nodes based on the layer of the surface under the node. + /// + /// You can for example make all surfaces with a specific layer make the nodes get a specific tag. + /// + /// [Open online documentation to see images] + /// + /// See: grid-rules (view in online documentation for working links) + /// </summary> + [Pathfinding.Util.Preserve] + public class RulePerLayerModifications : GridGraphRule { + public PerLayerRule[] layerRules = new PerLayerRule[0]; + const int SetTagBit = 1 << 30; + + public struct PerLayerRule { + /// <summary>Layer this rule applies to</summary> + public int layer; + /// <summary>The action to apply to matching nodes</summary> + public RuleAction action; + /// <summary> + /// Tag for the RuleAction.SetTag action. + /// Must be between 0 and <see cref="Pathfinding.GraphNode.MaxTagIndex"/> + /// </summary> + public int tag; + } + + public enum RuleAction { + /// <summary>Sets the tag of all affected nodes to <see cref="PerLayerRule.tag"/></summary> + SetTag, + /// <summary>Makes all affected nodes unwalkable</summary> + MakeUnwalkable, + } + + public override void Register (GridGraphRules rules) { + int[] layerToTag = new int[32]; + bool[] layerToUnwalkable = new bool[32]; + for (int i = 0; i < layerRules.Length; i++) { + var rule = layerRules[i]; + if (rule.action == RuleAction.SetTag) { + layerToTag[rule.layer] = SetTagBit | rule.tag; + } else { + layerToUnwalkable[rule.layer] = true; + } + } + + rules.AddMainThreadPass(Pass.BeforeConnections, context => { + if (!context.data.heightHits.IsCreated) { + UnityEngine.Debug.LogError("RulePerLayerModifications requires height testing to be enabled on the grid graph", context.graph.active); + return; + } + + var raycastHits = context.data.heightHits; + var nodeWalkable = context.data.nodes.walkable; + var nodeTags = context.data.nodes.tags; + var slice = new Slice3D(context.data.nodes.bounds, context.data.heightHitsBounds); + var size = slice.slice.size; + for (int y = 0; y < size.y; y++) { + for (int z = 0; z < size.z; z++) { + var rowOffset = y * size.x * size.z + z * size.x; + for (int x = 0; x < size.x; x++) { + var innerIndex = rowOffset + x; + var outerIndex = slice.InnerCoordinateToOuterIndex(x, y, z); + var coll = raycastHits[innerIndex].collider; + if (coll != null) { + var layer = coll.gameObject.layer; + if (layerToUnwalkable[layer]) nodeWalkable[outerIndex] = false; + var tag = layerToTag[layer]; + if ((tag & SetTagBit) != 0) nodeTags[outerIndex] = tag & 0xFF; + } + } + } + } + }); + } + } +} |