2023-04-24 15:49:03 +02:00

165 lines
5.1 KiB
C#

using UnityEngine;
namespace Pathfinding.Util {
public class GraphGizmoHelper : IAstarPooledObject, System.IDisposable {
public RetainedGizmos.Hasher hasher { get; private set; }
Pathfinding.Util.RetainedGizmos gizmos;
PathHandler debugData;
ushort debugPathID;
GraphDebugMode debugMode;
bool showSearchTree;
float debugFloor;
float debugRoof;
public RetainedGizmos.Builder builder { get; private set; }
Vector3 drawConnectionStart;
Color drawConnectionColor;
readonly System.Action<GraphNode> drawConnection;
public GraphGizmoHelper () {
// Cache a delegate to avoid allocating memory for it every time
drawConnection = DrawConnection;
}
public void Init (AstarPath active, RetainedGizmos.Hasher hasher, RetainedGizmos gizmos) {
if (active != null) {
debugData = active.debugPathData;
debugPathID = active.debugPathID;
debugMode = active.debugMode;
debugFloor = active.debugFloor;
debugRoof = active.debugRoof;
showSearchTree = active.showSearchTree && debugData != null;
}
this.gizmos = gizmos;
this.hasher = hasher;
builder = ObjectPool<RetainedGizmos.Builder>.Claim();
}
public void OnEnterPool () {
// Will cause pretty much all calls to throw null ref exceptions until Init is called
var bld = builder;
ObjectPool<RetainedGizmos.Builder>.Release(ref bld);
builder = null;
debugData = null;
}
public void DrawConnections (GraphNode node) {
if (showSearchTree) {
if (InSearchTree(node, debugData, debugPathID)) {
var pnode = debugData.GetPathNode(node);
if (pnode.parent != null) {
builder.DrawLine((Vector3)node.position, (Vector3)debugData.GetPathNode(node).parent.node.position, NodeColor(node));
}
}
} else {
// Calculate which color to use for drawing the node
// based on the settings specified in the editor
drawConnectionColor = NodeColor(node);
// Get the node position
// Cast it here to avoid doing it for every neighbour
drawConnectionStart = (Vector3)node.position;
node.GetConnections(drawConnection);
}
}
void DrawConnection (GraphNode other) {
builder.DrawLine(drawConnectionStart, Vector3.Lerp((Vector3)other.position, drawConnectionStart, 0.5f), drawConnectionColor);
}
/// <summary>
/// Color to use for gizmos.
/// Returns a color to be used for the specified node with the current debug settings (editor only).
///
/// Version: Since 3.6.1 this method will not handle null nodes
/// </summary>
public Color NodeColor (GraphNode node) {
if (showSearchTree && !InSearchTree(node, debugData, debugPathID)) return Color.clear;
Color color;
if (node.Walkable) {
switch (debugMode) {
case GraphDebugMode.Areas:
color = AstarColor.GetAreaColor(node.Area);
break;
case GraphDebugMode.HierarchicalNode:
color = AstarColor.GetTagColor((uint)node.HierarchicalNodeIndex);
break;
case GraphDebugMode.Penalty:
color = Color.Lerp(AstarColor.ConnectionLowLerp, AstarColor.ConnectionHighLerp, ((float)node.Penalty-debugFloor) / (debugRoof-debugFloor));
break;
case GraphDebugMode.Tags:
color = AstarColor.GetTagColor(node.Tag);
break;
case GraphDebugMode.SolidColor:
color = AstarColor.SolidColor;
break;
default:
if (debugData == null) {
color = AstarColor.SolidColor;
break;
}
PathNode pathNode = debugData.GetPathNode(node);
float value;
if (debugMode == GraphDebugMode.G) {
value = pathNode.G;
} else if (debugMode == GraphDebugMode.H) {
value = pathNode.H;
} else {
// mode == F
value = pathNode.F;
}
color = Color.Lerp(AstarColor.ConnectionLowLerp, AstarColor.ConnectionHighLerp, (value-debugFloor) / (debugRoof-debugFloor));
break;
}
} else {
color = AstarColor.UnwalkableNode;
}
return color;
}
/// <summary>
/// Returns if the node is in the search tree of the path.
/// Only guaranteed to be correct if path is the latest path calculated.
/// Use for gizmo drawing only.
/// </summary>
public static bool InSearchTree (GraphNode node, PathHandler handler, ushort pathID) {
return handler.GetPathNode(node).pathID == pathID;
}
public void DrawWireTriangle (Vector3 a, Vector3 b, Vector3 c, Color color) {
builder.DrawLine(a, b, color);
builder.DrawLine(b, c, color);
builder.DrawLine(c, a, color);
}
public void DrawTriangles (Vector3[] vertices, Color[] colors, int numTriangles) {
var triangles = ListPool<int>.Claim(numTriangles);
for (int i = 0; i < numTriangles*3; i++) triangles.Add(i);
builder.DrawMesh(gizmos, vertices, triangles, colors);
ListPool<int>.Release(ref triangles);
}
public void DrawWireTriangles (Vector3[] vertices, Color[] colors, int numTriangles) {
for (int i = 0; i < numTriangles; i++) {
DrawWireTriangle(vertices[i*3+0], vertices[i*3+1], vertices[i*3+2], colors[i*3+0]);
}
}
public void Submit () {
builder.Submit(gizmos, hasher);
}
void System.IDisposable.Dispose () {
var tmp = this;
Submit();
ObjectPool<GraphGizmoHelper>.Release(ref tmp);
}
}
}