mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-04-11 23:19:00 +08:00
refactoring
This commit is contained in:
parent
0614379590
commit
7367418de8
@ -3,21 +3,25 @@ using System.Collections.Immutable;
|
||||
using VRC.SDK3.Avatars.ScriptableObjects;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace nadena.dev.modular_avatar.core.editor {
|
||||
namespace nadena.dev.modular_avatar.core.editor
|
||||
{
|
||||
public static class ClonedMenuMappings {
|
||||
private static Dictionary<VRCExpressionsMenu, ImmutableArray<VRCExpressionsMenu>> ClonedMappings =
|
||||
private static readonly Dictionary<VRCExpressionsMenu, ImmutableArray<VRCExpressionsMenu>> ClonedMappings =
|
||||
new Dictionary<VRCExpressionsMenu, ImmutableArray<VRCExpressionsMenu>>();
|
||||
|
||||
private static Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> OriginalMapping =
|
||||
private static readonly Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> OriginalMapping =
|
||||
new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>();
|
||||
|
||||
public static void Clear() {
|
||||
public static void Clear()
|
||||
{
|
||||
ClonedMappings.Clear();
|
||||
OriginalMapping.Clear();
|
||||
}
|
||||
|
||||
public static void Add(VRCExpressionsMenu original, VRCExpressionsMenu clonedMenu) {
|
||||
if (!ClonedMappings.TryGetValue(original, out ImmutableArray<VRCExpressionsMenu> clonedMenus)) {
|
||||
public static void Add(VRCExpressionsMenu original, VRCExpressionsMenu clonedMenu)
|
||||
{
|
||||
if (!ClonedMappings.TryGetValue(original, out ImmutableArray<VRCExpressionsMenu> clonedMenus))
|
||||
{
|
||||
clonedMenus = ImmutableArray<VRCExpressionsMenu>.Empty;
|
||||
}
|
||||
// Usually, one menu is rarely duplicated in multiple menus, so don't bother using a Builder
|
||||
@ -25,11 +29,13 @@ namespace nadena.dev.modular_avatar.core.editor {
|
||||
OriginalMapping[clonedMenu] = original;
|
||||
}
|
||||
|
||||
public static bool TryGetClonedMenus(VRCExpressionsMenu original, out ImmutableArray<VRCExpressionsMenu> clonedMenus) {
|
||||
public static bool TryGetClonedMenus(VRCExpressionsMenu original, out ImmutableArray<VRCExpressionsMenu> clonedMenus)
|
||||
{
|
||||
return ClonedMappings.TryGetValue(original, out clonedMenus);
|
||||
}
|
||||
|
||||
public static VRCExpressionsMenu GetOriginal(VRCExpressionsMenu cloned) {
|
||||
public static VRCExpressionsMenu GetOriginal(VRCExpressionsMenu cloned)
|
||||
{
|
||||
return OriginalMapping.TryGetValue(cloned, out VRCExpressionsMenu original) ? original : null;
|
||||
}
|
||||
}
|
||||
|
@ -122,20 +122,24 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
OnDoubleclickSelect.Invoke();
|
||||
}
|
||||
|
||||
protected override TreeViewItem BuildRoot() {
|
||||
protected override TreeViewItem BuildRoot()
|
||||
{
|
||||
this._menuItems.Clear();
|
||||
this._visitedMenuStack.Clear();
|
||||
|
||||
_menuTree = new MenuTree(Avatar);
|
||||
_menuTree.AvatarsMenuMapping();
|
||||
foreach (ModularAvatarMenuInstaller installer in this.Avatar.gameObject.GetComponentsInChildren<ModularAvatarMenuInstaller>(true)) {
|
||||
foreach (ModularAvatarMenuInstaller installer in this.Avatar.gameObject.GetComponentsInChildren<ModularAvatarMenuInstaller>(true))
|
||||
{
|
||||
if (installer == Installer) continue;
|
||||
this._menuTree.MappingMenuInstaller(installer);
|
||||
}
|
||||
|
||||
var root = new TreeViewItem(-1, -1, "<root>");
|
||||
List<TreeViewItem> treeItems = new List<TreeViewItem> {
|
||||
new TreeViewItem {
|
||||
List<TreeViewItem> treeItems = new List<TreeViewItem>
|
||||
{
|
||||
new TreeViewItem
|
||||
{
|
||||
id = 0,
|
||||
depth = 0,
|
||||
displayName = $"{Avatar.gameObject.name} ({(Avatar.expressionsMenu == null ? "None" : Avatar.expressionsMenu.name)})"
|
||||
@ -149,15 +153,18 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
return root;
|
||||
}
|
||||
|
||||
private void TraverseMenu(int depth, List<TreeViewItem> items, VRCExpressionsMenu menu) {
|
||||
private void TraverseMenu(int depth, List<TreeViewItem> items, VRCExpressionsMenu menu)
|
||||
{
|
||||
IEnumerable<MenuTree.ChildElement> children = this._menuTree.GetChildren(menu)
|
||||
.Where(child => !this._visitedMenuStack.Contains(child.menu));
|
||||
foreach (MenuTree.ChildElement 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(
|
||||
new TreeViewItem {
|
||||
new TreeViewItem
|
||||
{
|
||||
id = items.Count,
|
||||
depth = depth,
|
||||
displayName = displayName
|
||||
@ -169,53 +176,5 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
this._visitedMenuStack.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
protected override TreeViewItem BuildRoot()
|
||||
{
|
||||
_menuItems.Clear();
|
||||
_visitedMenus.Clear();
|
||||
|
||||
if (Avatar.expressionsMenu == null)
|
||||
{
|
||||
return new TreeViewItem(0, -1, "No menu");
|
||||
}
|
||||
|
||||
_visitedMenus.Add(Avatar.expressionsMenu);
|
||||
_menuItems.Add(Avatar.expressionsMenu);
|
||||
var root = new TreeViewItem {id = -1, depth = -1, displayName = "<root>"};
|
||||
|
||||
var treeItems = new List<TreeViewItem>();
|
||||
treeItems.Add(new TreeViewItem
|
||||
{id = 0, depth = 0, displayName = $"{Avatar.gameObject.name} ({Avatar.expressionsMenu.name})"});
|
||||
|
||||
TraverseMenu(1, treeItems, Avatar.expressionsMenu);
|
||||
|
||||
SetupParentsAndChildrenFromDepths(root, treeItems);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void TraverseMenu(int depth, List<TreeViewItem> items, VRCExpressionsMenu menu)
|
||||
{
|
||||
foreach (var control in menu.controls)
|
||||
{
|
||||
if (control.type == VRCExpressionsMenu.Control.ControlType.SubMenu
|
||||
&& control.subMenu != null && !_visitedMenus.Contains(control.subMenu))
|
||||
{
|
||||
items.Add(new TreeViewItem
|
||||
{
|
||||
id = _menuItems.Count,
|
||||
depth = depth,
|
||||
displayName = $"{control.name} ({control.subMenu.name})"
|
||||
});
|
||||
_menuItems.Add(control.subMenu);
|
||||
_visitedMenus.Add(control.subMenu);
|
||||
|
||||
TraverseMenu(depth + 1, items, control.subMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
#define NEW
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
@ -22,11 +21,11 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
private VRCExpressionsMenu _rootMenu;
|
||||
|
||||
#if NEW
|
||||
private MenuTree _menuTree;
|
||||
private Stack<ModularAvatarMenuInstaller> _visitedInstallerStack;
|
||||
|
||||
public void OnPreprocessAvatar(GameObject avatarRoot) {
|
||||
public void OnPreprocessAvatar(GameObject avatarRoot)
|
||||
{
|
||||
ModularAvatarMenuInstaller[] menuInstallers = avatarRoot.GetComponentsInChildren<ModularAvatarMenuInstaller>(true)
|
||||
.Where(menuInstaller => menuInstaller.enabled)
|
||||
.ToArray();
|
||||
@ -38,7 +37,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
VRCAvatarDescriptor avatar = avatarRoot.GetComponent<VRCAvatarDescriptor>();
|
||||
|
||||
if (avatar.expressionsMenu == null) {
|
||||
if (avatar.expressionsMenu == null)
|
||||
{
|
||||
var menu = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
|
||||
AssetDatabase.CreateAsset(menu, Util.GenerateAssetPath());
|
||||
avatar.expressionsMenu = menu;
|
||||
@ -51,16 +51,18 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
avatar.expressionsMenu = CloneMenu(avatar.expressionsMenu);
|
||||
|
||||
foreach (ModularAvatarMenuInstaller installer in menuInstallers) {
|
||||
foreach (ModularAvatarMenuInstaller installer in menuInstallers)
|
||||
{
|
||||
_menuTree.MappingMenuInstaller(installer);
|
||||
}
|
||||
|
||||
foreach (MenuTree.ChildElement childElement in _menuTree.GetChildInstallers(null)) {
|
||||
InstallMenuToAvatarMenu(childElement.installer);
|
||||
foreach (MenuTree.ChildElement childElement in _menuTree.GetChildInstallers(null))
|
||||
{
|
||||
InstallMenu(childElement.installer);
|
||||
}
|
||||
}
|
||||
|
||||
private void InstallMenuToAvatarMenu(ModularAvatarMenuInstaller installer)
|
||||
private void InstallMenu(ModularAvatarMenuInstaller installer, VRCExpressionsMenu installTarget = null)
|
||||
{
|
||||
if (!installer.enabled) return;
|
||||
|
||||
@ -69,29 +71,9 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
installer.installTargetMenu = _rootMenu;
|
||||
}
|
||||
|
||||
if (installer.installTargetMenu == null || installer.menuToAppend == null) return;
|
||||
if (!_clonedMenus.TryGetValue(installer.installTargetMenu, out var targetMenu)) return;
|
||||
|
||||
// Clone before appending to sanitize menu icons
|
||||
targetMenu.controls.AddRange(CloneMenu(installer.menuToAppend).controls);
|
||||
|
||||
SplitMenu(installer, targetMenu);
|
||||
|
||||
if (_visitedInstallerStack.Contains(installer)) return;
|
||||
_visitedInstallerStack.Push(installer);
|
||||
foreach (MenuTree.ChildElement childElement in _menuTree.GetChildInstallers(installer)) {
|
||||
InstallMenuToInstallerMenu(childElement.parent, childElement.installer);
|
||||
}
|
||||
|
||||
_visitedInstallerStack.Pop();
|
||||
}
|
||||
|
||||
private void InstallMenuToInstallerMenu(VRCExpressionsMenu installTarget, ModularAvatarMenuInstaller installer) {
|
||||
if (!installer.enabled) return;
|
||||
|
||||
if (installer.installTargetMenu == null)
|
||||
if (installTarget == null)
|
||||
{
|
||||
installer.installTargetMenu = _rootMenu;
|
||||
installTarget = installer.installTargetMenu;
|
||||
}
|
||||
|
||||
if (installer.installTargetMenu == null || installer.menuToAppend == null) return;
|
||||
@ -101,32 +83,37 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
targetMenu.controls.AddRange(CloneMenu(installer.menuToAppend).controls);
|
||||
|
||||
SplitMenu(installer, targetMenu);
|
||||
|
||||
|
||||
if (_visitedInstallerStack.Contains(installer)) return;
|
||||
_visitedInstallerStack.Push(installer);
|
||||
foreach (MenuTree.ChildElement childElement in _menuTree.GetChildInstallers(installer)) {
|
||||
InstallMenuToInstallerMenu(childElement.parent, childElement.installer);
|
||||
foreach (MenuTree.ChildElement childElement in _menuTree.GetChildInstallers(installer))
|
||||
{
|
||||
InstallMenu(childElement.installer, childElement.parent);
|
||||
}
|
||||
|
||||
_visitedInstallerStack.Pop();
|
||||
}
|
||||
|
||||
private void SplitMenu(ModularAvatarMenuInstaller installer, VRCExpressionsMenu targetMenu) {
|
||||
while (targetMenu.controls.Count > VRCExpressionsMenu.MAX_CONTROLS) {
|
||||
private void SplitMenu(ModularAvatarMenuInstaller installer, VRCExpressionsMenu targetMenu)
|
||||
{
|
||||
while (targetMenu.controls.Count > VRCExpressionsMenu.MAX_CONTROLS)
|
||||
{
|
||||
// Split target menu
|
||||
var newMenu = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
|
||||
AssetDatabase.CreateAsset(newMenu, Util.GenerateAssetPath());
|
||||
var keepCount = VRCExpressionsMenu.MAX_CONTROLS - 1;
|
||||
const int keepCount = VRCExpressionsMenu.MAX_CONTROLS - 1;
|
||||
newMenu.controls.AddRange(targetMenu.controls.Skip(keepCount));
|
||||
targetMenu.controls.RemoveRange(keepCount,
|
||||
targetMenu.controls.Count - keepCount
|
||||
);
|
||||
|
||||
targetMenu.controls.Add(new VRCExpressionsMenu.Control() {
|
||||
targetMenu.controls.Add(new VRCExpressionsMenu.Control
|
||||
{
|
||||
name = "More",
|
||||
type = VRCExpressionsMenu.Control.ControlType.SubMenu,
|
||||
subMenu = newMenu,
|
||||
parameter = new VRCExpressionsMenu.Control.Parameter() {
|
||||
parameter = new VRCExpressionsMenu.Control.Parameter
|
||||
{
|
||||
name = ""
|
||||
},
|
||||
subParameters = Array.Empty<VRCExpressionsMenu.Control.Parameter>(),
|
||||
@ -138,86 +125,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
targetMenu = newMenu;
|
||||
}
|
||||
}
|
||||
#else
|
||||
private Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> _installTargets;
|
||||
|
||||
public void OnPreprocessAvatar(GameObject avatarRoot)
|
||||
{
|
||||
var menuInstallers = avatarRoot.GetComponentsInChildren<ModularAvatarMenuInstaller>(true)
|
||||
.Where(c => c.enabled)
|
||||
.ToArray();
|
||||
if (menuInstallers.Length == 0) return;
|
||||
|
||||
_clonedMenus = new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>();
|
||||
|
||||
var avatar = avatarRoot.GetComponent<VRCAvatarDescriptor>();
|
||||
|
||||
if (avatar.expressionsMenu == null)
|
||||
{
|
||||
var menu = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
|
||||
AssetDatabase.CreateAsset(menu, Util.GenerateAssetPath());
|
||||
avatar.expressionsMenu = menu;
|
||||
}
|
||||
|
||||
_rootMenu = avatar.expressionsMenu;
|
||||
avatar.expressionsMenu = CloneMenu(avatar.expressionsMenu);
|
||||
_installTargets = new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>(_clonedMenus);
|
||||
|
||||
foreach (var install in menuInstallers)
|
||||
{
|
||||
InstallMenu(install);
|
||||
}
|
||||
}
|
||||
|
||||
private void InstallMenu(ModularAvatarMenuInstaller installer)
|
||||
{
|
||||
if (!installer.enabled) return;
|
||||
|
||||
if (installer.installTargetMenu == null)
|
||||
{
|
||||
installer.installTargetMenu = _rootMenu;
|
||||
}
|
||||
|
||||
if (installer.installTargetMenu == null || installer.menuToAppend == null) return;
|
||||
if (!_installTargets.TryGetValue(installer.installTargetMenu, out var targetMenu)) return;
|
||||
if (_installTargets.ContainsKey(installer.menuToAppend)) return;
|
||||
|
||||
// Clone before appending to sanitize menu icons
|
||||
targetMenu.controls.AddRange(CloneMenu(installer.menuToAppend).controls);
|
||||
|
||||
while (targetMenu.controls.Count > VRCExpressionsMenu.MAX_CONTROLS)
|
||||
{
|
||||
// Split target menu
|
||||
var newMenu = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
|
||||
AssetDatabase.CreateAsset(newMenu, Util.GenerateAssetPath());
|
||||
var keepCount = VRCExpressionsMenu.MAX_CONTROLS - 1;
|
||||
newMenu.controls.AddRange(targetMenu.controls.Skip(keepCount));
|
||||
targetMenu.controls.RemoveRange(keepCount,
|
||||
targetMenu.controls.Count - keepCount
|
||||
);
|
||||
|
||||
targetMenu.controls.Add(new VRCExpressionsMenu.Control()
|
||||
{
|
||||
name = "More",
|
||||
type = VRCExpressionsMenu.Control.ControlType.SubMenu,
|
||||
subMenu = newMenu,
|
||||
parameter = new VRCExpressionsMenu.Control.Parameter()
|
||||
{
|
||||
name = ""
|
||||
},
|
||||
subParameters = Array.Empty<VRCExpressionsMenu.Control.Parameter>(),
|
||||
icon = _moreIcon,
|
||||
labels = Array.Empty<VRCExpressionsMenu.Control.Label>()
|
||||
});
|
||||
|
||||
_installTargets[installer.installTargetMenu] = newMenu;
|
||||
targetMenu = newMenu;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
private VRCExpressionsMenu CloneMenu(VRCExpressionsMenu menu)
|
||||
{
|
||||
if (menu == null) return null;
|
||||
|
@ -6,10 +6,12 @@ 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 {
|
||||
public struct ChildElement {
|
||||
namespace nadena.dev.modular_avatar.core.editor
|
||||
{
|
||||
public class MenuTree
|
||||
{
|
||||
public struct ChildElement
|
||||
{
|
||||
public string menuName;
|
||||
public VRCExpressionsMenu menu;
|
||||
public VRCExpressionsMenu parent;
|
||||
@ -17,61 +19,83 @@ namespace nadena.dev.modular_avatar.core.editor {
|
||||
public bool isInstallerRoot;
|
||||
}
|
||||
|
||||
private class ImmutableBuilder
|
||||
{
|
||||
public ImmutableArray<ChildElement> immutableArray;
|
||||
public ImmutableArray<ChildElement>.Builder builder;
|
||||
}
|
||||
|
||||
private readonly HashSet<VRCExpressionsMenu> _included;
|
||||
|
||||
private readonly VRCExpressionsMenu _rootMenu;
|
||||
private readonly Dictionary<VRCExpressionsMenu, List<ChildElement>> _menuChildrenMap;
|
||||
private readonly Dictionary<VRCExpressionsMenu, ImmutableBuilder> _menuChildrenMap;
|
||||
|
||||
public MenuTree(VRCAvatarDescriptor descriptor) {
|
||||
public MenuTree(VRCAvatarDescriptor descriptor)
|
||||
{
|
||||
this._rootMenu = descriptor.expressionsMenu;
|
||||
this._included = new HashSet<VRCExpressionsMenu>();
|
||||
this._menuChildrenMap = new Dictionary<VRCExpressionsMenu, List<ChildElement>>();
|
||||
this._menuChildrenMap = new Dictionary<VRCExpressionsMenu, ImmutableBuilder>();
|
||||
|
||||
if (this._rootMenu == null) {
|
||||
if (this._rootMenu == null)
|
||||
{
|
||||
this._rootMenu = ScriptableObject.CreateInstance<VRCExpressionsMenu>();
|
||||
}
|
||||
|
||||
this._included.Add(this._rootMenu);
|
||||
}
|
||||
|
||||
public void AvatarsMenuMapping() {
|
||||
public void AvatarsMenuMapping()
|
||||
{
|
||||
if (this._rootMenu == null) return;
|
||||
this.MappingMenu(this._rootMenu);
|
||||
}
|
||||
|
||||
public void MappingMenuInstaller(ModularAvatarMenuInstaller installer) {
|
||||
public void MappingMenuInstaller(ModularAvatarMenuInstaller installer)
|
||||
{
|
||||
if (!installer.enabled) return;
|
||||
if (installer.menuToAppend == null) return;
|
||||
this.MappingMenu(installer);
|
||||
}
|
||||
|
||||
public IEnumerable<ChildElement> GetChildren(VRCExpressionsMenu parent) {
|
||||
// TODO: ライブラリとするのであれば、複製したリスト or ImmutableArray,を返すのが好ましい
|
||||
public ImmutableArray<ChildElement> GetChildren(VRCExpressionsMenu parent)
|
||||
{
|
||||
if (parent == null) parent = this._rootMenu;
|
||||
return this._menuChildrenMap.TryGetValue(parent, out List<ChildElement> children)
|
||||
? children
|
||||
: Enumerable.Empty<ChildElement>();
|
||||
if (!this._menuChildrenMap.TryGetValue(parent, out ImmutableBuilder immutableBuilder)) return ImmutableArray<ChildElement>.Empty;
|
||||
if (immutableBuilder.immutableArray == ImmutableArray<ChildElement>.Empty)
|
||||
{
|
||||
immutableBuilder.immutableArray = immutableBuilder.builder.ToImmutable();
|
||||
}
|
||||
return immutableBuilder.immutableArray;
|
||||
}
|
||||
|
||||
public IEnumerable<ChildElement> GetChildInstallers(ModularAvatarMenuInstaller parentInstaller) {
|
||||
public IEnumerable<ChildElement> GetChildInstallers(ModularAvatarMenuInstaller parentInstaller)
|
||||
{
|
||||
HashSet<VRCExpressionsMenu> visitedMenus = new HashSet<VRCExpressionsMenu>();
|
||||
Queue<VRCExpressionsMenu> queue = new Queue<VRCExpressionsMenu>();
|
||||
if (parentInstaller != null && parentInstaller.menuToAppend == null) yield break;
|
||||
if (parentInstaller == null) {
|
||||
if (parentInstaller == null)
|
||||
{
|
||||
queue.Enqueue(this._rootMenu);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parentInstaller.menuToAppend == null) yield break;
|
||||
foreach (KeyValuePair<string,VRCExpressionsMenu> childMenu in GetChildMenus(parentInstaller.menuToAppend)) {
|
||||
foreach (KeyValuePair<string, VRCExpressionsMenu> childMenu in GetChildMenus(parentInstaller.menuToAppend))
|
||||
{
|
||||
queue.Enqueue(childMenu.Value);
|
||||
}
|
||||
}
|
||||
while (queue.Count > 0) {
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
VRCExpressionsMenu parentMenu = queue.Dequeue();
|
||||
if (visitedMenus.Contains(parentMenu)) continue;
|
||||
visitedMenus.Add(parentMenu);
|
||||
HashSet<ModularAvatarMenuInstaller> returnedInstallers = new HashSet<ModularAvatarMenuInstaller>();
|
||||
foreach (ChildElement childElement in this.GetChildren(parentMenu)) {
|
||||
if (!childElement.isInstallerRoot) {
|
||||
foreach (ChildElement childElement in this.GetChildren(parentMenu))
|
||||
{
|
||||
if (!childElement.isInstallerRoot)
|
||||
{
|
||||
queue.Enqueue(childElement.menu);
|
||||
continue;
|
||||
}
|
||||
@ -84,51 +108,82 @@ namespace nadena.dev.modular_avatar.core.editor {
|
||||
}
|
||||
|
||||
|
||||
private void MappingMenu(VRCExpressionsMenu root) {
|
||||
foreach (KeyValuePair<string, VRCExpressionsMenu> childMenu in GetChildMenus(root)) {
|
||||
this.MappingMenu(root, new ChildElement {
|
||||
private void MappingMenu(VRCExpressionsMenu root)
|
||||
{
|
||||
foreach (KeyValuePair<string, VRCExpressionsMenu> childMenu in GetChildMenus(root))
|
||||
{
|
||||
this.MappingMenu(root, new ChildElement
|
||||
{
|
||||
menuName = childMenu.Key,
|
||||
menu = childMenu.Value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void MappingMenu(ModularAvatarMenuInstaller installer) {
|
||||
private void MappingMenu(ModularAvatarMenuInstaller installer)
|
||||
{
|
||||
IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> childMenus = GetChildMenus(installer.menuToAppend);
|
||||
IEnumerable<VRCExpressionsMenu> parents = Enumerable.Empty<VRCExpressionsMenu>();
|
||||
if (installer.installTargetMenu != null &&
|
||||
ClonedMenuMappings.TryGetClonedMenus(installer.installTargetMenu, out ImmutableArray<VRCExpressionsMenu> parentMenus)) {
|
||||
ClonedMenuMappings.TryGetClonedMenus(installer.installTargetMenu, out ImmutableArray<VRCExpressionsMenu> parentMenus))
|
||||
{
|
||||
parents = parentMenus;
|
||||
}
|
||||
|
||||
VRCExpressionsMenu[] parentsMenus = parents.DefaultIfEmpty(installer.installTargetMenu).ToArray();
|
||||
|
||||
foreach (KeyValuePair<string, VRCExpressionsMenu> childMenu in childMenus) {
|
||||
ChildElement childElement = new ChildElement {
|
||||
bool isControlOnlyMenu = true;
|
||||
foreach (KeyValuePair<string, VRCExpressionsMenu> childMenu in childMenus)
|
||||
{
|
||||
isControlOnlyMenu = false;
|
||||
ChildElement childElement = new ChildElement
|
||||
{
|
||||
menuName = childMenu.Key,
|
||||
menu = childMenu.Value,
|
||||
installer = installer,
|
||||
isInstallerRoot = true
|
||||
};
|
||||
foreach (VRCExpressionsMenu parentMenu in parentsMenus) {
|
||||
foreach (VRCExpressionsMenu parentMenu in parentsMenus)
|
||||
{
|
||||
this.MappingMenu(parentMenu, childElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isControlOnlyMenu) return;
|
||||
{
|
||||
foreach (VRCExpressionsMenu parentMenu in parentsMenus)
|
||||
{
|
||||
this.MappingMenu(parentMenu, new ChildElement
|
||||
{
|
||||
installer = installer,
|
||||
isInstallerRoot = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MappingMenu(VRCExpressionsMenu parent, ChildElement childElement) {
|
||||
private void MappingMenu(VRCExpressionsMenu parent, ChildElement childElement)
|
||||
{
|
||||
if (parent == null) parent = this._rootMenu;
|
||||
childElement.parent = parent;
|
||||
if (!this._menuChildrenMap.TryGetValue(parent, out List<ChildElement> children)) {
|
||||
children = new List<ChildElement>();
|
||||
if (!this._menuChildrenMap.TryGetValue(parent, out ImmutableBuilder children))
|
||||
{
|
||||
children = new ImmutableBuilder
|
||||
{
|
||||
builder = ImmutableArray.CreateBuilder<ChildElement>(),
|
||||
immutableArray = ImmutableArray<ChildElement>.Empty
|
||||
};
|
||||
this._menuChildrenMap[parent] = children;
|
||||
}
|
||||
|
||||
children.Add(childElement);
|
||||
children.builder.Add(childElement);
|
||||
children.immutableArray = ImmutableArray<ChildElement>.Empty;
|
||||
if (childElement.menu == null) return;
|
||||
if (this._included.Contains(childElement.menu)) return;
|
||||
this._included.Add(childElement.menu);
|
||||
foreach (KeyValuePair<string, VRCExpressionsMenu> childMenu in GetChildMenus(childElement.menu)) {
|
||||
this.MappingMenu(childElement.menu, new ChildElement {
|
||||
foreach (KeyValuePair<string, VRCExpressionsMenu> childMenu in GetChildMenus(childElement.menu))
|
||||
{
|
||||
this.MappingMenu(childElement.menu, new ChildElement
|
||||
{
|
||||
menuName = childMenu.Key,
|
||||
menu = childMenu.Value,
|
||||
installer = childElement.installer
|
||||
@ -136,7 +191,8 @@ namespace nadena.dev.modular_avatar.core.editor {
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> GetChildMenus(VRCExpressionsMenu expressionsMenu) {
|
||||
private static IEnumerable<KeyValuePair<string, VRCExpressionsMenu>> GetChildMenus(VRCExpressionsMenu expressionsMenu)
|
||||
{
|
||||
return expressionsMenu.controls
|
||||
.Where(control => control.type == ControlType.SubMenu && control.subMenu != null)
|
||||
.Select(control => new KeyValuePair<string, VRCExpressionsMenu>(control.name, control.subMenu));
|
||||
|
Loading…
x
Reference in New Issue
Block a user