NavMeshComponentsGUIUtility.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. using UnityEngine;
  2. using UnityEngine.AI;
  3. namespace UnityEditor.AI
  4. {
  5. public static class NavMeshComponentsGUIUtility
  6. {
  7. public static void AreaPopup(string labelName, SerializedProperty areaProperty)
  8. {
  9. var areaIndex = -1;
  10. var areaNames = GameObjectUtility.GetNavMeshAreaNames();
  11. for (var i = 0; i < areaNames.Length; i++)
  12. {
  13. var areaValue = GameObjectUtility.GetNavMeshAreaFromName(areaNames[i]);
  14. if (areaValue == areaProperty.intValue)
  15. areaIndex = i;
  16. }
  17. ArrayUtility.Add(ref areaNames, "");
  18. ArrayUtility.Add(ref areaNames, "Open Area Settings...");
  19. var rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
  20. EditorGUI.BeginProperty(rect, GUIContent.none, areaProperty);
  21. EditorGUI.BeginChangeCheck();
  22. areaIndex = EditorGUI.Popup(rect, labelName, areaIndex, areaNames);
  23. if (EditorGUI.EndChangeCheck())
  24. {
  25. if (areaIndex >= 0 && areaIndex < areaNames.Length - 2)
  26. areaProperty.intValue = GameObjectUtility.GetNavMeshAreaFromName(areaNames[areaIndex]);
  27. else if (areaIndex == areaNames.Length - 1)
  28. NavMeshEditorHelpers.OpenAreaSettings();
  29. }
  30. EditorGUI.EndProperty();
  31. }
  32. public static void AgentTypePopup(string labelName, SerializedProperty agentTypeID)
  33. {
  34. var index = -1;
  35. var count = NavMesh.GetSettingsCount();
  36. var agentTypeNames = new string[count + 2];
  37. for (var i = 0; i < count; i++)
  38. {
  39. var id = NavMesh.GetSettingsByIndex(i).agentTypeID;
  40. var name = NavMesh.GetSettingsNameFromID(id);
  41. agentTypeNames[i] = name;
  42. if (id == agentTypeID.intValue)
  43. index = i;
  44. }
  45. agentTypeNames[count] = "";
  46. agentTypeNames[count + 1] = "Open Agent Settings...";
  47. bool validAgentType = index != -1;
  48. if (!validAgentType)
  49. {
  50. EditorGUILayout.HelpBox("Agent Type invalid.", MessageType.Warning);
  51. }
  52. var rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
  53. EditorGUI.BeginProperty(rect, GUIContent.none, agentTypeID);
  54. EditorGUI.BeginChangeCheck();
  55. index = EditorGUI.Popup(rect, labelName, index, agentTypeNames);
  56. if (EditorGUI.EndChangeCheck())
  57. {
  58. if (index >= 0 && index < count)
  59. {
  60. var id = NavMesh.GetSettingsByIndex(index).agentTypeID;
  61. agentTypeID.intValue = id;
  62. }
  63. else if (index == count + 1)
  64. {
  65. NavMeshEditorHelpers.OpenAgentSettings(-1);
  66. }
  67. }
  68. EditorGUI.EndProperty();
  69. }
  70. // Agent mask is a set (internally array/list) of agentTypeIDs.
  71. // It is used to describe which agents modifiers apply to.
  72. // There is a special case of "None" which is an empty array.
  73. // There is a special case of "All" which is an array of length 1, and value of -1.
  74. public static void AgentMaskPopup(string labelName, SerializedProperty agentMask)
  75. {
  76. // Contents of the dropdown box.
  77. string popupContent = "";
  78. if (agentMask.hasMultipleDifferentValues)
  79. popupContent = "\u2014";
  80. else
  81. popupContent = GetAgentMaskLabelName(agentMask);
  82. var content = new GUIContent(popupContent);
  83. var popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup);
  84. EditorGUI.BeginProperty(popupRect, GUIContent.none, agentMask);
  85. popupRect = EditorGUI.PrefixLabel(popupRect, 0, new GUIContent(labelName));
  86. bool pressed = GUI.Button(popupRect, content, EditorStyles.popup);
  87. if (pressed)
  88. {
  89. var show = !agentMask.hasMultipleDifferentValues;
  90. var showNone = show && agentMask.arraySize == 0;
  91. var showAll = show && IsAll(agentMask);
  92. var menu = new GenericMenu();
  93. menu.AddItem(new GUIContent("None"), showNone, SetAgentMaskNone, agentMask);
  94. menu.AddItem(new GUIContent("All"), showAll, SetAgentMaskAll, agentMask);
  95. menu.AddSeparator("");
  96. var count = NavMesh.GetSettingsCount();
  97. for (var i = 0; i < count; i++)
  98. {
  99. var id = NavMesh.GetSettingsByIndex(i).agentTypeID;
  100. var sname = NavMesh.GetSettingsNameFromID(id);
  101. var showSelected = show && AgentMaskHasSelectedAgentTypeID(agentMask, id);
  102. var userData = new object[] { agentMask, id, !showSelected };
  103. menu.AddItem(new GUIContent(sname), showSelected, ToggleAgentMaskItem, userData);
  104. }
  105. menu.DropDown(popupRect);
  106. }
  107. EditorGUI.EndProperty();
  108. }
  109. public static GameObject CreateAndSelectGameObject(string suggestedName, GameObject parent)
  110. {
  111. var parentTransform = parent != null ? parent.transform : null;
  112. var uniqueName = GameObjectUtility.GetUniqueNameForSibling(parentTransform, suggestedName);
  113. var child = new GameObject(uniqueName);
  114. Undo.RegisterCreatedObjectUndo(child, "Create " + uniqueName);
  115. if (parentTransform != null)
  116. Undo.SetTransformParent(child.transform, parentTransform, "Parent " + uniqueName);
  117. Selection.activeGameObject = child;
  118. return child;
  119. }
  120. static bool IsAll(SerializedProperty agentMask)
  121. {
  122. return agentMask.arraySize == 1 && agentMask.GetArrayElementAtIndex(0).intValue == -1;
  123. }
  124. static void ToggleAgentMaskItem(object userData)
  125. {
  126. var args = (object[])userData;
  127. var agentMask = (SerializedProperty)args[0];
  128. var agentTypeID = (int)args[1];
  129. var value = (bool)args[2];
  130. ToggleAgentMaskItem(agentMask, agentTypeID, value);
  131. }
  132. static void ToggleAgentMaskItem(SerializedProperty agentMask, int agentTypeID, bool value)
  133. {
  134. if (agentMask.hasMultipleDifferentValues)
  135. {
  136. agentMask.ClearArray();
  137. agentMask.serializedObject.ApplyModifiedProperties();
  138. }
  139. // Find which index this agent type is in the agentMask array.
  140. int idx = -1;
  141. for (var j = 0; j < agentMask.arraySize; j++)
  142. {
  143. var elem = agentMask.GetArrayElementAtIndex(j);
  144. if (elem.intValue == agentTypeID)
  145. idx = j;
  146. }
  147. // Handle "All" special case.
  148. if (IsAll(agentMask))
  149. {
  150. agentMask.DeleteArrayElementAtIndex(0);
  151. }
  152. // Toggle value.
  153. if (value)
  154. {
  155. if (idx == -1)
  156. {
  157. agentMask.InsertArrayElementAtIndex(agentMask.arraySize);
  158. agentMask.GetArrayElementAtIndex(agentMask.arraySize - 1).intValue = agentTypeID;
  159. }
  160. }
  161. else
  162. {
  163. if (idx != -1)
  164. {
  165. agentMask.DeleteArrayElementAtIndex(idx);
  166. }
  167. }
  168. agentMask.serializedObject.ApplyModifiedProperties();
  169. }
  170. static void SetAgentMaskNone(object data)
  171. {
  172. var agentMask = (SerializedProperty)data;
  173. agentMask.ClearArray();
  174. agentMask.serializedObject.ApplyModifiedProperties();
  175. }
  176. static void SetAgentMaskAll(object data)
  177. {
  178. var agentMask = (SerializedProperty)data;
  179. agentMask.ClearArray();
  180. agentMask.InsertArrayElementAtIndex(0);
  181. agentMask.GetArrayElementAtIndex(0).intValue = -1;
  182. agentMask.serializedObject.ApplyModifiedProperties();
  183. }
  184. static string GetAgentMaskLabelName(SerializedProperty agentMask)
  185. {
  186. if (agentMask.arraySize == 0)
  187. return "None";
  188. if (IsAll(agentMask))
  189. return "All";
  190. if (agentMask.arraySize <= 3)
  191. {
  192. var labelName = "";
  193. for (var j = 0; j < agentMask.arraySize; j++)
  194. {
  195. var elem = agentMask.GetArrayElementAtIndex(j);
  196. var settingsName = NavMesh.GetSettingsNameFromID(elem.intValue);
  197. if (string.IsNullOrEmpty(settingsName))
  198. continue;
  199. if (labelName.Length > 0)
  200. labelName += ", ";
  201. labelName += settingsName;
  202. }
  203. return labelName;
  204. }
  205. return "Mixed...";
  206. }
  207. static bool AgentMaskHasSelectedAgentTypeID(SerializedProperty agentMask, int agentTypeID)
  208. {
  209. for (var j = 0; j < agentMask.arraySize; j++)
  210. {
  211. var elem = agentMask.GetArrayElementAtIndex(j);
  212. if (elem.intValue == agentTypeID)
  213. return true;
  214. }
  215. return false;
  216. }
  217. }
  218. }