Add NDMF Mesh Compression instead of hardcoding guids

This commit is contained in:
Lillith Rose (Device: Lucia) 2025-06-19 12:09:40 -04:00
parent 18a72e2fda
commit fee524fe19
12 changed files with 209 additions and 49 deletions

8
MeshCompression.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1bb9c70d80eb84342b345f18f6d0a4c8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2b9a0244082348f4aa600e7977c4538c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e8cce0e980fea4544b91461e9f255a9e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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<MeshCompressionPlugin>
{
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<MeshCompressionConfig>();
var renderers = ctx.AvatarRootObject.GetComponentsInChildren<Renderer>(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<MeshFilter>();
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<MeshCompressionConfig>();
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
};
}
}
}

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: b3c950d938135a142a8c4a2a25093d10
guid: 49db9d5daf4107849999cae2dee12761
MonoImporter:
externalObjects: {}
serializedVersion: 2

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 74eb71d4a11c0b347ae6b1cea9e00824
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1f9481ca8d556f4da72ba66181e3b73
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
{
"name": "MeshCompressionRuntime",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 23e6cebda363f004aa6e529a95f8a6fc
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -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<string, (ModelImporterMeshCompression pc, ModelImporterMeshCompression android)> compressionMap
= new Dictionary<string, (ModelImporterMeshCompression, ModelImporterMeshCompression)>
{
{ "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