From bc12e3a9854f11c7603cdf533d87af9ca67c5036 Mon Sep 17 00:00:00 2001 From: bd_ Date: Mon, 13 May 2024 05:19:55 +0900 Subject: [PATCH] change: MA Info is now a normal editor window (#850) --- Editor/AvatarProcessor.cs | 8 +- Editor/EasySetupOutfit.cs | 4 +- Editor/HarmonyPatches/InjectParamsUsageUI.cs | 102 -------- .../InjectParamsUsageUI.cs.meta | 3 - Editor/HarmonyPatches/PatchLoader.cs | 1 - Editor/Inspector/Common/LogoElement.cs | 21 +- Editor/Inspector/Common/LogoImage.cs | 38 +++ Editor/Inspector/Common/LogoImage.cs.meta | 3 + Editor/Inspector/LogoDisplay.cs | 8 +- Editor/Localization/en-US.json | 3 +- Editor/Localization/ja-JP.json | 3 +- Editor/Menu/MenuExtractor.cs | 20 +- .../ParamsUsage/ModularAvatarInformation.cs | 23 -- .../ModularAvatarInformation.cs.meta | 11 - Editor/ParamsUsage/ParamsUsage.uss | 40 +++- Editor/ParamsUsage/ParamsUsage.uxml | 14 +- Editor/ParamsUsage/ParamsUsagePrefs.cs | 40 ---- Editor/ParamsUsage/ParamsUsagePrefs.cs.meta | 3 - Editor/ParamsUsage/ParamsUsageUI.cs | 220 ------------------ Editor/ParamsUsage/ParamsUsageUI.cs.meta | 3 - ...amsUsageEditor.cs => ParamsUsageWindow.cs} | 122 +++++++--- ...itor.cs.meta => ParamsUsageWindow.cs.meta} | 0 Runtime/UI/UnityMenuItems.cs | 21 +- 23 files changed, 239 insertions(+), 472 deletions(-) delete mode 100644 Editor/HarmonyPatches/InjectParamsUsageUI.cs delete mode 100644 Editor/HarmonyPatches/InjectParamsUsageUI.cs.meta create mode 100644 Editor/Inspector/Common/LogoImage.cs create mode 100644 Editor/Inspector/Common/LogoImage.cs.meta delete mode 100644 Editor/ParamsUsage/ModularAvatarInformation.cs delete mode 100644 Editor/ParamsUsage/ModularAvatarInformation.cs.meta delete mode 100644 Editor/ParamsUsage/ParamsUsagePrefs.cs delete mode 100644 Editor/ParamsUsage/ParamsUsagePrefs.cs.meta delete mode 100644 Editor/ParamsUsage/ParamsUsageUI.cs delete mode 100644 Editor/ParamsUsage/ParamsUsageUI.cs.meta rename Editor/ParamsUsage/{ParamsUsageEditor.cs => ParamsUsageWindow.cs} (69%) rename Editor/ParamsUsage/{ParamsUsageEditor.cs.meta => ParamsUsageWindow.cs.meta} (100%) diff --git a/Editor/AvatarProcessor.cs b/Editor/AvatarProcessor.cs index 2b08b290..227a4716 100644 --- a/Editor/AvatarProcessor.cs +++ b/Editor/AvatarProcessor.cs @@ -22,25 +22,29 @@ * SOFTWARE. */ +#region + using System; using System.Runtime.CompilerServices; using nadena.dev.modular_avatar.ui; using UnityEditor; using UnityEngine; +#endregion + [assembly: InternalsVisibleTo("Tests")] namespace nadena.dev.modular_avatar.core.editor { public class AvatarProcessor { - [MenuItem("GameObject/ModularAvatar/Manual bake avatar", true, 100)] + [MenuItem(UnityMenuItems.GameObject_ManualBake, true, UnityMenuItems.GameObject_ManualBakeOrder)] static bool ValidateApplyToCurrentAvatarGameobject() { return ValidateApplyToCurrentAvatar(); } - [MenuItem("GameObject/ModularAvatar/Manual bake avatar", false, 100)] + [MenuItem(UnityMenuItems.GameObject_ManualBake, false, UnityMenuItems.GameObject_ManualBakeOrder)] static void ApplyToCurrentAvatarGameobject() { ApplyToCurrentAvatar(); diff --git a/Editor/EasySetupOutfit.cs b/Editor/EasySetupOutfit.cs index 05014661..2ea31ade 100644 --- a/Editor/EasySetupOutfit.cs +++ b/Editor/EasySetupOutfit.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; +using nadena.dev.modular_avatar.ui; using UnityEditor; using UnityEngine; using Object = UnityEngine.Object; @@ -114,11 +115,10 @@ namespace nadena.dev.modular_avatar.core.editor internal static class EasySetupOutfit { - private const int PRIORITY = 49; private static string[] errorMessageGroups; private static string errorHeader; - [MenuItem("GameObject/ModularAvatar/Setup Outfit", false, PRIORITY)] + [MenuItem(UnityMenuItems.GameObject_SetupOutfit, false, UnityMenuItems.GameObject_SetupOutfitOrder)] internal static void SetupOutfit(MenuCommand cmd) { if (!ValidateSetupOutfit()) diff --git a/Editor/HarmonyPatches/InjectParamsUsageUI.cs b/Editor/HarmonyPatches/InjectParamsUsageUI.cs deleted file mode 100644 index e587fb8d..00000000 --- a/Editor/HarmonyPatches/InjectParamsUsageUI.cs +++ /dev/null @@ -1,102 +0,0 @@ -#region - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; -using HarmonyLib; -using UnityEditor; -using UnityEngine; -using UnityEngine.UIElements; -using Object = UnityEngine.Object; - -#endregion - -namespace nadena.dev.modular_avatar.core.editor.HarmonyPatches -{ - internal static class InjectParamsUsageUI - { - private static readonly Type type = AccessTools.TypeByName("UnityEditor.PropertyEditor"); - private static readonly PropertyInfo _editorsElement = AccessTools.Property(type, "editorsElement"); - - private static readonly Type editorElem = AccessTools.TypeByName("UnityEditor.UIElements.EditorElement"); - private static readonly PropertyInfo editorElem_editor = AccessTools.Property(editorElem, "editor"); - - public static void Patch(Harmony h) - { - var type = AccessTools.TypeByName("UnityEditor.PropertyEditor"); - var drawEditors = AccessTools.Method(type, "DrawEditors"); - - h.Patch(drawEditors, transpiler: new HarmonyMethod(typeof(InjectParamsUsageUI), nameof(Transpile))); - - var objNames = AccessTools.TypeByName("UnityEditor.ObjectNames"); - var m_GetObjectTypeName = AccessTools.Method(objNames, "GetObjectTypeName"); - var postfix_GetObjectTypeName = - AccessTools.Method(typeof(InjectParamsUsageUI), nameof(Postfix_GetObjectTypeName)); - - h.Patch(m_GetObjectTypeName, postfix: new HarmonyMethod(postfix_GetObjectTypeName)); - } - - private static void Postfix_GetObjectTypeName(ref string __result, Object o) - { - if (o is ModularAvatarInformation) - { - __result = "Modular Avatar Information"; - } - } - - private static IEnumerable Transpile(IEnumerable ci) - { - var target = AccessTools.Method(typeof(VisualElement), "Add"); - - foreach (var i in ci) - { - if (i.opcode != OpCodes.Callvirt) - { - yield return i; - continue; - } - - if (i.opcode == OpCodes.Callvirt - && i.operand is MethodInfo method - && method == target - ) - { - yield return new CodeInstruction(OpCodes.Ldarg_0); - yield return new CodeInstruction(OpCodes.Call, - AccessTools.Method(typeof(InjectParamsUsageUI), nameof(EditorAdd))); - continue; - } - - yield return i; - } - } - - private static void EditorAdd(VisualElement container, VisualElement child, object caller) - { - container.Add(child); - - var editorsElement = _editorsElement.GetValue(caller) as VisualElement; - if (editorsElement != container) - { - return; - } - - if (!child.ClassListContains("game-object-inspector")) - { - return; - } - - var editor = editorElem_editor.GetValue(child) as Editor; - if (editor == null) return; - - if (editor.targets.Length != 1) return; - - if (editor.target is GameObject obj) - { - var elem = new ParamsUsageUI(); - container.Add(elem); - } - } - } -} \ No newline at end of file diff --git a/Editor/HarmonyPatches/InjectParamsUsageUI.cs.meta b/Editor/HarmonyPatches/InjectParamsUsageUI.cs.meta deleted file mode 100644 index f5145038..00000000 --- a/Editor/HarmonyPatches/InjectParamsUsageUI.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 5d62a8f41641443ea8bffdc0429e0ad1 -timeCreated: 1710223876 \ No newline at end of file diff --git a/Editor/HarmonyPatches/PatchLoader.cs b/Editor/HarmonyPatches/PatchLoader.cs index 1de11221..092b79a4 100644 --- a/Editor/HarmonyPatches/PatchLoader.cs +++ b/Editor/HarmonyPatches/PatchLoader.cs @@ -17,7 +17,6 @@ namespace nadena.dev.modular_avatar.core.editor.HarmonyPatches #if UNITY_2022_3_OR_NEWER HandleUtilityPatches.Patch_FilterInstanceIDs, PickingObjectPatch.Patch, - InjectParamsUsageUI.Patch, #endif }; diff --git a/Editor/Inspector/Common/LogoElement.cs b/Editor/Inspector/Common/LogoElement.cs index 3c470ac3..92029fdc 100644 --- a/Editor/Inspector/Common/LogoElement.cs +++ b/Editor/Inspector/Common/LogoElement.cs @@ -1,11 +1,13 @@ -using System.Collections.Generic; +#region + +using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.UIElements; -using UnityEngine; -using UnityEngine.TestTools; using UnityEngine.UIElements; +#endregion + namespace nadena.dev.modular_avatar.core.editor { public class LogoElement : VisualElement @@ -85,19 +87,8 @@ namespace nadena.dev.modular_avatar.core.editor public LogoElement() { - _inner = new VisualElement(); - + _inner = new LogoImage(); _inner.style.display = DisplayStyle.None; - _inner.style.flexDirection = FlexDirection.Row; - _inner.style.alignItems = Align.Center; - _inner.style.justifyContent = Justify.Center; - - var image = new Image(); - image.image = LogoDisplay.LOGO_ASSET; - image.style.width = new Length(LogoDisplay.ImageWidth(LogoDisplay.TARGET_HEIGHT), LengthUnit.Pixel); - image.style.height = new Length(LogoDisplay.TARGET_HEIGHT, LengthUnit.Pixel); - - _inner.Add(image); this.Add(_inner); RegisterCallback(OnGeomChanged); diff --git a/Editor/Inspector/Common/LogoImage.cs b/Editor/Inspector/Common/LogoImage.cs new file mode 100644 index 00000000..b569671d --- /dev/null +++ b/Editor/Inspector/Common/LogoImage.cs @@ -0,0 +1,38 @@ +#region + +using UnityEngine.UIElements; + +#endregion + +namespace nadena.dev.modular_avatar.core.editor +{ + public class LogoImage : VisualElement + { + VisualElement _inner; + + public new class UxmlFactory : UxmlFactory + { + } + + public new class UxmlTraits : VisualElement.UxmlTraits + { + } + + public LogoImage() + { + _inner = new VisualElement(); + + _inner.style.flexDirection = FlexDirection.Row; + _inner.style.alignItems = Align.Center; + _inner.style.justifyContent = Justify.Center; + + var image = new Image(); + image.image = LogoDisplay.LOGO_ASSET; + image.style.width = new Length(LogoDisplay.ImageWidth(LogoDisplay.TARGET_HEIGHT), LengthUnit.Pixel); + image.style.height = new Length(LogoDisplay.TARGET_HEIGHT, LengthUnit.Pixel); + + _inner.Add(image); + Add(_inner); + } + } +} \ No newline at end of file diff --git a/Editor/Inspector/Common/LogoImage.cs.meta b/Editor/Inspector/Common/LogoImage.cs.meta new file mode 100644 index 00000000..e290f9be --- /dev/null +++ b/Editor/Inspector/Common/LogoImage.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d12c8166c3f14b78a76dbef22b07fad1 +timeCreated: 1715480586 \ No newline at end of file diff --git a/Editor/Inspector/LogoDisplay.cs b/Editor/Inspector/LogoDisplay.cs index b950232c..60473f9b 100644 --- a/Editor/Inspector/LogoDisplay.cs +++ b/Editor/Inspector/LogoDisplay.cs @@ -1,7 +1,11 @@ -using System; +#region + +using System; using UnityEditor; using UnityEngine; +#endregion + namespace nadena.dev.modular_avatar.core.editor { internal static class LogoDisplay @@ -37,7 +41,7 @@ namespace nadena.dev.modular_avatar.core.editor internal static void DisplayLogo() { - if (LOGO_ASSET == null) return; + if (LOGO_ASSET == null || EditorStyles.label == null) return; var height = TARGET_HEIGHT; var width = ImageWidth(height); diff --git a/Editor/Localization/en-US.json b/Editor/Localization/en-US.json index 65b4b4e8..d48d07fb 100644 --- a/Editor/Localization/en-US.json +++ b/Editor/Localization/en-US.json @@ -246,5 +246,6 @@ "ma_info.param_usage_ui.header": "Expressions Parameter Usage", "ma_info.param_usage_ui.other_objects": "Other objects on this avatar", "ma_info.param_usage_ui.free_space": "Unused parameter space ({0} bits)", - "ma_info.param_usage_ui.bits_template": "{0} ({1} bits)" + "ma_info.param_usage_ui.bits_template": "{0} ({1} bits)", + "ma_info.param_usage_ui.no_data": "[ NO DATA ]" } \ No newline at end of file diff --git a/Editor/Localization/ja-JP.json b/Editor/Localization/ja-JP.json index eddc58b2..3c0447e1 100644 --- a/Editor/Localization/ja-JP.json +++ b/Editor/Localization/ja-JP.json @@ -242,5 +242,6 @@ "ma_info.param_usage_ui.header": "Expressions Parameter 使用状況", "ma_info.param_usage_ui.other_objects": "このアバター内の他のオブジェクト", "ma_info.param_usage_ui.free_space": "未使用領域 ({0} 個のビット)", - "ma_info.param_usage_ui.bits_template": "{0} ({1} 個のビットを使用中)" + "ma_info.param_usage_ui.bits_template": "{0} ({1} 個のビットを使用中)", + "ma_info.param_usage_ui.no_data": "[ NO DATA ]" } \ No newline at end of file diff --git a/Editor/Menu/MenuExtractor.cs b/Editor/Menu/MenuExtractor.cs index 48662a24..89ee232c 100644 --- a/Editor/Menu/MenuExtractor.cs +++ b/Editor/Menu/MenuExtractor.cs @@ -1,19 +1,23 @@ #if MA_VRCSDK3_AVATARS +#region + using System; +using System.IO; using System.Linq; +using nadena.dev.modular_avatar.ui; using UnityEditor; using UnityEngine; using VRC.SDK3.Avatars.Components; using VRC.SDK3.Avatars.ScriptableObjects; +#endregion + namespace nadena.dev.modular_avatar.core.editor { internal class MenuExtractor { - private const int PRIORITY = 49; - - [MenuItem("GameObject/ModularAvatar/Extract menu", false, PRIORITY)] + [MenuItem(UnityMenuItems.GameObject_ExtractMenu, false, UnityMenuItems.GameObject_ExtractMenuOrder)] static void ExtractMenu(MenuCommand menuCommand) { if (!(menuCommand.context is GameObject gameObj)) return; @@ -32,10 +36,10 @@ namespace nadena.dev.modular_avatar.core.editor var assetPath = AssetDatabase.GetAssetPath(avatar.expressionsMenu); var dummyAssetPathBase = assetPath.Replace(".asset", " placeholder"); - if (dummyAssetPathBase.StartsWith("Packages" + System.IO.Path.DirectorySeparatorChar)) + if (dummyAssetPathBase.StartsWith("Packages" + Path.DirectorySeparatorChar)) { - var filename = System.IO.Path.GetFileName(dummyAssetPathBase); - dummyAssetPathBase = System.IO.Path.Combine("Assets", filename); + var filename = Path.GetFileName(dummyAssetPathBase); + dummyAssetPathBase = Path.Combine("Assets", filename); } // Check that a similarly-named file doesn't already exist @@ -43,7 +47,7 @@ namespace nadena.dev.modular_avatar.core.editor do { var fullPath = dummyAssetPathBase + (i > 0 ? " " + i : "") + ".asset"; - if (System.IO.File.Exists(fullPath)) + if (File.Exists(fullPath)) { var asset = AssetDatabase.LoadAssetAtPath(fullPath); if (asset != null && asset.controls.Count == 0) @@ -52,7 +56,7 @@ namespace nadena.dev.modular_avatar.core.editor break; } } - else if (!System.IO.File.Exists(fullPath)) + else if (!File.Exists(fullPath)) { var dummyAsset = ScriptableObject.CreateInstance(); AssetDatabase.CreateAsset(dummyAsset, fullPath); diff --git a/Editor/ParamsUsage/ModularAvatarInformation.cs b/Editor/ParamsUsage/ModularAvatarInformation.cs deleted file mode 100644 index f5c1bf89..00000000 --- a/Editor/ParamsUsage/ModularAvatarInformation.cs +++ /dev/null @@ -1,23 +0,0 @@ -#region - -using UnityEngine; - -#endregion - -namespace nadena.dev.modular_avatar.core.editor -{ - [HelpURL("https://m-a.nadena.dev/docs/intro?lang=auto")] - internal class ModularAvatarInformation : ScriptableObject - { - internal static ModularAvatarInformation _instance; - - internal static ModularAvatarInformation instance - { - get - { - if (_instance == null) _instance = CreateInstance(); - return _instance; - } - } - } -} \ No newline at end of file diff --git a/Editor/ParamsUsage/ModularAvatarInformation.cs.meta b/Editor/ParamsUsage/ModularAvatarInformation.cs.meta deleted file mode 100644 index b966108d..00000000 --- a/Editor/ParamsUsage/ModularAvatarInformation.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f902feee12ad4fcbb8a975bbea565ab1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: a8edd5bd1a0a64a40aa99cc09fb5f198, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/ParamsUsage/ParamsUsage.uss b/Editor/ParamsUsage/ParamsUsage.uss index 6dbc4c52..0ccdef97 100644 --- a/Editor/ParamsUsage/ParamsUsage.uss +++ b/Editor/ParamsUsage/ParamsUsage.uss @@ -5,10 +5,12 @@ #Outerbox { margin-top: 4px; + margin-bottom: 8px; + border-top-width: 1px; border-bottom-width: 1px; - border-left-width: 1px; - border-right-width: 1px; + /*border-left-width: 1px; + border-right-width: 1px;*/ border-color: black; padding: 4px; @@ -18,6 +20,11 @@ margin-bottom: 12px; } +#Footer { + margin-left: 15px; + margin-right: 15px; +} + #UsageBox { height: 16px; flex-direction: row; @@ -72,4 +79,33 @@ margin-right: -4px; border-left-width: 4px; border-right-width: 4px; +} + +/* NO DATA display */ +#Outerbox Toggle { + display: flex; +} + +/* Why doesn't #Outerbox.no-data > .unity-foldout__content > * work here? */ +#Outerbox.no-data #UsageBox { + display: none; +} + +#Outerbox.no-data #Legend { + display: none; +} + +#NoData { + display: none; +} + +#Outerbox.no-data #NoData { + font-size: 150%; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + height: 100%; + margin-top: 20px; + margin-bottom: 20px; } \ No newline at end of file diff --git a/Editor/ParamsUsage/ParamsUsage.uxml b/Editor/ParamsUsage/ParamsUsage.uxml index 351a77a7..96433da1 100644 --- a/Editor/ParamsUsage/ParamsUsage.uxml +++ b/Editor/ParamsUsage/ParamsUsage.uxml @@ -1,8 +1,12 @@  - + + + + + + - @@ -28,8 +32,10 @@ - + - + + + \ No newline at end of file diff --git a/Editor/ParamsUsage/ParamsUsagePrefs.cs b/Editor/ParamsUsage/ParamsUsagePrefs.cs deleted file mode 100644 index e6ea1268..00000000 --- a/Editor/ParamsUsage/ParamsUsagePrefs.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using nadena.dev.modular_avatar.ui; -using UnityEditor; -using UnityEngine.Serialization; - -namespace nadena.dev.modular_avatar.core.editor -{ - #if UNITY_2022_3_OR_NEWER - [FilePath("modular-avatar/ParamsUsagePrefs.asset", FilePathAttribute.Location.PreferencesFolder)] - internal sealed class ParamsUsagePrefs : ScriptableSingleton - { - public static event Action OnChange_EnableInfoMenu; - - [FormerlySerializedAs("EnableInfoMenu")] public bool enableInfoMenu = true; - - [MenuItem(UnityMenuItems.TopMenu_EnableInfo, false, UnityMenuItems.TopMenu_EnableInfoOrder)] - private static void Menu_EnableInfo() - { - ParamsUsagePrefs.instance.enableInfoMenu = !ParamsUsagePrefs.instance.enableInfoMenu; - Menu.SetChecked(UnityMenuItems.TopMenu_EnableInfo, ParamsUsagePrefs.instance.enableInfoMenu); - ParamsUsagePrefs.instance.Save(true); - - OnChange_EnableInfoMenu?.Invoke(ParamsUsagePrefs.instance.enableInfoMenu); - } - - [InitializeOnLoadMethod] - private static void Initialize() - { - Menu.SetChecked(UnityMenuItems.TopMenu_EnableInfo, ParamsUsagePrefs.instance.enableInfoMenu); - } - } - #else - internal sealed class ParamsUsagePrefs - { - public static ParamsUsagePrefs instance => new ParamsUsagePrefs(); - public static event Action OnChange_EnableInfoMenu; - public bool enableInfoMenu => false; - } - #endif -} \ No newline at end of file diff --git a/Editor/ParamsUsage/ParamsUsagePrefs.cs.meta b/Editor/ParamsUsage/ParamsUsagePrefs.cs.meta deleted file mode 100644 index c5975d10..00000000 --- a/Editor/ParamsUsage/ParamsUsagePrefs.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 3ebf965fd4064a52896def62c36c6a90 -timeCreated: 1713742583 \ No newline at end of file diff --git a/Editor/ParamsUsage/ParamsUsageUI.cs b/Editor/ParamsUsage/ParamsUsageUI.cs deleted file mode 100644 index bd73a1c2..00000000 --- a/Editor/ParamsUsage/ParamsUsageUI.cs +++ /dev/null @@ -1,220 +0,0 @@ -#region - -using System; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using HarmonyLib; -using nadena.dev.ndmf.localization; -using UnityEditor; -using UnityEditor.UIElements; -using UnityEngine; -using UnityEngine.UIElements; -using Object = UnityEngine.Object; - -#endregion - -namespace nadena.dev.modular_avatar.core.editor -{ - internal class ParamsUsageUI : VisualElement - { - private static readonly Type editorElem = AccessTools.TypeByName("UnityEditor.UIElements.EditorElement"); - private static readonly PropertyInfo editorElem_editor = AccessTools.Property(editorElem, "editor"); - - private class FoldoutState - { - public bool Visible; - } - - private static ConditionalWeakTable FoldoutStateHolder = - new ConditionalWeakTable(); - - private VisualElement _gameObjectEditorElement; - private Editor _parentEditor; - private Object _rawTarget; - private GameObject _target; - private ParamsUsageEditor _editor; - private FoldoutState _foldoutState; - - private bool _recursing = false; - - public ParamsUsageUI() - { - RegisterCallback(OnAttach); - RegisterCallback(OnDetach); - - LanguagePrefs.RegisterLanguageChangeCallback(this, - (self) => self.OnLanguageChangedCallback()); - } - - private void OnChange_EnableState(bool enableState) - { - if (_editor != null) - { - Rebuild(); - } - } - - private void OnLanguageChangedCallback() - { - if (_editor != null) - { - Rebuild(); - } - } - - private void OnDetach(DetachFromPanelEvent evt) - { - if (_recursing) return; - - Clear(); - - if (_editor != null) - { - Object.DestroyImmediate(_editor); - _editor = null; - } - - ParamsUsagePrefs.OnChange_EnableInfoMenu -= OnChange_EnableState; - } - - private void OnAttach(AttachToPanelEvent evt) - { - if (_recursing) return; - - Rebuild(); - - ParamsUsagePrefs.OnChange_EnableInfoMenu += OnChange_EnableState; - } - - private void Rebuild() - { - if (parent == null) return; - - if (!ParamsUsagePrefs.instance.enableInfoMenu) - { - Clear(); - return; - } - - SetRedrawSensor(); - - if (_gameObjectEditorElement?.parent != parent) - { - _gameObjectEditorElement = null; - - var kv = FindEditorElement(); - if (kv != null) - { - var elem = kv.Value.Item1; - var index = kv.Value.Item2; - - if (index != parent.Children().ToList().IndexOf(this)) - { - _recursing = true; - var p = parent; - RemoveFromHierarchy(); - p.Insert(index + 1, this); - _recursing = false; - } - - _gameObjectEditorElement = elem; - } - } - - if (_gameObjectEditorElement == null) return; - - _parentEditor = editorElem_editor.GetValue(_gameObjectEditorElement) as Editor; - if (_parentEditor == null) return; - - _rawTarget = _parentEditor.target; - _target = _rawTarget as GameObject; - - if (_target == null) return; - - Clear(); - _redrawSensorActive = false; - BuildContent(); - } - - private (VisualElement, int)? FindEditorElement() - { - foreach (var (elem, index) in parent.Children().Select((e, i) => (e, i))) - { - if (elem.ClassListContains("game-object-inspector")) - { - return (elem, index); - } - } - - return null; - } - - private bool _redrawSensorActive = false; - - private void SetRedrawSensor() - { - if (_redrawSensorActive) return; - - Clear(); - _redrawSensorActive = true; - Add(new IMGUIContainer(() => EditorApplication.delayCall += Rebuild)); - } - - private void BuildContent() - { - Clear(); - - if (!FoldoutStateHolder.TryGetValue(parent, out _foldoutState)) - { - _foldoutState = new FoldoutState(); - FoldoutStateHolder.Add(parent, _foldoutState); - } - - if (RuntimeUtil.FindAvatarTransformInParents(_target.transform) == null) - { - return; - } - - _editor = Editor.CreateEditorWithContext(new Object[] { ModularAvatarInformation.instance }, _target, - typeof(ParamsUsageEditor)) - as ParamsUsageEditor; - - if (_editor == null) return; - - var inspectorElement = new InspectorElement(_editor); - - Add(new IMGUIContainer(() => - { - if (_gameObjectEditorElement?.parent != parent || _parentEditor == null || - _parentEditor.target != _rawTarget) - { - EditorApplication.delayCall += Rebuild; - return; - } - - switch (Event.current.rawType) - { - case EventType.Repaint: - case EventType.MouseMove: - case EventType.Layout: - break; - case EventType.MouseDrag: - case EventType.DragUpdated: - case EventType.DragPerform: - case EventType.DragExited: - return; - - default: - break; - } - - _foldoutState.Visible = EditorGUILayout.InspectorTitlebar(_foldoutState.Visible, _editor); - inspectorElement.style.display = _foldoutState.Visible ? DisplayStyle.Flex : DisplayStyle.None; - _editor.Visible = _foldoutState.Visible; - })); - _editor.Visible = _foldoutState.Visible; - Add(inspectorElement); - } - } -} \ No newline at end of file diff --git a/Editor/ParamsUsage/ParamsUsageUI.cs.meta b/Editor/ParamsUsage/ParamsUsageUI.cs.meta deleted file mode 100644 index 4269d505..00000000 --- a/Editor/ParamsUsage/ParamsUsageUI.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 18364f2754ed43c3baba0f1e18ac03cd -timeCreated: 1710226452 \ No newline at end of file diff --git a/Editor/ParamsUsage/ParamsUsageEditor.cs b/Editor/ParamsUsage/ParamsUsageWindow.cs similarity index 69% rename from Editor/ParamsUsage/ParamsUsageEditor.cs rename to Editor/ParamsUsage/ParamsUsageWindow.cs index 3d255963..4d8f58ee 100644 --- a/Editor/ParamsUsage/ParamsUsageEditor.cs +++ b/Editor/ParamsUsage/ParamsUsageWindow.cs @@ -1,7 +1,9 @@ #region +using System; using System.Collections.Generic; using System.Linq; +using nadena.dev.modular_avatar.ui; using nadena.dev.ndmf; using UnityEditor; using UnityEngine; @@ -12,7 +14,7 @@ using VRC.SDK3.Avatars.ScriptableObjects; namespace nadena.dev.modular_avatar.core.editor { - internal class ParamsUsageEditor : MAEditorBase + internal class ParamsUsageWindow : EditorWindow { [SerializeField] private StyleSheet uss; [SerializeField] private VisualTreeAsset uxml; @@ -32,11 +34,59 @@ namespace nadena.dev.modular_avatar.core.editor if (_visible == value) return; _visible = value; - if (_visible) Recalculate(); +#if UNITY_2022_1_OR_NEWER + if (_visible) + { + Recalculate(); + ObjectChangeEvents.changesPublished += OnChangesPublished; + } + else + { + ObjectChangeEvents.changesPublished -= OnChangesPublished; + } +#endif + } + } + + private void OnBecameVisible() + { + Visible = true; + } + + private void OnBecameInvisible() + { + Visible = false; + } + + private void OnSelectionChange() + { + if (Visible) + { + Recalculate(); } } #if UNITY_2022_1_OR_NEWER + [MenuItem(UnityMenuItems.TopMenu_EnableInfo, false, UnityMenuItems.TopMenu_EnableInfoOrder)] + public static void ShowWindow() + { + var window = GetWindow(); + window.titleContent = new GUIContent("MA Information"); + window.Show(); + } + + [MenuItem(UnityMenuItems.GameObject_EnableInfo, false, UnityMenuItems.GameObject_EnableInfoOrder)] + public static void ShowWindowFromGameObject() + { + ShowWindow(); + } + + [MenuItem(UnityMenuItems.GameObject_EnableInfo, true, UnityMenuItems.GameObject_EnableInfoOrder)] + public static bool ValidateShowWindowFromGameObject() + { + return Selection.gameObjects.Length == 1; + } + private bool _delayPending = false; private void DelayRecalculate() @@ -47,40 +97,46 @@ namespace nadena.dev.modular_avatar.core.editor private void OnChangesPublished(ref ObjectChangeEventStream stream) { + if (_root == null || !_visible) return; if (!_delayPending) EditorApplication.delayCall += DelayRecalculate; _delayPending = true; } #endif - protected override VisualElement CreateInnerInspectorGUI() + bool GUIIsReady() { + try + { + return uxml != null && EditorStyles.label != null; + } + catch (NullReferenceException _) + { + return false; + } + } + + protected void CreateGUI() + { + if (!GUIIsReady()) + { + // After domain reload, the uxml field (and EditorStyles, etc) isn't initialized immediately. + // Try again in the next frame. + EditorApplication.delayCall += CreateGUI; + return; + } + _root = uxml.CloneTree(); + + rootVisualElement.Add(_root); _root.styleSheets.Add(uss); Localization.L.LocalizeUIElements(_root); - + _legendContainer = _root.Q("Legend"); _usageBoxContainer = _root.Q("UsageBox"); -#if UNITY_2022_1_OR_NEWER - _root.RegisterCallback(_evt => - { - ObjectChangeEvents.changesPublished += OnChangesPublished; - Recalculate(); - }); - - _root.RegisterCallback(_evt => - { - ObjectChangeEvents.changesPublished -= OnChangesPublished; - }); -#endif - - return _root; + Recalculate(); } - protected override void OnInnerInspectorGUI() - { - // no-op - } private static IEnumerable Colors() { @@ -108,15 +164,25 @@ namespace nadena.dev.modular_avatar.core.editor private void Recalculate() { if (_root == null || !_visible) return; - - var ctx = serializedObject.context as GameObject; - if (ctx == null) return; + var objects = Selection.gameObjects; + var target = objects.Length == 1 ? objects[0] : null; + var avatarRoot = target != null + ? RuntimeUtil.FindAvatarTransformInParents(target.transform)?.gameObject + : null; - var avatarRoot = RuntimeUtil.FindAvatarTransformInParents(ctx.transform)?.gameObject; - if (avatarRoot == null) return; + var outerbox = _root.Q("Outerbox"); + if (avatarRoot == null) + { + outerbox.AddToClassList("no-data"); + return; + } + else + { + outerbox.RemoveFromClassList("no-data"); + } - var orderedPlugins = ParameterInfo.ForUI.GetParametersForObject(ctx) + var orderedPlugins = ParameterInfo.ForUI.GetParametersForObject(target) .GroupBy(p => p.Plugin) .Select(group => (group.Key, group.Sum(p => p.BitUsage))) .Where((kv, index) => kv.Item2 > 0) diff --git a/Editor/ParamsUsage/ParamsUsageEditor.cs.meta b/Editor/ParamsUsage/ParamsUsageWindow.cs.meta similarity index 100% rename from Editor/ParamsUsage/ParamsUsageEditor.cs.meta rename to Editor/ParamsUsage/ParamsUsageWindow.cs.meta diff --git a/Runtime/UI/UnityMenuItems.cs b/Runtime/UI/UnityMenuItems.cs index b89b778c..0de512b7 100644 --- a/Runtime/UI/UnityMenuItems.cs +++ b/Runtime/UI/UnityMenuItems.cs @@ -1,12 +1,31 @@ namespace nadena.dev.modular_avatar.ui { - internal class UnityMenuItems + internal static class UnityMenuItems { + internal const string GameObject_SetupOutfit = "GameObject/Modular Avatar/Setup Outfit"; + internal const int GameObject_SetupOutfitOrder = -1000; + + internal const string GameObject_ManualBake = "GameObject/Modular Avatar/Manual Bake Avatar"; + internal const int GameObject_ManualBakeOrder = GameObject_SetupOutfitOrder + 1; + + // + + internal const string GameObject_EnableInfo = "GameObject/Modular Avatar/Show Modular Avatar Information"; + internal const int GameObject_EnableInfoOrder = -799; + + internal const string GameObject_ExtractMenu = "GameObject/Modular Avatar/Extract Menu"; + internal const int GameObject_ExtractMenuOrder = GameObject_EnableInfoOrder + 1; + + + + internal const string TopMenu_EditModeBoneSync = "Tools/Modular Avatar/Sync Bones in Edit Mode"; internal const int TopMenu_EditModeBoneSyncOrder = 100; internal const string TopMenu_EnableInfo = "Tools/Modular Avatar/Show Modular Avatar Information"; internal const int TopMenu_EnableInfoOrder = 101; + + // internal const string TopMenu_ManualBakeAvatar = "Tools/Modular Avatar/Manual Bake Avatar"; internal const int TopMenu_ManualBakeAvatarOrder = 1000;