From fee524fe19e522f667412cada082611d72626523 Mon Sep 17 00:00:00 2001 From: "Lillith Rose (Device: Lucia)" Date: Thu, 19 Jun 2025 12:09:40 -0400 Subject: [PATCH] Add NDMF Mesh Compression instead of hardcoding guids --- MeshCompression.meta | 8 ++ MeshCompression/Editor.meta | 8 ++ .../Editor/MeshCompressionEditor.asmdef | 20 ++++ .../Editor/MeshCompressionEditor.asmdef.meta | 7 ++ .../Editor/MeshCompressionPlugin.cs | 94 +++++++++++++++++++ .../Editor/MeshCompressionPlugin.cs.meta | 2 +- MeshCompression/Runtime.meta | 8 ++ MeshCompression/Runtime/MeshCompression.cs | 31 ++++++ .../Runtime/MeshCompression.cs.meta | 11 +++ .../Runtime/MeshCompressionRuntime.asmdef | 14 +++ .../MeshCompressionRuntime.asmdef.meta | 7 ++ PlatformMeshCompression.cs | 48 ---------- 12 files changed, 209 insertions(+), 49 deletions(-) create mode 100644 MeshCompression.meta create mode 100644 MeshCompression/Editor.meta create mode 100644 MeshCompression/Editor/MeshCompressionEditor.asmdef create mode 100644 MeshCompression/Editor/MeshCompressionEditor.asmdef.meta create mode 100644 MeshCompression/Editor/MeshCompressionPlugin.cs rename PlatformMeshCompression.cs.meta => MeshCompression/Editor/MeshCompressionPlugin.cs.meta (83%) create mode 100644 MeshCompression/Runtime.meta create mode 100644 MeshCompression/Runtime/MeshCompression.cs create mode 100644 MeshCompression/Runtime/MeshCompression.cs.meta create mode 100644 MeshCompression/Runtime/MeshCompressionRuntime.asmdef create mode 100644 MeshCompression/Runtime/MeshCompressionRuntime.asmdef.meta delete mode 100644 PlatformMeshCompression.cs diff --git a/MeshCompression.meta b/MeshCompression.meta new file mode 100644 index 0000000..dbd1d67 --- /dev/null +++ b/MeshCompression.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1bb9c70d80eb84342b345f18f6d0a4c8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MeshCompression/Editor.meta b/MeshCompression/Editor.meta new file mode 100644 index 0000000..69b3ec0 --- /dev/null +++ b/MeshCompression/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2b9a0244082348f4aa600e7977c4538c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MeshCompression/Editor/MeshCompressionEditor.asmdef b/MeshCompression/Editor/MeshCompressionEditor.asmdef new file mode 100644 index 0000000..b7c238b --- /dev/null +++ b/MeshCompression/Editor/MeshCompressionEditor.asmdef @@ -0,0 +1,20 @@ +{ + "name": "MeshCompressionEditor", + "rootNamespace": "", + "references": [ + "GUID:23e6cebda363f004aa6e529a95f8a6fc", + "GUID:62ced99b048af7f4d8dfe4bed8373d76", + "GUID:5718fb738711cd34ea54e9553040911d" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/MeshCompression/Editor/MeshCompressionEditor.asmdef.meta b/MeshCompression/Editor/MeshCompressionEditor.asmdef.meta new file mode 100644 index 0000000..034af70 --- /dev/null +++ b/MeshCompression/Editor/MeshCompressionEditor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e8cce0e980fea4544b91461e9f255a9e +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MeshCompression/Editor/MeshCompressionPlugin.cs b/MeshCompression/Editor/MeshCompressionPlugin.cs new file mode 100644 index 0000000..48e2cc6 --- /dev/null +++ b/MeshCompression/Editor/MeshCompressionPlugin.cs @@ -0,0 +1,94 @@ +using gay.lilyy.MeshCompression; +using nadena.dev.ndmf; +using UnityEditor; +using UnityEngine; + +[assembly: ExportsPlugin(typeof(MeshCompressionPlugin))] + +namespace gay.lilyy.MeshCompression +{ + public class MeshCompressionPlugin : Plugin + { + public override string DisplayName => "MeshCompression"; + public override string QualifiedName => "gay.lilyy.MeshCompression"; + + public static ModelImporterMeshCompression GetCompression(RuntimeModelImporterMeshCompression compression) + { + return compression switch + { + RuntimeModelImporterMeshCompression.Off => ModelImporterMeshCompression.Off, + RuntimeModelImporterMeshCompression.Low => ModelImporterMeshCompression.Low, + RuntimeModelImporterMeshCompression.Medium => ModelImporterMeshCompression.Medium, + RuntimeModelImporterMeshCompression.High => ModelImporterMeshCompression.High, + _ => ModelImporterMeshCompression.Off + }; + } + + protected override void Configure() + { + InPhase(BuildPhase.Optimizing) + .Run("Set Mesh Compression", ctx => + { + var defaultConfig = ctx.AvatarRootObject.GetComponent(); + var renderers = ctx.AvatarRootObject.GetComponentsInChildren(true); + + foreach (var renderer in renderers) + { + Mesh mesh = null; + + if (renderer is SkinnedMeshRenderer skinnedRenderer) + { + mesh = skinnedRenderer.sharedMesh; + } + else if (renderer is MeshRenderer meshRenderer) + { + var filter = meshRenderer.GetComponent(); + if (filter != null) + { + mesh = filter.sharedMesh; + } + } + + if (mesh == null) continue; + + var path = AssetDatabase.GetAssetPath(mesh); + if (string.IsNullOrEmpty(path) || !path.EndsWith(".fbx", System.StringComparison.OrdinalIgnoreCase)) + continue; + + var importer = AssetImporter.GetAtPath(path) as ModelImporter; + if (importer == null) continue; + + var localConfig = renderer.GetComponent(); + var effectiveConfig = localConfig != null ? localConfig : defaultConfig; + if (effectiveConfig == null) continue; + + var targetCompression = GetTargetCompression(effectiveConfig); + var unityCompression = GetCompression(targetCompression); + + if (importer.meshCompression != unityCompression) + { + importer.meshCompression = unityCompression; + importer.SaveAndReimport(); + Debug.Log($"[NDMF] Set mesh compression to {unityCompression} for {path}"); + } + else + { + Debug.Log($"[NDMF] Mesh compression already set to {unityCompression} for {path}"); + } + } + }); + } + + private static RuntimeModelImporterMeshCompression GetTargetCompression(MeshCompressionConfig settings) + { + var target = EditorUserBuildSettings.activeBuildTarget; + return target switch + { + BuildTarget.StandaloneWindows => settings.windowsCompression, + BuildTarget.StandaloneWindows64 => settings.windowsCompression, + BuildTarget.Android => settings.androidCompression, + _ => RuntimeModelImporterMeshCompression.Off + }; + } + } +} diff --git a/PlatformMeshCompression.cs.meta b/MeshCompression/Editor/MeshCompressionPlugin.cs.meta similarity index 83% rename from PlatformMeshCompression.cs.meta rename to MeshCompression/Editor/MeshCompressionPlugin.cs.meta index 9e0c4a4..913d872 100644 --- a/PlatformMeshCompression.cs.meta +++ b/MeshCompression/Editor/MeshCompressionPlugin.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b3c950d938135a142a8c4a2a25093d10 +guid: 49db9d5daf4107849999cae2dee12761 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/MeshCompression/Runtime.meta b/MeshCompression/Runtime.meta new file mode 100644 index 0000000..49f2cdc --- /dev/null +++ b/MeshCompression/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 74eb71d4a11c0b347ae6b1cea9e00824 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MeshCompression/Runtime/MeshCompression.cs b/MeshCompression/Runtime/MeshCompression.cs new file mode 100644 index 0000000..287075a --- /dev/null +++ b/MeshCompression/Runtime/MeshCompression.cs @@ -0,0 +1,31 @@ + +using UnityEngine; + +public enum RuntimeModelImporterMeshCompression +{ + // + // Summary: + // No mesh compression (default). + Off, + // + // Summary: + // Low amount of mesh compression. + Low, + // + // Summary: + // Medium amount of mesh compression. + Medium, + // + // Summary: + // High amount of mesh compression. + High +} +namespace gay.lilyy.MeshCompression +{ + public class MeshCompressionConfig : MonoBehaviour, VRC.SDKBase.IEditorOnly + { + public RuntimeModelImporterMeshCompression windowsCompression = RuntimeModelImporterMeshCompression.Off; + public RuntimeModelImporterMeshCompression androidCompression = RuntimeModelImporterMeshCompression.Medium; + + } +} \ No newline at end of file diff --git a/MeshCompression/Runtime/MeshCompression.cs.meta b/MeshCompression/Runtime/MeshCompression.cs.meta new file mode 100644 index 0000000..cd4ea7b --- /dev/null +++ b/MeshCompression/Runtime/MeshCompression.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e1f9481ca8d556f4da72ba66181e3b73 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MeshCompression/Runtime/MeshCompressionRuntime.asmdef b/MeshCompression/Runtime/MeshCompressionRuntime.asmdef new file mode 100644 index 0000000..8285fb5 --- /dev/null +++ b/MeshCompression/Runtime/MeshCompressionRuntime.asmdef @@ -0,0 +1,14 @@ +{ + "name": "MeshCompressionRuntime", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/MeshCompression/Runtime/MeshCompressionRuntime.asmdef.meta b/MeshCompression/Runtime/MeshCompressionRuntime.asmdef.meta new file mode 100644 index 0000000..8fdbc4a --- /dev/null +++ b/MeshCompression/Runtime/MeshCompressionRuntime.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 23e6cebda363f004aa6e529a95f8a6fc +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PlatformMeshCompression.cs b/PlatformMeshCompression.cs deleted file mode 100644 index 24b1545..0000000 --- a/PlatformMeshCompression.cs +++ /dev/null @@ -1,48 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; -using System.Collections.Generic; - -[InitializeOnLoad] -public class PlatformMeshCompression : AssetPostprocessor -{ - // Map GUIDs to compression settings: (PC, Android) - static readonly Dictionary compressionMap - = new Dictionary - { - { "e82fc872936dfa44a8653aab54da1bba", (ModelImporterMeshCompression.Off, ModelImporterMeshCompression.Medium) }, - }; - - static PlatformMeshCompression() - { - EditorApplication.delayCall += ReimportMappedAssets; - } - - static void ReimportMappedAssets() - { - foreach (var guid in compressionMap.Keys) - { - string path = AssetDatabase.GUIDToAssetPath(guid); - if (!string.IsNullOrEmpty(path)) - { - AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); - } - } - } - - void OnPreprocessModel() - { - var modelImporter = (ModelImporter)assetImporter; - string guid = AssetDatabase.AssetPathToGUID(assetPath); - - if (compressionMap.TryGetValue(guid, out var compressions)) - { -#if UNITY_ANDROID - modelImporter.meshCompression = compressions.android; -#else - modelImporter.meshCompression = compressions.pc; -#endif - } - } -} -#endif