diff --git a/Packages/nadena.dev.modular-avatar/Editor/Inspector/AvMenuTreeView.cs b/Packages/nadena.dev.modular-avatar/Editor/Inspector/AvMenuTreeView.cs index b3ee28c2..7577b340 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Inspector/AvMenuTreeView.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Inspector/AvMenuTreeView.cs @@ -150,19 +150,22 @@ namespace nadena.dev.modular_avatar.core.editor } private void TraverseMenu(int depth, List items, VRCExpressionsMenu menu) { - IEnumerable> children = this._menuTree.GetChildren(menu) - .Where(child => !this._visitedMenuStack.Contains(child.Value)); - foreach (KeyValuePair child in children) { + IEnumerable children = this._menuTree.GetChildren(menu) + .Where(child => !this._visitedMenuStack.Contains(child.menu)); + foreach (MenuTree.ChildElement child in children) { + string displayName = child.installer == null ? + $"{child.menuName} ({child.menu.name})" : + $"{child.menuName} ({child.menu.name}) InstallerObject : {child.installer.name}"; items.Add( new TreeViewItem { id = items.Count, depth = depth, - displayName = $"{child.Key} ({child.Value.name})" + displayName = displayName } ); - this._menuItems.Add(child.Value); - this._visitedMenuStack.Push(child.Value); - this.TraverseMenu(depth + 1, items, child.Value); + this._menuItems.Add(child.menu); + this._visitedMenuStack.Push(child.menu); + this.TraverseMenu(depth + 1, items, child.menu); this._visitedMenuStack.Pop(); } } diff --git a/Packages/nadena.dev.modular-avatar/Editor/MenuTree.cs b/Packages/nadena.dev.modular-avatar/Editor/MenuTree.cs index f0eeffee..fe51db9a 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/MenuTree.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/MenuTree.cs @@ -9,16 +9,22 @@ using static VRC.SDK3.Avatars.ScriptableObjects.VRCExpressionsMenu.Control; // ReSharper disable once CheckNamespace namespace nadena.dev.modular_avatar.core.editor { public class MenuTree { + public struct ChildElement { + public string menuName; + public VRCExpressionsMenu menu; + public ModularAvatarMenuInstaller installer; + } + private readonly VRCExpressionsMenu _rootMenu; private readonly HashSet _included; - private readonly Dictionary>> _childrenMap; + private readonly Dictionary> _childrenMap; private readonly Dictionary> _flashedChildrenMap; public MenuTree(VRCAvatarDescriptor descriptor) { this._rootMenu = descriptor.expressionsMenu; this._included = new HashSet(); - this._childrenMap = new Dictionary>>(); + this._childrenMap = new Dictionary>(); if (this._rootMenu == null) { this._rootMenu = ScriptableObject.CreateInstance(); @@ -34,46 +40,49 @@ namespace nadena.dev.modular_avatar.core.editor { public void MappingMenuInstaller(ModularAvatarMenuInstaller installer) { if (installer.menuToAppend == null) return; - VRCExpressionsMenu parent = installer.installTargetMenu; - if (parent == null) parent = this._rootMenu; - this.MappingMenu(installer.menuToAppend, parent); + this.MappingMenu(installer.menuToAppend, installer); } - public IEnumerable> GetChildren(VRCExpressionsMenu parent) { + public IEnumerable GetChildren(VRCExpressionsMenu parent) { // TODO: ライブラリとするのであれば、複製したリスト or ImmutableArray,を返すのが好ましい if (parent == null) parent = this._rootMenu; - return this._childrenMap.TryGetValue(parent, out List> children) + return this._childrenMap.TryGetValue(parent, out List children) ? children - : Enumerable.Empty>(); + : Enumerable.Empty(); } - private void MappingMenu(VRCExpressionsMenu root, VRCExpressionsMenu customParent = null) { + private void MappingMenu(VRCExpressionsMenu root, ModularAvatarMenuInstaller installer = null) { Queue queue = new Queue(); queue.Enqueue(root); + bool first = true; while (queue.Count > 0) { VRCExpressionsMenu parent = queue.Dequeue(); - IEnumerable> subMenus = GetSubMenus(parent); - if (customParent != null) { - parent = customParent; - customParent = null; + IEnumerable> childMenus = GetChildMenus(parent); + + if (first && installer != null) { + parent = installer.installTargetMenu != null ? installer.installTargetMenu : _rootMenu; + } - foreach (KeyValuePair subMenu in subMenus) { - if (!this._childrenMap.TryGetValue(parent, out List> children)) { - children = new List>(); + foreach (KeyValuePair childMenu in childMenus) { + if (!this._childrenMap.TryGetValue(parent, out List children)) { + children = new List(); this._childrenMap[parent] = children; } - children.Add(subMenu); - if (this._included.Contains(subMenu.Value)) continue; - queue.Enqueue(subMenu.Value); - this._included.Add(subMenu.Value); + ChildElement childElement = new ChildElement { menuName = childMenu.Key, menu = childMenu.Value, installer = installer }; + children.Add(childElement); + if (this._included.Contains(childElement.menu)) continue; + queue.Enqueue(childElement.menu); + this._included.Add(childElement.menu); } + + first = false; } } - private static IEnumerable> GetSubMenus(VRCExpressionsMenu expressionsMenu) { + private static IEnumerable> GetChildMenus(VRCExpressionsMenu expressionsMenu) { return expressionsMenu.controls .Where(control => control.type == ControlType.SubMenu && control.subMenu != null) .Select(control => new KeyValuePair(control.name, control.subMenu));