-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathNavMeshPrefabInstanceEditor.cs
More file actions
155 lines (128 loc) · 4.67 KB
/
NavMeshPrefabInstanceEditor.cs
File metadata and controls
155 lines (128 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.AI;
[CanEditMultipleObjects]
[CustomEditor(typeof(NavMeshPrefabInstance))]
class NavMeshPrefabInstanceEditor : Editor
{
SerializedProperty m_FollowTransformProp;
SerializedProperty m_NavMeshDataProp;
public void OnEnable()
{
m_FollowTransformProp = serializedObject.FindProperty("m_FollowTransform");
m_NavMeshDataProp = serializedObject.FindProperty("m_NavMesh");
}
public override void OnInspectorGUI()
{
var instance = (NavMeshPrefabInstance)target;
var go = instance.gameObject;
serializedObject.Update();
GUI.enabled = false;
EditorGUILayout.PropertyField(m_NavMeshDataProp);
GUI.enabled = true;
EditorGUILayout.PropertyField(m_FollowTransformProp);
EditorGUILayout.Space();
OnInspectorGUIPrefab(go);
serializedObject.ApplyModifiedProperties();
}
string GetAssetPath(GameObject go)
{
var stage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
if (stage != null && stage.IsPartOfPrefabContents(go))
{
return stage.prefabAssetPath;
}
return PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(go);
}
void OnInspectorGUIPrefab(GameObject go)
{
var stage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
if (stage == null || !stage.IsPartOfPrefabContents(go))
{
if (GUILayout.Button("Edit the Prefab asset to bake or clear the navmesh", EditorStyles.helpBox))
{
Selection.activeObject = PrefabUtility.GetCorrespondingObjectFromSource(go);
EditorGUIUtility.PingObject(Selection.activeObject);
}
return;
}
var path = GetAssetPath(go);
if (string.IsNullOrEmpty(path))
return;
GUILayout.BeginHorizontal();
GUILayout.Space(EditorGUIUtility.labelWidth);
if (GUILayout.Button("Clear"))
OnClear();
if (GUILayout.Button("Bake"))
OnBake();
GUILayout.EndHorizontal();
}
NavMeshData Build(NavMeshPrefabInstance instance)
{
var root = instance.transform;
var sources = new List<NavMeshBuildSource>();
var markups = new List<NavMeshBuildMarkup>();
UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage(
root, ~0, NavMeshCollectGeometry.RenderMeshes, 0, markups, instance.gameObject.scene, sources);
var settings = NavMesh.GetSettingsByID(0);
var bounds = new Bounds(Vector3.zero, 1000.0f * Vector3.one);
var navmesh = NavMeshBuilder.BuildNavMeshData(settings, sources, bounds, root.position, root.rotation);
navmesh.name = "Navmesh";
return navmesh;
}
void OnClear()
{
foreach (var tgt in targets)
{
var instance = (NavMeshPrefabInstance)tgt;
var go = instance.gameObject;
var path = GetAssetPath(go);
if (string.IsNullOrEmpty(path))
{
Debug.LogError("GameObject: " + go + " has no valid prefab path");
continue;
}
DestroyNavMeshData(path);
AssetDatabase.SaveAssets();
}
}
void OnBake()
{
foreach (var tgt in targets)
{
var instance = (NavMeshPrefabInstance)tgt;
var go = instance.gameObject;
var path = GetAssetPath(go);
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (string.IsNullOrEmpty(path))
{
Debug.LogError("GameObject: " + go + " has no valid prefab path");
continue;
}
DestroyNavMeshData(path);
// Store navmesh as a sub-asset of the prefab
var navmesh = Build(instance);
AssetDatabase.AddObjectToAsset(navmesh, prefab);
instance.navMeshData = navmesh;
AssetDatabase.SaveAssets();
}
}
void DestroyNavMeshData(string path)
{
// Destroy and remove all existing NavMeshData sub-assets
var assets = AssetDatabase.LoadAllAssetsAtPath(path);
foreach (var o in assets)
{
var data = o as NavMeshData;
if (data != null)
DestroyImmediate(o, true);
}
}
[DrawGizmo(GizmoType.Selected | GizmoType.Active | GizmoType.Pickable)]
static void RenderGizmo(NavMeshPrefabInstance instance, GizmoType gizmoType)
{
if (!EditorApplication.isPlaying)
instance.UpdateInstance();
}
}