From 9e2c8fadf5ef3018bbabb693b95aa32374dab562 Mon Sep 17 00:00:00 2001 From: bd_ Date: Fri, 24 Feb 2023 20:33:12 +0900 Subject: [PATCH] fixing some bugs --- .../Editor/Inspector/AvMenuTreeView.cs | 8 ++++ .../MenuGeneration/MenuInstallerEditor.cs | 47 +++++++++---------- .../Editor/MenuExtractor.cs | 1 + .../Editor/MenuGeneration/VirtualMenu.cs | 19 ++++++-- .../Runtime/menu/VirtualMenuAPI.cs | 2 +- 5 files changed, 49 insertions(+), 28 deletions(-) diff --git a/Packages/nadena.dev.modular-avatar/Editor/Inspector/AvMenuTreeView.cs b/Packages/nadena.dev.modular-avatar/Editor/Inspector/AvMenuTreeView.cs index 3e089c77..c5fefa54 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Inspector/AvMenuTreeView.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Inspector/AvMenuTreeView.cs @@ -17,6 +17,7 @@ namespace nadena.dev.modular_avatar.core.editor { private VRCAvatarDescriptor _avatarDescriptor; private AvMenuTreeView _treeView; + private long _cacheIndex = -1; public VRCAvatarDescriptor Avatar { @@ -37,6 +38,7 @@ namespace nadena.dev.modular_avatar.core.editor _treeView = new AvMenuTreeView(new TreeViewState()); _treeView.OnSelect = (menu) => OnMenuSelected.Invoke(menu); _treeView.OnDoubleclickSelect = Close; + _cacheIndex = -1; } private void OnLostFocus() @@ -57,6 +59,12 @@ namespace nadena.dev.modular_avatar.core.editor return; } + if (_cacheIndex != VirtualMenu.CacheSequence) + { + _treeView.Reload(); + _cacheIndex = VirtualMenu.CacheSequence; + } + _treeView.OnGUI(new Rect(0, 0, position.width, position.height)); } diff --git a/Packages/nadena.dev.modular-avatar/Editor/Inspector/MenuGeneration/MenuInstallerEditor.cs b/Packages/nadena.dev.modular-avatar/Editor/Inspector/MenuGeneration/MenuInstallerEditor.cs index a4ab167b..7ec187f4 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Inspector/MenuGeneration/MenuInstallerEditor.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Inspector/MenuGeneration/MenuInstallerEditor.cs @@ -202,6 +202,22 @@ namespace nadena.dev.modular_avatar.core.editor DestroyInstallTargets(); } + if (menu is ModularAvatarMenuItem item) + { + if (item.MenuSource == SubmenuSource.MenuAsset) + { + menu = item.Control.subMenu; + } + else + { + var menuParent = item.menuSource_otherObjectChildren != null + ? item.menuSource_otherObjectChildren + : item.gameObject; + + menu = new MenuNodesUnder(menuParent); + } + } + if (menu is VRCExpressionsMenu expMenu) { if (expMenu == avatar.expressionsMenu) installTo.objectReferenceValue = null; @@ -211,7 +227,7 @@ namespace nadena.dev.modular_avatar.core.editor { installTo.objectReferenceValue = null; } - else if (menu is ModularAvatarMenuItem item) + else if (menu is MenuNodesUnder nodesUnder) { installTo.objectReferenceValue = null; @@ -220,11 +236,13 @@ namespace nadena.dev.modular_avatar.core.editor var installer = (ModularAvatarMenuInstaller) target; var child = new GameObject(); Undo.RegisterCreatedObjectUndo(child, "Set install target"); - child.transform.SetParent(item.transform, false); + child.transform.SetParent(nodesUnder.root.transform, false); child.name = installer.gameObject.name; var targetComponent = child.AddComponent(); targetComponent.installer = installer; + + EditorGUIUtility.PingObject(child); } } @@ -504,30 +522,11 @@ namespace nadena.dev.modular_avatar.core.editor } } - private bool IsMenuReachable(VRCAvatarDescriptor avatar, VRCExpressionsMenu menu, - HashSet visitedInstaller = null) + private bool IsMenuReachable(VRCAvatarDescriptor avatar, VRCExpressionsMenu menu) { - if (_avatarMenus == null || _avatarMenus.Contains(menu)) return true; + var virtualMenu = VirtualMenu.ForAvatar(avatar); - if (_menuInstallersMap == null) return true; - if (visitedInstaller == null) - visitedInstaller = new HashSet {(ModularAvatarMenuInstaller) target}; - - if (!_menuInstallersMap.TryGetValue(menu, out List installers)) return false; - foreach (ModularAvatarMenuInstaller installer in installers) - { - // Root is always reachable if installTargetMenu is null - if (installer.installTargetMenu == null) return true; - // Even in a circular structure, it may be possible to reach root by another path. - if (visitedInstaller.Contains(installer)) continue; - visitedInstaller.Add(installer); - if (IsMenuReachable(avatar, installer.installTargetMenu, visitedInstaller)) - { - return true; - } - } - - return false; + return virtualMenu.ContainsMenu(menu); } private static ValidateExpressionMenuIconResult ValidateExpressionMenuIcon(VRCExpressionsMenu menu, diff --git a/Packages/nadena.dev.modular-avatar/Editor/MenuExtractor.cs b/Packages/nadena.dev.modular-avatar/Editor/MenuExtractor.cs index 79cc3163..8ce9865d 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/MenuExtractor.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/MenuExtractor.cs @@ -21,6 +21,7 @@ namespace nadena.dev.modular_avatar.core.editor var parent = ExtractSingleLayerMenu(avatar.expressionsMenu, gameObj, "Avatar Menu"); parent.AddComponent(); + parent.AddComponent(); // The VRCSDK requires that an expressions menu asset be provided if any parameters are defined. // We can't just remove the asset, so we'll replace it with a dummy asset. However, to avoid users diff --git a/Packages/nadena.dev.modular-avatar/Editor/MenuGeneration/VirtualMenu.cs b/Packages/nadena.dev.modular-avatar/Editor/MenuGeneration/VirtualMenu.cs index d82f6183..54c238ef 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/MenuGeneration/VirtualMenu.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/MenuGeneration/VirtualMenu.cs @@ -40,16 +40,20 @@ namespace nadena.dev.modular_avatar.core.editor.menu private readonly VirtualMenuNode _node; private readonly NodeForDelegate _nodeFor; + private readonly Action _visitedMenu; private readonly HashSet _visited = new HashSet(); public NodeContextImpl( VirtualMenuNode node, NodeForDelegate nodeFor, - ImmutableDictionary> menuToInstallerMap) + ImmutableDictionary> menuToInstallerMap, + Action visitedMenu + ) { _node = node; _nodeFor = nodeFor; _menuToInstallerMap = menuToInstallerMap; + _visitedMenu = visitedMenu; } public void PushNode(VRCExpressionsMenu expMenu) @@ -57,6 +61,7 @@ namespace nadena.dev.modular_avatar.core.editor.menu if (expMenu == null) return; if (_visited.Contains(expMenu)) return; _visited.Add(expMenu); + _visitedMenu(expMenu); foreach (var control in expMenu.controls) { @@ -169,6 +174,7 @@ namespace nadena.dev.modular_avatar.core.editor.menu public VirtualMenuNode RootMenuNode => ResolvedMenu[RootMenuKey]; private Queue _pendingGeneration = new Queue(); + private HashSet _visitedMenus = new HashSet(); /// /// Initializes the VirtualMenu. @@ -271,7 +277,8 @@ namespace nadena.dev.modular_avatar.core.editor.menu var RootNode = new VirtualMenuNode(RootMenuKey); _resolvedMenu[RootMenuKey] = RootNode; - var rootContext = new NodeContextImpl(RootNode, NodeFor, menuToInstallerFiltered); + var rootContext = + new NodeContextImpl(RootNode, NodeFor, menuToInstallerFiltered, m => _visitedMenus.Add(m)); if (RootMenuKey is VRCExpressionsMenu menu) { foreach (var control in menu.controls) @@ -303,7 +310,8 @@ namespace nadena.dev.modular_avatar.core.editor.menu { BuildReport.ReportingObject(key as UnityEngine.Object, () => { - var context = new NodeContextImpl(node, NodeFor, menuToInstallerFiltered); + var context = new NodeContextImpl(node, NodeFor, menuToInstallerFiltered, + m => _visitedMenus.Add(m)); if (key is VRCExpressionsMenu expMenu) { context.PushNode(expMenu); @@ -361,5 +369,10 @@ namespace nadena.dev.modular_avatar.core.editor.menu return menu; } } + + public bool ContainsMenu(VRCExpressionsMenu menu) + { + return _visitedMenus.Contains(menu); + } } } \ No newline at end of file diff --git a/Packages/nadena.dev.modular-avatar/Runtime/menu/VirtualMenuAPI.cs b/Packages/nadena.dev.modular-avatar/Runtime/menu/VirtualMenuAPI.cs index 7e6aa8b6..d0159a11 100644 --- a/Packages/nadena.dev.modular-avatar/Runtime/menu/VirtualMenuAPI.cs +++ b/Packages/nadena.dev.modular-avatar/Runtime/menu/VirtualMenuAPI.cs @@ -64,7 +64,7 @@ namespace nadena.dev.modular_avatar.core.menu /// internal class MenuNodesUnder : MenuSource { - private readonly GameObject root; + internal readonly GameObject root; public MenuNodesUnder(GameObject root) {