From 19e42f3422fcd437476bf858497a5c798f26927f Mon Sep 17 00:00:00 2001 From: bd_ Date: Wed, 22 Feb 2023 21:08:54 +0900 Subject: [PATCH] add menu serialization logic --- .../VirtualMenuTests/VirtualMenuTests.cs | 54 +++++++++++++++++++ .../Editor/MenuGeneration/VirtualMenu.cs | 39 ++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/Assets/_ModularAvatar/EditModeTests/VirtualMenuTests/VirtualMenuTests.cs b/Assets/_ModularAvatar/EditModeTests/VirtualMenuTests/VirtualMenuTests.cs index fdc5d5cf..b5abe2e9 100644 --- a/Assets/_ModularAvatar/EditModeTests/VirtualMenuTests/VirtualMenuTests.cs +++ b/Assets/_ModularAvatar/EditModeTests/VirtualMenuTests/VirtualMenuTests.cs @@ -3,6 +3,7 @@ using nadena.dev.modular_avatar.core; using nadena.dev.modular_avatar.core.editor.menu; using NUnit.Framework; using UnityEditor; +using UnityEditor.VersionControl; using UnityEngine; using VRC.SDK3.Avatars.ScriptableObjects; @@ -470,6 +471,59 @@ namespace modular_avatar_tests.VirtualMenuTests AssertControlEquals(menu_b.controls[0], rootNode.Controls[0]); } + [Test] + public void TestSerializeMenu() + { + var menu_a = Create("test"); + var menu_b = Create("test2"); + var menu_c = Create("test3"); + + menu_a.controls = new List() + { + GenerateTestControl(), + GenerateTestSubmenu(menu_b), + }; + + menu_b.controls = new List() + { + GenerateTestControl(), + GenerateTestSubmenu(menu_c), + }; + + menu_c.controls = new List() + { + GenerateTestSubmenu(menu_a), + }; + + var virtualMenu = new VirtualMenu(menu_a); + virtualMenu.FreezeMenu(); + + var assetSet = new HashSet(); + var serialized = virtualMenu.SerializeMenu(obj => assetSet.Add(obj)); + + Assert.AreEqual(3, assetSet.Count); + Assert.AreEqual(2, serialized.controls.Count); + + AssertControlEquals(menu_a.controls[0], serialized.controls[0]); + AssertControlEquals(menu_a.controls[1], serialized.controls[1]); + + var serialized_b = serialized.controls[1].subMenu; + Assert.AreEqual(2, serialized_b.controls.Count); + + AssertControlEquals(menu_b.controls[0], serialized_b.controls[0]); + AssertControlEquals(menu_b.controls[1], serialized_b.controls[1]); + + var serialized_c = serialized_b.controls[1].subMenu; + Assert.AreEqual(1, serialized_c.controls.Count); + + AssertControlEquals(menu_c.controls[0], serialized_c.controls[0]); + + Assert.True(assetSet.Contains(serialized)); + Assert.True(assetSet.Contains(serialized_b)); + Assert.True(assetSet.Contains(serialized_c)); + } + + ModularAvatarMenuInstaller CreateInstaller(string name) { GameObject obj = new GameObject(); diff --git a/Packages/nadena.dev.modular-avatar/Editor/MenuGeneration/VirtualMenu.cs b/Packages/nadena.dev.modular-avatar/Editor/MenuGeneration/VirtualMenu.cs index 8d99409c..22a427f5 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/MenuGeneration/VirtualMenu.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/MenuGeneration/VirtualMenu.cs @@ -174,6 +174,45 @@ namespace nadena.dev.modular_avatar.core.editor.menu ResolveNode(RootMenuKey); } + internal VRCExpressionsMenu SerializeMenu(Action SaveAsset) + { + Dictionary serializedMenus = new Dictionary(); + + return Serialize(RootMenuKey); + + VRCExpressionsMenu Serialize(object menuKey) + { + if (menuKey == null) return null; + if (serializedMenus.TryGetValue(menuKey, out var menu)) return menu; + if (!_resolvedMenu.TryGetValue(menuKey, out var node)) return null; + + menu = ScriptableObject.CreateInstance(); + serializedMenus[menuKey] = menu; + menu.controls = node.Controls.Select(c => + { + var control = new VRCExpressionsMenu.Control(); + control.name = c.name; + control.type = c.type; + control.parameter = new VRCExpressionsMenu.Control.Parameter() {name = c.parameter.name}; + control.value = c.value; + control.icon = c.icon; + control.style = c.style; + control.labels = c.labels.ToArray(); + control.subParameters = c.subParameters.Select(p => new VRCExpressionsMenu.Control.Parameter() + { + name = p.name + }).ToArray(); + control.subMenu = Serialize(c.SubmenuNode?.NodeKey); + + return control; + }).ToList(); + + SaveAsset(menu); + + return menu; + } + } + private HashSet _sourceTrace = null; private MenuNode ResolveNode(object nodeKey)