mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-04-24 13:29:01 +08:00
fixing some bugs
This commit is contained in:
parent
55491dfa05
commit
9e2c8fadf5
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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<ModularAvatarMenuInstallTarget>();
|
||||
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<ModularAvatarMenuInstaller> 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> {(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;
|
||||
return virtualMenu.ContainsMenu(menu);
|
||||
}
|
||||
|
||||
private static ValidateExpressionMenuIconResult ValidateExpressionMenuIcon(VRCExpressionsMenu menu,
|
||||
|
@ -21,6 +21,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
var parent = ExtractSingleLayerMenu(avatar.expressionsMenu, gameObj, "Avatar Menu");
|
||||
parent.AddComponent<ModularAvatarMenuInstaller>();
|
||||
parent.AddComponent<ModularAvatarMenuGroup>();
|
||||
|
||||
// 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
|
||||
|
@ -40,16 +40,20 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
||||
|
||||
private readonly VirtualMenuNode _node;
|
||||
private readonly NodeForDelegate _nodeFor;
|
||||
private readonly Action<VRCExpressionsMenu> _visitedMenu;
|
||||
private readonly HashSet<object> _visited = new HashSet<object>();
|
||||
|
||||
public NodeContextImpl(
|
||||
VirtualMenuNode node,
|
||||
NodeForDelegate nodeFor,
|
||||
ImmutableDictionary<object, ImmutableList<ModularAvatarMenuInstaller>> menuToInstallerMap)
|
||||
ImmutableDictionary<object, ImmutableList<ModularAvatarMenuInstaller>> menuToInstallerMap,
|
||||
Action<VRCExpressionsMenu> 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<Action> _pendingGeneration = new Queue<Action>();
|
||||
private HashSet<VRCExpressionsMenu> _visitedMenus = new HashSet<VRCExpressionsMenu>();
|
||||
|
||||
/// <summary>
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -64,7 +64,7 @@ namespace nadena.dev.modular_avatar.core.menu
|
||||
/// </summary>
|
||||
internal class MenuNodesUnder : MenuSource
|
||||
{
|
||||
private readonly GameObject root;
|
||||
internal readonly GameObject root;
|
||||
|
||||
public MenuNodesUnder(GameObject root)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user