/** Draws the inspector for the given graph with the given graph editor */ bool DrawGraph (NavGraph graph, GraphEditor graphEditor) { // Graph guid, just used to get a unique value string graphGUIDString = graph.guid.ToString(); Color tmp1 = GUI.color; EditorGUILayoutx.FadeArea topFadeArea = guiLayoutx.BeginFadeArea (graph.open, "", graphGUIDString, graphBoxStyle); Color tmp2 = GUI.color; GUI.color = tmp1; GUILayout.BeginHorizontal (); // Make sure that the graph name is not null graph.name = graph.name ?? graphEditorTypes[graph.GetType ().Name].displayName; GUI.SetNextControlName (graphGUIDString); graph.name = GUILayout.TextField (graph.name, EditorGUILayoutx.defaultLabelStyle, GUILayout.ExpandWidth(false),GUILayout.ExpandHeight(false)); // If the graph name text field is not focused and the graph name is empty, then fill it in if (graph.name == "" && Event.current.type == EventType.Repaint && GUI.GetNameOfFocusedControl() != graphGUIDString) { graph.name = graphEditorTypes[graph.GetType ().Name].displayName; } if (GUILayout.Button ("", EditorGUILayoutx.defaultLabelStyle)) { graph.open = !graph.open; if (!graph.open) { graph.infoScreenOpen = false; } RepaintSceneView (); return true; } if (script.prioritizeGraphs) { if (GUILayout.Button (new GUIContent ("Up","Increase the graph priority"),GUILayout.Width (40))) { int index = script.astarData.GetGraphIndex (graph); // Find the previous non null graph int next = index-1; for (;next >= 0;next--) if (script.graphs[next] != null) break; if (next >= 0) { NavGraph tmp = script.graphs[next]; script.graphs[next] = graph; script.graphs[index] = tmp; GraphEditor tmpEditor = graphEditors[next]; graphEditors[next] = graphEditors[index]; graphEditors[index] = tmpEditor; } CheckGraphEditors (); Repaint (); } if (GUILayout.Button (new GUIContent ("Down","Decrease the graph priority"),GUILayout.Width (40))) { int index = script.astarData.GetGraphIndex (graph); // Find the next non null graph int next = index+1; for (;next<script.graphs.Length;next++) if (script.graphs[next] != null) break; if (next < script.graphs.Length) { NavGraph tmp = script.graphs[next]; script.graphs[next] = graph; script.graphs[index] = tmp; GraphEditor tmpEditor = graphEditors[next]; graphEditors[next] = graphEditors[index]; graphEditors[index] = tmpEditor; } CheckGraphEditors (); Repaint (); } } bool drawGizmos = GUILayout.Toggle (graph.drawGizmos, "Draw Gizmos", graphGizmoButtonStyle); if (drawGizmos != graph.drawGizmos) { graph.drawGizmos = drawGizmos; // Make sure that the scene view is repainted when gizmos are toggled on or off RepaintSceneView (); } if (GUILayout.Toggle (graph.infoScreenOpen,"Info",graphInfoButtonStyle)) { if (!graph.infoScreenOpen) { graph.infoScreenOpen = true; graph.open = true; } } else { graph.infoScreenOpen = false; } if (GUILayout.Button ("Delete",graphDeleteButtonStyle)) { RemoveGraph (graph); return true; } GUILayout.EndHorizontal (); if (topFadeArea.Show () ) { EditorGUILayoutx.FadeArea fadeArea = guiLayoutx.BeginFadeArea (graph.infoScreenOpen,"graph_info_"+graphGUIDString,0); if (fadeArea.Show ()) { bool nodenull = false; int total = 0; int numWalkable = 0; KeyValuePair<float,KeyValuePair<int,int>> pair; graphNodeCounts = graphNodeCounts ?? new Dictionary<NavGraph, KeyValuePair<float, KeyValuePair<int, int>>>(); if ( !graphNodeCounts.TryGetValue ( graph, out pair ) || (Time.realtimeSinceStartup-pair.Key) > 2 ) { GraphNodeDelegateCancelable counter = node => { if (node == null) { nodenull = true; } else { total++; if (node.Walkable) numWalkable++; } return true; }; graph.GetNodes (counter); pair = new KeyValuePair<float, KeyValuePair<int, int>> (Time.realtimeSinceStartup, new KeyValuePair<int,int>( total, numWalkable ) ); graphNodeCounts[graph] = pair; } total = pair.Value.Key; numWalkable = pair.Value.Value; EditorGUI.indentLevel++; if (nodenull) { //EditorGUILayout.HelpBox ("Some nodes in the graph are null. Please report this error.", MessageType.Info); Debug.LogError ("Some nodes in the graph are null. Please report this error."); } EditorGUILayout.LabelField ("Nodes",total.ToString()); EditorGUILayout.LabelField ("Walkable",numWalkable.ToString ()); EditorGUILayout.LabelField ("Unwalkable",(total-numWalkable).ToString ()); if (total == 0) EditorGUILayout.HelpBox ("The number of nodes in the graph is zero. The graph might not be scanned",MessageType.Info); EditorGUI.indentLevel--; } guiLayoutx.EndFadeArea (); GUI.color = tmp2; graphEditor.OnInspectorGUI (graph); graphEditor.OnBaseInspectorGUI (graph); } guiLayoutx.EndFadeArea (); return false; }
/** This performs a linear search through all polygons returning the closest one. * This will fill the NNInfo with .node for the closest node not necessarily complying with the NNConstraint, and .constrainedNode with the closest node * complying with the NNConstraint. * \see GetNearestForce(Node[],Int3[],Vector3,NNConstraint,bool) */ public static NNInfo GetNearestForceBoth (NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { var pos = (Int3)position; float minDist = -1; GraphNode minNode = null; float minConstDist = -1; GraphNode minConstNode = null; float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity; GraphNodeDelegateCancelable del = delegate (GraphNode _node) { var node = _node as TriangleMeshNode; if (accurateNearestNode) { Vector3 closest = node.ClosestPointOnNode (position); float dist = ((Vector3)pos-closest).sqrMagnitude; if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable (node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } else { if (!node.ContainsPoint ((Int3)position)) { float dist = (node.position-pos).sqrMagnitude; if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable (node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } else { int dist = AstarMath.Abs (node.position.y-pos.y); if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable (node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } } return true; }; graph.GetNodes (del); var nninfo = new NNInfo (minNode); //Find the point closest to the nearest triangle if (nninfo.node != null) { var node = nninfo.node as TriangleMeshNode;//minNode2 as MeshNode; Vector3 clP = node.ClosestPointOnNode (position); nninfo.clampedPosition = clP; } nninfo.constrainedNode = minConstNode; if (nninfo.constrainedNode != null) { var node = nninfo.constrainedNode as TriangleMeshNode;//minNode2 as MeshNode; Vector3 clP = node.ClosestPointOnNode (position); nninfo.constClampedPosition = clP; } return nninfo; }