The menu added by the installer should display the installer name

This commit is contained in:
raiti-chan 2022-12-12 22:27:04 +09:00
parent 260fdb44a7
commit 3d26682718
2 changed files with 40 additions and 28 deletions

View File

@ -150,19 +150,22 @@ namespace nadena.dev.modular_avatar.core.editor
} }
private void TraverseMenu(int depth, List<TreeViewItem> items, VRCExpressionsMenu menu) { private void TraverseMenu(int depth, List<TreeViewItem> items, VRCExpressionsMenu menu) {
IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> children = this._menuTree.GetChildren(menu) IEnumerable<MenuTree.ChildElement> children = this._menuTree.GetChildren(menu)
.Where(child => !this._visitedMenuStack.Contains(child.Value)); .Where(child => !this._visitedMenuStack.Contains(child.menu));
foreach (KeyValuePair<string, VRCExpressionsMenu> child in children) { 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( items.Add(
new TreeViewItem { new TreeViewItem {
id = items.Count, id = items.Count,
depth = depth, depth = depth,
displayName = $"{child.Key} ({child.Value.name})" displayName = displayName
} }
); );
this._menuItems.Add(child.Value); this._menuItems.Add(child.menu);
this._visitedMenuStack.Push(child.Value); this._visitedMenuStack.Push(child.menu);
this.TraverseMenu(depth + 1, items, child.Value); this.TraverseMenu(depth + 1, items, child.menu);
this._visitedMenuStack.Pop(); this._visitedMenuStack.Pop();
} }
} }

View File

@ -9,16 +9,22 @@ using static VRC.SDK3.Avatars.ScriptableObjects.VRCExpressionsMenu.Control;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace nadena.dev.modular_avatar.core.editor { namespace nadena.dev.modular_avatar.core.editor {
public class MenuTree { public class MenuTree {
public struct ChildElement {
public string menuName;
public VRCExpressionsMenu menu;
public ModularAvatarMenuInstaller installer;
}
private readonly VRCExpressionsMenu _rootMenu; private readonly VRCExpressionsMenu _rootMenu;
private readonly HashSet<VRCExpressionsMenu> _included; private readonly HashSet<VRCExpressionsMenu> _included;
private readonly Dictionary<VRCExpressionsMenu, List<KeyValuePair<string, VRCExpressionsMenu>>> _childrenMap; private readonly Dictionary<VRCExpressionsMenu, List<ChildElement>> _childrenMap;
private readonly Dictionary<VRCExpressionsMenu, ImmutableArray<VRCExpressionsMenu>> _flashedChildrenMap; private readonly Dictionary<VRCExpressionsMenu, ImmutableArray<VRCExpressionsMenu>> _flashedChildrenMap;
public MenuTree(VRCAvatarDescriptor descriptor) { public MenuTree(VRCAvatarDescriptor descriptor) {
this._rootMenu = descriptor.expressionsMenu; this._rootMenu = descriptor.expressionsMenu;
this._included = new HashSet<VRCExpressionsMenu>(); this._included = new HashSet<VRCExpressionsMenu>();
this._childrenMap = new Dictionary<VRCExpressionsMenu, List<KeyValuePair<string, VRCExpressionsMenu>>>(); this._childrenMap = new Dictionary<VRCExpressionsMenu, List<ChildElement>>();
if (this._rootMenu == null) { if (this._rootMenu == null) {
this._rootMenu = ScriptableObject.CreateInstance<VRCExpressionsMenu>(); this._rootMenu = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
@ -34,46 +40,49 @@ namespace nadena.dev.modular_avatar.core.editor {
public void MappingMenuInstaller(ModularAvatarMenuInstaller installer) { public void MappingMenuInstaller(ModularAvatarMenuInstaller installer) {
if (installer.menuToAppend == null) return; if (installer.menuToAppend == null) return;
VRCExpressionsMenu parent = installer.installTargetMenu; this.MappingMenu(installer.menuToAppend, installer);
if (parent == null) parent = this._rootMenu;
this.MappingMenu(installer.menuToAppend, parent);
} }
public IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> GetChildren(VRCExpressionsMenu parent) { public IEnumerable<ChildElement> GetChildren(VRCExpressionsMenu parent) {
// TODO: ライブラリとするのであれば、複製したリスト or ImmutableArray,を返すのが好ましい // TODO: ライブラリとするのであれば、複製したリスト or ImmutableArray,を返すのが好ましい
if (parent == null) parent = this._rootMenu; if (parent == null) parent = this._rootMenu;
return this._childrenMap.TryGetValue(parent, out List<KeyValuePair<string, VRCExpressionsMenu>> children) return this._childrenMap.TryGetValue(parent, out List<ChildElement> children)
? children ? children
: Enumerable.Empty<KeyValuePair<string, VRCExpressionsMenu>>(); : Enumerable.Empty<ChildElement>();
} }
private void MappingMenu(VRCExpressionsMenu root, VRCExpressionsMenu customParent = null) { private void MappingMenu(VRCExpressionsMenu root, ModularAvatarMenuInstaller installer = null) {
Queue<VRCExpressionsMenu> queue = new Queue<VRCExpressionsMenu>(); Queue<VRCExpressionsMenu> queue = new Queue<VRCExpressionsMenu>();
queue.Enqueue(root); queue.Enqueue(root);
bool first = true;
while (queue.Count > 0) { while (queue.Count > 0) {
VRCExpressionsMenu parent = queue.Dequeue(); VRCExpressionsMenu parent = queue.Dequeue();
IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> subMenus = GetSubMenus(parent); IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> childMenus = GetChildMenus(parent);
if (customParent != null) {
parent = customParent; if (first && installer != null) {
customParent = null; parent = installer.installTargetMenu != null ? installer.installTargetMenu : _rootMenu;
} }
foreach (KeyValuePair<string, VRCExpressionsMenu> subMenu in subMenus) { foreach (KeyValuePair<string, VRCExpressionsMenu> childMenu in childMenus) {
if (!this._childrenMap.TryGetValue(parent, out List<KeyValuePair<string, VRCExpressionsMenu>> children)) { if (!this._childrenMap.TryGetValue(parent, out List<ChildElement> children)) {
children = new List<KeyValuePair<string, VRCExpressionsMenu>>(); children = new List<ChildElement>();
this._childrenMap[parent] = children; this._childrenMap[parent] = children;
} }
children.Add(subMenu); ChildElement childElement = new ChildElement { menuName = childMenu.Key, menu = childMenu.Value, installer = installer };
if (this._included.Contains(subMenu.Value)) continue; children.Add(childElement);
queue.Enqueue(subMenu.Value); if (this._included.Contains(childElement.menu)) continue;
this._included.Add(subMenu.Value); queue.Enqueue(childElement.menu);
this._included.Add(childElement.menu);
} }
first = false;
} }
} }
private static IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> GetSubMenus(VRCExpressionsMenu expressionsMenu) { private static IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> GetChildMenus(VRCExpressionsMenu expressionsMenu) {
return expressionsMenu.controls return expressionsMenu.controls
.Where(control => control.type == ControlType.SubMenu && control.subMenu != null) .Where(control => control.type == ControlType.SubMenu && control.subMenu != null)
.Select(control => new KeyValuePair<string, VRCExpressionsMenu>(control.name, control.subMenu)); .Select(control => new KeyValuePair<string, VRCExpressionsMenu>(control.name, control.subMenu));