+Add : Blocking test & Cleanup

This commit is contained in:
Ferlat Thibaud
2026-03-26 02:37:05 +01:00
parent 0c0a539af3
commit 900cc079c8
85 changed files with 101475 additions and 1084 deletions
@@ -14,10 +14,8 @@ namespace FBXImporter
/// 4. Force reimport
/// 5. Connect PBR textures → create .mat files
/// 6. Extract animation clips → Animations/
/// 7. Generate prefab
/// 7. Generate prefab(s) — one per mesh if multi-mesh FBX
/// 8. Create AnimatorController + assign to prefab
/// 9. Delete Sources/Materials/ (Unity auto-generates it, we don't need it)
/// 10. Delete original source folder (cleanup)
/// </summary>
public static void Process(string fbxAssetPath,
ModelImporterAnimationType animationType = ModelImporterAnimationType.Generic,
@@ -33,8 +31,8 @@ namespace FBXImporter
Debug.Log($"[FBXImporter] ── Processing {Path.GetFileName(fbxAssetPath)} ──");
var source = FBXSourceDetector.Detect(fbxAssetPath);
var folders = FolderSetup.Resolve(fbxAssetPath);
var source = FBXSourceDetector.Detect(fbxAssetPath);
var folders = FolderSetup.Resolve(fbxAssetPath);
bool withAnims = animationType != ModelImporterAnimationType.None;
FolderSetup.Create(
@@ -67,10 +65,10 @@ namespace FBXImporter
if (withAnims && !string.IsNullOrEmpty(folders.Animations))
AnimationExtractor.ExtractClips(fbxAssetPath, folders.Animations);
// Generate prefab
// Generate prefab(s)
string assetName = Path.GetFileNameWithoutExtension(fbxAssetPath);
string prefabPath = $"{folders.Prefabs}/{assetName}.prefab";
PrefabBuilder.CreatePrefab(fbxAsset, folders.Prefabs, assetName);
PrefabBuilder.CreatePrefabs(fbxAsset, folders, assetName);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
@@ -79,28 +77,9 @@ namespace FBXImporter
if (withAnims && !string.IsNullOrEmpty(folders.Animations))
AnimatorControllerBuilder.CreateAndAssign(folders.Animations, prefabPath, assetName);
// Delete Sources/Materials/ — Unity creates it automatically but we use
// the root Materials/ folder instead, so this one is redundant
string sourceMaterialsPath = $"{folders.Sources}/Materials";
if (AssetDatabase.IsValidFolder(sourceMaterialsPath))
{
AssetDatabase.DeleteAsset(sourceMaterialsPath);
Debug.Log($"[FBXImporter] Deleted Sources/Materials/ (using root Materials/ instead)");
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
// Cleanup original source folder if provided and different from our Sources/
if (!string.IsNullOrEmpty(originalSourceFolder) &&
originalSourceFolder != folders.Sources &&
originalSourceFolder != folders.Root &&
AssetDatabase.IsValidFolder(originalSourceFolder))
{
AssetDatabase.DeleteAsset(originalSourceFolder);
Debug.Log($"[FBXImporter] Deleted original folder: {originalSourceFolder}");
}
Debug.Log($"[FBXImporter] ── Done: {assetName} ──");
}
@@ -121,7 +100,7 @@ namespace FBXImporter
importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription;
importer.materialLocation = ModelImporterMaterialLocation.External;
importer.materialName = ModelImporterMaterialName.BasedOnMaterialName;
importer.materialSearch = ModelImporterMaterialSearch.RecursiveUp;
importer.materialSearch = ModelImporterMaterialSearch.Local;
importer.animationType = animType;
if (!string.IsNullOrWhiteSpace(rootNode))
@@ -1,20 +1,29 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
namespace FBXImporter
{
public static class PrefabBuilder
{
/// <summary>
/// Creates a single prefab from the imported FBX root GameObject.
/// Adds a LODGroup automatically if _LOD0, _LOD1... meshes are found.
/// </summary>
public static void CreatePrefabs(GameObject fbxRoot, AssetFolders folders, string assetName)
{
CreateSinglePrefab(fbxRoot, folders.Prefabs, assetName);
}
public static GameObject CreatePrefab(GameObject fbxRoot, string prefabDir, string assetName)
{
if (fbxRoot == null) return null;
return CreateSinglePrefab(fbxRoot, prefabDir, assetName);
}
if (!AssetDatabase.IsValidFolder(prefabDir))
{
string parent = System.IO.Path.GetDirectoryName(prefabDir).Replace("\\", "/");
AssetDatabase.CreateFolder(parent, System.IO.Path.GetFileName(prefabDir));
}
static GameObject CreateSinglePrefab(GameObject fbxRoot, string prefabDir, string assetName)
{
EnsureFolder(prefabDir);
var instance = Object.Instantiate(fbxRoot);
instance.name = assetName;
@@ -68,5 +77,14 @@ namespace FBXImporter
if (idx < 0) return -1;
return int.TryParse(name.Substring(idx + 4), out int level) ? level : -1;
}
static void EnsureFolder(string path)
{
if (AssetDatabase.IsValidFolder(path)) return;
string parent = Path.GetDirectoryName(path).Replace("\\", "/");
string child = Path.GetFileName(path);
if (!AssetDatabase.IsValidFolder(parent)) EnsureFolder(parent);
AssetDatabase.CreateFolder(parent, child);
}
}
}
@@ -9,10 +9,34 @@ namespace FBXImporter
/// Persistent registry of FBX files seen by the importer.
/// Stores GUID + filename so the file is human-readable.
/// Format per line: "guid TAB filename.fbx"
/// Registry file is stored next to this script, wherever the plugin is installed.
/// </summary>
public static class ProcessedFBXRegistry
{
static readonly string RegistryPath = "Assets/Scripts/Editor/FBXImporter/processed_fbx.txt";
// Resolved dynamically so the registry follows the plugin wherever it's installed
static string _registryPath;
static string RegistryPath
{
get
{
if (_registryPath != null) return _registryPath;
var guids = AssetDatabase.FindAssets("ProcessedFBXRegistry t:Script");
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
if (path.Contains("FBXImporter"))
{
_registryPath = Path.GetDirectoryName(path).Replace("\\", "/") + "/processed_fbx.txt";
return _registryPath;
}
}
// Fallback — should never happen if plugin is properly installed
_registryPath = "Assets/processed_fbx.txt";
return _registryPath;
}
}
// guid → filename (for display)
static Dictionary<string, string> _registry;
@@ -28,7 +52,7 @@ namespace FBXImporter
return !string.IsNullOrEmpty(guid) && Registry.ContainsKey(guid);
}
public static void Register(IEnumerable<string> assetPaths)
public static void Register(System.Collections.Generic.IEnumerable<string> assetPaths)
{
bool changed = false;
foreach (var path in assetPaths)
@@ -95,8 +119,7 @@ namespace FBXImporter
var lines = Registry.Select(kvp => $"{kvp.Key}\t{kvp.Value}").ToArray();
File.WriteAllLines(RegistryPath, lines);
// Nullify cache so the next access reloads from disk.
// This prevents stale in-memory state after domain reloads.
// Nullify cache so the next access reloads from disk
_registry = null;
}
}
@@ -1,65 +0,0 @@
using UnityEditor;
using System.Collections.Generic;
namespace FBXImporter
{
public class FBXDropWatcher : AssetPostprocessor
{
static readonly List<string> _pendingNewFBX = new List<string>();
static bool _dialogScheduled = false;
bool ShouldWatch()
{
return assetPath.StartsWith("Assets/")
&& assetPath.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase)
&& !ProcessedFBXRegistry.IsRegistered(assetPath);
}
void OnPreprocessModel()
{
if (!ShouldWatch()) return;
var importer = assetImporter as ModelImporter;
importer.importCameras = false;
importer.importLights = false;
importer.importNormals = ModelImporterNormals.Import;
importer.importTangents = ModelImporterTangents.CalculateMikk;
importer.importBlendShapes = true;
importer.importVisibility = true;
importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription;
importer.materialLocation = ModelImporterMaterialLocation.External;
importer.materialName = ModelImporterMaterialName.BasedOnMaterialName;
importer.materialSearch = ModelImporterMaterialSearch.RecursiveUp;
importer.useFileScale = true;
importer.globalScale = 1f;
}
void OnPostprocessModel(UnityEngine.GameObject root)
{
if (!ShouldWatch()) return;
if (!_pendingNewFBX.Contains(assetPath))
_pendingNewFBX.Add(assetPath);
if (!_dialogScheduled)
{
_dialogScheduled = true;
EditorApplication.delayCall += ShowBatchDialog;
}
}
static void ShowBatchDialog()
{
_dialogScheduled = false;
if (_pendingNewFBX.Count == 0) return;
var batch = new List<string>(_pendingNewFBX);
_pendingNewFBX.Clear();
// Register all immediately — won't appear again regardless of user choice
ProcessedFBXRegistry.Register(batch);
FBXBatchDialog.Show(batch);
}
}
}
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 9b0ef00f525fdd4498665e9164696f58
@@ -27,7 +27,6 @@ namespace FBXImporter
void OnGUI()
{
minSize = new Vector2(450, 650);
GUILayout.Label("FBX Importer", EditorStyles.boldLabel);
EditorGUILayout.HelpBox(
"Select a .fbx in the Project panel.\n" +