diff --git a/Editor/PluginDefinition/PluginDefinition.cs b/Editor/PluginDefinition/PluginDefinition.cs index 69f179d7..2d258b23 100644 --- a/Editor/PluginDefinition/PluginDefinition.cs +++ b/Editor/PluginDefinition/PluginDefinition.cs @@ -59,6 +59,13 @@ namespace nadena.dev.modular_avatar.core.editor.plugin { seq.Run("Shape Changer", ctx => new ReactiveObjectPass(ctx).Execute()) .PreviewingWith(new ShapeChangerPreview(), new ObjectSwitcherPreview(), new MaterialSetterPreview()); +#if MA_VRCSDK3_AVATARS + // TODO: We currently run this above MergeArmaturePlugin, because Merge Armature might destroy + // game objects which contain Menu Installers. It'd probably be better however to teach Merge Armature + // to retain those objects? maybe? + seq.Run(MenuInstallPluginPass.Instance); +#endif + seq.Run(MergeArmaturePluginPass.Instance); seq.Run(BoneProxyPluginPass.Instance); seq.Run(VisibleHeadAccessoryPluginPass.Instance); @@ -73,7 +80,6 @@ namespace nadena.dev.modular_avatar.core.editor.plugin seq.Run(ConstraintConverterPass.Instance); }); #if MA_VRCSDK3_AVATARS - seq.Run(MenuInstallPluginPass.Instance); seq.Run(PhysbonesBlockerPluginPass.Instance); seq.Run("Fixup Expressions Menu", ctx => { diff --git a/UnitTests~/VirtualMenuTests/VirtualMenuTests.cs b/UnitTests~/VirtualMenuTests/VirtualMenuTests.cs index 81a9ffa3..5450dba0 100644 --- a/UnitTests~/VirtualMenuTests/VirtualMenuTests.cs +++ b/UnitTests~/VirtualMenuTests/VirtualMenuTests.cs @@ -698,6 +698,32 @@ namespace modular_avatar_tests.VirtualMenuTests Assert.AreEqual(4, virtualMenu.RootMenuNode.Controls[0].SubmenuNode.Controls[5].subParameters.Length); } + [Test] + public void MergeArmatureAndMenuInstallerOnSameObjectWorks() + { + var root = CreateRoot("root"); + var armature = CreateChild(root, "Armature"); + var installer = armature.AddComponent(); + + var merge = installer.gameObject.AddComponent(); + merge.mergeTarget.Set(root); + + var menu = Create(); + menu.controls.Add(new VRCExpressionsMenu.Control() + { + name = "control", + type = VRCExpressionsMenu.Control.ControlType.Toggle + }); + + installer.menuToAppend = menu; + + AvatarProcessor.ProcessAvatar(root); + + var realizedMenu = root.GetComponent().expressionsMenu; + Assert.AreEqual(1, realizedMenu.controls.Count); + Assert.AreEqual("control", realizedMenu.controls[0].name); + } + ModularAvatarMenuInstaller CreateInstaller(string name) { GameObject obj = new GameObject();