ToggleGroup UI

This commit is contained in:
bd_ 2023-03-01 00:26:45 +09:00
parent 64d831672a
commit f2ef8099b0
4 changed files with 199 additions and 74 deletions

View File

@ -81,10 +81,7 @@ namespace nadena.dev.modular_avatar.core.editor
protected virtual VisualElement CreateInnerInspectorGUI()
{
var throwaway = new InspectorElement();
MethodInfo m = typeof(InspectorElement).GetMethod("CreateIMGUIInspectorFromEditor",
BindingFlags.NonPublic | BindingFlags.Instance);
return m.Invoke(throwaway, new object[] {serializedObject, this, false}) as VisualElement;
return null;
}
public sealed override VisualElement CreateInspectorGUI()
@ -94,10 +91,19 @@ namespace nadena.dev.modular_avatar.core.editor
var inner = CreateInnerInspectorGUI();
bool innerIsImgui = (inner == null);
if (innerIsImgui)
{
var throwaway = new InspectorElement();
MethodInfo m = typeof(InspectorElement).GetMethod("CreateIMGUIInspectorFromEditor",
BindingFlags.NonPublic | BindingFlags.Instance);
inner = m.Invoke(throwaway, new object[] {serializedObject, this, false}) as VisualElement;
}
_visualElement = new MAVisualElement();
_visualElement.Add(inner);
_suppressOnceDefaultMargins = true;
_suppressOnceDefaultMargins = innerIsImgui;
return _visualElement;
}

View File

@ -7,69 +7,38 @@ using VRC.SDK3.Avatars.ScriptableObjects;
namespace nadena.dev.modular_avatar.core.editor
{
internal class MenuPreviewGUI
internal class MenuObjectHeader
{
private const float INDENT_PER_LEVEL = 2;
private Action _redraw;
private float _indentLevel = 0;
private readonly Dictionary<object, Action> _guiNodes = new Dictionary<object, Action>();
private static float _indentLevel = 0;
public MenuPreviewGUI(Action redraw)
private UnityEngine.Object _headerObj;
private SerializedProperty _disableProp;
public MenuObjectHeader(UnityEngine.Object headerObj, SerializedProperty disableProp = null)
{
_redraw = redraw;
_headerObj = headerObj;
_disableProp = disableProp;
}
public void DoGUI(MenuSource root)
public static void ClearIndent()
{
_indentLevel = 0;
new VisitorContext(this).PushNode(root);
}
public void DoGUI(ModularAvatarMenuInstaller root)
public IDisposable Scope()
{
_indentLevel = 0;
new VisitorContext(this).PushMenuInstaller(root);
}
GUILayout.BeginHorizontal();
GUILayout.Space(_indentLevel);
_indentLevel += INDENT_PER_LEVEL;
public void DoGUI(VRCExpressionsMenu menu, GameObject parameterReference = null)
{
_indentLevel = 0;
new VisitorContext(this).PushNode(menu);
}
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
private void PushGuiNode(object key, Func<Action> guiBuilder)
{
if (!_guiNodes.TryGetValue(key, out var gui))
if (_headerObj != null)
{
gui = guiBuilder();
_guiNodes.Add(key, gui);
}
gui();
}
private class Header
{
private MenuPreviewGUI _gui;
private UnityEngine.Object _headerObj;
private SerializedProperty _disableProp;
public Header(MenuPreviewGUI gui, UnityEngine.Object headerObj, SerializedProperty disableProp = null)
{
_gui = gui;
_headerObj = headerObj;
_disableProp = disableProp;
}
public IDisposable Scope()
{
GUILayout.BeginHorizontal();
GUILayout.Space(_gui._indentLevel);
_gui._indentLevel += INDENT_PER_LEVEL;
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
if (_headerObj != null)
var oldIndent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
try
{
GUILayout.BeginHorizontal();
using (new EditorGUI.DisabledScope(true))
@ -91,27 +60,66 @@ namespace nadena.dev.modular_avatar.core.editor
GUILayout.EndHorizontal();
}
return new ScopeSentinel(_gui);
finally
{
EditorGUI.indentLevel = oldIndent;
}
}
private class ScopeSentinel : IDisposable
return new ScopeSentinel();
}
private class ScopeSentinel : IDisposable
{
public ScopeSentinel()
{
private readonly MenuPreviewGUI _gui;
}
public ScopeSentinel(MenuPreviewGUI gui)
{
_gui = gui;
}
public void Dispose()
{
GUILayout.EndVertical();
_gui._indentLevel -= INDENT_PER_LEVEL;
GUILayout.EndHorizontal();
}
public void Dispose()
{
GUILayout.EndVertical();
_indentLevel -= INDENT_PER_LEVEL;
GUILayout.EndHorizontal();
}
}
}
internal class MenuPreviewGUI
{
private Action _redraw;
private readonly Dictionary<object, Action> _guiNodes = new Dictionary<object, Action>();
public MenuPreviewGUI(Action redraw)
{
_redraw = redraw;
}
public void DoGUI(MenuSource root)
{
new VisitorContext(this).PushNode(root);
}
public void DoGUI(ModularAvatarMenuInstaller root)
{
new VisitorContext(this).PushMenuInstaller(root);
}
public void DoGUI(VRCExpressionsMenu menu, GameObject parameterReference = null)
{
new VisitorContext(this).PushNode(menu);
}
private void PushGuiNode(object key, Func<Action> guiBuilder)
{
if (!_guiNodes.TryGetValue(key, out var gui))
{
gui = guiBuilder();
_guiNodes.Add(key, gui);
}
gui();
}
private class VisitorContext : NodeContext
{
@ -127,7 +135,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
_gui.PushGuiNode((expMenu, parameterReference), () =>
{
var header = new Header(_gui, expMenu);
var header = new MenuObjectHeader(expMenu);
var obj = new SerializedObject(expMenu);
var controls = obj.FindProperty(nameof(expMenu.controls));
var subGui = new List<MenuItemCoreGUI>();
@ -143,7 +151,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
foreach (var gui in subGui)
{
using (new Header(_gui, null).Scope())
using (new MenuObjectHeader(null).Scope())
{
gui.DoGUI();
}
@ -164,7 +172,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
_gui.PushGuiNode(item, () =>
{
var header = new Header(_gui, item,
var header = new MenuObjectHeader(item,
new SerializedObject(item.gameObject).FindProperty("m_IsActive"));
var gui = new MenuItemCoreGUI(new SerializedObject(item), _gui._redraw);
return () =>
@ -178,7 +186,7 @@ namespace nadena.dev.modular_avatar.core.editor
}
else
{
using (new Header(_gui, source as UnityEngine.Object).Scope())
using (new MenuObjectHeader(source as UnityEngine.Object).Scope())
{
if (_visited.Contains(source)) return;
_visited.Add(source);
@ -190,7 +198,7 @@ namespace nadena.dev.modular_avatar.core.editor
public void PushNode(ModularAvatarMenuInstaller installer)
{
using (new Header(_gui, installer).Scope())
using (new MenuObjectHeader(installer).Scope())
{
PushMenuInstaller(installer);
}

View File

@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace nadena.dev.modular_avatar.core.editor
{
[CustomEditor(typeof(ToggleGroup))]
internal class ToggleGroupInspector : MAEditorBase
{
private void OnEnable()
{
EditorApplication.hierarchyChanged += Invalidate;
}
private void OnDisable()
{
EditorApplication.hierarchyChanged -= Invalidate;
}
private List<Action> _menuItemActions = null;
private void Invalidate()
{
var target = (ToggleGroup) this.target;
var avatar = RuntimeUtil.FindAvatarInParents(target.transform);
var menuItems = avatar.GetComponentsInChildren<ModularAvatarMenuItem>(true);
_menuItemActions = new List<Action>();
foreach (var menuItem in menuItems.Where(item => item.toggleGroup == target))
{
var node = CreateMenuItemNode(menuItem);
_menuItemActions.Add(node);
}
}
private Action CreateMenuItemNode(ModularAvatarMenuItem menuItem)
{
bool foldout = false;
var coreUI = new MenuItemCoreGUI(new SerializedObject(menuItem), Repaint);
var enableMenuItem = new SerializedObject(menuItem.gameObject).FindProperty("m_IsActive");
List<Action> foldoutInspectors = null;
return () =>
{
using (new MenuObjectHeader(menuItem, enableMenuItem).Scope())
{
coreUI.DoGUI();
foldout = EditorGUILayout.Foldout(foldout, "Actions");
if (foldout)
{
if (foldoutInspectors == null)
{
foldoutInspectors = menuItem.GetComponents<MenuAction>()
.Select(action =>
{
var component = (Component) action;
var editor = CreateEditor(component);
var enabled_prop = new SerializedObject(component).FindProperty("m_Enabled");
return (Action) (() =>
{
using (new MenuObjectHeader(component, enabled_prop).Scope())
{
editor.OnInspectorGUI();
}
});
})
.ToList();
}
foreach (var inspector in foldoutInspectors)
{
inspector();
}
}
}
};
}
protected override void OnInnerInspectorGUI()
{
if (_menuItemActions == null) Invalidate();
EditorGUILayout.LabelField("Bound menu items", EditorStyles.boldLabel);
foreach (var action in _menuItemActions)
{
try
{
EditorGUI.indentLevel++;
action();
}
finally
{
EditorGUI.indentLevel--;
}
EditorGUILayout.Space(4);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 357527439f084cd6812d6e5dcd9692f8
timeCreated: 1677595893