Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

NavigationOverlay.cs 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. #if UNITY_2022_2_OR_NEWER
  2. using UnityEditor;
  3. using UnityEditor.AI;
  4. using UnityEditor.Overlays;
  5. using UnityEditor.SceneManagement;
  6. using UnityEngine;
  7. using UnityEngine.UIElements;
  8. namespace Unity.AI.Navigation.Editor
  9. {
  10. [Overlay(typeof(SceneView), "AINavigationOverlay", "AI Navigation", defaultDisplay = true)]
  11. [Icon(NavMeshComponentsGUIUtility.k_PackageEditorResourcesFolder + "Overlay/NavigationOverlay.png")]
  12. internal class NavigationOverlay : Overlay
  13. {
  14. static class Style
  15. {
  16. internal static readonly GUIContent SurfacesSectionTexts =
  17. EditorGUIUtility.TrTextContent("Surfaces");
  18. internal static readonly GUIContent SurfacesSelectedOnlyTexts =
  19. EditorGUIUtility.TrTextContent("Show Only Selected", "Check this to hide surfaces which are not part of the selection hierarchy");
  20. internal static readonly GUIContent SurfacesNavMeshTexts =
  21. EditorGUIUtility.TrTextContent("Show NavMesh", "Display navigation mesh using the associated area's color");
  22. internal static readonly GUIContent SurfacesHeightMeshTexts =
  23. EditorGUIUtility.TrTextContent("Show HeightMesh", "Display height mesh used for accurate vertical placement");
  24. internal static readonly GUIContent AgentsSectionTexts =
  25. EditorGUIUtility.TrTextContent("Agents");
  26. internal static readonly GUIContent AgentsPathPolysTexts =
  27. EditorGUIUtility.TrTextContent("Show Path Polygons", "Shows the polygons leading to goal.");
  28. internal static readonly GUIContent AgentsPathNodesTexts =
  29. EditorGUIUtility.TrTextContent("Show Path Query Nodes", "Shows the nodes expanded during last path query.");
  30. internal static readonly GUIContent AgentsNeighboursTexts =
  31. EditorGUIUtility.TrTextContent("Show Neighbours", "Show the agent neighbours considered during simulation.");
  32. internal static readonly GUIContent AgentsWallsTexts =
  33. EditorGUIUtility.TrTextContent("Show Walls", "Shows the wall segments handled during simulation.");
  34. internal static readonly GUIContent AgentsAvoidanceTexts =
  35. EditorGUIUtility.TrTextContent("Show Avoidance", "Shows the processed avoidance geometry from simulation.");
  36. internal static readonly GUIContent AgentsAvoidancePendingDebugRequestTexts =
  37. EditorGUIUtility.TrTextContent("Avoidance display is not valid until after next game update.", "Avoidance information will be computed on the next game update");
  38. internal static readonly GUIContent AgentsAvoidanceDebugRequestsCountExceededTexts =
  39. EditorGUIUtility.TrTextContent("", "Avoidance information display is limited to a fixed number of agents"); // This text is dynamic
  40. internal static readonly GUIContent ObstaclesSectionTexts =
  41. EditorGUIUtility.TrTextContent("Obstacles");
  42. internal static readonly GUIContent ObstaclesCarveHullText =
  43. EditorGUIUtility.TrTextContent("Show Carve Hull", "Shows the hull used to carve the obstacle from navmesh.");
  44. internal static readonly GUIContent DeveloperModeSectionTexts =
  45. EditorGUIUtility.TrTextContent("Developer Mode");
  46. internal static readonly GUIContent SurfacesPortalsTexts =
  47. EditorGUIUtility.TrTextContent("Show NavMesh Portals");
  48. internal static readonly GUIContent SurfacesTileLinksTexts =
  49. EditorGUIUtility.TrTextContent("Show NavMesh Tile Links");
  50. internal static readonly GUIContent SurfacesHeightMeshBVTreeTexts =
  51. EditorGUIUtility.TrTextContent("Show HeightMesh BV-Tree");
  52. internal static readonly GUIContent SurfacesHeightMapsTexts =
  53. EditorGUIUtility.TrTextContent("Show HeightMaps", "Display terrain height maps used for accurate vertical placement");
  54. internal static readonly GUIContent SurfacesProximityGridTexts =
  55. EditorGUIUtility.TrTextContent("Show Proximity Grid");
  56. internal static readonly GUIContent NavigationVisualizationDisabledTexts =
  57. EditorGUIUtility.TrTextContent("Navigation visualization is not available in prefab edition.", "");
  58. }
  59. VisualElement m_RootPanel;
  60. VisualElement m_OptionsPanel;
  61. VisualElement m_AgentFoldOut;
  62. HelpBox m_VisualizationDisabledHelpBox;
  63. HelpBox m_AgentCountWarning;
  64. HelpBox m_AgentPendingRequestWarning;
  65. public override void OnCreated()
  66. {
  67. base.OnCreated();
  68. NavMeshEditorHelpers.agentRejectedDebugInfoRequestsCountChanged += OnAgentRejectedDebugInfoRequestsCountChanged;
  69. NavMeshEditorHelpers.agentDebugRequestsPending += DisplayAgentPendingRequestWarningBox;
  70. NavMeshEditorHelpers.agentDebugRequestsProcessed += HideAgentPendingRequestWarningBox;
  71. PrefabStage.prefabStageOpened += OnPrefabStageOpened;
  72. PrefabStage.prefabStageClosing += OnPrefabStageClosing;
  73. }
  74. public override void OnWillBeDestroyed()
  75. {
  76. NavMeshEditorHelpers.agentRejectedDebugInfoRequestsCountChanged -= OnAgentRejectedDebugInfoRequestsCountChanged;
  77. NavMeshEditorHelpers.agentDebugRequestsPending -= DisplayAgentPendingRequestWarningBox;
  78. NavMeshEditorHelpers.agentDebugRequestsProcessed -= HideAgentPendingRequestWarningBox;
  79. PrefabStage.prefabStageOpened -= OnPrefabStageOpened;
  80. PrefabStage.prefabStageClosing -= OnPrefabStageClosing;
  81. base.OnWillBeDestroyed();
  82. }
  83. public override VisualElement CreatePanelContent()
  84. {
  85. m_RootPanel = new VisualElement();
  86. m_OptionsPanel = new VisualElement();
  87. m_RootPanel.Add(m_OptionsPanel);
  88. m_VisualizationDisabledHelpBox = AddHelpBox(HelpBoxMessageType.Info, Style.NavigationVisualizationDisabledTexts, 200, 10, false);
  89. var visualizationEnabled = PrefabStageUtility.GetCurrentPrefabStage() == null;
  90. SetVisualizationEnabled(visualizationEnabled);
  91. // Surfaces
  92. var surfacesFoldout = AddFoldout(m_OptionsPanel, Style.SurfacesSectionTexts, 5);
  93. AddToggle(surfacesFoldout, Style.SurfacesSelectedOnlyTexts, NavMeshVisualizationSettings.showOnlySelectedSurfaces,
  94. (evt => NavMeshVisualizationSettings.showOnlySelectedSurfaces = evt.newValue));
  95. AddToggle(surfacesFoldout, Style.SurfacesNavMeshTexts, NavMeshVisualizationSettings.showNavMesh,
  96. evt => NavMeshVisualizationSettings.showNavMesh = evt.newValue);
  97. AddToggle(surfacesFoldout, Style.SurfacesHeightMeshTexts, NavMeshVisualizationSettings.showHeightMesh,
  98. evt => NavMeshVisualizationSettings.showHeightMesh = evt.newValue);
  99. // Agents
  100. m_AgentFoldOut = AddFoldout(m_OptionsPanel, Style.AgentsSectionTexts, 5);
  101. AddToggle(m_AgentFoldOut, Style.AgentsPathPolysTexts, NavMeshVisualizationSettings.showAgentPath, evt => NavMeshVisualizationSettings.showAgentPath = evt.newValue);
  102. AddToggle(m_AgentFoldOut, Style.AgentsPathNodesTexts, NavMeshVisualizationSettings.showAgentPathInfo,
  103. evt => NavMeshVisualizationSettings.showAgentPathInfo = evt.newValue);
  104. AddToggle(m_AgentFoldOut, Style.AgentsNeighboursTexts, NavMeshVisualizationSettings.showAgentNeighbours,
  105. evt => NavMeshVisualizationSettings.showAgentNeighbours = evt.newValue);
  106. AddToggle(m_AgentFoldOut, Style.AgentsWallsTexts, NavMeshVisualizationSettings.showAgentWalls, evt => NavMeshVisualizationSettings.showAgentWalls = evt.newValue);
  107. AddToggle(m_AgentFoldOut, Style.AgentsAvoidanceTexts, NavMeshVisualizationSettings.showAgentAvoidance,
  108. evt => NavMeshVisualizationSettings.showAgentAvoidance = evt.newValue);
  109. // Create avoidance requests count warning box and display it if needed
  110. m_AgentCountWarning = AddHelpBox(HelpBoxMessageType.Warning, Style.AgentsAvoidanceDebugRequestsCountExceededTexts, 180, 5, false);
  111. NavMeshEditorHelpers.GetAgentsDebugInfoRejectedRequestsCount(out var rejected, out var allowed);
  112. if (rejected > 0)
  113. {
  114. DisplayAgentCountWarningBox(rejected, allowed);
  115. }
  116. // Create avoidance pending requests warning box and display it if needed
  117. m_AgentPendingRequestWarning = AddHelpBox(HelpBoxMessageType.Warning, Style.AgentsAvoidancePendingDebugRequestTexts, 180, 5, false);
  118. if (NavMeshEditorHelpers.HasPendingAgentDebugInfoRequests())
  119. {
  120. DisplayAgentPendingRequestWarningBox();
  121. }
  122. // Obstacles
  123. var obstaclesFoldout = AddFoldout(m_OptionsPanel, Style.ObstaclesSectionTexts, 5);
  124. AddToggle(obstaclesFoldout, Style.ObstaclesCarveHullText, NavMeshVisualizationSettings.showObstacleCarveHull,
  125. evt => NavMeshVisualizationSettings.showObstacleCarveHull = evt.newValue);
  126. // Developer Mode only
  127. if (Unsupported.IsDeveloperMode())
  128. {
  129. var developerModeFoldout = AddFoldout(m_OptionsPanel, Style.DeveloperModeSectionTexts, 5);
  130. AddToggle(developerModeFoldout, Style.SurfacesPortalsTexts, NavMeshVisualizationSettings.showNavMeshPortals,
  131. evt => NavMeshVisualizationSettings.showNavMeshPortals = evt.newValue);
  132. AddToggle(developerModeFoldout, Style.SurfacesTileLinksTexts, NavMeshVisualizationSettings.showNavMeshLinks,
  133. evt => NavMeshVisualizationSettings.showNavMeshLinks = evt.newValue);
  134. AddToggle(developerModeFoldout, Style.SurfacesHeightMeshBVTreeTexts, NavMeshVisualizationSettings.showHeightMeshBVTree,
  135. evt => NavMeshVisualizationSettings.showHeightMeshBVTree = evt.newValue);
  136. AddToggle(developerModeFoldout, Style.SurfacesHeightMapsTexts, NavMeshVisualizationSettings.showHeightMaps,
  137. evt => NavMeshVisualizationSettings.showHeightMaps = evt.newValue);
  138. AddToggle(developerModeFoldout, Style.SurfacesProximityGridTexts, NavMeshVisualizationSettings.showProximityGrid,
  139. evt => NavMeshVisualizationSettings.showProximityGrid = evt.newValue);
  140. }
  141. return m_RootPanel;
  142. }
  143. void OnAgentRejectedDebugInfoRequestsCountChanged(int rejected, int allowed)
  144. {
  145. if (rejected == 0)
  146. {
  147. HideAgentCountWarningBox();
  148. }
  149. else
  150. {
  151. DisplayAgentCountWarningBox(rejected, allowed);
  152. }
  153. }
  154. void OnPrefabStageOpened(PrefabStage obj)
  155. {
  156. SetVisualizationEnabled(false);
  157. }
  158. void OnPrefabStageClosing(PrefabStage obj)
  159. {
  160. SetVisualizationEnabled(true);
  161. }
  162. static Foldout AddFoldout(VisualElement parent, GUIContent text, int padding)
  163. {
  164. var prefName = $"AINavigationOverlay_Foldout_{text.text}";
  165. var foldout = new Foldout
  166. {
  167. text = text.text,
  168. tooltip = text.tooltip,
  169. style =
  170. {
  171. paddingBottom = padding
  172. },
  173. value = EditorPrefs.GetBool(prefName, true)
  174. };
  175. foldout.RegisterValueChangedCallback(evt =>
  176. EditorPrefs.SetBool(prefName, evt.newValue));
  177. parent.Add(foldout);
  178. return foldout;
  179. }
  180. static void AddToggle(VisualElement parent, GUIContent text, bool parameter, EventCallback<ChangeEvent<bool>> callback)
  181. {
  182. // Create toggle element with the desired text content
  183. var toggle = new Toggle
  184. {
  185. label = text.text,
  186. value = parameter,
  187. tooltip = text.tooltip,
  188. style =
  189. {
  190. marginBottom = 0 // To compact a bit the checkboxes list layout
  191. }
  192. };
  193. // Add padding to guarantee a minimum separation between labels and checkboxes
  194. toggle.labelElement.style.paddingRight = 20;
  195. // Look for the checkbox container and make it align the checkbox to the right (so that all checkboxes are justified)
  196. foreach (VisualElement child in toggle.Children())
  197. {
  198. if (child != toggle.labelElement)
  199. {
  200. child.style.justifyContent = Justify.FlexEnd;
  201. break;
  202. }
  203. }
  204. toggle.RegisterCallback(callback);
  205. parent.Add(toggle);
  206. }
  207. static HelpBox AddHelpBox(HelpBoxMessageType messageType, GUIContent text, int maxWidth, int verticalMargin, bool visible)
  208. {
  209. var helpBox = new HelpBox(text.text, messageType)
  210. {
  211. tooltip = text.tooltip,
  212. style =
  213. {
  214. marginBottom = verticalMargin,
  215. marginTop = verticalMargin,
  216. maxWidth = maxWidth,
  217. alignSelf = Align.Center,
  218. },
  219. visible = visible
  220. };
  221. return helpBox;
  222. }
  223. void DisplayAgentCountWarningBox(int rejected, int allowed)
  224. {
  225. m_AgentCountWarning.text = $"Avoidance visualization can be drawn for {allowed} agents ({allowed + rejected} selected).";
  226. if (!m_AgentCountWarning.visible)
  227. {
  228. m_AgentCountWarning.visible = true;
  229. m_AgentFoldOut.Add(m_AgentCountWarning);
  230. }
  231. }
  232. void HideAgentCountWarningBox()
  233. {
  234. if (m_AgentCountWarning.visible)
  235. {
  236. m_AgentCountWarning.visible = false;
  237. m_AgentFoldOut.Remove(m_AgentCountWarning);
  238. }
  239. }
  240. void DisplayAgentPendingRequestWarningBox()
  241. {
  242. if (!m_AgentPendingRequestWarning.visible)
  243. {
  244. m_AgentPendingRequestWarning.visible = true;
  245. m_AgentFoldOut.Add(m_AgentPendingRequestWarning);
  246. }
  247. }
  248. void HideAgentPendingRequestWarningBox()
  249. {
  250. if (m_AgentPendingRequestWarning.visible)
  251. {
  252. m_AgentPendingRequestWarning.visible = false;
  253. m_AgentFoldOut.Remove(m_AgentPendingRequestWarning);
  254. }
  255. }
  256. void SetVisualizationEnabled(bool enabled)
  257. {
  258. if (m_VisualizationDisabledHelpBox == null)
  259. return;
  260. if (enabled)
  261. {
  262. if (m_VisualizationDisabledHelpBox.visible)
  263. {
  264. m_RootPanel.Remove(m_VisualizationDisabledHelpBox);
  265. m_OptionsPanel.SetEnabled(true);
  266. m_OptionsPanel.tooltip = "";
  267. m_VisualizationDisabledHelpBox.visible = false;
  268. }
  269. }
  270. else
  271. {
  272. if (!m_VisualizationDisabledHelpBox.visible)
  273. {
  274. m_RootPanel.Insert(0, m_VisualizationDisabledHelpBox);
  275. m_OptionsPanel.SetEnabled(false);
  276. m_OptionsPanel.tooltip = Style.NavigationVisualizationDisabledTexts.tooltip;
  277. m_VisualizationDisabledHelpBox.visible = true;
  278. }
  279. }
  280. }
  281. }
  282. }
  283. #endif