From b7e4409d6bdee050e7a4388939b36e69325737c3 Mon Sep 17 00:00:00 2001 From: bd_ Date: Thu, 10 Nov 2022 20:30:10 -0800 Subject: [PATCH] Only show the logo once per inspector pane --- .../Inspector/AvatarParametersEditor.cs | 7 +- .../Editor/Inspector/BlendshapeSyncEditor.cs | 8 +- .../Editor/Inspector/BoneProxyEditor.cs | 7 +- .../Inspector/FirstPersonVisibleEditor.cs | 7 +- .../Editor/Inspector/LogoDisplay.cs | 9 +- .../Editor/Inspector/MAEditorBase.cs | 125 ++++++++++++++++++ .../Editor/Inspector/MAEditorBase.cs.meta | 3 + .../Editor/Inspector/MenuInstallerEditor.cs | 7 +- .../Editor/Inspector/MergeAnimationEditor.cs | 8 +- .../Editor/Inspector/MergeArmatureEditor.cs | 7 +- 10 files changed, 148 insertions(+), 40 deletions(-) create mode 100644 Packages/net.fushizen.modular-avatar/Editor/Inspector/MAEditorBase.cs create mode 100644 Packages/net.fushizen.modular-avatar/Editor/Inspector/MAEditorBase.cs.meta diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/AvatarParametersEditor.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/AvatarParametersEditor.cs index 850aed16..f8babb6b 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Inspector/AvatarParametersEditor.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/AvatarParametersEditor.cs @@ -12,7 +12,7 @@ using Debug = System.Diagnostics.Debug; namespace net.fushizen.modular_avatar.core.editor { [CustomEditor(typeof(ModularAvatarParameters))] - public class AvatarParametersEditor : Editor + internal class AvatarParametersEditor : MAEditorBase { /********************************************************************** * | Field name | Remap to / config | @@ -410,11 +410,8 @@ namespace net.fushizen.modular_avatar.core.editor if (!_devMode) EditorGUI.LabelField(rightHalf, G("params.remapto")); } - public override void OnInspectorGUI() + protected override void OnInnerInspectorGUI() { - LogoDisplay.DisplayLogo(); - InspectorCommon.DisplayOutOfAvatarWarning(targets); - EditorGUI.BeginChangeCheck(); _devMode = EditorGUILayout.Toggle(G("params.devmode"), _devMode); if (EditorGUI.EndChangeCheck() || _reorderableList == null || _needsRebuild) SetupList(); diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/BlendshapeSyncEditor.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/BlendshapeSyncEditor.cs index b9aced4f..531edccc 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Inspector/BlendshapeSyncEditor.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/BlendshapeSyncEditor.cs @@ -14,7 +14,7 @@ namespace net.fushizen.modular_avatar.core.editor { [CustomEditor(typeof(ModularAvatarBlendshapeSync))] [CanEditMultipleObjects] - internal class BlendshapeSyncEditor : Editor + internal class BlendshapeSyncEditor : MAEditorBase { private static FieldInfo f_m_SerializedObject; private BlendshapeSelectWindow _window; @@ -242,12 +242,8 @@ namespace net.fushizen.modular_avatar.core.editor return selections; } - public override void OnInspectorGUI() + protected override void OnInnerInspectorGUI() { - LogoDisplay.DisplayLogo(); - - InspectorCommon.DisplayOutOfAvatarWarning(targets); - serializedObject.Update(); _list.DoLayoutList(); diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/BoneProxyEditor.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/BoneProxyEditor.cs index 7abb37b3..b411c233 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Inspector/BoneProxyEditor.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/BoneProxyEditor.cs @@ -11,7 +11,7 @@ namespace net.fushizen.modular_avatar.core.editor [CustomEditor(typeof(ModularAvatarBoneProxy))] [CanEditMultipleObjects] - internal class BoneProxyEditor : Editor + internal class BoneProxyEditor : MAEditorBase { private bool foldout = false; @@ -26,11 +26,8 @@ namespace net.fushizen.modular_avatar.core.editor } } - public override void OnInspectorGUI() + protected override void OnInnerInspectorGUI() { - LogoDisplay.DisplayLogo(); - InspectorCommon.DisplayOutOfAvatarWarning(targets); - GameObject parentAvatar = null; bool suppressTarget = false; diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/FirstPersonVisibleEditor.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/FirstPersonVisibleEditor.cs index 01d76a16..6a0dd4cb 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Inspector/FirstPersonVisibleEditor.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/FirstPersonVisibleEditor.cs @@ -5,7 +5,7 @@ using UnityEngine; namespace net.fushizen.modular_avatar.core.editor { [CustomEditor(typeof(ModularAvatarVisibleHeadAccessory))] - public class FirstPersonVisibleEditor : Editor + internal class FirstPersonVisibleEditor : MAEditorBase { private VisibleHeadAccessoryProcessor _processor; @@ -17,13 +17,10 @@ namespace net.fushizen.modular_avatar.core.editor if (avatar != null) _processor = new VisibleHeadAccessoryProcessor(avatar); } - public override void OnInspectorGUI() + protected override void OnInnerInspectorGUI() { var target = (ModularAvatarVisibleHeadAccessory) this.target; - LogoDisplay.DisplayLogo(); - - InspectorCommon.DisplayOutOfAvatarWarning(targets); #if UNITY_ANDROID EditorGUILayout.HelpBox(Localization.S("fpvisible.quest"), MessageType.Warning); diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/LogoDisplay.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/LogoDisplay.cs index 705d360a..d636ac7e 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Inspector/LogoDisplay.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/LogoDisplay.cs @@ -12,7 +12,7 @@ namespace net.fushizen.modular_avatar.core.editor private static GUIStyle STYLE => new GUIStyle() { fixedHeight = TARGET_HEIGHT, - fixedWidth = TARGET_HEIGHT * (LOGO_ASSET.width / (float)LOGO_ASSET.height), + fixedWidth = TARGET_HEIGHT * (LOGO_ASSET.width / (float) LOGO_ASSET.height), stretchHeight = false, stretchWidth = false, imagePosition = ImagePosition.ImageOnly @@ -21,7 +21,7 @@ namespace net.fushizen.modular_avatar.core.editor static LogoDisplay() { var placeholderPath = AssetDatabase.GUIDToAssetPath("2a2bb4e0b8e906743890ef10c778e65c"); - + var path = placeholderPath.Substring(0, placeholderPath.LastIndexOf("/", StringComparison.Ordinal)); path += "/ma_logo.png"; @@ -35,10 +35,11 @@ namespace net.fushizen.modular_avatar.core.editor if (LOGO_ASSET == null) return; var height = TARGET_HEIGHT; - var width = (height / (float)LOGO_ASSET.height) * LOGO_ASSET.width; + var width = (height / (float) LOGO_ASSET.height) * LOGO_ASSET.width; var rect = GUILayoutUtility.GetRect(width, height); - + GUI.DrawTexture(rect, LOGO_ASSET, ScaleMode.ScaleToFit); + GUILayoutUtility.GetRect(width, EditorStyles.label.lineHeight / 2); } } } \ No newline at end of file diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/MAEditorBase.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MAEditorBase.cs new file mode 100644 index 00000000..5c8496e4 --- /dev/null +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MAEditorBase.cs @@ -0,0 +1,125 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace net.fushizen.modular_avatar.core.editor +{ + // This class performs common setup for Modular Avatar editors, including ensuring that only one instance of the\ + // logo is rendered per container. + internal abstract class MAEditorBase : Editor + { + private static Dictionary + _logoDisplayNode = new Dictionary(); + + private static void Cleanup() + { + _logoDisplayNode.Clear(); + EditorApplication.update -= Cleanup; + } + + private static MAVisualElement GetCachedLogoDisplayNode(VisualElement start) + { + while (start?.parent != null && start.GetType() != typeof(InspectorElement)) + { + start = start.parent; + } + + // Next one up is an EditorElement, followed by the container of all Editors + var container = start?.parent?.parent; + + if (container == null) return null; + + if (_logoDisplayNode.TryGetValue(container, out var elem)) return elem; + + var node = FindLogoDisplayNode(container); + if (node != null) _logoDisplayNode[container] = node; + EditorApplication.update += Cleanup; + return node; + } + + private static MAVisualElement FindLogoDisplayNode(VisualElement container) + { + // Now walk down to find the MAVisualElements. We only walk one level past an InspectorElement to avoid + // descending too deep into madness. + List elements = new List(); + + WalkTree(container); + + return elements.FirstOrDefault(e => e.resolvedStyle.visibility == Visibility.Visible); + + void WalkTree(VisualElement visualElement) + { + if (visualElement.resolvedStyle.visibility == Visibility.Hidden || + visualElement.resolvedStyle.height < 0.5) return; + + var isInspector = visualElement.GetType() == typeof(InspectorElement); + + foreach (var child in visualElement.Children()) + { + if (child is MAVisualElement maChild) + { + elements.Add(maChild); + return; + } + else if (!isInspector) + { + WalkTree(child); + } + } + } + } + + private class MAVisualElement : VisualElement + { + } + + private MAVisualElement _visualElement; + private bool _suppressOnceDefaultMargins; + + 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; + } + + public sealed override VisualElement CreateInspectorGUI() + { + // CreateInspectorElementFromEditor does a bunch of extra setup that makes our inspector look a little bit + // nicer. In particular, the label column won't auto-size if we just use IMGUIElement, for some reason + + var inner = CreateInnerInspectorGUI(); + + _visualElement = new MAVisualElement(); + _visualElement.Add(inner); + + _suppressOnceDefaultMargins = true; + return _visualElement; + } + + public override bool UseDefaultMargins() + { + var useDefaults = !_suppressOnceDefaultMargins; + _suppressOnceDefaultMargins = false; + return useDefaults; + } + + public sealed override void OnInspectorGUI() + { + if (GetCachedLogoDisplayNode(_visualElement) == _visualElement) + { + LogoDisplay.DisplayLogo(); + } + + InspectorCommon.DisplayOutOfAvatarWarning(targets); + + OnInnerInspectorGUI(); + } + + protected abstract void OnInnerInspectorGUI(); + } +} \ No newline at end of file diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/MAEditorBase.cs.meta b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MAEditorBase.cs.meta new file mode 100644 index 00000000..f4a773bb --- /dev/null +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MAEditorBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5abd585ebadf4f71931ecb3328bf10e8 +timeCreated: 1668058504 \ No newline at end of file diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/MenuInstallerEditor.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MenuInstallerEditor.cs index 9496759e..af3c021d 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Inspector/MenuInstallerEditor.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MenuInstallerEditor.cs @@ -10,7 +10,7 @@ namespace net.fushizen.modular_avatar.core.editor { [CustomEditor(typeof(ModularAvatarMenuInstaller))] [CanEditMultipleObjects] - public class MenuInstallerEditor : Editor + internal class MenuInstallerEditor : MAEditorBase { private ModularAvatarMenuInstaller _installer; private Editor _innerMenuEditor; @@ -47,11 +47,8 @@ namespace net.fushizen.modular_avatar.core.editor } } - public override void OnInspectorGUI() + protected override void OnInnerInspectorGUI() { - LogoDisplay.DisplayLogo(); - InspectorCommon.DisplayOutOfAvatarWarning(targets); - SetupMenuEditor(); var installTo = serializedObject.FindProperty(nameof(ModularAvatarMenuInstaller.installTargetMenu)); diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/MergeAnimationEditor.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MergeAnimationEditor.cs index 27d99d05..1ec7b959 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Inspector/MergeAnimationEditor.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MergeAnimationEditor.cs @@ -1,5 +1,6 @@ using UnityEditor; using UnityEngine; +using UnityEngine.UIElements; using static net.fushizen.modular_avatar.core.editor.Localization; namespace net.fushizen.modular_avatar.core.editor @@ -27,7 +28,7 @@ namespace net.fushizen.modular_avatar.core.editor } [CustomEditor(typeof(ModularAvatarMergeAnimator))] - class MergeAnimationEditor : Editor + class MergeAnimationEditor : MAEditorBase { private SerializedProperty prop_animator, prop_layerType, @@ -46,11 +47,8 @@ namespace net.fushizen.modular_avatar.core.editor serializedObject.FindProperty(nameof(ModularAvatarMergeAnimator.matchAvatarWriteDefaults)); } - public override void OnInspectorGUI() + protected override void OnInnerInspectorGUI() { - LogoDisplay.DisplayLogo(); - InspectorCommon.DisplayOutOfAvatarWarning(targets); - serializedObject.Update(); EditorGUILayout.PropertyField(prop_animator, G("merge_animator.animator")); diff --git a/Packages/net.fushizen.modular-avatar/Editor/Inspector/MergeArmatureEditor.cs b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MergeArmatureEditor.cs index cc31a784..0f9f3add 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Inspector/MergeArmatureEditor.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Inspector/MergeArmatureEditor.cs @@ -6,7 +6,7 @@ using static net.fushizen.modular_avatar.core.editor.Localization; namespace net.fushizen.modular_avatar.core.editor { [CustomEditor(typeof(ModularAvatarMergeArmature))] - public class MergeArmatureEditor : Editor + internal class MergeArmatureEditor : MAEditorBase { private SerializedProperty prop_mergeTarget, prop_prefix, prop_suffix, prop_locked; @@ -30,11 +30,8 @@ namespace net.fushizen.modular_avatar.core.editor serializedObject.ApplyModifiedProperties(); } - public override void OnInspectorGUI() + protected override void OnInnerInspectorGUI() { - LogoDisplay.DisplayLogo(); - InspectorCommon.DisplayOutOfAvatarWarning(targets); - var target = (ModularAvatarMergeArmature) this.target; var priorMergeTarget = target.mergeTargetObject;