context: using System.IO;
  using UnityEditor.IMGUI.Controls;
  using UnityEditor.SceneManagement;
  using UnityEditorInternal;
  using UnityEngine.AI;
  using UnityEngine;
  
  namespace UnityEditor.AI
  {
  	[CanEditMultipleObjects]
      [CustomEditor(typeof(NavMeshSurface))]
      class NavMeshSurfaceEditor : Editor
      {
          SerializedProperty m_AgentTypeID;
          SerializedProperty m_BuildHeightMesh;
          SerializedProperty m_Center;
          SerializedProperty m_CollectObjects;
          SerializedProperty m_DefaultArea;
          SerializedProperty m_LayerMask;
          SerializedProperty m_OverrideTileSize;
          SerializedProperty m_OverrideVoxelSize;
          SerializedProperty m_Size;
          SerializedProperty m_TileSize;
          SerializedProperty m_UseGeometry;
          SerializedProperty m_VoxelSize;
  
          class Styles
          {
              public readonly GUIContent m_LayerMask = new GUIContent("Include Layers");
  
              public readonly GUIContent m_ShowInputGeom = new GUIContent("Show Input Geom");
              public readonly GUIContent m_ShowVoxels = new GUIContent("Show Voxels");
              public readonly GUIContent m_ShowRegions = new GUIContent("Show Regions");
              public readonly GUIContent m_ShowRawContours = new GUIContent("Show Raw Contours");
              public readonly GUIContent m_ShowContours = new GUIContent("Show Contours");
              public readonly GUIContent m_ShowPolyMesh = new GUIContent("Show Poly Mesh");
              public readonly GUIContent m_ShowPolyMeshDetail = new GUIContent("Show Poly Mesh Detail");
          }
  
          static Styles s_Styles;
  
          static bool s_ShowDebugOptions;
  
          static Color s_HandleColor = new Color(127f, 214f, 244f, 100f) / 255;
          static Color s_HandleColorSelected = new Color(127f, 214f, 244f, 210f) / 255;
          static Color s_HandleColorDisabled = new Color(127f * 0.75f, 214f * 0.75f, 244f * 0.75f, 100f) / 255;
  
          static int s_HandleControlIDHint = typeof(NavMeshSurfaceEditor).Name.GetHashCode();
          BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(s_HandleControlIDHint);
  
          bool editingCollider
          {
              get { return EditMode.editMode == EditMode.SceneViewEditMode.Collider && EditMode.IsOwner(this); }
          }
  
          void OnEnable()
          {
              m_AgentTypeID = serializedObject.FindProperty("m_AgentTypeID");
              m_BuildHeightMesh = serializedObject.FindProperty("m_BuildHeightMesh");
              m_Center = serializedObject.FindProperty("m_Center");
              m_CollectObjects = serializedObject.FindProperty("m_CollectObjects");
              m_DefaultArea = serializedObject.FindProperty("m_DefaultArea");
              m_LayerMask = serializedObject.FindProperty("m_LayerMask");
              m_OverrideTileSize = serializedObject.FindProperty("m_OverrideTileSize");
              m_OverrideVoxelSize = serializedObject.FindProperty("m_OverrideVoxelSize");
              m_Size = serializedObject.FindProperty("m_Size");
              m_TileSize = serializedObject.FindProperty("m_TileSize");
              m_UseGeometry = serializedObject.FindProperty("m_UseGeometry");
              m_VoxelSize = serializedObject.FindProperty("m_VoxelSize");
  
              NavMeshVisualizationSettings.showNavigation++;
          }
  
          void OnDisable()
          {
              NavMeshVisualizationSettings.showNavigation--;
          }
  
          static string GetAndEnsureTargetPath(NavMeshSurface surface)
          {
              // Create directory for the asset if it does not exist yet.
              var activeScenePath = surface.gameObject.scene.path;
  
              var targetPath = "Assets";
              if (!string.IsNullOrEmpty(activeScenePath))
                  targetPath = Path.Combine(Path.GetDirectoryName(activeScenePath), Path.GetFileNameWithoutExtension(activeScenePath));
              if (!Directory.Exists(targetPath))
                  Directory.CreateDirectory(targetPath);
              return targetPath;
          }
  
          void CreateNavMeshAsset(NavMeshSurface surface)
          {
              var targetPath = GetAndEnsureTargetPath(surface);
  
              var combinedAssetPath = Path.Combine(targetPath, "NavMesh-" + surface.name + ".asset");
              combinedAssetPath = AssetDatabase.GenerateUniqueAssetPath(combinedAssetPath);
              AssetDatabase.CreateAsset(surface.bakedNavMeshData, combinedAssetPath);
          }
  
          NavMeshData GetNavMeshAssetToDelete(NavMeshSurface navSurface)
          {
              var prefabType = PrefabUtility.GetPrefabType(navSurface);
              if (prefabType == PrefabType.PrefabInstance || prefabType == PrefabType.DisconnectedPrefabInstance)
              {
                  // Don't allow deleting the asset belonging to the prefab parent
                  var parentSurface = PrefabUtility.GetPrefabParent(navSurface) as NavMeshSurface;
                  if (parentSurface && navSurface.bakedNavMeshData == parentSurface.bakedNavMeshData)
                      return null;
              }
              return navSurface.bakedNavMeshData;
          }
  
          void BakeSurface(NavMeshSurface navSurface)
          {
              var assetToDelete = GetNavMeshAssetToDelete(navSurface);
              navSurface.Bake();
              EditorUtility.SetDirty(navSurface);
  
              if (assetToDelete)
              {
                  AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(assetToDelete));
              }
              CreateNavMeshAsset(navSurface);
              EditorSceneManager.MarkSceneDirty(navSurface.gameObject.scene);
          }
  
          void ClearSurface(NavMeshSurface navSurface)
          {
              var assetToDelete = GetNavMeshAssetToDelete(navSurface);
              navSurface.RemoveData();
              navSurface.bakedNavMeshData = null;
              EditorUtility.SetDirty(navSurface);
  
              if (assetToDelete)
              {
                  AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(assetToDelete));
                  EditorSceneManager.MarkSceneDirty(navSurface.gameObject.scene);
              }
          }
  
          public override void OnInspectorGUI()
          {
              if (s_Styles == null)
                  s_Styles = new Styles();
  
              serializedObject.Update();
  
              var bs = NavMesh.GetSettingsByID(m_AgentTypeID.intValue);
  
              if (bs.agentTypeID != -1)
              {
                  // Draw image
                  const float diagramHeight = 80.0f;
                  Rect agentDiagramRect = EditorGUILayout.GetControlRect(false, diagramHeight);
                  NavMeshEditorHelpers.DrawAgentDiagram(agentDiagramRect, bs.agentRadius, bs.agentHeight, bs.agentClimb, bs.agentSlope);
              }
              NavMeshComponentsGUIUtility.AgentTypePopup("Agent Type", m_AgentTypeID);
  
              EditorGUILayout.Space();
  
              EditorGUILayout.PropertyField(m_CollectObjects);
              if ((CollectObjects)m_CollectObjects.enumValueIndex == CollectObjects.Volume)
              {
                  EditorGUI.indentLevel++;
                  InspectorEditButtonGUI();
                  EditorGUILayout.PropertyField(m_Size);
                  EditorGUILayout.PropertyField(m_Center);
              }
              else
              {
                  if (editingCollider)
                      EditMode.QuitEditMode();
              }
  
              EditorGUILayout.PropertyField(m_LayerMask, s_Styles.m_LayerMask);
              EditorGUILayout.PropertyField(m_UseGeometry);
  
              EditorGUILayout.Space();
  
              EditorGUILayout.Space();
  
              m_OverrideVoxelSize.isExpanded = EditorGUILayout.Foldout(m_OverrideVoxelSize.isExpanded, "Advanced");
              if (m_OverrideVoxelSize.isExpanded)
              {
                  EditorGUI.indentLevel++;
  
                  NavMeshComponentsGUIUtility.AreaPopup("Default Area", m_DefaultArea);
  
                  // Override voxel size.
                  EditorGUILayout.PropertyField(m_OverrideVoxelSize);
  
                  using (new EditorGUI.DisabledScope(!m_OverrideVoxelSize.boolValue || m_OverrideVoxelSize.hasMultipleDifferentValues))
                  {
                      EditorGUI.indentLevel++;
  
                      EditorGUILayout.PropertyField(m_VoxelSize);
  
                      if (!m_OverrideVoxelSize.hasMultipleDifferentValues)
                      {
                          if (!m_AgentTypeID.hasMultipleDifferentValues)
                          {
                              float voxelsPerRadius = m_VoxelSize.floatValue > 0.0f ? (bs.agentRadius / m_VoxelSize.floatValue) : 0.0f;
                              EditorGUILayout.LabelField(" ", voxelsPerRadius.ToString("0.00") + " voxels per agent radius", EditorStyles.miniLabel);
                          }
                          if (m_OverrideVoxelSize.boolValue)
                              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);
                      }
                      EditorGUI.indentLevel--;
                  }
  
                  // Override tile size
                  EditorGUILayout.PropertyField(m_OverrideTileSize);
  
                  using (new EditorGUI.DisabledScope(!m_OverrideTileSize.boolValue || m_OverrideTileSize.hasMultipleDifferentValues))
                  {
                      EditorGUI.indentLevel++;
  
                      EditorGUILayout.PropertyField(m_TileSize);
  
                      if (!m_TileSize.hasMultipleDifferentValues && !m_VoxelSize.hasMultipleDifferentValues)
                      {
                          float tileWorldSize = m_TileSize.intValue * m_VoxelSize.floatValue;
                          EditorGUILayout.LabelField(" ", tileWorldSize.ToString("0.00") + " world units", EditorStyles.miniLabel);
                      }
  
                      if (!m_OverrideTileSize.hasMultipleDifferentValues)
                      {
                          if (m_OverrideTileSize.boolValue)
                              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 in overal.", MessageType.None);
                      }
                      EditorGUI.indentLevel--;
                  }
  
  
                  // Height mesh
                  using (new EditorGUI.DisabledScope(true))
                  {
                      EditorGUILayout.PropertyField(m_BuildHeightMesh);
                  }
  
                  EditorGUILayout.Space();
                  EditorGUI.indentLevel--;
              }
  
              EditorGUILayout.Space();
  
              serializedObject.ApplyModifiedProperties();
  
              var hadError = false;
              var multipleTargets = targets.Length > 1;
              foreach (NavMeshSurface navSurface in targets)
              {
                  var settings = navSurface.GetBuildSettings();
                  // Calculating bounds is potentially expensive when unbounded - so here we just use the center/size.
                  // It means the validation is not checking vertical voxel limit correctly when the surface is set to something else than "in volume".
                  var bounds = new Bounds(Vector3.zero, Vector3.zero);
                  if (navSurface.collectObjects == CollectObjects.Volume)
                  {
                      bounds = new Bounds(navSurface.center, navSurface.size);
                  }
  
                  var errors = settings.ValidationReport(bounds);
                  if (errors.Length > 0)
                  {
                      if (multipleTargets)
                          EditorGUILayout.LabelField(navSurface.name);
                      foreach (var err in errors)
                      {
                          EditorGUILayout.HelpBox(err, MessageType.Warning);
                      }
                      GUILayout.BeginHorizontal();
                      GUILayout.Space(EditorGUIUtility.labelWidth);
                      if (GUILayout.Button("Open Agent Settings...", EditorStyles.miniButton))
                          NavMeshEditorHelpers.OpenAgentSettings(navSurface.agentTypeID);
                      GUILayout.EndHorizontal();
                      hadError = true;
                  }
              }
  
              if (hadError)
                  EditorGUILayout.Space();
  
              using (new EditorGUI.DisabledScope(Application.isPlaying || m_AgentTypeID.intValue == -1))
              {
                  GUILayout.BeginHorizontal();
                  GUILayout.Space(EditorGUIUtility.labelWidth);
                  if (GUILayout.Button("Clear"))
                  {
                      foreach (NavMeshSurface s in targets)
                          ClearSurface(s);
                      SceneView.RepaintAll();
                  }
  
                  if (GUILayout.Button("Bake"))
                  {
                      foreach (NavMeshSurface navSurface in targets)
                          BakeSurface(navSurface);
                      SceneView.RepaintAll();
                  }
                  GUILayout.EndHorizontal();
              }
          }
  
          [DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.Pickable)]
          static void RenderBoxGizmoSelected(NavMeshSurface navSurface, GizmoType gizmoType)
          {
              RenderBoxGizmo(navSurface, gizmoType, true);
          }
  
          [DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.Pickable)]
          static void RenderBoxGizmoNotSelected(NavMeshSurface navSurface, GizmoType gizmoType)
          {
              if (NavMeshVisualizationSettings.showNavigation > 0)
                  RenderBoxGizmo(navSurface, gizmoType, false);
              else
                  Gizmos.DrawIcon(navSurface.transform.position, "NavMeshSurface Icon", true);
          }
  
          static void RenderBoxGizmo(NavMeshSurface navSurface, GizmoType gizmoType, bool selected)
          {
  
gt:             var color = selected ? s_HandleColorSelected : s_HandleColor;