fix: Menu Installers on the same object as Merge Armature are not processed

Changes to pass ordering caused Merge Armature to destroy menus before being
processed by Menu Installer; fix this by hoisting menu generation to occur within
the animation services context, before Merge Armature runs. This is safe because
the menu installer pass does not interact with the avatar's animator controllers
directly.
This commit is contained in:
bd_ 2024-10-01 19:52:25 -07:00
parent 838f1dac7e
commit cb2afcc3d5
2 changed files with 33 additions and 1 deletions

View File

@ -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 =>
{

View File

@ -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<ModularAvatarMenuInstaller>();
var merge = installer.gameObject.AddComponent<ModularAvatarMergeArmature>();
merge.mergeTarget.Set(root);
var menu = Create<VRCExpressionsMenu>();
menu.controls.Add(new VRCExpressionsMenu.Control()
{
name = "control",
type = VRCExpressionsMenu.Control.ControlType.Toggle
});
installer.menuToAppend = menu;
AvatarProcessor.ProcessAvatar(root);
var realizedMenu = root.GetComponent<VRCAvatarDescriptor>().expressionsMenu;
Assert.AreEqual(1, realizedMenu.controls.Count);
Assert.AreEqual("control", realizedMenu.controls[0].name);
}
ModularAvatarMenuInstaller CreateInstaller(string name)
{
GameObject obj = new GameObject();