From 86fc302fa55fe87862ba316af5a26b64525a4847 Mon Sep 17 00:00:00 2001 From: bd_ Date: Sat, 27 Jan 2024 20:06:22 +0900 Subject: [PATCH] ui(parameters): Rebuild MAParameters UI for Unity 2022 (#634) --- .../Inspector/AvatarParametersEditor.cs.meta | 3 - Editor/Inspector/Common/UXMLExtensions.cs | 1 + Editor/Inspector/Parameters.meta | 3 + .../Parameters/AvatarParametersEditor.cs | 165 ++++++++++++++++++ .../Parameters/AvatarParametersEditor.cs.meta | 13 ++ .../AvatarParametersEditor2019.cs} | 19 +- .../AvatarParametersEditor2019.cs.meta | 11 ++ .../Parameters/ParameterConfigDrawer.cs | 79 +++++++++ .../Parameters/ParameterConfigDrawer.cs.meta | 3 + .../Parameters/ParameterConfigDrawer.uxml | 28 +++ .../ParameterConfigDrawer.uxml.meta | 3 + .../Parameters/ParameterSyncTypeDrawer.cs | 21 +++ .../ParameterSyncTypeDrawer.cs.meta | 3 + Editor/Inspector/Parameters/Parameters.uss | 99 +++++++++++ .../Inspector/Parameters/Parameters.uss.meta | 11 ++ .../Parameters/ParametersMainUI.uxml | 37 ++++ .../Parameters/ParametersMainUI.uxml.meta | 10 ++ Editor/Localization/Localization.cs | 2 + Editor/Localization/UIElementLocalizer.cs | 90 ++++++++++ .../Localization/UIElementLocalizer.cs.meta | 3 + Editor/Localization/en-us.json | 31 +++- Editor/Localization/ja-jp.json | 31 +++- Editor/ParameterPolicy.cs | 16 +- 23 files changed, 652 insertions(+), 30 deletions(-) delete mode 100644 Editor/Inspector/AvatarParametersEditor.cs.meta create mode 100644 Editor/Inspector/Parameters.meta create mode 100644 Editor/Inspector/Parameters/AvatarParametersEditor.cs create mode 100644 Editor/Inspector/Parameters/AvatarParametersEditor.cs.meta rename Editor/Inspector/{AvatarParametersEditor.cs => Parameters/AvatarParametersEditor2019.cs} (97%) create mode 100644 Editor/Inspector/Parameters/AvatarParametersEditor2019.cs.meta create mode 100644 Editor/Inspector/Parameters/ParameterConfigDrawer.cs create mode 100644 Editor/Inspector/Parameters/ParameterConfigDrawer.cs.meta create mode 100644 Editor/Inspector/Parameters/ParameterConfigDrawer.uxml create mode 100644 Editor/Inspector/Parameters/ParameterConfigDrawer.uxml.meta create mode 100644 Editor/Inspector/Parameters/ParameterSyncTypeDrawer.cs create mode 100644 Editor/Inspector/Parameters/ParameterSyncTypeDrawer.cs.meta create mode 100644 Editor/Inspector/Parameters/Parameters.uss create mode 100644 Editor/Inspector/Parameters/Parameters.uss.meta create mode 100644 Editor/Inspector/Parameters/ParametersMainUI.uxml create mode 100644 Editor/Inspector/Parameters/ParametersMainUI.uxml.meta create mode 100644 Editor/Localization/UIElementLocalizer.cs create mode 100644 Editor/Localization/UIElementLocalizer.cs.meta diff --git a/Editor/Inspector/AvatarParametersEditor.cs.meta b/Editor/Inspector/AvatarParametersEditor.cs.meta deleted file mode 100644 index aa9165bc..00000000 --- a/Editor/Inspector/AvatarParametersEditor.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 21089a5ec87c4e4fa1616376cbb8fbd7 -timeCreated: 1664847495 \ No newline at end of file diff --git a/Editor/Inspector/Common/UXMLExtensions.cs b/Editor/Inspector/Common/UXMLExtensions.cs index c9d968b1..582ca69a 100644 --- a/Editor/Inspector/Common/UXMLExtensions.cs +++ b/Editor/Inspector/Common/UXMLExtensions.cs @@ -12,6 +12,7 @@ namespace nadena.dev.modular_avatar.core.editor private static Dictionary> _localizers = new Dictionary>(); + [Obsolete("Use UIElementLocalizer instead")] public static VisualElement Localize(this VisualTreeAsset asset) { var root = asset.CloneTree(); diff --git a/Editor/Inspector/Parameters.meta b/Editor/Inspector/Parameters.meta new file mode 100644 index 00000000..76502279 --- /dev/null +++ b/Editor/Inspector/Parameters.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5b0bd0302666483e9fb9572cc5df36e1 +timeCreated: 1706005296 \ No newline at end of file diff --git a/Editor/Inspector/Parameters/AvatarParametersEditor.cs b/Editor/Inspector/Parameters/AvatarParametersEditor.cs new file mode 100644 index 00000000..40d7c5bb --- /dev/null +++ b/Editor/Inspector/Parameters/AvatarParametersEditor.cs @@ -0,0 +1,165 @@ +#if MA_VRCSDK3_AVATARS && UNITY_2022_1_OR_NEWER + +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; +using static nadena.dev.modular_avatar.core.editor.Localization; + +namespace nadena.dev.modular_avatar.core.editor +{ + [CustomEditor(typeof(ModularAvatarParameters))] + internal class AvatarParametersEditor : MAEditorBase + { + [SerializeField] private StyleSheet uss; + [SerializeField] private VisualTreeAsset uxml; + + private ListView listView, unregisteredListView; + + private List detectedParameters = new List(); + + protected override void OnInnerInspectorGUI() + { + EditorGUILayout.HelpBox("Unable to show override changes", MessageType.Info); + } + + protected override VisualElement CreateInnerInspectorGUI() + { + var root = uxml.CloneTree(); + UI.Localize(root); + root.styleSheets.Add(uss); + + listView = root.Q("Parameters"); + + listView.showBoundCollectionSize = false; + listView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight; + + unregisteredListView = root.Q("UnregisteredParameters"); + + unregisteredListView.showBoundCollectionSize = false; + unregisteredListView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight; + + unregisteredListView.makeItem = () => + { + var row = new VisualElement(); + row.AddToClassList("DetectedParameter"); + + return row; + }; + unregisteredListView.bindItem = (elem, i) => + { + var parameter = detectedParameters[i]; + elem.Clear(); + + var button = new Button(); + button.text = "merge_parameter.ui.add_button"; + button.AddToClassList("ndmf-tr"); + UI.Localize(button); + + var label = new Label(); + label.text = parameter.OriginalName; + elem.Add(button); + elem.Add(label); + + if (parameter.Source != null) + { + var tex = EditorGUIUtility.FindTexture("d_Search Icon"); + + var sourceButton = new Button(); + sourceButton.AddToClassList("SourceButton"); + sourceButton.text = ""; + + var image = new Image(); + sourceButton.Add(image); + image.image = tex; + + sourceButton.clicked += () => + { + EditorGUIUtility.PingObject(parameter.Source); + }; + elem.Add(sourceButton); + } + + button.clicked += () => + { + detectedParameters.RemoveAt(i); + + var target = (ModularAvatarParameters)this.target; + target.parameters.Add(new ParameterConfig() + { + internalParameter = false, + nameOrPrefix = parameter.OriginalName, + isPrefix = parameter.IsPrefix, + remapTo = "", + syncType = parameter.syncType, + defaultValue = parameter.defaultValue, + saved = parameter.saved, + }); + EditorUtility.SetDirty(target); + PrefabUtility.RecordPrefabInstancePropertyModifications(target); + + unregisteredListView.RefreshItems(); + listView.RefreshItems(); + listView.selectedIndex = target.parameters.Count - 1; + }; + }; + + unregisteredListView.itemsSource = detectedParameters; + + var unregisteredFoldout = root.Q("UnregisteredFoldout"); + unregisteredFoldout.RegisterValueChangedCallback(evt => + { + if (evt.newValue) + { + DetectParameters(); + } + }); + + root.Bind(serializedObject); + + listView.itemsRemoved += _ => + { + if (unregisteredFoldout.value) + { + // We haven't committed the removal to the backing object yet, so defer this one frame to allow that + // to happen. + EditorApplication.delayCall += DetectParameters; + } + }; + + return root; + } + + private void DetectParameters() + { + var known = new HashSet(); + var knownPB = new HashSet(); + + var target = (ModularAvatarParameters)this.target; + foreach (var parameter in target.parameters) + { + if (parameter.isPrefix) + { + knownPB.Add(parameter.nameOrPrefix); + } + else + { + known.Add(parameter.nameOrPrefix); + } + } + + var detected = ParameterPolicy.ProbeParameters(target.gameObject); + detectedParameters.Clear(); + detectedParameters.AddRange( + detected.Values + .Where(p => + p.IsPrefix ? !knownPB.Contains(p.OriginalName) : !known.Contains(p.OriginalName)) + .OrderBy(p => p.OriginalName) + ); + unregisteredListView.RefreshItems(); + } + } +} +#endif \ No newline at end of file diff --git a/Editor/Inspector/Parameters/AvatarParametersEditor.cs.meta b/Editor/Inspector/Parameters/AvatarParametersEditor.cs.meta new file mode 100644 index 00000000..221d0e89 --- /dev/null +++ b/Editor/Inspector/Parameters/AvatarParametersEditor.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 21089a5ec87c4e4fa1616376cbb8fbd7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: + - uss: {fileID: 7433441132597879392, guid: d72e507abb5be28499d149b3c22f80bc, type: 3} + - uxml: {fileID: 9197481963319205126, guid: 00e4e2766c4ae9f4687e98ed34685b4f, type: 3} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Inspector/AvatarParametersEditor.cs b/Editor/Inspector/Parameters/AvatarParametersEditor2019.cs similarity index 97% rename from Editor/Inspector/AvatarParametersEditor.cs rename to Editor/Inspector/Parameters/AvatarParametersEditor2019.cs index ff330cc1..ff0c4340 100644 --- a/Editor/Inspector/AvatarParametersEditor.cs +++ b/Editor/Inspector/Parameters/AvatarParametersEditor2019.cs @@ -1,6 +1,5 @@ #if MA_VRCSDK3_AVATARS -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -12,22 +11,10 @@ using Debug = System.Diagnostics.Debug; namespace nadena.dev.modular_avatar.core.editor { - [CustomPropertyDrawer(typeof(ParameterSyncType))] - internal class ParameterSyncTypeDrawer : EnumDrawer - { - protected override string localizationPrefix => "params.syncmode"; - - protected override Array enumValues => new object[] - { - ParameterSyncType.NotSynced, - ParameterSyncType.Bool, - ParameterSyncType.Float, - ParameterSyncType.Int, - }; - } - +#if !UNITY_2022_1_OR_NEWER [CustomEditor(typeof(ModularAvatarParameters))] - internal class AvatarParametersEditor : MAEditorBase +#endif + internal class AvatarParametersEditor2019 : MAEditorBase { /********************************************************************** * | Field name | Remap to / config | diff --git a/Editor/Inspector/Parameters/AvatarParametersEditor2019.cs.meta b/Editor/Inspector/Parameters/AvatarParametersEditor2019.cs.meta new file mode 100644 index 00000000..015ce842 --- /dev/null +++ b/Editor/Inspector/Parameters/AvatarParametersEditor2019.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7fd14c3a2e157c4dba0955d7d64cf5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Inspector/Parameters/ParameterConfigDrawer.cs b/Editor/Inspector/Parameters/ParameterConfigDrawer.cs new file mode 100644 index 00000000..278641cb --- /dev/null +++ b/Editor/Inspector/Parameters/ParameterConfigDrawer.cs @@ -0,0 +1,79 @@ +#if MA_VRCSDK3_AVATARS && UNITY_2022_1_OR_NEWER + +using System; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace nadena.dev.modular_avatar.core.editor.Parameters +{ + [CustomPropertyDrawer(typeof(ParameterConfig))] + internal class ParameterConfigDrawer : PropertyDrawer + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var rootPath = "Packages/nadena.dev.modular-avatar/Editor/Inspector/Parameters"; + var uss = AssetDatabase.LoadAssetAtPath(rootPath + "/Parameters.uss"); + var uxml = AssetDatabase.LoadAssetAtPath(rootPath + "/ParameterConfigDrawer.uxml"); + + var root = uxml.CloneTree(); + Localization.UI.Localize(root); + root.styleSheets.Add(uss); + + var foldout = root.Q(); + var foldoutLabel = foldout?.Q