mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-04-24 21:38:59 +08:00
Changed IsMenuReachable method to verify that AvatarMenu can be reached via multiple Installers
This commit is contained in:
parent
3d26682718
commit
fc3ee7a47f
@ -26,11 +26,14 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
private HashSet<VRCExpressionsMenu> _avatarMenus;
|
private HashSet<VRCExpressionsMenu> _avatarMenus;
|
||||||
private HashSet<ModularAvatarSubMenuCreator> _menuFolderCreators;
|
private HashSet<ModularAvatarSubMenuCreator> _menuFolderCreators;
|
||||||
|
|
||||||
|
private Dictionary<VRCExpressionsMenu, List<ModularAvatarMenuInstaller>> _menuInstallersMap;
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
_installer = (ModularAvatarMenuInstaller) target;
|
_installer = (ModularAvatarMenuInstaller) target;
|
||||||
|
|
||||||
FindMenus();
|
FindMenus();
|
||||||
|
FindMenuInstallers();
|
||||||
FindMenuFolderCreators();
|
FindMenuFolderCreators();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +253,48 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FindMenuInstallers()
|
||||||
|
{
|
||||||
|
if (targets.Length > 1)
|
||||||
|
{
|
||||||
|
_menuInstallersMap = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_menuInstallersMap = new Dictionary<VRCExpressionsMenu, List<ModularAvatarMenuInstaller>>();
|
||||||
|
var avatar = RuntimeUtil.FindAvatarInParents(((Component)target).transform);
|
||||||
|
if (avatar == null) return;
|
||||||
|
var menuInstallers = avatar.GetComponentsInChildren<ModularAvatarMenuInstaller>();
|
||||||
|
foreach (ModularAvatarMenuInstaller menuInstaller in menuInstallers)
|
||||||
|
{
|
||||||
|
if (menuInstaller == target) continue;
|
||||||
|
if (menuInstaller.menuToAppend == null) continue;
|
||||||
|
var visitedMenus = new HashSet<VRCExpressionsMenu>();
|
||||||
|
var queue = new Queue<VRCExpressionsMenu>();
|
||||||
|
queue.Enqueue(menuInstaller.menuToAppend);
|
||||||
|
|
||||||
|
while (queue.Count > 0)
|
||||||
|
{
|
||||||
|
VRCExpressionsMenu parent = queue.Dequeue();
|
||||||
|
var controls = parent.controls.Where(control => control.type == VRCExpressionsMenu.Control.ControlType.SubMenu && control.subMenu != null);
|
||||||
|
foreach (VRCExpressionsMenu.Control control in controls)
|
||||||
|
{
|
||||||
|
// Do not filter in LINQ to avoid closure allocation
|
||||||
|
if (visitedMenus.Contains(control.subMenu)) continue;
|
||||||
|
if (!_menuInstallersMap.TryGetValue(control.subMenu, out List<ModularAvatarMenuInstaller> fromInstallers))
|
||||||
|
{
|
||||||
|
fromInstallers = new List<ModularAvatarMenuInstaller>();
|
||||||
|
_menuInstallersMap[control.subMenu] = fromInstallers;
|
||||||
|
}
|
||||||
|
|
||||||
|
fromInstallers.Add(menuInstaller);
|
||||||
|
visitedMenus.Add(control.subMenu);
|
||||||
|
queue.Enqueue(control.subMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void FindMenuFolderCreators()
|
private void FindMenuFolderCreators()
|
||||||
{
|
{
|
||||||
if (this.targets.Length > 1)
|
if (this.targets.Length > 1)
|
||||||
@ -267,9 +312,28 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsMenuReachable(VRCAvatarDescriptor avatar, VRCExpressionsMenu menu)
|
private bool IsMenuReachable(VRCAvatarDescriptor avatar, VRCExpressionsMenu menu, HashSet<ModularAvatarMenuInstaller> visitedInstaller = null)
|
||||||
{
|
{
|
||||||
return _avatarMenus == null || _avatarMenus.Contains(menu);
|
if (_avatarMenus == null || _avatarMenus.Contains(menu)) return true;
|
||||||
|
|
||||||
|
if (_menuInstallersMap == null) return true;
|
||||||
|
if (visitedInstaller == null) visitedInstaller = new HashSet<ModularAvatarMenuInstaller> { (ModularAvatarMenuInstaller)target };
|
||||||
|
|
||||||
|
if (!_menuInstallersMap.TryGetValue(menu, out List<ModularAvatarMenuInstaller> 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsMenuReachable(VRCAvatarDescriptor avatar, ModularAvatarSubMenuCreator creator, HashSet<ModularAvatarSubMenuCreator> session)
|
private bool IsMenuReachable(VRCAvatarDescriptor avatar, ModularAvatarSubMenuCreator creator, HashSet<ModularAvatarSubMenuCreator> session)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user