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