Skip to content

Commit 09b9e39

Browse files
committed
WIP Manual Linked Prefab update
1 parent 0698464 commit 09b9e39

File tree

1 file changed

+142
-11
lines changed

1 file changed

+142
-11
lines changed

Assets/FbxExporters/Editor/FbxPrefabAutoUpdater.cs

Lines changed: 142 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using UnityEditor;
66
using System.Linq;
77
using System;
8+
using FbxExporters.Editor;
89

910
namespace FbxExporters
1011
{
@@ -25,19 +26,22 @@ namespace FbxExporters
2526
/// </summary>
2627
public /*static*/ class FbxPrefabAutoUpdater : UnityEditor.AssetPostprocessor
2728
{
28-
#if UNITY_EDITOR
29+
#if UNITY_EDITOR
2930
public const string FBX_PREFAB_FILE = "/FbxPrefab.cs";
30-
#else
31+
#else
3132
public const string FBX_PREFAB_FILE = "/UnityFbxPrefab.dll";
32-
#endif
33+
#endif
34+
35+
static string[] importedAssets;
36+
3337
public static string FindFbxPrefabAssetPath()
3438
{
3539
// Find guids that are scripts that look like FbxPrefab.
3640
// That catches FbxPrefabTest too, so we have to make sure.
3741
var allGuids = AssetDatabase.FindAssets("FbxPrefab t:MonoScript");
38-
foreach(var guid in allGuids) {
42+
foreach (var guid in allGuids) {
3943
var path = AssetDatabase.GUIDToAssetPath(guid);
40-
if (path.EndsWith (FBX_PREFAB_FILE)) {
44+
if (path.EndsWith(FBX_PREFAB_FILE)) {
4145
return path;
4246
}
4347
}
@@ -53,6 +57,8 @@ public static bool IsPrefabAsset(string assetPath) {
5357
return assetPath.EndsWith(".prefab");
5458
}
5559

60+
const string MenuItemName = "GameObject/Update from Fbx";
61+
5662
/// <summary>
5763
/// Return false if the prefab definitely does not have an
5864
/// FbxPrefab component that points to one of the Fbx assets
@@ -65,7 +71,7 @@ public static bool MayHaveFbxPrefabToFbxAsset(string prefabPath,
6571
var depPaths = AssetDatabase.GetDependencies(prefabPath, recursive: false);
6672
bool dependsOnFbxPrefab = false;
6773
bool dependsOnImportedFbx = false;
68-
foreach(var dep in depPaths) {
74+
foreach (var dep in depPaths) {
6975
if (dep == fbxPrefabScriptPath) {
7076
if (dependsOnImportedFbx) { return true; }
7177
dependsOnFbxPrefab = true;
@@ -79,11 +85,13 @@ public static bool MayHaveFbxPrefabToFbxAsset(string prefabPath,
7985
return false;
8086
}
8187

82-
static void OnPostprocessAllAssets(string [] imported, string [] deleted, string [] moved, string [] movedFrom)
88+
static void OnPostprocessAllAssets(string[] imported, string[] deleted, string[] moved, string[] movedFrom)
8389
{
8490
// Do not start if Auto Updater is disabled in FBX Exporter Settings
8591
if (!FbxExporters.EditorTools.ExportSettings.instance.autoUpdaterEnabled)
8692
{
93+
// Store imported assets to reuse them later
94+
importedAssets = imported;
8795
return;
8896
}
8997

@@ -92,7 +100,7 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
92100
// Did we import an fbx file at all?
93101
// Optimize to not allocate in the common case of 'no'
94102
HashSet<string> fbxImported = null;
95-
foreach(var fbxModel in imported) {
103+
foreach (var fbxModel in imported) {
96104
if (IsFbxAsset(fbxModel)) {
97105
if (fbxImported == null) { fbxImported = new HashSet<string>(); }
98106
fbxImported.Add(fbxModel);
@@ -116,7 +124,7 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
116124
//
117125
var fbxPrefabScriptPath = FindFbxPrefabAssetPath();
118126
var allObjectGuids = AssetDatabase.FindAssets("t:GameObject");
119-
foreach(var guid in allObjectGuids) {
127+
foreach (var guid in allObjectGuids) {
120128
var prefabPath = AssetDatabase.GUIDToAssetPath(guid);
121129
if (!IsPrefabAsset(prefabPath)) {
122130
//Debug.Log("Not a prefab: " + prefabPath);
@@ -140,8 +148,8 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
140148
//Debug.LogWarning("FbxPrefab reimport: failed to update prefab " + prefabPath);
141149
continue;
142150
}
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);
145153
if (!fbxPrefabUtility.WantsAutoUpdate()) {
146154
//Debug.Log("Not auto-updating " + prefabPath);
147155
continue;
@@ -157,6 +165,129 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
157165
}
158166
}
159167

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+
}
160291

161292
public class FbxPrefabUtility{
162293

0 commit comments

Comments
 (0)