2022-12-11 22:08:41 +09:00
|
|
|
|
using System.Collections.Generic;
|
2022-12-12 18:19:50 +09:00
|
|
|
|
using System.Collections.Immutable;
|
2022-12-11 22:08:41 +09:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using VRC.SDK3.Avatars.Components;
|
|
|
|
|
using VRC.SDK3.Avatars.ScriptableObjects;
|
|
|
|
|
using static VRC.SDK3.Avatars.ScriptableObjects.VRCExpressionsMenu.Control;
|
|
|
|
|
|
|
|
|
|
// ReSharper disable once CheckNamespace
|
|
|
|
|
namespace nadena.dev.modular_avatar.core.editor {
|
|
|
|
|
public class MenuTree {
|
|
|
|
|
private readonly VRCExpressionsMenu _rootMenu;
|
|
|
|
|
private readonly HashSet<VRCExpressionsMenu> _included;
|
2022-12-12 19:19:55 +09:00
|
|
|
|
private readonly Dictionary<VRCExpressionsMenu, List<KeyValuePair<string, VRCExpressionsMenu>>> _childrenMap;
|
2022-12-11 22:08:41 +09:00
|
|
|
|
|
2022-12-12 18:19:50 +09:00
|
|
|
|
private readonly Dictionary<VRCExpressionsMenu, ImmutableArray<VRCExpressionsMenu>> _flashedChildrenMap;
|
|
|
|
|
|
2022-12-11 22:08:41 +09:00
|
|
|
|
public MenuTree(VRCAvatarDescriptor descriptor) {
|
|
|
|
|
this._rootMenu = descriptor.expressionsMenu;
|
|
|
|
|
this._included = new HashSet<VRCExpressionsMenu>();
|
2022-12-12 19:19:55 +09:00
|
|
|
|
this._childrenMap = new Dictionary<VRCExpressionsMenu, List<KeyValuePair<string, VRCExpressionsMenu>>>();
|
2022-12-11 22:08:41 +09:00
|
|
|
|
|
|
|
|
|
if (this._rootMenu == null) {
|
|
|
|
|
this._rootMenu = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._included.Add(this._rootMenu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AvatarsMenuMapping() {
|
|
|
|
|
if (this._rootMenu == null) return;
|
|
|
|
|
this.MappingMenu(this._rootMenu);
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-12 19:19:55 +09:00
|
|
|
|
public void MappingMenuInstaller(ModularAvatarMenuInstaller installer) {
|
2022-12-11 22:08:41 +09:00
|
|
|
|
if (installer.menuToAppend == null) return;
|
|
|
|
|
VRCExpressionsMenu parent = installer.installTargetMenu;
|
|
|
|
|
if (parent == null) parent = this._rootMenu;
|
|
|
|
|
this.MappingMenu(installer.menuToAppend, parent);
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-12 19:19:55 +09:00
|
|
|
|
public IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> GetChildren(VRCExpressionsMenu parent) {
|
2022-12-12 18:19:50 +09:00
|
|
|
|
// TODO: ライブラリとするのであれば、複製したリスト or ImmutableArray,を返すのが好ましい
|
|
|
|
|
if (parent == null) parent = this._rootMenu;
|
2022-12-12 19:19:55 +09:00
|
|
|
|
return this._childrenMap.TryGetValue(parent, out List<KeyValuePair<string, VRCExpressionsMenu>> children)
|
|
|
|
|
? children
|
|
|
|
|
: Enumerable.Empty<KeyValuePair<string, VRCExpressionsMenu>>();
|
2022-12-12 18:19:50 +09:00
|
|
|
|
}
|
|
|
|
|
|
2022-12-11 22:08:41 +09:00
|
|
|
|
private void MappingMenu(VRCExpressionsMenu root, VRCExpressionsMenu customParent = null) {
|
|
|
|
|
Queue<VRCExpressionsMenu> queue = new Queue<VRCExpressionsMenu>();
|
|
|
|
|
queue.Enqueue(root);
|
|
|
|
|
|
|
|
|
|
while (queue.Count > 0) {
|
|
|
|
|
VRCExpressionsMenu parent = queue.Dequeue();
|
2022-12-12 19:19:55 +09:00
|
|
|
|
IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> subMenus = GetSubMenus(parent);
|
2022-12-11 22:08:41 +09:00
|
|
|
|
if (customParent != null) {
|
|
|
|
|
parent = customParent;
|
|
|
|
|
customParent = null;
|
|
|
|
|
}
|
2022-12-12 19:19:55 +09:00
|
|
|
|
|
|
|
|
|
foreach (KeyValuePair<string, VRCExpressionsMenu> subMenu in subMenus) {
|
|
|
|
|
if (!this._childrenMap.TryGetValue(parent, out List<KeyValuePair<string, VRCExpressionsMenu>> children)) {
|
|
|
|
|
children = new List<KeyValuePair<string, VRCExpressionsMenu>>();
|
2022-12-11 22:08:41 +09:00
|
|
|
|
this._childrenMap[parent] = children;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
children.Add(subMenu);
|
2022-12-12 19:19:55 +09:00
|
|
|
|
if (this._included.Contains(subMenu.Value)) continue;
|
|
|
|
|
queue.Enqueue(subMenu.Value);
|
|
|
|
|
this._included.Add(subMenu.Value);
|
2022-12-11 22:08:41 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-12 19:19:55 +09:00
|
|
|
|
private static IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> GetSubMenus(VRCExpressionsMenu expressionsMenu) {
|
2022-12-11 22:08:41 +09:00
|
|
|
|
return expressionsMenu.controls
|
|
|
|
|
.Where(control => control.type == ControlType.SubMenu && control.subMenu != null)
|
2022-12-12 19:19:55 +09:00
|
|
|
|
.Select(control => new KeyValuePair<string, VRCExpressionsMenu>(control.name, control.subMenu));
|
2022-12-11 22:08:41 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|