diff --git a/Editor/PluginDefinition/PluginDefinition.cs b/Editor/PluginDefinition/PluginDefinition.cs index 3bc7cf1b..d6c58b19 100644 --- a/Editor/PluginDefinition/PluginDefinition.cs +++ b/Editor/PluginDefinition/PluginDefinition.cs @@ -88,6 +88,7 @@ namespace nadena.dev.modular_avatar.core.editor.plugin var maContext = ctx.Extension().BuildContext; FixupExpressionsMenuPass.FixupExpressionsMenu(maContext); }); + seq.Run(RemoveVertexColorPass.Instance); #endif seq.Run(RebindHumanoidAvatarPass.Instance); seq.Run("Purge ModularAvatar components", ctx => diff --git a/Editor/RemoveVertexColorPass.cs b/Editor/RemoveVertexColorPass.cs new file mode 100644 index 00000000..b19f95d2 --- /dev/null +++ b/Editor/RemoveVertexColorPass.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using System.Linq; +using nadena.dev.ndmf; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace nadena.dev.modular_avatar.core.editor +{ + internal class RemoveVertexColorPass : Pass + { + protected override void Execute(ndmf.BuildContext context) + { + var removers = context.AvatarRootTransform.GetComponentsInChildren(true); + + Dictionary conversionMap = new(); + + foreach (var remover in removers) + { + foreach (var smr in remover.GetComponentsInChildren(true)) + { + TryRemove(context, smr, conversionMap); + } + + foreach (var mf in remover.GetComponentsInChildren(true)) + { + TryRemove(context, mf, conversionMap); + } + } + } + + private const string PROP_PATH = "m_Mesh"; + + private void TryRemove(ndmf.BuildContext context, Component c, Dictionary conversionMap) + { + SerializedObject obj; + SerializedProperty prop; + + if (c is SkinnedMeshRenderer smr) + { + obj = new SerializedObject(smr); + prop = obj.FindProperty(PROP_PATH); + } else if (c is MeshFilter mf) + { + obj = new SerializedObject(mf); + prop = obj.FindProperty(PROP_PATH); + } else + { + //Debug.LogWarning($"Could not find a mesh to remove vertex colors from on {remover.name}"); + // TODO: warning + return; + } + + var mesh = prop.objectReferenceValue as Mesh; + Mesh originalMesh = mesh; + if (mesh == null) + { + // TODO: warning; + return; + } + + if (conversionMap.TryGetValue(mesh, out var converted)) + { + prop.objectReferenceValue = converted; + obj.ApplyModifiedPropertiesWithoutUndo(); + return; + } + + if (mesh.GetVertexAttributes().All(va => va.attribute != VertexAttribute.Color)) + { + // no-op + return; + } + + if (!context.IsTemporaryAsset(mesh)) + { + mesh = UnityEngine.Object.Instantiate(mesh); + prop.objectReferenceValue = mesh; + obj.ApplyModifiedPropertiesWithoutUndo(); + } + + mesh.colors = null; + + conversionMap[originalMesh] = mesh; + } + } +} \ No newline at end of file diff --git a/Editor/RemoveVertexColorPass.cs.meta b/Editor/RemoveVertexColorPass.cs.meta new file mode 100644 index 00000000..4c61929e --- /dev/null +++ b/Editor/RemoveVertexColorPass.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a227da6f9f1548c3867b1ed113f28e9d +timeCreated: 1733008734 \ No newline at end of file diff --git a/Runtime/RemoveVertexColor.cs b/Runtime/RemoveVertexColor.cs new file mode 100644 index 00000000..4fcb15ec --- /dev/null +++ b/Runtime/RemoveVertexColor.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace nadena.dev.modular_avatar.core +{ + [AddComponentMenu("Modular Avatar/MA Remove Vertex Color")] + [DisallowMultipleComponent] + [HelpURL("https://modular-avatar.nadena.dev/docs/reference/remove-vertex-color?lang=auto")] + public class ModularAvatarRemoveVertexColor : AvatarTagComponent + { + + } +} \ No newline at end of file diff --git a/Runtime/RemoveVertexColor.cs.meta b/Runtime/RemoveVertexColor.cs.meta new file mode 100644 index 00000000..8b5de08b --- /dev/null +++ b/Runtime/RemoveVertexColor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: dc5f8bfae24244aeaedcd6c2bb7264f9 +timeCreated: 1733008656 \ No newline at end of file