SeekerEditor.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections.Generic;
  4. namespace Pathfinding {
  5. [CustomEditor(typeof(Seeker))]
  6. [CanEditMultipleObjects]
  7. public class SeekerEditor : EditorBase {
  8. static bool tagPenaltiesOpen;
  9. static List<Seeker> scripts = new List<Seeker>();
  10. GUIContent[] exactnessLabels = new [] { new GUIContent("Node Center (Snap To Node)"), new GUIContent("Original"), new GUIContent("Interpolate (deprecated)"), new GUIContent("Closest On Node Surface"), new GUIContent("Node Connection") };
  11. protected override void Inspector () {
  12. base.Inspector();
  13. scripts.Clear();
  14. foreach (var script in targets) scripts.Add(script as Seeker);
  15. Undo.RecordObjects(targets, "Modify settings on Seeker");
  16. var startEndModifierProp = FindProperty("startEndModifier");
  17. startEndModifierProp.isExpanded = EditorGUILayout.Foldout(startEndModifierProp.isExpanded, startEndModifierProp.displayName);
  18. if (startEndModifierProp.isExpanded) {
  19. EditorGUI.indentLevel++;
  20. Popup("startEndModifier.exactStartPoint", exactnessLabels, "Start Point Snapping");
  21. Popup("startEndModifier.exactEndPoint", exactnessLabels, "End Point Snapping");
  22. PropertyField("startEndModifier.addPoints", "Add Points");
  23. if (FindProperty("startEndModifier.exactStartPoint").enumValueIndex == (int)StartEndModifier.Exactness.Original || FindProperty("startEndModifier.exactEndPoint").enumValueIndex == (int)StartEndModifier.Exactness.Original) {
  24. if (PropertyField("startEndModifier.useRaycasting", "Physics Raycasting")) {
  25. EditorGUI.indentLevel++;
  26. PropertyField("startEndModifier.mask", "Layer Mask");
  27. EditorGUI.indentLevel--;
  28. EditorGUILayout.HelpBox("Using raycasting to snap the start/end points has largely been superseded by the 'ClosestOnNode' snapping option. It is both faster and usually closer to what you want to achieve.", MessageType.Info);
  29. }
  30. if (PropertyField("startEndModifier.useGraphRaycasting", "Graph Raycasting")) {
  31. EditorGUILayout.HelpBox("Using raycasting to snap the start/end points has largely been superseded by the 'ClosestOnNode' snapping option. It is both faster and usually closer to what you want to achieve.", MessageType.Info);
  32. }
  33. }
  34. EditorGUI.indentLevel--;
  35. }
  36. PropertyField("graphMask", "Traversable Graphs");
  37. tagPenaltiesOpen = EditorGUILayout.Foldout(tagPenaltiesOpen, new GUIContent("Tags", "Settings for each tag"));
  38. if (tagPenaltiesOpen) {
  39. string[] tagNames = AstarPath.FindTagNames();
  40. EditorGUI.indentLevel++;
  41. if (tagNames.Length != 32) {
  42. tagNames = new string[32];
  43. for (int i = 0; i < tagNames.Length; i++) tagNames[i] = "" + i;
  44. }
  45. EditorGUILayout.BeginHorizontal();
  46. EditorGUILayout.BeginVertical();
  47. EditorGUILayout.LabelField("Tag", EditorStyles.boldLabel, GUILayout.MaxWidth(120));
  48. for (int i = 0; i < tagNames.Length; i++) {
  49. EditorGUILayout.LabelField(tagNames[i], GUILayout.MaxWidth(120));
  50. }
  51. // Make sure the arrays are all of the correct size
  52. for (int i = 0; i < scripts.Count; i++) {
  53. if (scripts[i].tagPenalties == null || scripts[i].tagPenalties.Length != tagNames.Length) scripts[i].tagPenalties = new int[tagNames.Length];
  54. }
  55. if (GUILayout.Button("Edit names", EditorStyles.miniButton)) {
  56. AstarPathEditor.EditTags();
  57. }
  58. EditorGUILayout.EndVertical();
  59. #if !ASTAR_NoTagPenalty
  60. EditorGUILayout.BeginVertical();
  61. EditorGUILayout.LabelField("Penalty", EditorStyles.boldLabel, GUILayout.MaxWidth(100));
  62. var prop = FindProperty("tagPenalties").FindPropertyRelative("Array");
  63. prop.Next(true);
  64. for (int i = 0; i < tagNames.Length; i++) {
  65. prop.Next(false);
  66. EditorGUILayout.PropertyField(prop, GUIContent.none, false, GUILayout.MinWidth(100));
  67. // Penalties should not be negative
  68. if (prop.intValue < 0) prop.intValue = 0;
  69. }
  70. if (GUILayout.Button("Reset all", EditorStyles.miniButton)) {
  71. for (int i = 0; i < tagNames.Length; i++) {
  72. for (int j = 0; j < scripts.Count; j++) {
  73. scripts[j].tagPenalties[i] = 0;
  74. }
  75. }
  76. }
  77. EditorGUILayout.EndVertical();
  78. #endif
  79. EditorGUILayout.BeginVertical();
  80. EditorGUILayout.LabelField("Traversable", EditorStyles.boldLabel, GUILayout.MaxWidth(100));
  81. for (int i = 0; i < tagNames.Length; i++) {
  82. var anyFalse = false;
  83. var anyTrue = false;
  84. for (int j = 0; j < scripts.Count; j++) {
  85. var prevTraversable = ((scripts[j].traversableTags >> i) & 0x1) != 0;
  86. anyTrue |= prevTraversable;
  87. anyFalse |= !prevTraversable;
  88. }
  89. EditorGUI.BeginChangeCheck();
  90. EditorGUI.showMixedValue = anyTrue & anyFalse;
  91. var newTraversable = EditorGUILayout.Toggle(anyTrue);
  92. EditorGUI.showMixedValue = false;
  93. if (EditorGUI.EndChangeCheck()) {
  94. for (int j = 0; j < scripts.Count; j++) {
  95. scripts[j].traversableTags = (scripts[j].traversableTags & ~(1 << i)) | ((newTraversable ? 1 : 0) << i);
  96. }
  97. }
  98. }
  99. if (GUILayout.Button("Set all/none", EditorStyles.miniButton)) {
  100. for (int j = scripts.Count - 1; j >= 0; j--) {
  101. scripts[j].traversableTags = (scripts[0].traversableTags & 0x1) == 0 ? -1 : 0;
  102. }
  103. }
  104. EditorGUILayout.EndVertical();
  105. EditorGUILayout.EndHorizontal();
  106. }
  107. // Make sure we don't leak any memory
  108. scripts.Clear();
  109. }
  110. }
  111. }