From 0138a89b5438381da71ff05edd96565b930c8276 Mon Sep 17 00:00:00 2001 From: tliks Date: Sat, 15 Mar 2025 11:50:38 +0900 Subject: [PATCH] chore: create toggle with submenu in CreateToggleForSelection --- .../Inspector/Menu/ToggleCreatorShortcut.cs | 97 ++++++++++++++++++- 1 file changed, 93 insertions(+), 4 deletions(-) diff --git a/Editor/Inspector/Menu/ToggleCreatorShortcut.cs b/Editor/Inspector/Menu/ToggleCreatorShortcut.cs index 14d7e9cb..04eda66b 100644 --- a/Editor/Inspector/Menu/ToggleCreatorShortcut.cs +++ b/Editor/Inspector/Menu/ToggleCreatorShortcut.cs @@ -1,5 +1,7 @@ #if MA_VRCSDK3_AVATARS +using System; using System.Linq; +using System.Collections.Generic; using nadena.dev.modular_avatar.ui; using UnityEditor; using UnityEngine; @@ -19,15 +21,72 @@ namespace nadena.dev.modular_avatar.core.editor selections = selections.Where(s => !TryGetChildrenSourceSubmenu(s, out var _)); if (selections.Count() == 0) return; + // Grouping according to parent + var groups = new Dictionary>(); foreach (var selected in selections) { - var avatarRoot = RuntimeUtil.FindAvatarTransformInParents(selected.transform); - if (avatarRoot == null) return; - var parent = selected.transform.parent?.gameObject; if (parent == null) continue; - CreateToggleImpl(selected, parent, selected.name + " Toggle", forSelection, createInstaller:true); + if (!groups.ContainsKey(parent)) + { + groups[parent] = new(); + } + groups[parent].Add(selected); + } + + foreach (var group in groups) + { + var parent = group.Key; + var targets = group.Value; + + if (parent == null) continue; + if (targets == null || targets.Count() == 0) continue; + + var avatarRoot = RuntimeUtil.FindAvatarTransformInParents(parent.transform); + if (avatarRoot == null) continue; + + var subMenuName = parent.name + " Toggles"; + + // Try to find target submenu that should be the parent of toggles + ModularAvatarMenuItem targetSubMenu = null; + if (TryGetChildrenSourceSubmenu(parent, out var subMenu)) + { + // If parent has subMenu, use it as target submenu. + targetSubMenu = subMenu; + } + else + { + // If parent hasn't subMenu, get submenus at the same level + var subMenus = new List(); + foreach (Transform sibling in parent.transform) + { + if (TryGetChildrenSourceSubmenu(sibling.gameObject, out var m)) { subMenus.Add(m); } + } + // Filter to submenus with the same name + subMenus = subMenus.Where(m => m.gameObject.name == subMenuName).ToList(); + // If only one submenu as target is found, use it as target submenu. + if (subMenus.Count() == 1) targetSubMenu = subMenus.First(); + } + + if (targetSubMenu != null) // If target SubMenu is found, add the toggles as children of it. + { + parent = targetSubMenu.gameObject; + CreateToggleImpl(targets, parent, s => s.name, forSelection, createInstaller:false); + } + else + { + if (targets.Count() > 1) // Create a submenu and add the toggles as children of it. + { + parent = CreateSubMenu(parent, subMenuName).gameObject; + CreateToggleImpl(targets, parent, s => s.name, forSelection, createInstaller:false); + } + else // Create a single toggle with installer. + { + var target = targets.First(); + CreateToggleImpl(target, parent, target.name + " Toggle", forSelection, createInstaller:true); + } + } } Selection.objects = null; @@ -79,7 +138,37 @@ namespace nadena.dev.modular_avatar.core.editor } return false; } + + private static ModularAvatarMenuItem CreateSubMenu(GameObject parent, string submenuname) + { + var submenu = new GameObject(submenuname); + submenu.transform.SetParent(parent.transform); + var mami = submenu.AddComponent(); + mami.InitSettings(); + mami.Control = new VRCExpressionsMenu.Control + { + type = VRCExpressionsMenu.Control.ControlType.SubMenu, + name = submenuname, + }; + submenu.AddComponent(); + + Selection.activeGameObject = submenu; + EditorGUIUtility.PingObject(submenu); + + Undo.RegisterCreatedObjectUndo(submenu, "Create SubMenu"); + + return mami; + } + + private static void CreateToggleImpl(IEnumerable selections, GameObject parent, Func nameFunc, bool forSelection = false, bool createInstaller = true) + { + foreach (var selected in selections) + { + CreateToggleImpl(selected, parent, nameFunc(selected), forSelection, createInstaller); + } + } + private static void CreateToggleImpl(GameObject selected, GameObject parent, string name, bool forSelection = false, bool createInstaller = true) { var avatarRoot = RuntimeUtil.FindAvatarTransformInParents(selected.transform);