2021년 4학년 1학기 기업연계프로젝트2 컴퓨터소프트웨어공학과 <원광투어팀> 팀장 : 송유진 팀원 : 김나영, 이경희, 한유진
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
16 KiB

5 years ago
  1. #define NAVMESHCOMPONENTS_SHOW_NAVMESHDATA_REF
  2. using System.Linq;
  3. using UnityEditor.IMGUI.Controls;
  4. using UnityEditorInternal;
  5. using UnityEngine.AI;
  6. using UnityEngine;
  7. namespace UnityEditor.AI
  8. {
  9. [CanEditMultipleObjects]
  10. [CustomEditor(typeof(NavMeshSurface))]
  11. class NavMeshSurfaceEditor : Editor
  12. {
  13. SerializedProperty m_AgentTypeID;
  14. SerializedProperty m_BuildHeightMesh;
  15. SerializedProperty m_Center;
  16. SerializedProperty m_CollectObjects;
  17. SerializedProperty m_DefaultArea;
  18. SerializedProperty m_LayerMask;
  19. SerializedProperty m_OverrideTileSize;
  20. SerializedProperty m_OverrideVoxelSize;
  21. SerializedProperty m_Size;
  22. SerializedProperty m_TileSize;
  23. SerializedProperty m_UseGeometry;
  24. SerializedProperty m_VoxelSize;
  25. #if NAVMESHCOMPONENTS_SHOW_NAVMESHDATA_REF
  26. SerializedProperty m_NavMeshData;
  27. #endif
  28. class Styles
  29. {
  30. public readonly GUIContent m_LayerMask = new GUIContent("Include Layers");
  31. public readonly GUIContent m_ShowInputGeom = new GUIContent("Show Input Geom");
  32. public readonly GUIContent m_ShowVoxels = new GUIContent("Show Voxels");
  33. public readonly GUIContent m_ShowRegions = new GUIContent("Show Regions");
  34. public readonly GUIContent m_ShowRawContours = new GUIContent("Show Raw Contours");
  35. public readonly GUIContent m_ShowContours = new GUIContent("Show Contours");
  36. public readonly GUIContent m_ShowPolyMesh = new GUIContent("Show Poly Mesh");
  37. public readonly GUIContent m_ShowPolyMeshDetail = new GUIContent("Show Poly Mesh Detail");
  38. }
  39. static Styles s_Styles;
  40. static bool s_ShowDebugOptions;
  41. static Color s_HandleColor = new Color(127f, 214f, 244f, 100f) / 255;
  42. static Color s_HandleColorSelected = new Color(127f, 214f, 244f, 210f) / 255;
  43. static Color s_HandleColorDisabled = new Color(127f * 0.75f, 214f * 0.75f, 244f * 0.75f, 100f) / 255;
  44. BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle();
  45. bool editingCollider
  46. {
  47. get { return EditMode.editMode == EditMode.SceneViewEditMode.Collider && EditMode.IsOwner(this); }
  48. }
  49. void OnEnable()
  50. {
  51. m_AgentTypeID = serializedObject.FindProperty("m_AgentTypeID");
  52. m_BuildHeightMesh = serializedObject.FindProperty("m_BuildHeightMesh");
  53. m_Center = serializedObject.FindProperty("m_Center");
  54. m_CollectObjects = serializedObject.FindProperty("m_CollectObjects");
  55. m_DefaultArea = serializedObject.FindProperty("m_DefaultArea");
  56. m_LayerMask = serializedObject.FindProperty("m_LayerMask");
  57. m_OverrideTileSize = serializedObject.FindProperty("m_OverrideTileSize");
  58. m_OverrideVoxelSize = serializedObject.FindProperty("m_OverrideVoxelSize");
  59. m_Size = serializedObject.FindProperty("m_Size");
  60. m_TileSize = serializedObject.FindProperty("m_TileSize");
  61. m_UseGeometry = serializedObject.FindProperty("m_UseGeometry");
  62. m_VoxelSize = serializedObject.FindProperty("m_VoxelSize");
  63. #if NAVMESHCOMPONENTS_SHOW_NAVMESHDATA_REF
  64. m_NavMeshData = serializedObject.FindProperty("m_NavMeshData");
  65. #endif
  66. NavMeshVisualizationSettings.showNavigation++;
  67. }
  68. void OnDisable()
  69. {
  70. NavMeshVisualizationSettings.showNavigation--;
  71. }
  72. Bounds GetBounds()
  73. {
  74. var navSurface = (NavMeshSurface)target;
  75. return new Bounds(navSurface.transform.position, navSurface.size);
  76. }
  77. public override void OnInspectorGUI()
  78. {
  79. if (s_Styles == null)
  80. s_Styles = new Styles();
  81. serializedObject.Update();
  82. var bs = NavMesh.GetSettingsByID(m_AgentTypeID.intValue);
  83. if (bs.agentTypeID != -1)
  84. {
  85. // Draw image
  86. const float diagramHeight = 80.0f;
  87. Rect agentDiagramRect = EditorGUILayout.GetControlRect(false, diagramHeight);
  88. NavMeshEditorHelpers.DrawAgentDiagram(agentDiagramRect, bs.agentRadius, bs.agentHeight, bs.agentClimb, bs.agentSlope);
  89. }
  90. NavMeshComponentsGUIUtility.AgentTypePopup("Agent Type", m_AgentTypeID);
  91. EditorGUILayout.Space();
  92. EditorGUILayout.PropertyField(m_CollectObjects);
  93. if ((CollectObjects)m_CollectObjects.enumValueIndex == CollectObjects.Volume)
  94. {
  95. EditorGUI.indentLevel++;
  96. EditMode.DoEditModeInspectorModeButton(EditMode.SceneViewEditMode.Collider, "Edit Volume",
  97. EditorGUIUtility.IconContent("EditCollider"), GetBounds, this);
  98. EditorGUILayout.PropertyField(m_Size);
  99. EditorGUILayout.PropertyField(m_Center);
  100. EditorGUI.indentLevel--;
  101. }
  102. else
  103. {
  104. if (editingCollider)
  105. EditMode.QuitEditMode();
  106. }
  107. EditorGUILayout.PropertyField(m_LayerMask, s_Styles.m_LayerMask);
  108. EditorGUILayout.PropertyField(m_UseGeometry);
  109. EditorGUILayout.Space();
  110. m_OverrideVoxelSize.isExpanded = EditorGUILayout.Foldout(m_OverrideVoxelSize.isExpanded, "Advanced");
  111. if (m_OverrideVoxelSize.isExpanded)
  112. {
  113. EditorGUI.indentLevel++;
  114. NavMeshComponentsGUIUtility.AreaPopup("Default Area", m_DefaultArea);
  115. // Override voxel size.
  116. EditorGUILayout.PropertyField(m_OverrideVoxelSize);
  117. using (new EditorGUI.DisabledScope(!m_OverrideVoxelSize.boolValue || m_OverrideVoxelSize.hasMultipleDifferentValues))
  118. {
  119. EditorGUI.indentLevel++;
  120. EditorGUILayout.PropertyField(m_VoxelSize);
  121. if (!m_OverrideVoxelSize.hasMultipleDifferentValues)
  122. {
  123. if (!m_AgentTypeID.hasMultipleDifferentValues)
  124. {
  125. float voxelsPerRadius = m_VoxelSize.floatValue > 0.0f ? (bs.agentRadius / m_VoxelSize.floatValue) : 0.0f;
  126. EditorGUILayout.LabelField(" ", voxelsPerRadius.ToString("0.00") + " voxels per agent radius", EditorStyles.miniLabel);
  127. }
  128. if (m_OverrideVoxelSize.boolValue)
  129. EditorGUILayout.HelpBox("Voxel size controls how accurately the navigation mesh is generated from the level geometry. A good voxel size is 2-4 voxels per agent radius. Making voxel size smaller will increase build time.", MessageType.None);
  130. }
  131. EditorGUI.indentLevel--;
  132. }
  133. // Override tile size
  134. EditorGUILayout.PropertyField(m_OverrideTileSize);
  135. using (new EditorGUI.DisabledScope(!m_OverrideTileSize.boolValue || m_OverrideTileSize.hasMultipleDifferentValues))
  136. {
  137. EditorGUI.indentLevel++;
  138. EditorGUILayout.PropertyField(m_TileSize);
  139. if (!m_TileSize.hasMultipleDifferentValues && !m_VoxelSize.hasMultipleDifferentValues)
  140. {
  141. float tileWorldSize = m_TileSize.intValue * m_VoxelSize.floatValue;
  142. EditorGUILayout.LabelField(" ", tileWorldSize.ToString("0.00") + " world units", EditorStyles.miniLabel);
  143. }
  144. if (!m_OverrideTileSize.hasMultipleDifferentValues)
  145. {
  146. if (m_OverrideTileSize.boolValue)
  147. EditorGUILayout.HelpBox("Tile size controls the how local the changes to the world are (rebuild or carve). Small tile size allows more local changes, while potentially generating more data overall.", MessageType.None);
  148. }
  149. EditorGUI.indentLevel--;
  150. }
  151. // Height mesh
  152. using (new EditorGUI.DisabledScope(true))
  153. {
  154. EditorGUILayout.PropertyField(m_BuildHeightMesh);
  155. }
  156. EditorGUILayout.Space();
  157. EditorGUI.indentLevel--;
  158. }
  159. EditorGUILayout.Space();
  160. serializedObject.ApplyModifiedProperties();
  161. var hadError = false;
  162. var multipleTargets = targets.Length > 1;
  163. foreach (NavMeshSurface navSurface in targets)
  164. {
  165. var settings = navSurface.GetBuildSettings();
  166. // Calculating bounds is potentially expensive when unbounded - so here we just use the center/size.
  167. // It means the validation is not checking vertical voxel limit correctly when the surface is set to something else than "in volume".
  168. var bounds = new Bounds(Vector3.zero, Vector3.zero);
  169. if (navSurface.collectObjects == CollectObjects.Volume)
  170. {
  171. bounds = new Bounds(navSurface.center, navSurface.size);
  172. }
  173. var errors = settings.ValidationReport(bounds);
  174. if (errors.Length > 0)
  175. {
  176. if (multipleTargets)
  177. EditorGUILayout.LabelField(navSurface.name);
  178. foreach (var err in errors)
  179. {
  180. EditorGUILayout.HelpBox(err, MessageType.Warning);
  181. }
  182. GUILayout.BeginHorizontal();
  183. GUILayout.Space(EditorGUIUtility.labelWidth);
  184. if (GUILayout.Button("Open Agent Settings...", EditorStyles.miniButton))
  185. NavMeshEditorHelpers.OpenAgentSettings(navSurface.agentTypeID);
  186. GUILayout.EndHorizontal();
  187. hadError = true;
  188. }
  189. }
  190. if (hadError)
  191. EditorGUILayout.Space();
  192. #if NAVMESHCOMPONENTS_SHOW_NAVMESHDATA_REF
  193. var nmdRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
  194. EditorGUI.BeginProperty(nmdRect, GUIContent.none, m_NavMeshData);
  195. var rectLabel = EditorGUI.PrefixLabel(nmdRect, GUIUtility.GetControlID(FocusType.Passive), new GUIContent(m_NavMeshData.displayName));
  196. EditorGUI.EndProperty();
  197. using (new EditorGUI.DisabledScope(true))
  198. {
  199. EditorGUI.BeginProperty(nmdRect, GUIContent.none, m_NavMeshData);
  200. EditorGUI.ObjectField(rectLabel, m_NavMeshData, GUIContent.none);
  201. EditorGUI.EndProperty();
  202. }
  203. #endif
  204. using (new EditorGUI.DisabledScope(Application.isPlaying || m_AgentTypeID.intValue == -1))
  205. {
  206. GUILayout.BeginHorizontal();
  207. GUILayout.Space(EditorGUIUtility.labelWidth);
  208. if (GUILayout.Button("Clear"))
  209. {
  210. NavMeshAssetManager.instance.ClearSurfaces(targets);
  211. SceneView.RepaintAll();
  212. }
  213. if (GUILayout.Button("Bake"))
  214. {
  215. NavMeshAssetManager.instance.StartBakingSurfaces(targets);
  216. }
  217. GUILayout.EndHorizontal();
  218. }
  219. // Show progress for the selected targets
  220. var bakeOperations = NavMeshAssetManager.instance.GetBakeOperations();
  221. for (int i = bakeOperations.Count - 1; i >= 0; --i)
  222. {
  223. if (!targets.Contains(bakeOperations[i].Surface))
  224. continue;
  225. var oper = bakeOperations[i].BakeOperation;
  226. if (oper == null)
  227. continue;
  228. var p = oper.progress;
  229. if (oper.isDone)
  230. {
  231. SceneView.RepaintAll();
  232. continue;
  233. }
  234. GUILayout.BeginHorizontal();
  235. if (GUILayout.Button("Cancel", EditorStyles.miniButton))
  236. {
  237. var bakeData = bakeOperations[i].BakeData;
  238. UnityEngine.AI.NavMeshBuilder.Cancel(bakeData);
  239. bakeOperations.RemoveAt(i);
  240. }
  241. EditorGUI.ProgressBar(EditorGUILayout.GetControlRect(), p, "Baking: " + (int)(100 * p) + "%");
  242. if (p <= 1)
  243. Repaint();
  244. GUILayout.EndHorizontal();
  245. }
  246. }
  247. [DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.Pickable)]
  248. static void RenderBoxGizmoSelected(NavMeshSurface navSurface, GizmoType gizmoType)
  249. {
  250. RenderBoxGizmo(navSurface, gizmoType, true);
  251. }
  252. [DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.Pickable)]
  253. static void RenderBoxGizmoNotSelected(NavMeshSurface navSurface, GizmoType gizmoType)
  254. {
  255. if (NavMeshVisualizationSettings.showNavigation > 0)
  256. RenderBoxGizmo(navSurface, gizmoType, false);
  257. else
  258. Gizmos.DrawIcon(navSurface.transform.position, "NavMeshSurface Icon", true);
  259. }
  260. static void RenderBoxGizmo(NavMeshSurface navSurface, GizmoType gizmoType, bool selected)
  261. {
  262. var color = selected ? s_HandleColorSelected : s_HandleColor;
  263. if (!navSurface.enabled)
  264. color = s_HandleColorDisabled;
  265. var oldColor = Gizmos.color;
  266. var oldMatrix = Gizmos.matrix;
  267. // Use the unscaled matrix for the NavMeshSurface
  268. var localToWorld = Matrix4x4.TRS(navSurface.transform.position, navSurface.transform.rotation, Vector3.one);
  269. Gizmos.matrix = localToWorld;
  270. if (navSurface.collectObjects == CollectObjects.Volume)
  271. {
  272. Gizmos.color = color;
  273. Gizmos.DrawWireCube(navSurface.center, navSurface.size);
  274. if (selected && navSurface.enabled)
  275. {
  276. var colorTrans = new Color(color.r * 0.75f, color.g * 0.75f, color.b * 0.75f, color.a * 0.15f);
  277. Gizmos.color = colorTrans;
  278. Gizmos.DrawCube(navSurface.center, navSurface.size);
  279. }
  280. }
  281. else
  282. {
  283. if (navSurface.navMeshData != null)
  284. {
  285. var bounds = navSurface.navMeshData.sourceBounds;
  286. Gizmos.color = Color.grey;
  287. Gizmos.DrawWireCube(bounds.center, bounds.size);
  288. }
  289. }
  290. Gizmos.matrix = oldMatrix;
  291. Gizmos.color = oldColor;
  292. Gizmos.DrawIcon(navSurface.transform.position, "NavMeshSurface Icon", true);
  293. }
  294. void OnSceneGUI()
  295. {
  296. if (!editingCollider)
  297. return;
  298. var navSurface = (NavMeshSurface)target;
  299. var color = navSurface.enabled ? s_HandleColor : s_HandleColorDisabled;
  300. var localToWorld = Matrix4x4.TRS(navSurface.transform.position, navSurface.transform.rotation, Vector3.one);
  301. using (new Handles.DrawingScope(color, localToWorld))
  302. {
  303. m_BoundsHandle.center = navSurface.center;
  304. m_BoundsHandle.size = navSurface.size;
  305. EditorGUI.BeginChangeCheck();
  306. m_BoundsHandle.DrawHandle();
  307. if (EditorGUI.EndChangeCheck())
  308. {
  309. Undo.RecordObject(navSurface, "Modified NavMesh Surface");
  310. Vector3 center = m_BoundsHandle.center;
  311. Vector3 size = m_BoundsHandle.size;
  312. navSurface.center = center;
  313. navSurface.size = size;
  314. EditorUtility.SetDirty(target);
  315. }
  316. }
  317. }
  318. [MenuItem("GameObject/AI/NavMesh Surface", false, 2000)]
  319. public static void CreateNavMeshSurface(MenuCommand menuCommand)
  320. {
  321. var parent = menuCommand.context as GameObject;
  322. var go = NavMeshComponentsGUIUtility.CreateAndSelectGameObject("NavMesh Surface", parent);
  323. go.AddComponent<NavMeshSurface>();
  324. var view = SceneView.lastActiveSceneView;
  325. if (view != null)
  326. view.MoveToView(go.transform);
  327. }
  328. }
  329. }