diff --git a/Editor/Animation/AnimationDatabase.cs b/Editor/Animation/AnimationDatabase.cs index bf788923..fd9d8552 100644 --- a/Editor/Animation/AnimationDatabase.cs +++ b/Editor/Animation/AnimationDatabase.cs @@ -145,6 +145,8 @@ internal void OnActivate(BuildContext context) #if MA_VRCSDK3_AVATARS var avatarDescriptor = context.AvatarDescriptor; + if (!avatarDescriptor) return; + foreach (var layer in avatarDescriptor.baseAnimationLayers) { BootstrapLayer(layer); diff --git a/Editor/Animation/AnimationUtil.cs b/Editor/Animation/AnimationUtil.cs index aa026548..2c138544 100644 --- a/Editor/Animation/AnimationUtil.cs +++ b/Editor/Animation/AnimationUtil.cs @@ -53,9 +53,12 @@ internal static void CloneAllControllers(BuildContext context) // This helps reduce the risk that we'll accidentally modify the original assets. #if MA_VRCSDK3_AVATARS - context.AvatarDescriptor.baseAnimationLayers = + var avatarDescriptor = context.AvatarDescriptor; + if (!avatarDescriptor) return; + + avatarDescriptor.baseAnimationLayers = CloneLayers(context, context.AvatarDescriptor.baseAnimationLayers); - context.AvatarDescriptor.specialAnimationLayers = + avatarDescriptor.specialAnimationLayers = CloneLayers(context, context.AvatarDescriptor.specialAnimationLayers); #endif } diff --git a/Editor/FixupPasses/FixupExpressionsMenuPass.cs b/Editor/FixupPasses/FixupExpressionsMenuPass.cs index f4b549ee..4f36ec2b 100644 --- a/Editor/FixupPasses/FixupExpressionsMenuPass.cs +++ b/Editor/FixupPasses/FixupExpressionsMenuPass.cs @@ -19,6 +19,8 @@ internal class FixupExpressionsMenuPass internal static void FixupExpressionsMenu(BuildContext context) { + if (!context.AvatarDescriptor) return; + context.AvatarDescriptor.customExpressions = true; var expressionsMenu = context.AvatarDescriptor.expressionsMenu; diff --git a/Editor/MergeAnimatorProcessor.cs b/Editor/MergeAnimatorProcessor.cs index 50efd939..646dce34 100644 --- a/Editor/MergeAnimatorProcessor.cs +++ b/Editor/MergeAnimatorProcessor.cs @@ -65,6 +65,7 @@ internal void OnPreprocessAvatar(GameObject avatarGameObject, BuildContext conte mergeSessions.Clear(); var descriptor = avatarGameObject.GetComponent(); + if (!descriptor) return; if (descriptor.baseAnimationLayers != null) InitSessions(descriptor.baseAnimationLayers); if (descriptor.specialAnimationLayers != null) InitSessions(descriptor.specialAnimationLayers); diff --git a/Editor/MergeArmatureHook.cs b/Editor/MergeArmatureHook.cs index cd0d05cc..84337609 100644 --- a/Editor/MergeArmatureHook.cs +++ b/Editor/MergeArmatureHook.cs @@ -36,6 +36,15 @@ using UnityEditor; using UnityEngine; using UnityEngine.Animations; + +#if MA_VRM0 +using VRM; +#endif + +#if MA_VRM1 +using UniVRM10; +#endif + using Object = UnityEngine.Object; #endregion @@ -112,6 +121,35 @@ internal void OnPreprocessAvatar(ndmf.BuildContext context, GameObject avatarGam RetainBoneReferences(c); #endif +#if MA_VRM0 + foreach (var c in avatarGameObject.transform.GetComponentsInChildren(true)) + { + RetainBoneReferences(c); + } + + foreach (var c in avatarGameObject.transform.GetComponentsInChildren(true)) + { + RetainBoneReferences(c); + } +#endif + +#if MA_VRM1 + foreach (var c in avatarGameObject.transform.GetComponentsInChildren(true)) + { + RetainBoneReferences(c); + } + + foreach (var c in avatarGameObject.transform.GetComponentsInChildren(true)) + { + RetainBoneReferences(c); + } + + foreach (var c in avatarGameObject.transform.GetComponentsInChildren(true)) + { + RetainBoneReferences(c); + } +#endif + foreach (var c in avatarGameObject.transform.GetComponentsInChildren(true)) { RetainBoneReferences(c as Component); @@ -480,5 +518,7 @@ private void PruneDuplicatePhysBones() } } #endif + + // TODO - deduplicate VRM0/1 SpringBone components... doesn't break avatars either } } \ No newline at end of file diff --git a/Editor/OptimizationPasses/GCGameObjectsPass.cs b/Editor/OptimizationPasses/GCGameObjectsPass.cs index 0214494a..cff1a80a 100644 --- a/Editor/OptimizationPasses/GCGameObjectsPass.cs +++ b/Editor/OptimizationPasses/GCGameObjectsPass.cs @@ -7,6 +7,10 @@ using VRC.SDK3.Dynamics.PhysBone.Components; #endif +#if MA_VRM0 +using VRM; +#endif + namespace nadena.dev.modular_avatar.core.editor { /// @@ -66,6 +70,13 @@ private void MarkAll() break; #endif +#if MA_VRM0 + case VRMSpringBone sb: + MarkObject(obj); + MarkSpringBone(sb); + break; +#endif + case AvatarTagComponent _: // Tag components will not be retained at runtime, so pretend they're not there. break; @@ -147,6 +158,22 @@ private void MarkPhysBone(VRCPhysBone pb) } #endif +#if MA_VRM0 + private void MarkSpringBone(VRMSpringBone sb) + { + foreach (var rootBone in sb.RootBones) + { + foreach (var obj in GameObjects(rootBone.gameObject)) + { + MarkObject(obj); + } + } + + // Mark etc + MarkAllReferencedObjects(sb); + } +#endif + private void MarkAllReferencedObjects(Component component) { var so = new SerializedObject(component); diff --git a/Editor/OptimizationPasses/PruneParametersPass.cs b/Editor/OptimizationPasses/PruneParametersPass.cs index a38b3655..801fb3e9 100644 --- a/Editor/OptimizationPasses/PruneParametersPass.cs +++ b/Editor/OptimizationPasses/PruneParametersPass.cs @@ -9,6 +9,8 @@ internal class PruneParametersPass : Pass { protected override void Execute(ndmf.BuildContext context) { + if (!context.AvatarDescriptor) return; + var expParams = context.AvatarDescriptor.expressionParameters; if (expParams != null && context.IsTemporaryAsset(expParams)) { diff --git a/Editor/RenameParametersHook.cs b/Editor/RenameParametersHook.cs index 5bd401c3..d5ebb953 100644 --- a/Editor/RenameParametersHook.cs +++ b/Editor/RenameParametersHook.cs @@ -182,6 +182,8 @@ private void SetExpressionParameters(GameObject avatarRoot, ImmutableDictionary< .ToImmutableDictionary(); var avatar = avatarRoot.GetComponent(); + if (!avatar) return; + var expParams = avatar.expressionParameters; if (expParams == null) diff --git a/Editor/nadena.dev.modular-avatar.core.editor.asmdef b/Editor/nadena.dev.modular-avatar.core.editor.asmdef index 6372b236..e86c993b 100644 --- a/Editor/nadena.dev.modular-avatar.core.editor.asmdef +++ b/Editor/nadena.dev.modular-avatar.core.editor.asmdef @@ -7,6 +7,9 @@ "VRC.SDKBase", "nadena.dev.ndmf", "nadena.dev.ndmf.vrchat", + "VRM", + "VRM10", + "nadena.dev.ndmf.reactive-query.core", "nadena.dev.ndmf.runtime", "VRC.SDK3A.Editor", "Unity.Burst" @@ -44,6 +47,16 @@ "expression": "", "define": "MA_VRCSDK3_AVATARS" }, + { + "name": "com.vrmc.univrm", + "expression": "", + "define": "MA_VRM0" + }, + { + "name": "com.vrmc.vrm", + "expression": "", + "define": "MA_VRM1" + }, { "name": "com.vrchat.avatars", "expression": "3.5.2", diff --git a/Editor/nadena.dev.modular-avatar.core.editor.asmdef~ b/Editor/nadena.dev.modular-avatar.core.editor.asmdef~ deleted file mode 100644 index 6372b236..00000000 --- a/Editor/nadena.dev.modular-avatar.core.editor.asmdef~ +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "nadena.dev.modular-avatar.core.editor", - "rootNamespace": "", - "references": [ - "nadena.dev.modular-avatar.core", - "VRC.SDK3A", - "VRC.SDKBase", - "nadena.dev.ndmf", - "nadena.dev.ndmf.vrchat", - "nadena.dev.ndmf.runtime", - "VRC.SDK3A.Editor", - "Unity.Burst" - ], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": true, - "precompiledReferences": [ - "Newtonsoft.Json.dll", - "System.Collections.Immutable.dll", - "VRCSDKBase.dll", - "VRCSDKBase-Editor.dll", - "VRCSDK3A.dll", - "VRCSDK3A-Editor.dll", - "VRC.Dynamics.dll", - "VRC.SDK3.Dynamics.Contact.dll", - "VRC.SDK3.Dynamics.Contact.Editor.dll", - "VRC.SDK3.Dynamics.PhysBone.dll", - "VRC.SDK3.Dynamics.PhysBone.Editor.dll", - "VRCCore-Editor.dll" - ], - "autoReferenced": false, - "defineConstraints": [], - "versionDefines": [ - { - "name": "com.anatawa12.avatar-optimizer", - "expression": "(,1.5.0-rc.8)", - "define": "LEGACY_AVATAR_OPTIMIZER" - }, - { - "name": "com.vrchat.avatars", - "expression": "", - "define": "MA_VRCSDK3_AVATARS" - }, - { - "name": "com.vrchat.avatars", - "expression": "3.5.2", - "define": "MA_VRCSDK3_AVATARS_3_5_2_OR_NEWER" - }, - { - "name": "com.vrchat.avatars", - "expression": "3.7.0-beta.2", - "define": "MA_VRCSDK3_AVATARS_3_7_0_OR_NEWER" - } - ], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Runtime/nadena.dev.modular-avatar.core.asmdef b/Runtime/nadena.dev.modular-avatar.core.asmdef index 6e529bce..2cee7277 100644 --- a/Runtime/nadena.dev.modular-avatar.core.asmdef +++ b/Runtime/nadena.dev.modular-avatar.core.asmdef @@ -24,6 +24,16 @@ "name": "com.vrchat.avatars", "expression": "", "define": "MA_VRCSDK3_AVATARS" + }, + { + "name": "com.vrmc.univrm", + "expression": "", + "define": "MA_VRM0" + }, + { + "name": "com.vrmc.vrm", + "expression": "", + "define": "MA_VRM1" } ], "noEngineReferences": false diff --git a/UnitTests~/Tests.asmdef b/UnitTests~/Tests.asmdef index ed1e9598..e2482626 100644 --- a/UnitTests~/Tests.asmdef +++ b/UnitTests~/Tests.asmdef @@ -31,6 +31,16 @@ "expression": "", "define": "MA_VRCSDK3_AVATARS" }, + { + "name": "com.vrmc.univrm", + "expression": "", + "define": "MA_VRM0" + }, + { + "name": "com.vrmc.vrm", + "expression": "", + "define": "MA_VRM1" + }, { "name": "com.vrchat.avatars", "expression": "3.5.2",