5
5
using UnityEditor ;
6
6
using System . Linq ;
7
7
using System ;
8
+ using FbxExporters . Editor ;
8
9
9
10
namespace FbxExporters
10
11
{
@@ -25,19 +26,22 @@ namespace FbxExporters
25
26
/// </summary>
26
27
public /*static*/ class FbxPrefabAutoUpdater : UnityEditor . AssetPostprocessor
27
28
{
28
- #if UNITY_EDITOR
29
+ #if UNITY_EDITOR
29
30
public const string FBX_PREFAB_FILE = "/FbxPrefab.cs" ;
30
- #else
31
+ #else
31
32
public const string FBX_PREFAB_FILE = "/UnityFbxPrefab.dll" ;
32
- #endif
33
+ #endif
34
+
35
+ static string [ ] importedAssets ;
36
+
33
37
public static string FindFbxPrefabAssetPath ( )
34
38
{
35
39
// Find guids that are scripts that look like FbxPrefab.
36
40
// That catches FbxPrefabTest too, so we have to make sure.
37
41
var allGuids = AssetDatabase . FindAssets ( "FbxPrefab t:MonoScript" ) ;
38
- foreach ( var guid in allGuids ) {
42
+ foreach ( var guid in allGuids ) {
39
43
var path = AssetDatabase . GUIDToAssetPath ( guid ) ;
40
- if ( path . EndsWith ( FBX_PREFAB_FILE ) ) {
44
+ if ( path . EndsWith ( FBX_PREFAB_FILE ) ) {
41
45
return path ;
42
46
}
43
47
}
@@ -53,6 +57,8 @@ public static bool IsPrefabAsset(string assetPath) {
53
57
return assetPath . EndsWith ( ".prefab" ) ;
54
58
}
55
59
60
+ const string MenuItemName = "GameObject/Update from Fbx" ;
61
+
56
62
/// <summary>
57
63
/// Return false if the prefab definitely does not have an
58
64
/// FbxPrefab component that points to one of the Fbx assets
@@ -65,7 +71,7 @@ public static bool MayHaveFbxPrefabToFbxAsset(string prefabPath,
65
71
var depPaths = AssetDatabase . GetDependencies ( prefabPath , recursive : false ) ;
66
72
bool dependsOnFbxPrefab = false ;
67
73
bool dependsOnImportedFbx = false ;
68
- foreach ( var dep in depPaths ) {
74
+ foreach ( var dep in depPaths ) {
69
75
if ( dep == fbxPrefabScriptPath ) {
70
76
if ( dependsOnImportedFbx ) { return true ; }
71
77
dependsOnFbxPrefab = true ;
@@ -79,11 +85,13 @@ public static bool MayHaveFbxPrefabToFbxAsset(string prefabPath,
79
85
return false ;
80
86
}
81
87
82
- static void OnPostprocessAllAssets ( string [ ] imported , string [ ] deleted , string [ ] moved , string [ ] movedFrom )
88
+ static void OnPostprocessAllAssets ( string [ ] imported , string [ ] deleted , string [ ] moved , string [ ] movedFrom )
83
89
{
84
90
// Do not start if Auto Updater is disabled in FBX Exporter Settings
85
91
if ( ! FbxExporters . EditorTools . ExportSettings . instance . autoUpdaterEnabled )
86
92
{
93
+ // Store imported assets to reuse them later
94
+ importedAssets = imported ;
87
95
return ;
88
96
}
89
97
@@ -92,7 +100,7 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
92
100
// Did we import an fbx file at all?
93
101
// Optimize to not allocate in the common case of 'no'
94
102
HashSet < string > fbxImported = null ;
95
- foreach ( var fbxModel in imported ) {
103
+ foreach ( var fbxModel in imported ) {
96
104
if ( IsFbxAsset ( fbxModel ) ) {
97
105
if ( fbxImported == null ) { fbxImported = new HashSet < string > ( ) ; }
98
106
fbxImported . Add ( fbxModel ) ;
@@ -116,7 +124,7 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
116
124
//
117
125
var fbxPrefabScriptPath = FindFbxPrefabAssetPath ( ) ;
118
126
var allObjectGuids = AssetDatabase . FindAssets ( "t:GameObject" ) ;
119
- foreach ( var guid in allObjectGuids ) {
127
+ foreach ( var guid in allObjectGuids ) {
120
128
var prefabPath = AssetDatabase . GUIDToAssetPath ( guid ) ;
121
129
if ( ! IsPrefabAsset ( prefabPath ) ) {
122
130
//Debug.Log("Not a prefab: " + prefabPath);
@@ -140,8 +148,8 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
140
148
//Debug.LogWarning("FbxPrefab reimport: failed to update prefab " + prefabPath);
141
149
continue ;
142
150
}
143
- foreach ( var fbxPrefabComponent in prefab . GetComponentsInChildren < FbxPrefab > ( ) ) {
144
- var fbxPrefabUtility = new FbxPrefabUtility ( fbxPrefabComponent ) ;
151
+ foreach ( var fbxPrefabComponent in prefab . GetComponentsInChildren < FbxPrefab > ( ) ) {
152
+ var fbxPrefabUtility = new FbxPrefabUtility ( fbxPrefabComponent ) ;
145
153
if ( ! fbxPrefabUtility . WantsAutoUpdate ( ) ) {
146
154
//Debug.Log("Not auto-updating " + prefabPath);
147
155
continue ;
@@ -157,6 +165,129 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
157
165
}
158
166
}
159
167
168
+ [ MenuItem ( MenuItemName , false , 30 ) ]
169
+ public static void OnContextItem ( MenuCommand command )
170
+ {
171
+ GameObject [ ] selection = null ;
172
+
173
+ if ( command == null || command . context == null )
174
+ {
175
+ // We were actually invoked from the top GameObject menu, so use the selection.
176
+ //selection = Selection.GetFiltered<GameObject>(SelectionMode.Unfiltered);
177
+ selection = Selection . gameObjects ;
178
+ }
179
+ else
180
+ {
181
+ // We were invoked from the right-click menu, so use the context of the context menu.
182
+ var selected = command . context as GameObject ;
183
+ if ( selected )
184
+ {
185
+ selection = new GameObject [ ] { selected } ;
186
+ }
187
+ }
188
+
189
+ if ( selection == null || selection . Length == 0 )
190
+ {
191
+ ModelExporter . DisplayNoSelectionDialog ( ) ;
192
+ return ;
193
+ }
194
+
195
+
196
+ // Did we import an fbx file at all?
197
+ // Optimize to not allocate in the common case of 'no'
198
+ HashSet < string > fbxImported = null ;
199
+ if ( importedAssets != null )
200
+ {
201
+ foreach ( var fbxModel in importedAssets )
202
+ {
203
+ if ( IsFbxAsset ( fbxModel ) )
204
+ {
205
+ if ( fbxImported == null ) { fbxImported = new HashSet < string > ( ) ; }
206
+ fbxImported . Add ( fbxModel ) ;
207
+ //Debug.Log("Tracking fbx asset " + fbxModel);
208
+ }
209
+ else
210
+ {
211
+ //Debug.Log("Not an fbx asset " + fbxModel);
212
+ }
213
+ }
214
+ }
215
+
216
+ if ( fbxImported != null )
217
+ {
218
+ //Selection.objects = UpdateLinkedPrefab(selection);
219
+ UpdateLinkedPrefab ( selection , fbxImported ) ;
220
+ }
221
+ }
222
+
223
+ /// <summary>
224
+ // Validate the menu item defined by the function above.
225
+ /// </summary>
226
+ [ MenuItem ( MenuItemName , true , 30 ) ]
227
+ public static bool OnValidateMenuItem ( )
228
+ {
229
+ //GameObject[] selection = Selection.GetFiltered<GameObject>(SelectionMode.Unfiltered);
230
+ GameObject [ ] selection = Selection . gameObjects ;
231
+
232
+ if ( selection == null || selection . Length == 0 )
233
+ {
234
+ ModelExporter . DisplayNoSelectionDialog ( ) ;
235
+ return false ;
236
+ }
237
+
238
+ bool allObjectsPrefab = true ;
239
+ // Check if it's a prefab
240
+ foreach ( GameObject selectedObject in selection )
241
+ {
242
+ if ( selectedObject . GetComponent < FbxPrefab > ( ) != null || PrefabUtility . FindPrefabRoot ( selectedObject ) . GetComponent < FbxPrefab > ( ) != null )
243
+ {
244
+ allObjectsPrefab = true ;
245
+ }
246
+ else
247
+ {
248
+ allObjectsPrefab = false ;
249
+ break ;
250
+ }
251
+ }
252
+
253
+ return allObjectsPrefab ;
254
+ }
255
+
256
+ static void UpdateLinkedPrefab ( GameObject [ ] selection , HashSet < string > fbxImported )
257
+ {
258
+ // Iterate over all the prefabs that have an FbxPrefab component that
259
+ // points to an FBX file that got (re)-imported.
260
+ //
261
+ // There's no one-line query to get those, so we search for a much
262
+ // larger set and whittle it down, hopefully without needing to
263
+ // load the asset into memory if it's not necessary.
264
+ //
265
+ foreach ( GameObject prefab in selection )
266
+ {
267
+ if ( ! prefab )
268
+ {
269
+ //Debug.LogWarning("FbxPrefab reimport: failed to update prefab " + prefabPath);
270
+ continue ;
271
+ }
272
+ foreach ( var fbxPrefabComponent in prefab . GetComponentsInChildren < FbxPrefab > ( ) )
273
+ {
274
+ var fbxPrefabUtility = new FbxPrefabUtility ( fbxPrefabComponent ) ;
275
+ if ( ! fbxPrefabUtility . WantsAutoUpdate ( ) )
276
+ {
277
+ //Debug.Log("Not auto-updating " + prefabPath);
278
+ continue ;
279
+ }
280
+ var fbxAssetPath = fbxPrefabUtility . GetFbxAssetPath ( ) ;
281
+ if ( ! fbxImported . Contains ( fbxAssetPath ) )
282
+ {
283
+ //Debug.Log("False-positive dependence: " + prefabPath + " via " + fbxAssetPath);
284
+ continue ;
285
+ }
286
+ //Debug.Log("Updating " + prefabPath + "...");
287
+ fbxPrefabUtility . SyncPrefab ( ) ;
288
+ }
289
+ }
290
+ }
160
291
161
292
public class FbxPrefabUtility {
162
293
0 commit comments