diff --git a/Packages/nadena.dev.modular-avatar/Editor/ClonedMenuMappings.cs b/Packages/nadena.dev.modular-avatar/Editor/ClonedMenuMappings.cs index 0d938f27..a886193e 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/ClonedMenuMappings.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/ClonedMenuMappings.cs @@ -6,9 +6,17 @@ namespace nadena.dev.modular_avatar.core.editor { internal static class ClonedMenuMappings { + /// + /// Map to link the cloned menu from the clone source. + /// If one menu is specified for multiple installers, they are replicated separately, so there is a one-to-many relationship. + /// private static readonly Dictionary> ClonedMappings = new Dictionary>(); + /// + /// Map to link the clone source from the cloned menu. + /// Map is the opposite of ClonedMappings. + /// private static readonly Dictionary OriginalMapping = new Dictionary(); diff --git a/Packages/nadena.dev.modular-avatar/Editor/MenuTree.cs b/Packages/nadena.dev.modular-avatar/Editor/MenuTree.cs index 58c16de0..cde6ab69 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/MenuTree.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/MenuTree.cs @@ -13,16 +13,29 @@ namespace nadena.dev.modular_avatar.core.editor public struct ChildElement { + /// + /// Parent menu control name + /// public string menuName; public VRCExpressionsMenu menu; public VRCExpressionsMenu parent; + /// + /// Installer to install this menu. Is null if the this menu is not installed by the installer. + /// public ModularAvatarMenuInstaller installer; + /// + /// Whether the this submenu is added directly by the installer + /// public bool isInstallerRoot; } private readonly HashSet _included; private readonly VRCExpressionsMenu _rootMenu; + + /// + /// Map to link child menus from parent menu + /// private readonly Dictionary> _menuChildrenMap; public MenuTree(VRCAvatarDescriptor descriptor) @@ -33,6 +46,7 @@ namespace nadena.dev.modular_avatar.core.editor if (_rootMenu == null) { + // If the route menu is null, create a temporary menu indicating the route _rootMenu = ScriptableObject.CreateInstance(); } @@ -89,7 +103,8 @@ namespace nadena.dev.modular_avatar.core.editor queue.Enqueue(childElement.menu); continue; } - + + // One installer may add multiple children, so filter to return only one. if (returnedInstallers.Contains(childElement.installer)) continue; returnedInstallers.Add(childElement.installer); yield return childElement; @@ -122,6 +137,11 @@ namespace nadena.dev.modular_avatar.core.editor VRCExpressionsMenu[] parentsMenus = parents.DefaultIfEmpty(installer.installTargetMenu).ToArray(); bool hasChildMenu = false; + /* + * Installer adds the controls in specified menu to the installation destination. + * So, since the specified menu itself does not exist as a child menu, + * and the child menus of the specified menu are the actual child menus, a single installer may add multiple child menus. + */ foreach (KeyValuePair childMenu in childMenus) { hasChildMenu = true; @@ -139,6 +159,10 @@ namespace nadena.dev.modular_avatar.core.editor } if (hasChildMenu) return; + /* + * If the specified menu does not have any submenus, it is not mapped as a child menu and the Installer information itself is not registered. + * Therefore, register elements that do not have child menus themselves, but only have information about the installer. + */ foreach (VRCExpressionsMenu parentMenu in parentsMenus) { TraverseMenu(parentMenu, new ChildElement