Rework : FBX importer

This commit is contained in:
Ferlat Thibaud
2026-03-24 21:11:48 +01:00
parent b1c1b31354
commit 547ece7bd1
72 changed files with 536 additions and 13791 deletions
@@ -1,21 +1,2 @@
c06b2649582e3ff449d54d9931db8f9d f01584905fdd447489fd65c7e3c03a15 RobotHolo_5.fbx
8151b43ce05ee454d935c91f1c40f127 5aec27fd964155d41b84ae456ea4e99f RobotHolo5.fbx
a117ffd897689164e9b74b1b8b10f644
c1945069c65686a48a85348ceba705d4
42770493577c58b4ab7a2bcfe049da31
425b96800f54d9f4b8b57e40443920dd
b20e627ff4cf8ea4dbf4059c1c381d83
341f068d693d6a74e89cf4af6f1e58d8
d5d3540015d9b9542aed75c39ca4a71a
494656fe12e424d41ac58f589d42a152
7938ecb9a0326364db0c064473f84e82
c9052386b99a77d40937f48408e7673c
7afac586bb790e048b630dddec7e379e
8b3f002e29745db4294c0c97111df417
ab07a0ce3e1c9664bb55274b40fea140
cd786ffadc82e5a409e68f3750372636
be9f495fe888d0c4eaf53cc022b1eb64
5fd19d2221bd83b45bbf93526c6b203e
df955fddcea22c44ba108674c3613cf5
e09d33c54df432341807da486b52a9e4
5aec27fd964155d41b84ae456ea4e99f
@@ -198,7 +198,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: abd0f63a44b2272448eb41767c2ce44e, type: 3} m_Script: {fileID: 11500000, guid: abd0f63a44b2272448eb41767c2ce44e, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_choiceTextComponent: {fileID: 0} _choiceTextComponent: {fileID: 4616063974384180762}
_ghostTextComponent: {fileID: 0} _ghostTextComponent: {fileID: 0}
_focusLerpSpeed: 2 _focusLerpSpeed: 2
_colliderSizeMultiplier: 1.4 _colliderSizeMultiplier: 1.4
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 8a132f55b17c4344b9d44db14eb025bc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 2a8be0791ab101a40babb14ce63e2bd9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 78cdf2640e4904d43aa85f087794ded3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 0f05bd51823e6b24391d661fc80b9f5f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,139 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-2836397226836403046
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
version: 10
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: bot
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _EMISSION
- _METALLICSPECGLOSSMAP
m_InvalidKeywords: []
m_LightmapFlags: 2
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 2800000, guid: 88517fcbe8b304649a926ea69e917ede, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 2800000, guid: faf9866f5df1a8d47b6022b833f7ad86, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 88517fcbe8b304649a926ea69e917ede, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 2800000, guid: 2f37d44f239cf4342b1b3e5f507adea0, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 2800000, guid: 41a4dbf27816f8a4ba87b8ac56be1864, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 0210814bf293fce419b6c7e7a8845cd7
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,139 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: holo
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _EMISSION
- _OCCLUSIONMAP
m_InvalidKeywords: []
m_LightmapFlags: 2
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 2800000, guid: a812e13655cd1e74c81618e613ae66f5, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 2800000, guid: 174faaf95e0e3014b91de34582e08785, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: a812e13655cd1e74c81618e613ae66f5, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 2800000, guid: 709ed575fa8ce4343b2d2368e481334e, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
--- !u!114 &2035265382296632057
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
version: 10
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c7d7d2bc65c043d4e9f7c2bbcaeb7d00
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f8e0f779772d9fa478d4e06c5b364a3e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: b377e5ec68272df449d25e955fa4108f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: ce0b356c8a6508a43bfd2a703d1e6f39
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: cd8feab4cf017f946a702887398b73ed
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,139 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: bot
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 1
- _Glossiness: 0
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _UVSec: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 0.7353569, g: 0.7353569, b: 0.7353569, a: 1}
- _Color: {r: 0.7353569, g: 0.7353569, b: 0.7353569, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
--- !u!114 &3303473900455001232
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
version: 10
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 7f497ecc13c508c43ab32c2e162118a8
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,139 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-7952054674656876053
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
version: 10
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: holo1
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses:
- MOTIONVECTORS
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AddPrecomputedVelocity: 0
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 1
- _Glossiness: 0
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _UVSec: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 0.7353569, g: 0.7353569, b: 0.7353569, a: 1}
- _Color: {r: 0.7353569, g: 0.7353569, b: 0.7353569, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: af71842e32ec87d4b9738201ebbb6fc3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,110 +0,0 @@
fileFormatVersion: 2
guid: 5aec27fd964155d41b84ae456ea4e99f
ModelImporter:
serializedVersion: 24200
internalIDToNameTable: []
externalObjects: {}
materials:
materialImportMode: 2
materialName: 1
materialSearch: 1
materialLocation: 0
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
removeConstantScaleCurves: 0
motionNodeName:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
useSRGBMaterialColor: 1
sortHierarchyByName: 1
importPhysicalCameras: 1
importVisibility: 1
importBlendShapes: 1
importCameras: 0
importLights: 0
nodeNameCollisionStrategy: 1
fileIdsGeneration: 2
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
keepQuads: 0
weldVertices: 1
bakeAxisConversion: 0
preserveHierarchy: 0
skinWeightsMode: 0
maxBonesPerVertex: 4
minBoneWeight: 0.001
optimizeBones: 1
generateMeshLods: 0
meshLodGenerationFlags: 0
maximumMeshLod: -1
meshOptimizationFlags: -1
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVMarginMethod: 1
secondaryUVMinLightmapResolution: 40
secondaryUVMinObjectScale: 1
secondaryUVPackMargin: 4
useFileScale: 1
strictVertexDataChecks: 0
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
blendShapeNormalImportMode: 1
normalSmoothingSource: 0
referencedClips: []
importAnimation: 1
humanDescription:
serializedVersion: 3
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
globalScale: 1
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
autoGenerateAvatarMappingIfUnspecified: 1
animationType: 2
humanoidOversampling: 1
avatarSetup: 0
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
importBlendShapeDeformPercent: 1
remapMaterialsIfMaterialImportModeIsNone: 0
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f5d0edcd74b65d047828c2c997cf7a8d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

@@ -1,117 +0,0 @@
fileFormatVersion: 2
guid: 88517fcbe8b304649a926ea69e917ede
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

@@ -1,117 +0,0 @@
fileFormatVersion: 2
guid: faf9866f5df1a8d47b6022b833f7ad86
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

@@ -1,117 +0,0 @@
fileFormatVersion: 2
guid: 2f37d44f239cf4342b1b3e5f507adea0
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

@@ -1,117 +0,0 @@
fileFormatVersion: 2
guid: 41a4dbf27816f8a4ba87b8ac56be1864
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

@@ -1,117 +0,0 @@
fileFormatVersion: 2
guid: 709ed575fa8ce4343b2d2368e481334e
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

@@ -1,117 +0,0 @@
fileFormatVersion: 2
guid: a812e13655cd1e74c81618e613ae66f5
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

@@ -1,117 +0,0 @@
fileFormatVersion: 2
guid: 174faaf95e0e3014b91de34582e08785
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a58631a76acca5f408050a4bb8a8e459
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,8 +1,5 @@
namespace FBXImporter namespace FBXImporter
{ {
/// <summary>
/// Holds all resolved folder paths for a single imported asset.
/// </summary>
public class AssetFolders public class AssetFolders
{ {
public string Root { get; set; } public string Root { get; set; }
@@ -0,0 +1,23 @@
using UnityEditor;
namespace FBXImporter
{
/// <summary>
/// Automatically removes a FBX from the registry when it's deleted from the project.
/// This ensures deleted assets will show up again in the batch dialog if re-imported.
/// </summary>
public class FBXDeletionWatcher : UnityEditor.AssetModificationProcessor
{
static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions options)
{
if (path.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase)
&& ProcessedFBXRegistry.IsRegistered(path))
{
ProcessedFBXRegistry.Unregister(path);
}
// Always let Unity handle the actual deletion
return AssetDeleteResult.DidNotDelete;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 689b81497b9e3a444965cbdf9a0260a2
@@ -4,82 +4,64 @@ using System.IO;
namespace FBXImporter namespace FBXImporter
{ {
/// <summary>
/// Core processing logic. Called explicitly by the right-click menu or the Inspector window.
/// Never runs automatically — no AssetPostprocessor, no domain reload triggers.
/// </summary>
public static class FBXProcessor public static class FBXProcessor
{ {
/// <summary> /// <summary>
/// Full pipeline for a single FBX asset path: /// Full pipeline for a single FBX.
/// 1. Detect source (Blender / Maya) /// animationType: None=0, Legacy=1, Generic=2, Humanoid=3
/// 2. Configure ModelImporter settings
/// 3. Create folder structure
/// 4. Force reimport with new settings
/// 5. Connect PBR textures → create .mat files
/// 6. Generate prefab (with LODGroup if applicable)
/// </summary> /// </summary>
public static void Process(string fbxAssetPath) public static void Process(string fbxAssetPath,
ModelImporterAnimationType animationType = ModelImporterAnimationType.Generic,
string rootNode = "")
{ {
if (!fbxAssetPath.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase)) if (!fbxAssetPath.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase) ||
!fbxAssetPath.StartsWith("Assets/"))
{ {
Debug.LogWarning($"[FBXImporter] Not a FBX file: {fbxAssetPath}"); Debug.LogWarning($"[FBXImporter] Skipped: {fbxAssetPath}");
return; return;
} }
if (!fbxAssetPath.StartsWith("Assets/")) Debug.Log($"[FBXImporter] ── Processing {Path.GetFileName(fbxAssetPath)} ──");
{
Debug.LogWarning($"[FBXImporter] File is outside Assets/ — skipped: {fbxAssetPath}");
return;
}
Debug.Log($"[FBXImporter] ── Processing {Path.GetFileName(fbxAssetPath)} ──────────────");
// 1. Detect source
var source = FBXSourceDetector.Detect(fbxAssetPath); var source = FBXSourceDetector.Detect(fbxAssetPath);
Debug.Log($"[FBXImporter] Source detected: {source}");
// 2. Resolve / create folder structure
var folders = FolderSetup.Resolve(fbxAssetPath); var folders = FolderSetup.Resolve(fbxAssetPath);
FolderSetup.Create( FolderSetup.Create(
Path.GetDirectoryName(folders.Root), Path.GetDirectoryName(folders.Root),
Path.GetFileName(folders.Root), Path.GetFileName(folders.Root),
false // Animations folder only if user wants it — see dialog animationType != ModelImporterAnimationType.None
); );
folders = FolderSetup.Resolve(fbxAssetPath); // re-resolve after creation folders = FolderSetup.Resolve(fbxAssetPath);
// 3. Configure ModelImporter // Configure importer
var importer = AssetImporter.GetAtPath(fbxAssetPath) as ModelImporter; var importer = AssetImporter.GetAtPath(fbxAssetPath) as ModelImporter;
if (importer != null) if (importer != null)
{ {
ConfigureImporter(importer, source); ConfigureImporter(importer, source, animationType, rootNode);
importer.SaveAndReimport(); // force reimport with new settings importer.SaveAndReimport();
} }
// 4. Load the imported model
var fbxAsset = AssetDatabase.LoadAssetAtPath<GameObject>(fbxAssetPath); var fbxAsset = AssetDatabase.LoadAssetAtPath<GameObject>(fbxAssetPath);
if (fbxAsset == null) if (fbxAsset == null)
{ {
Debug.LogError($"[FBXImporter] Could not load FBX as GameObject: {fbxAssetPath}"); Debug.LogError($"[FBXImporter] Could not load: {fbxAssetPath}");
return; return;
} }
// 5. Connect PBR textures
ProcessMaterials(fbxAsset, folders, source); ProcessMaterials(fbxAsset, folders, source);
// 6. Create prefab
string assetName = Path.GetFileNameWithoutExtension(fbxAssetPath); string assetName = Path.GetFileNameWithoutExtension(fbxAssetPath);
PrefabBuilder.CreatePrefab(fbxAsset, folders.Prefabs, assetName); PrefabBuilder.CreatePrefab(fbxAsset, folders.Prefabs, assetName);
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
AssetDatabase.Refresh(); AssetDatabase.Refresh();
Debug.Log($"[FBXImporter] ── Done: {assetName} ──────────────────────────────────────"); Debug.Log($"[FBXImporter] ── Done: {assetName} ──");
} }
// ─── ModelImporter settings ─────────────────────────────────────────────── // ── Importer settings ─────────────────────────────────────────────────────
static void ConfigureImporter(ModelImporter importer, FBXSource source) static void ConfigureImporter(ModelImporter importer, FBXSource source,
ModelImporterAnimationType animType, string rootNode)
{ {
importer.importCameras = false; importer.importCameras = false;
importer.importLights = false; importer.importLights = false;
@@ -87,18 +69,21 @@ namespace FBXImporter
importer.importTangents = ModelImporterTangents.CalculateMikk; importer.importTangents = ModelImporterTangents.CalculateMikk;
importer.importBlendShapes = true; importer.importBlendShapes = true;
importer.importVisibility = true; importer.importVisibility = true;
importer.useFileScale = true;
importer.globalScale = 1f;
importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription; importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription;
importer.materialLocation = ModelImporterMaterialLocation.External; importer.materialLocation = ModelImporterMaterialLocation.External;
importer.materialName = ModelImporterMaterialName.BasedOnMaterialName; importer.materialName = ModelImporterMaterialName.BasedOnMaterialName;
importer.materialSearch = ModelImporterMaterialSearch.RecursiveUp; importer.materialSearch = ModelImporterMaterialSearch.RecursiveUp;
// Both Blender and Maya: let FBX unit metadata handle scale // Rig / animation settings
importer.useFileScale = true; importer.animationType = animType;
importer.globalScale = 1f; if (!string.IsNullOrWhiteSpace(rootNode))
importer.motionNodeName = rootNode;
} }
// ─── Material processing ────────────────────────────────────────────────── // ── Materials ─────────────────────────────────────────────────────────────
static void ProcessMaterials(GameObject root, AssetFolders folders, FBXSource source) static void ProcessMaterials(GameObject root, AssetFolders folders, FBXSource source)
{ {
@@ -149,7 +134,7 @@ namespace FBXImporter
static void ConnectPBRTextures(Material mat, string textureDir, string baseName) static void ConnectPBRTextures(Material mat, string textureDir, string baseName)
{ {
foreach (var slot in TextureMatcher.SlotSuffixes.Keys) foreach (var slot in TextureMatcher.SlotKeywords.Keys)
{ {
var tex = TextureMatcher.FindForSlot(textureDir, baseName, slot); var tex = TextureMatcher.FindForSlot(textureDir, baseName, slot);
if (tex == null) continue; if (tex == null) continue;
@@ -7,10 +7,6 @@ namespace FBXImporter
public static class FBXSourceDetector public static class FBXSourceDetector
{ {
/// <summary>
/// Detects whether a FBX was authored in Blender or Maya.
/// Priority: folder convention → binary header fallback.
/// </summary>
public static FBXSource Detect(string assetPath) public static FBXSource Detect(string assetPath)
{ {
if (assetPath.Contains("/BlenderAssets/")) return FBXSource.Blender; if (assetPath.Contains("/BlenderAssets/")) return FBXSource.Blender;
@@ -26,7 +22,6 @@ namespace FBXImporter
fs.Read(buffer, 0, buffer.Length); fs.Read(buffer, 0, buffer.Length);
string header = Encoding.ASCII.GetString(buffer); string header = Encoding.ASCII.GetString(buffer);
if (header.Contains("Blender")) return FBXSource.Blender; if (header.Contains("Blender")) return FBXSource.Blender;
if (header.Contains("Maya")) return FBXSource.Maya; if (header.Contains("Maya")) return FBXSource.Maya;
if (header.Contains("FBX SDK")) return FBXSource.Maya; if (header.Contains("FBX SDK")) return FBXSource.Maya;
@@ -7,31 +7,20 @@ namespace FBXImporter
{ {
static readonly string[] RequiredFolders = { "Sources", "Textures", "Materials", "Prefabs", "Audio", "VFX" }; static readonly string[] RequiredFolders = { "Sources", "Textures", "Materials", "Prefabs", "Audio", "VFX" };
/// <summary>
/// Creates the full folder structure under parentPath/assetName.
/// Safe to call multiple times — skips folders that already exist.
/// </summary>
public static AssetFolders Create(string parentPath, string assetName, bool withAnimations = false) public static AssetFolders Create(string parentPath, string assetName, bool withAnimations = false)
{ {
string root = $"{parentPath}/{assetName}"; string root = $"{parentPath}/{assetName}";
EnsureFolder(parentPath, assetName); EnsureFolder(parentPath, assetName);
foreach (var folder in RequiredFolders) foreach (var folder in RequiredFolders)
EnsureFolder(root, folder); EnsureFolder(root, folder);
string animPath = $"{root}/Animations"; string animPath = $"{root}/Animations";
if (withAnimations) if (withAnimations) EnsureFolder(root, "Animations");
EnsureFolder(root, "Animations");
AssetDatabase.Refresh(); AssetDatabase.Refresh();
return BuildFolders(root, withAnimations ? animPath : null); return BuildFolders(root, withAnimations ? animPath : null);
} }
/// <summary>
/// Resolves existing folder paths from a known FBX asset path.
/// If the FBX is inside Sources/, goes one level up to the root.
/// </summary>
public static AssetFolders Resolve(string fbxAssetPath) public static AssetFolders Resolve(string fbxAssetPath)
{ {
string dir = Path.GetDirectoryName(fbxAssetPath).Replace("\\", "/"); string dir = Path.GetDirectoryName(fbxAssetPath).Replace("\\", "/");
@@ -6,10 +6,6 @@ namespace FBXImporter
{ {
public static class PrefabBuilder public static class PrefabBuilder
{ {
/// <summary>
/// Creates a prefab from a loaded FBX GameObject.
/// Adds a LODGroup automatically if _LOD0, _LOD1... meshes are found.
/// </summary>
public static GameObject CreatePrefab(GameObject fbxRoot, string prefabDir, string assetName) public static GameObject CreatePrefab(GameObject fbxRoot, string prefabDir, string assetName)
{ {
if (fbxRoot == null) return null; if (fbxRoot == null) return null;
@@ -39,7 +35,6 @@ namespace FBXImporter
static bool TrySetupLODGroup(GameObject root) static bool TrySetupLODGroup(GameObject root)
{ {
var lodMap = new SortedDictionary<int, List<Renderer>>(); var lodMap = new SortedDictionary<int, List<Renderer>>();
foreach (var r in root.GetComponentsInChildren<Renderer>(true)) foreach (var r in root.GetComponentsInChildren<Renderer>(true))
{ {
int idx = ExtractLODIndex(r.gameObject.name.ToUpper()); int idx = ExtractLODIndex(r.gameObject.name.ToUpper());
@@ -57,13 +52,11 @@ namespace FBXImporter
float[] thresh = { 0.6f, 0.3f, 0.1f, 0.05f, 0.01f }; float[] thresh = { 0.6f, 0.3f, 0.1f, 0.05f, 0.01f };
var lods = new LOD[lodMap.Count]; var lods = new LOD[lodMap.Count];
int i = 0; int i = 0;
foreach (var kvp in lodMap) foreach (var kvp in lodMap)
{ {
lods[i] = new LOD(i < thresh.Length ? thresh[i] : 0.01f, kvp.Value.ToArray()); lods[i] = new LOD(i < thresh.Length ? thresh[i] : 0.01f, kvp.Value.ToArray());
i++; i++;
} }
group.SetLODs(lods); group.SetLODs(lods);
group.RecalculateBounds(); group.RecalculateBounds();
return true; return true;
@@ -0,0 +1,86 @@
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace FBXImporter
{
/// <summary>
/// Persistent registry of FBX files seen by the importer.
/// Stores GUID + filename so the file is human-readable.
/// Format per line: "guid filename.fbx"
/// </summary>
public static class ProcessedFBXRegistry
{
static readonly string RegistryPath = "Assets/Scripts/Editor/FBXImporter/processed_fbx.txt";
// guid → filename (for display)
static Dictionary<string, string> _registry;
static Dictionary<string, string> Registry
{
get { if (_registry == null) Load(); return _registry; }
}
public static bool IsRegistered(string assetPath)
{
string guid = AssetDatabase.AssetPathToGUID(assetPath);
return !string.IsNullOrEmpty(guid) && Registry.ContainsKey(guid);
}
public static void Register(IEnumerable<string> assetPaths)
{
bool changed = false;
foreach (var path in assetPaths)
{
string guid = AssetDatabase.AssetPathToGUID(path);
if (string.IsNullOrEmpty(guid)) continue;
if (!Registry.ContainsKey(guid))
{
Registry[guid] = Path.GetFileName(path);
changed = true;
}
}
if (changed) Save();
}
/// <summary>Removes a single FBX from the registry by asset path.</summary>
public static void Unregister(string assetPath)
{
string guid = AssetDatabase.AssetPathToGUID(assetPath);
if (!string.IsNullOrEmpty(guid) && Registry.Remove(guid))
{
Save();
UnityEngine.Debug.Log($"[FBXImporter] Removed from registry: {Path.GetFileName(assetPath)}");
}
}
// ── Persistence ───────────────────────────────────────────────────────────
static void Load()
{
_registry = new Dictionary<string, string>();
if (!File.Exists(RegistryPath)) return;
foreach (var line in File.ReadAllLines(RegistryPath))
{
string trimmed = line.Trim();
if (string.IsNullOrEmpty(trimmed)) continue;
// Format: "guid filename.fbx"
var parts = trimmed.Split(new[] { '\t', ' ' }, 2, System.StringSplitOptions.RemoveEmptyEntries);
if (parts.Length >= 1)
_registry[parts[0]] = parts.Length >= 2 ? parts[1] : "unknown";
}
}
static void Save()
{
string dir = Path.GetDirectoryName(RegistryPath);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
var lines = Registry.Select(kvp => $"{kvp.Key}\t{kvp.Value}").ToArray();
File.WriteAllLines(RegistryPath, lines);
}
}
}
@@ -0,0 +1,121 @@
using System.IO;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace FBXImporter
{
public static class TextureMatcher
{
static readonly string[] SupportedExtensions = { ".png", ".tga", ".jpg", ".jpeg", ".tiff", ".exr" };
/// <summary>
/// Maps shader slot → list of keywords.
/// Keywords are matched ANYWHERE in the filename (case-insensitive).
/// More specific keywords first to avoid false positives.
/// </summary>
public static readonly Dictionary<string, string[]> SlotKeywords = new Dictionary<string, string[]>
{
{ "_BaseMap", new[] { "albedo", "diffuse", "basecolor", "base_color", "color", "_D", "_d" } },
{ "_BumpMap", new[] { "normal", "nrm", "_N", "_n" } },
{ "_MetallicGlossMap", new[] { "metallic", "metal", "_M", "_m" } },
{ "_SpecGlossMap", new[] { "roughness", "rough", "_R", "_r" } },
{ "_OcclusionMap", new[] { "occlusion", "ambientocclusion", "_AO", "_ao" } },
{ "_EmissionMap", new[] { "emissive", "emission", "_E", "_e" } },
{ "_ParallaxMap", new[] { "height", "parallax", "opacity", "_H", "_h" } },
};
/// <summary>
/// Finds a texture in textureDir whose filename:
/// 1. Starts with baseName (links texture to the right material)
/// 2. Contains any known keyword for the given shader slot (case-insensitive)
/// Example: baseName="bot", slot="_BaseMap"
/// → matches bot_sg_albedo.jpg, bot_D.jpg, bot_color_v2.jpg
/// </summary>
public static Texture2D FindForSlot(string textureDir, string baseName, string shaderSlot)
{
if (!SlotKeywords.TryGetValue(shaderSlot, out string[] keywords))
return null;
if (!AssetDatabase.IsValidFolder(textureDir)) return null;
// Get all texture files in the directory
string[] guids = AssetDatabase.FindAssets("t:Texture2D", new[] { textureDir });
foreach (var guid in guids)
{
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
string filename = Path.GetFileNameWithoutExtension(assetPath).ToLower();
string ext = Path.GetExtension(assetPath).ToLower();
// Check extension is supported
bool validExt = false;
foreach (var e in SupportedExtensions)
if (ext == e) { validExt = true; break; }
if (!validExt) continue;
// Must start with baseName (case-insensitive)
if (!filename.StartsWith(baseName.ToLower())) continue;
// Must contain a keyword for this slot
foreach (var keyword in keywords)
{
if (filename.Contains(keyword.ToLower()))
{
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
if (tex == null) continue;
if (shaderSlot == "_BumpMap")
EnsureNormalMapType(assetPath);
return tex;
}
}
}
return null;
}
/// <summary>
/// Strips DCC-specific suffixes to recover the clean base name.
/// Maya : "hero_blinn1" → "hero" / "standardSurface1" → "Material"
/// </summary>
public static string CleanMaterialName(string rawName, FBXSource source)
{
string name = rawName;
if (source == FBXSource.Maya)
{
string[] mayaSuffixes = { "_blinn", "_phong", "_lambert", "_aiStandardSurface", "_standardSurface", "_SG" };
foreach (var s in mayaSuffixes)
{
int idx = name.ToLower().IndexOf(s.ToLower());
if (idx > 0) { name = name.Substring(0, idx); break; }
}
if (name.ToLower().StartsWith("standardsurface") ||
name.ToLower().StartsWith("lambert") ||
name.ToLower().StartsWith("phong") ||
name.ToLower().StartsWith("blinn"))
name = "Material";
name = System.Text.RegularExpressions.Regex.Replace(name, @"\d+$", "").TrimEnd('_');
}
foreach (var s in new[] { "_MAT", "_Mat", "_material", "_Material" })
if (name.EndsWith(s)) name = name.Substring(0, name.Length - s.Length);
return string.IsNullOrWhiteSpace(name) ? rawName : name;
}
static void EnsureNormalMapType(string assetPath)
{
var ti = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (ti != null && ti.textureType != TextureImporterType.NormalMap)
{
ti.textureType = TextureImporterType.NormalMap;
ti.SaveAndReimport();
}
}
}
}
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: b7a761cf384e2d143b6e8b9fafd6281e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,76 +0,0 @@
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace FBXImporter
{
/// <summary>
/// Persistent registry of FBX files that have already been seen by the importer.
/// Stores asset GUIDs in a text file so it survives domain reloads and Unity restarts.
///
/// A FBX is "registered" as soon as the user confirms the batch dialog —
/// regardless of whether they chose to process it or not.
/// This ensures the dialog never shows the same file twice.
/// </summary>
public static class ProcessedFBXRegistry
{
// Stored inside the plugin folder so it travels with the project
static readonly string RegistryPath = "Assets/Scripts/Editor/FBXImporter/processed_fbx.txt";
static HashSet<string> _guids;
static HashSet<string> Guids
{
get
{
if (_guids == null) Load();
return _guids;
}
}
/// <summary>Returns true if this FBX GUID has already been seen.</summary>
public static bool IsRegistered(string assetPath)
{
string guid = AssetDatabase.AssetPathToGUID(assetPath);
return !string.IsNullOrEmpty(guid) && Guids.Contains(guid);
}
/// <summary>Marks one or more FBX paths as seen and saves the registry.</summary>
public static void Register(IEnumerable<string> assetPaths)
{
bool changed = false;
foreach (var path in assetPaths)
{
string guid = AssetDatabase.AssetPathToGUID(path);
if (!string.IsNullOrEmpty(guid) && Guids.Add(guid))
changed = true;
}
if (changed) Save();
}
// ── Persistence ───────────────────────────────────────────────────────────
static void Load()
{
_guids = new HashSet<string>();
if (!File.Exists(RegistryPath)) return;
foreach (var line in File.ReadAllLines(RegistryPath))
{
string trimmed = line.Trim();
if (!string.IsNullOrEmpty(trimmed))
_guids.Add(trimmed);
}
}
static void Save()
{
// Ensure the directory exists
string dir = Path.GetDirectoryName(RegistryPath);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
File.WriteAllLines(RegistryPath, Guids.ToArray());
}
}
}
@@ -1,95 +0,0 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace FBXImporter
{
public static class TextureMatcher
{
static readonly string[] SupportedExtensions = { ".png", ".tga", ".jpg", ".jpeg", ".tiff", ".exr" };
public static readonly Dictionary<string, string[]> SlotSuffixes = new Dictionary<string, string[]>
{
{ "_BaseMap", new[] { "_D", "_d", "_Diffuse", "_diffuse", "_Albedo", "_albedo", "_Color", "_BaseColor" } },
{ "_BumpMap", new[] { "_N", "_n", "_Normal", "_normal", "_NRM", "_nrm" } },
{ "_MetallicGlossMap", new[] { "_M", "_m", "_Metallic", "_metallic" } },
{ "_SpecGlossMap", new[] { "_R", "_r", "_Roughness", "_roughness" } },
{ "_OcclusionMap", new[] { "_AO", "_ao", "_Occlusion", "_occlusion" } },
{ "_EmissionMap", new[] { "_E", "_e", "_Emission", "_emission" } },
{ "_ParallaxMap", new[] { "_H", "_h", "_Height", "_height" } },
};
public static Texture2D FindForSlot(string textureDir, string baseName, string shaderSlot)
{
if (!SlotSuffixes.TryGetValue(shaderSlot, out string[] suffixes))
return null;
foreach (var suffix in suffixes)
{
var tex = FindFile(textureDir, baseName, suffix);
if (tex == null) continue;
if (shaderSlot == "_BumpMap")
EnsureNormalMapType(AssetDatabase.GetAssetPath(tex));
return tex;
}
return null;
}
/// <summary>
/// Strips DCC-specific suffixes to recover the clean base name.
/// Maya : "hero_blinn1" → "hero" / "standardSurface1" → "Material"
/// Both : "tree_MAT" → "tree"
/// </summary>
public static string CleanMaterialName(string rawName, FBXSource source)
{
string name = rawName;
if (source == FBXSource.Maya)
{
string[] mayaSuffixes = { "_blinn", "_phong", "_lambert", "_aiStandardSurface", "_standardSurface", "_SG" };
foreach (var s in mayaSuffixes)
{
int idx = name.ToLower().IndexOf(s.ToLower());
if (idx > 0) { name = name.Substring(0, idx); break; }
}
// Handle names that ARE a maya default shader (e.g. "standardSurface1")
if (name.ToLower().StartsWith("standardsurface") ||
name.ToLower().StartsWith("lambert") ||
name.ToLower().StartsWith("phong") ||
name.ToLower().StartsWith("blinn"))
name = "Material";
name = System.Text.RegularExpressions.Regex.Replace(name, @"\d+$", "").TrimEnd('_');
}
foreach (var s in new[] { "_MAT", "_Mat", "_material", "_Material" })
if (name.EndsWith(s)) name = name.Substring(0, name.Length - s.Length);
return string.IsNullOrWhiteSpace(name) ? rawName : name;
}
static Texture2D FindFile(string dir, string baseName, string suffix)
{
foreach (var ext in SupportedExtensions)
{
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>($"{dir}/{baseName}{suffix}{ext}");
if (tex != null) return tex;
}
return null;
}
static void EnsureNormalMapType(string assetPath)
{
var ti = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (ti != null && ti.textureType != TextureImporterType.NormalMap)
{
ti.textureType = TextureImporterType.NormalMap;
ti.SaveAndReimport();
}
}
}
}
@@ -1,139 +0,0 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
namespace FBXImporter
{
/// <summary>
/// Batch dialog shown once after a drop that contains new FBX files.
/// Lists every new FBX with a toggle — user decides which ones to process.
/// All listed files are already registered so they won't appear again.
/// </summary>
public class FBXBatchDialog : EditorWindow
{
// ── Entry data ────────────────────────────────────────────────────────────
private class FBXEntry
{
public string Path;
public string Name;
public FBXSource Source;
public bool ShouldProcess = true; // checked by default
}
private List<FBXEntry> _entries = new List<FBXEntry>();
private Vector2 _scroll;
// ── Entry point ───────────────────────────────────────────────────────────
public static void Show(List<string> fbxPaths)
{
var window = GetWindow<FBXBatchDialog>(true, "FBX Importer — New Assets", true);
window.minSize = new Vector2(500, 300);
foreach (var path in fbxPaths)
{
window._entries.Add(new FBXEntry
{
Path = path,
Name = Path.GetFileName(path),
Source = FBXSourceDetector.Detect(path),
ShouldProcess = true,
});
}
window.ShowModal();
}
// ── GUI ───────────────────────────────────────────────────────────────────
void OnGUI()
{
GUILayout.Space(10);
GUILayout.Label($"{_entries.Count} new FBX detected", EditorStyles.boldLabel);
GUILayout.Label("All files are registered. Check which ones you want to process.",
EditorStyles.miniLabel);
GUILayout.Space(8);
// ── Header ────────────────────────────────────────────────────────────
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
{
GUILayout.Label("Process", GUILayout.Width(55));
GUILayout.Label("File", GUILayout.Width(220));
GUILayout.Label("Source", GUILayout.Width(70));
GUILayout.Label("Path", GUILayout.ExpandWidth(true));
}
// ── File list ─────────────────────────────────────────────────────────
_scroll = EditorGUILayout.BeginScrollView(_scroll, GUILayout.ExpandHeight(true));
foreach (var entry in _entries)
{
using (new EditorGUILayout.HorizontalScope())
{
entry.ShouldProcess = EditorGUILayout.Toggle(entry.ShouldProcess, GUILayout.Width(55));
var nameStyle = new GUIStyle(EditorStyles.label)
{ normal = { textColor = entry.ShouldProcess ? Color.white : Color.gray } };
GUILayout.Label(entry.Name, nameStyle, GUILayout.Width(220));
GUILayout.Label(entry.Source.ToString(), EditorStyles.miniLabel, GUILayout.Width(70));
GUILayout.Label(entry.Path, EditorStyles.miniLabel, GUILayout.ExpandWidth(true));
}
}
EditorGUILayout.EndScrollView();
// ── Select all / none ─────────────────────────────────────────────────
GUILayout.Space(4);
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("All", GUILayout.Width(60)))
_entries.ForEach(e => e.ShouldProcess = true);
if (GUILayout.Button("None", GUILayout.Width(60)))
_entries.ForEach(e => e.ShouldProcess = false);
}
GUILayout.Space(8);
// ── Action buttons ────────────────────────────────────────────────────
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (GUILayout.Button("Skip all", GUILayout.Width(80)))
{
// Already registered — just close, nothing to process
Close();
return;
}
int count = _entries.FindAll(e => e.ShouldProcess).Count;
string label = count > 0 ? $"Process {count} FBX" : "Process (none selected)";
using (new EditorGUI.DisabledScope(count == 0))
{
if (GUILayout.Button(label, GUILayout.Width(140)))
{
ProcessSelected();
Close();
}
}
}
GUILayout.Space(8);
}
// ── Processing ────────────────────────────────────────────────────────────
void ProcessSelected()
{
foreach (var entry in _entries)
{
if (!entry.ShouldProcess) continue;
// Open individual config dialog for each selected FBX
FBXImportDialog.Show(entry.Path, entry.Source);
}
}
}
}
@@ -1,118 +0,0 @@
using UnityEngine;
using UnityEditor;
using System.Linq;
namespace FBXImporter
{
/// <summary>
/// Adds a right-click context menu to FBX files in the Project panel.
/// This is the ONLY way to trigger the FBX import pipeline.
/// Nothing runs automatically — the user always initiates processing explicitly.
/// </summary>
public static class FBXContextMenu
{
// ── Single FBX ────────────────────────────────────────────────────────────
/// <summary>
/// Right-click a .fbx file → "FBX Importer / Process this FBX"
/// Runs the full pipeline: folders + settings + materials + prefab.
/// </summary>
[MenuItem("Assets/FBX Importer/Process this FBX", false, 1000)]
static void ProcessSingle()
{
foreach (var obj in Selection.objects)
{
string path = AssetDatabase.GetAssetPath(obj);
if (!path.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase))
{
Debug.LogWarning($"[FBXImporter] Skipped (not a FBX): {path}");
continue;
}
FBXProcessor.Process(path);
}
}
[MenuItem("Assets/FBX Importer/Process this FBX", true)]
static bool ProcessSingleValidate()
{
// Only show the menu item when at least one selected file is a .fbx
return Selection.objects.Any(o =>
AssetDatabase.GetAssetPath(o).EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase));
}
// ── Reconnect textures only (no reimport, no prefab) ─────────────────────
/// <summary>
/// Right-click a .fbx → "FBX Importer / Reconnect Textures Only"
/// Useful when you've added new textures to Textures/ after the first import.
/// </summary>
[MenuItem("Assets/FBX Importer/Reconnect Textures Only", false, 1001)]
static void ReconnectTextures()
{
foreach (var obj in Selection.objects)
{
string path = AssetDatabase.GetAssetPath(obj);
if (!path.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase)) continue;
var source = FBXSourceDetector.Detect(path);
var folders = FolderSetup.Resolve(path);
var fbxRoot = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (fbxRoot == null)
{
Debug.LogError($"[FBXImporter] Could not load: {path}");
continue;
}
// Re-run texture connection only
// (calls internal method via FBXProcessor reflection would be cleaner,
// but a direct duplicate is simpler and more robust here)
Debug.Log($"[FBXImporter] Reconnecting textures for {System.IO.Path.GetFileName(path)}");
FBXProcessor.Process(path); // Process handles idempotency — existing mats are reused
}
}
[MenuItem("Assets/FBX Importer/Reconnect Textures Only", true)]
static bool ReconnectTexturesValidate()
{
return Selection.objects.Any(o =>
AssetDatabase.GetAssetPath(o).EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase));
}
// ── Create folder structure only ──────────────────────────────────────────
/// <summary>
/// Right-click anywhere in the Project panel →
/// "FBX Importer / Create Asset Folder Structure"
/// Creates Sources/Textures/Materials/Prefabs/Audio/VFX under the selected folder.
/// </summary>
[MenuItem("Assets/FBX Importer/Create Asset Folder Structure", false, 1020)]
static void CreateFolderStructure()
{
string selectedPath = GetSelectedFolderPath();
if (string.IsNullOrEmpty(selectedPath))
{
Debug.LogWarning("[FBXImporter] Select a folder first.");
return;
}
string parent = System.IO.Path.GetDirectoryName(selectedPath).Replace("\\", "/");
string folderName = System.IO.Path.GetFileName(selectedPath);
FolderSetup.Create(parent, folderName, false);
Debug.Log($"[FBXImporter] Folder structure created under: {selectedPath}");
}
[MenuItem("Assets/FBX Importer/Create Asset Folder Structure", true)]
static bool CreateFolderStructureValidate() => !string.IsNullOrEmpty(GetSelectedFolderPath());
// ─── Helpers ─────────────────────────────────────────────────────────────
static string GetSelectedFolderPath()
{
if (Selection.activeObject == null) return null;
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
return AssetDatabase.IsValidFolder(path) ? path : null;
}
}
}
@@ -0,0 +1,106 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
namespace FBXImporter
{
public class FBXBatchDialog : EditorWindow
{
private class FBXEntry
{
public string Path;
public string Name;
public FBXSource Source;
public bool ShouldProcess = true;
}
private List<FBXEntry> _entries = new List<FBXEntry>();
private Vector2 _scroll;
public static void Show(List<string> fbxPaths)
{
var window = GetWindow<FBXBatchDialog>(true, "FBX Importer — New Assets", true);
window.minSize = new Vector2(520, 320);
foreach (var path in fbxPaths)
window._entries.Add(new FBXEntry {
Path = path,
Name = Path.GetFileName(path),
Source = FBXSourceDetector.Detect(path),
ShouldProcess = true,
});
window.ShowModal();
}
void OnGUI()
{
GUILayout.Space(10);
GUILayout.Label($"{_entries.Count} new FBX detected", EditorStyles.boldLabel);
GUILayout.Label("All files are registered. Check which ones to process.", EditorStyles.miniLabel);
GUILayout.Space(8);
// Header
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
{
GUILayout.Label("Process", GUILayout.Width(55));
GUILayout.Label("File", GUILayout.Width(200));
GUILayout.Label("Source", GUILayout.Width(70));
GUILayout.Label("Path", GUILayout.ExpandWidth(true));
}
// List
_scroll = EditorGUILayout.BeginScrollView(_scroll, GUILayout.ExpandHeight(true));
foreach (var entry in _entries)
{
using (new EditorGUILayout.HorizontalScope())
{
entry.ShouldProcess = EditorGUILayout.Toggle(entry.ShouldProcess, GUILayout.Width(55));
var style = new GUIStyle(EditorStyles.label)
{ normal = { textColor = entry.ShouldProcess ? Color.white : Color.gray } };
GUILayout.Label(entry.Name, style, GUILayout.Width(200));
GUILayout.Label(entry.Source.ToString(), EditorStyles.miniLabel, GUILayout.Width(70));
GUILayout.Label(entry.Path, EditorStyles.miniLabel, GUILayout.ExpandWidth(true));
}
}
EditorGUILayout.EndScrollView();
// Select all / none
GUILayout.Space(4);
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("All", GUILayout.Width(60))) _entries.ForEach(e => e.ShouldProcess = true);
if (GUILayout.Button("None", GUILayout.Width(60))) _entries.ForEach(e => e.ShouldProcess = false);
}
GUILayout.Space(8);
// Actions
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (GUILayout.Button("Skip all", GUILayout.Width(80)))
{ Close(); return; }
int count = _entries.FindAll(e => e.ShouldProcess).Count;
using (new EditorGUI.DisabledScope(count == 0))
{
if (GUILayout.Button($"Process {count} FBX", GUILayout.Width(130)))
{ ProcessSelected(); Close(); }
}
}
GUILayout.Space(8);
}
void ProcessSelected()
{
foreach (var entry in _entries)
{
if (!entry.ShouldProcess) continue;
FBXImportDialog.Show(entry.Path, entry.Source);
}
}
}
}
@@ -0,0 +1,61 @@
using UnityEditor;
using System.Linq;
namespace FBXImporter
{
public static class FBXContextMenu
{
[MenuItem("Assets/FBX Importer/Process this FBX", false, 1000)]
static void ProcessSingle()
{
foreach (var obj in Selection.objects)
{
string path = AssetDatabase.GetAssetPath(obj);
if (!path.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase)) continue;
var source = FBXSourceDetector.Detect(path);
FBXImportDialog.Show(path, source);
}
}
[MenuItem("Assets/FBX Importer/Process this FBX", true)]
static bool ProcessSingleValidate() =>
Selection.objects.Any(o => AssetDatabase.GetAssetPath(o)
.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase));
[MenuItem("Assets/FBX Importer/Remove from registry", false, 1001)]
static void RemoveFromRegistry()
{
foreach (var obj in Selection.objects)
{
string path = AssetDatabase.GetAssetPath(obj);
if (path.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase))
ProcessedFBXRegistry.Unregister(path);
}
}
[MenuItem("Assets/FBX Importer/Remove from registry", true)]
static bool RemoveFromRegistryValidate() =>
Selection.objects.Any(o => AssetDatabase.GetAssetPath(o)
.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase));
[MenuItem("Assets/FBX Importer/Create Asset Folder Structure", false, 1020)]
static void CreateFolderStructure()
{
string selectedPath = GetSelectedFolderPath();
if (string.IsNullOrEmpty(selectedPath)) return;
string parent = System.IO.Path.GetDirectoryName(selectedPath).Replace("\\", "/");
FolderSetup.Create(parent, System.IO.Path.GetFileName(selectedPath), false);
}
[MenuItem("Assets/FBX Importer/Create Asset Folder Structure", true)]
static bool CreateFolderStructureValidate() => !string.IsNullOrEmpty(GetSelectedFolderPath());
static string GetSelectedFolderPath()
{
if (Selection.activeObject == null) return null;
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
return AssetDatabase.IsValidFolder(path) ? path : null;
}
}
}
@@ -3,29 +3,11 @@ using System.Collections.Generic;
namespace FBXImporter namespace FBXImporter
{ {
/// <summary>
/// Watches for FBX files imported into Assets/.
/// Collects all NEW files across the entire import batch, then shows
/// a single dialog listing them all — user decides which ones to process.
///
/// "New" means: not in ProcessedFBXRegistry (GUID-based, persistent).
/// All files shown in the dialog are registered immediately so they
/// never appear again, regardless of whether the user chose to process them.
///
/// SAFETY:
/// - Hard blocked on anything outside Assets/
/// - No asset DB writes during import hooks
/// - Dialog + processing deferred via EditorApplication.delayCall
/// </summary>
public class FBXDropWatcher : AssetPostprocessor public class FBXDropWatcher : AssetPostprocessor
{ {
// Accumulates new FBX paths across the current import batch.
// Static so all postprocessor instances share the same list.
static readonly List<string> _pendingNewFBX = new List<string>(); static readonly List<string> _pendingNewFBX = new List<string>();
static bool _dialogScheduled = false; static bool _dialogScheduled = false;
// ── Guard ─────────────────────────────────────────────────────────────────
bool ShouldWatch() bool ShouldWatch()
{ {
return assetPath.StartsWith("Assets/") return assetPath.StartsWith("Assets/")
@@ -33,27 +15,21 @@ namespace FBXImporter
&& !ProcessedFBXRegistry.IsRegistered(assetPath); && !ProcessedFBXRegistry.IsRegistered(assetPath);
} }
// ── Import hooks ──────────────────────────────────────────────────────────
void OnPreprocessModel() void OnPreprocessModel()
{ {
if (!ShouldWatch()) return; if (!ShouldWatch()) return;
// Configure ModelImporter settings only — no asset DB writes here
var importer = assetImporter as ModelImporter; var importer = assetImporter as ModelImporter;
importer.importCameras = false; importer.importCameras = false;
importer.importLights = false; importer.importLights = false;
importer.importNormals = ModelImporterNormals.Import; importer.importNormals = ModelImporterNormals.Import;
importer.importTangents = ModelImporterTangents.CalculateMikk; importer.importTangents = ModelImporterTangents.CalculateMikk;
importer.importBlendShapes = true; importer.importBlendShapes = true;
importer.importVisibility = true; importer.importVisibility = true;
importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription; importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription;
importer.materialLocation = ModelImporterMaterialLocation.External; importer.materialLocation = ModelImporterMaterialLocation.External;
importer.materialName = ModelImporterMaterialName.BasedOnMaterialName; importer.materialName = ModelImporterMaterialName.BasedOnMaterialName;
importer.materialSearch = ModelImporterMaterialSearch.RecursiveUp; importer.materialSearch = ModelImporterMaterialSearch.RecursiveUp;
importer.useFileScale = true; importer.useFileScale = true;
importer.globalScale = 1f; importer.globalScale = 1f;
} }
@@ -62,11 +38,9 @@ namespace FBXImporter
{ {
if (!ShouldWatch()) return; if (!ShouldWatch()) return;
// Add to the pending batch
if (!_pendingNewFBX.Contains(assetPath)) if (!_pendingNewFBX.Contains(assetPath))
_pendingNewFBX.Add(assetPath); _pendingNewFBX.Add(assetPath);
// Schedule ONE dialog for the whole batch (deduped with the flag)
if (!_dialogScheduled) if (!_dialogScheduled)
{ {
_dialogScheduled = true; _dialogScheduled = true;
@@ -74,22 +48,17 @@ namespace FBXImporter
} }
} }
// ── Batch dialog ──────────────────────────────────────────────────────────
static void ShowBatchDialog() static void ShowBatchDialog()
{ {
_dialogScheduled = false; _dialogScheduled = false;
if (_pendingNewFBX.Count == 0) return; if (_pendingNewFBX.Count == 0) return;
// Snapshot and clear before opening the dialog
var batch = new List<string>(_pendingNewFBX); var batch = new List<string>(_pendingNewFBX);
_pendingNewFBX.Clear(); _pendingNewFBX.Clear();
// Register ALL files immediately — they won't appear again // Register all immediately — won't appear again regardless of user choice
ProcessedFBXRegistry.Register(batch); ProcessedFBXRegistry.Register(batch);
// Open the batch dialog
FBXBatchDialog.Show(batch); FBXBatchDialog.Show(batch);
} }
} }
@@ -5,8 +5,7 @@ using System.IO;
namespace FBXImporter namespace FBXImporter
{ {
/// <summary> /// <summary>
/// Per-asset config dialog opened after the batch dialog for each selected FBX. /// Per-asset config dialog — name, destination, rig type.
/// User sets the asset name and destination folder, then confirms.
/// </summary> /// </summary>
public class FBXImportDialog : EditorWindow public class FBXImportDialog : EditorWindow
{ {
@@ -17,11 +16,24 @@ namespace FBXImporter
private bool _createAnims = false; private bool _createAnims = false;
private string _errorMessage = ""; private string _errorMessage = "";
// Rig settings
private ModelImporterAnimationType _animType = ModelImporterAnimationType.Generic;
private string _rootNode = "";
static readonly string[] AnimTypeLabels = { "None", "Legacy", "Generic", "Humanoid" };
static readonly ModelImporterAnimationType[] AnimTypeValues =
{
ModelImporterAnimationType.None,
ModelImporterAnimationType.Legacy,
ModelImporterAnimationType.Generic,
ModelImporterAnimationType.Human,
};
public static void Show(string fbxAssetPath, FBXSource source) public static void Show(string fbxAssetPath, FBXSource source)
{ {
var window = GetWindow<FBXImportDialog>(true, $"Configure — {Path.GetFileName(fbxAssetPath)}", true); var window = GetWindow<FBXImportDialog>(true, $"Configure — {Path.GetFileName(fbxAssetPath)}", true);
window.minSize = new Vector2(440, 260); window.minSize = new Vector2(460, 360);
window.maxSize = new Vector2(440, 260); window.maxSize = new Vector2(460, 360);
window._fbxSourcePath = fbxAssetPath; window._fbxSourcePath = fbxAssetPath;
window._detectedSource = source; window._detectedSource = source;
window._assetName = Path.GetFileNameWithoutExtension(fbxAssetPath); window._assetName = Path.GetFileNameWithoutExtension(fbxAssetPath);
@@ -39,10 +51,12 @@ namespace FBXImporter
DrawRow("Source", _detectedSource.ToString()); DrawRow("Source", _detectedSource.ToString());
GUILayout.Space(10); GUILayout.Space(10);
// Asset name
GUILayout.Label("Asset Name", EditorStyles.miniBoldLabel); GUILayout.Label("Asset Name", EditorStyles.miniBoldLabel);
_assetName = EditorGUILayout.TextField(_assetName); _assetName = EditorGUILayout.TextField(_assetName);
GUILayout.Space(6); GUILayout.Space(6);
// Destination
GUILayout.Label("Destination Folder", EditorStyles.miniBoldLabel); GUILayout.Label("Destination Folder", EditorStyles.miniBoldLabel);
using (new EditorGUILayout.HorizontalScope()) using (new EditorGUILayout.HorizontalScope())
{ {
@@ -59,10 +73,30 @@ namespace FBXImporter
} }
} }
} }
EditorGUILayout.LabelField($"→ {_destinationPath}/{_assetName}", EditorStyles.miniLabel); EditorGUILayout.LabelField($"→ {_destinationPath}/{_assetName}", EditorStyles.miniLabel);
GUILayout.Space(6); GUILayout.Space(8);
// Rig / animation type
GUILayout.Label("Rig & Animation", EditorStyles.miniBoldLabel);
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label("Animation Type", GUILayout.Width(120));
int current = System.Array.IndexOf(AnimTypeValues, _animType);
int selected = GUILayout.SelectionGrid(current, AnimTypeLabels, 4);
_animType = AnimTypeValues[selected];
}
if (_animType != ModelImporterAnimationType.None)
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label("Root Node (opt.)", GUILayout.Width(120));
_rootNode = EditorGUILayout.TextField(_rootNode);
}
_createAnims = true; // auto-enable Animations/ folder if rig is set
}
GUILayout.Space(6);
_createAnims = EditorGUILayout.ToggleLeft("Create Animations/ folder", _createAnims); _createAnims = EditorGUILayout.ToggleLeft("Create Animations/ folder", _createAnims);
GUILayout.Space(8); GUILayout.Space(8);
@@ -72,27 +106,21 @@ namespace FBXImporter
GUILayout.Space(4); GUILayout.Space(4);
} }
// Buttons
using (new EditorGUILayout.HorizontalScope()) using (new EditorGUILayout.HorizontalScope())
{ {
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
if (GUILayout.Button("Skip", GUILayout.Width(70))) if (GUILayout.Button("Skip", GUILayout.Width(70)))
{ { Close(); return; }
Debug.Log($"[FBXImporter] Skipped config for: {_fbxSourcePath}");
Close();
return;
}
bool valid = !string.IsNullOrWhiteSpace(_assetName) bool valid = !string.IsNullOrWhiteSpace(_assetName)
&& AssetDatabase.IsValidFolder(_destinationPath); && (!string.IsNullOrWhiteSpace(_destinationPath));
using (new EditorGUI.DisabledScope(!valid)) using (new EditorGUI.DisabledScope(!valid))
{ {
if (GUILayout.Button("Create & Import", GUILayout.Width(120))) if (GUILayout.Button("Create & Import", GUILayout.Width(120)))
{ { Confirm(); Close(); }
Confirm();
Close();
}
} }
} }
} }
@@ -112,7 +140,7 @@ namespace FBXImporter
} }
} }
FBXProcessor.Process(targetFBX); FBXProcessor.Process(targetFBX, _animType, _rootNode);
var rootObj = AssetDatabase.LoadAssetAtPath<Object>(folders.Root); var rootObj = AssetDatabase.LoadAssetAtPath<Object>(folders.Root);
if (rootObj != null) EditorGUIUtility.PingObject(rootObj); if (rootObj != null) EditorGUIUtility.PingObject(rootObj);
@@ -4,10 +4,6 @@ using System.IO;
namespace FBXImporter namespace FBXImporter
{ {
/// <summary>
/// Editor utility window — Window > FBX Importer > Inspector
/// Inspect any FBX and trigger processing manually.
/// </summary>
public class FBXImporterWindow : EditorWindow public class FBXImporterWindow : EditorWindow
{ {
private Object _selectedFBX; private Object _selectedFBX;
@@ -18,16 +14,15 @@ namespace FBXImporter
void OnGUI() void OnGUI()
{ {
GUILayout.Label("FBX Importer — Manual Pipeline", EditorStyles.boldLabel); GUILayout.Label("FBX Importer", EditorStyles.boldLabel);
EditorGUILayout.HelpBox( EditorGUILayout.HelpBox(
"Drop a FBX here or select one in the Project panel.\n" + "Select a .fbx in the Project panel or drag it here.\n" +
"Nothing runs automatically — you trigger processing explicitly.", "Processing is always manual — nothing runs automatically.",
MessageType.Info); MessageType.Info);
EditorGUILayout.Space(6); GUILayout.Space(6);
_selectedFBX = EditorGUILayout.ObjectField("FBX Asset", _selectedFBX, typeof(Object), false); _selectedFBX = EditorGUILayout.ObjectField("FBX Asset", _selectedFBX, typeof(Object), false);
// Auto-fill from Project panel selection
if (_selectedFBX == null && Selection.activeObject != null) if (_selectedFBX == null && Selection.activeObject != null)
{ {
string sel = AssetDatabase.GetAssetPath(Selection.activeObject); string sel = AssetDatabase.GetAssetPath(Selection.activeObject);
@@ -40,7 +35,7 @@ namespace FBXImporter
string path = AssetDatabase.GetAssetPath(_selectedFBX); string path = AssetDatabase.GetAssetPath(_selectedFBX);
if (!path.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase)) if (!path.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase))
{ {
EditorGUILayout.HelpBox("Selected asset is not a .fbx file.", MessageType.Warning); EditorGUILayout.HelpBox("Not a .fbx file.", MessageType.Warning);
return; return;
} }
@@ -53,34 +48,33 @@ namespace FBXImporter
var source = FBXSourceDetector.Detect(assetPath); var source = FBXSourceDetector.Detect(assetPath);
var folders = FolderSetup.Resolve(assetPath); var folders = FolderSetup.Resolve(assetPath);
bool registered = ProcessedFBXRegistry.IsRegistered(assetPath);
string clean = TextureMatcher.CleanMaterialName( string clean = TextureMatcher.CleanMaterialName(
Path.GetFileNameWithoutExtension(assetPath), source); Path.GetFileNameWithoutExtension(assetPath), source);
// ── Info ───────────────────────────────────────────────────────────── // Info
GUILayout.Label("Detection", EditorStyles.boldLabel); GUILayout.Label("Detection", EditorStyles.boldLabel);
DrawRow("Source", source.ToString(), DrawRow("Source", source.ToString(),
source != FBXSource.Unknown ? Color.green : Color.yellow); source != FBXSource.Unknown ? Color.green : Color.yellow);
DrawRow("Registered", registered ? "Yes — won't appear in batch dialog" : "No — will appear on next drop",
registered ? Color.green : Color.yellow);
DrawRow("Textures/", folders.Textures, DrawRow("Textures/", folders.Textures,
AssetDatabase.IsValidFolder(folders.Textures) ? Color.green : Color.red); AssetDatabase.IsValidFolder(folders.Textures) ? Color.green : Color.red);
DrawRow("Materials/", folders.Materials, DrawRow("Materials/", folders.Materials,
AssetDatabase.IsValidFolder(folders.Materials) ? Color.green : Color.yellow); AssetDatabase.IsValidFolder(folders.Materials) ? Color.green : Color.yellow);
DrawRow("Prefabs/", folders.Prefabs,
AssetDatabase.IsValidFolder(folders.Prefabs) ? Color.green : Color.yellow);
// ── Texture preview ─────────────────────────────────────────────────── // Texture preview
EditorGUILayout.Space(8); EditorGUILayout.Space(8);
GUILayout.Label("Texture Slot Preview", EditorStyles.boldLabel); GUILayout.Label("Texture Slot Preview", EditorStyles.boldLabel);
_scroll = EditorGUILayout.BeginScrollView(_scroll, GUILayout.Height(150)); _scroll = EditorGUILayout.BeginScrollView(_scroll, GUILayout.Height(150));
foreach (var kvp in TextureMatcher.SlotSuffixes) foreach (var kvp in TextureMatcher.SlotKeywords)
{ {
var tex = TextureMatcher.FindForSlot(folders.Textures, clean, kvp.Key); var tex = TextureMatcher.FindForSlot(folders.Textures, clean, kvp.Key);
bool found = tex != null; bool found = tex != null;
using (new EditorGUILayout.HorizontalScope()) using (new EditorGUILayout.HorizontalScope())
{ {
var style = new GUIStyle(EditorStyles.label) var style = new GUIStyle(EditorStyles.label)
{ normal = { textColor = found ? new Color(0.4f, 1f, 0.4f) : new Color(0.6f, 0.6f, 0.6f) } }; { normal = { textColor = found ? new Color(0.4f, 1f, 0.4f) : new Color(0.5f, 0.5f, 0.5f) } };
GUILayout.Label(found ? "✓" : "○", style, GUILayout.Width(16)); GUILayout.Label(found ? "✓" : "○", style, GUILayout.Width(16));
GUILayout.Label(kvp.Key, GUILayout.Width(170)); GUILayout.Label(kvp.Key, GUILayout.Width(170));
GUILayout.Label(found ? tex.name : "–", EditorStyles.miniLabel); GUILayout.Label(found ? tex.name : "–", EditorStyles.miniLabel);
@@ -88,23 +82,26 @@ namespace FBXImporter
} }
EditorGUILayout.EndScrollView(); EditorGUILayout.EndScrollView();
// ── Actions ─────────────────────────────────────────────────────────── // Actions
EditorGUILayout.Space(8); EditorGUILayout.Space(8);
GUILayout.Label("Actions", EditorStyles.boldLabel); GUILayout.Label("Actions", EditorStyles.boldLabel);
var bigButton = GUILayout.Height(30); if (GUILayout.Button("▶ Process this FBX (full pipeline)", GUILayout.Height(28)))
{
var src = FBXSourceDetector.Detect(assetPath);
FBXImportDialog.Show(assetPath, src);
}
if (GUILayout.Button("▶ Process this FBX (full pipeline)", bigButton)) EditorGUILayout.Space(2);
FBXProcessor.Process(assetPath);
EditorGUILayout.Space(4); if (GUILayout.Button("🗑 Remove from registry (will reappear on next drop)"))
ProcessedFBXRegistry.Unregister(assetPath);
if (GUILayout.Button("📁 Create folder structure only")) if (GUILayout.Button("📁 Create missing folders"))
{ {
FolderSetup.Create( FolderSetup.Create(
Path.GetDirectoryName(folders.Root), Path.GetDirectoryName(folders.Root),
Path.GetFileName(folders.Root), Path.GetFileName(folders.Root), false);
false);
} }
if (GUILayout.Button("🔍 Ping in Project panel")) if (GUILayout.Button("🔍 Ping in Project panel"))
@@ -1,32 +1,33 @@
# FBX Importer v5 # FBX Importer v6
## Nouveautés vs v5
- Nomenclature intelligente : reconnait les mots-clés n'importe où dans le nom de fichier
- Config rig dans le dialog : None / Legacy / Generic / Humanoid + Root Node
- Suppression auto du registry quand tu supprimes un FBX
- Bouton "Remove from registry" dans l'Inspector et clic droit
## Flow ## Flow
1. Drop un dossier avec FBX → batch dialog
2. Coche ceux à traiter
3. Pour chacun : nom + destination + type de rig
4. Pipeline complet : dossiers / materials / prefab
1. Tu glisses un dossier avec FBX dans Unity ## Nomenclature textures
2. Une seule pop up liste TOUS les nouveaux FBX Le plugin reconnait les mots-clés n'importe où dans le nom :
3. Tu coches ceux que tu veux traiter bot_sg_albedo.jpg → BaseMap (contient "albedo")
4. Pour chacun → dialog de config (nom + destination) bot_sg_roughness → Roughness (contient "roughness")
5. Pipeline complet : dossiers / materials / prefab holo_sg_emissive → Emission (contient "emissive")
## "Nouveau" = jamais vu par le plugin Mots-clés reconnus :
Les GUIDs sont stockés dans processed_fbx.txt. BaseMap : albedo, diffuse, basecolor, color, _D
Un FBX vu une fois (même si skip) ne repasse plus jamais. Normal : normal, nrm, _N
Metallic : metallic, metal, _M
Roughness : roughness, rough, _R
AO : occlusion, ambientocclusion, _AO
Emission : emissive, emission, _E
Height : height, parallax, opacity, _H
## Reset un FBX ## Registry
Clic droit → FBX Importer → Reset (remove from registry) processed_fbx.txt — liste GUID + nom de fichier
Ou supprime son GUID dans processed_fbx.txt Suppression FBX → retiré automatiquement
Clic droit → "Remove from registry" → réapparaît au prochain drop
## Process manuel
Clic droit sur un .fbx → FBX Importer → Process this FBX
## Structure attendue
AssetName/
├── Sources/ ← FBX
├── Textures/ ← PNG/TGA
├── Materials/ ← auto
├── Prefabs/ ← auto
├── Audio/ ← auto vide
└── VFX/ ← auto vide
## Texture naming
_D / _N / _R / _M / _AO / _E / _H