diff --git a/Editor/Inspector/Parameters/AvatarParametersEditor.cs b/Editor/Inspector/Parameters/AvatarParametersEditor.cs index 40d7c5bb..f8af2fa2 100644 --- a/Editor/Inspector/Parameters/AvatarParametersEditor.cs +++ b/Editor/Inspector/Parameters/AvatarParametersEditor.cs @@ -5,8 +5,12 @@ using System.Linq; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; +using UnityEngine.UI; using UnityEngine.UIElements; +using VRC.SDK3.Avatars.ScriptableObjects; using static nadena.dev.modular_avatar.core.editor.Localization; +using Button = UnityEngine.UIElements.Button; +using Image = UnityEngine.UIElements.Image; namespace nadena.dev.modular_avatar.core.editor { @@ -35,6 +39,37 @@ namespace nadena.dev.modular_avatar.core.editor listView.showBoundCollectionSize = false; listView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight; + listView.selectionType = SelectionType.Multiple; + listView.RegisterCallback(evt => + { + if (evt.keyCode == KeyCode.Delete) + { + serializedObject.Update(); + + var prop = serializedObject.FindProperty("parameters"); + + var indices = listView.selectedIndices.ToList(); + + foreach (var index in indices.OrderByDescending(i => i)) + { + prop.DeleteArrayElementAtIndex(index); + } + + serializedObject.ApplyModifiedProperties(); + + if (indices.Count == 0) + { + EditorApplication.delayCall += () => + { + // Works around an issue where the inner text boxes are auto-selected, preventing you from + // just hitting delete over and over + listView.SetSelectionWithoutNotify(indices); + }; + } + } + + evt.StopPropagation(); + }, TrickleDown.NoTrickleDown); unregisteredListView = root.Q("UnregisteredParameters"); @@ -128,10 +163,73 @@ namespace nadena.dev.modular_avatar.core.editor EditorApplication.delayCall += DetectParameters; } }; + + var importProp = root.Q("p_import"); + importProp.RegisterValueChangedCallback(evt => + { + ImportValues(importProp); + importProp.SetValueWithoutNotify(null); + }); + importProp.objectType = typeof(VRCExpressionParameters); + importProp.allowSceneObjects = false; return root; } + private void ImportValues(ObjectField importProp) + { + var known = new HashSet(); + + var target = (ModularAvatarParameters)this.target; + foreach (var parameter in target.parameters) + { + if (!parameter.isPrefix) + { + known.Add(parameter.nameOrPrefix); + } + } + + Undo.RecordObject(target, "Import parameters"); + + var source = (VRCExpressionParameters)importProp.value; + if (source == null) + { + return; + } + + foreach (var parameter in source.parameters) + { + if (!known.Contains(parameter.name)) + { + ParameterSyncType pst; + + switch (parameter.valueType) + { + case VRCExpressionParameters.ValueType.Bool: pst = ParameterSyncType.Bool; break; + case VRCExpressionParameters.ValueType.Float: pst = ParameterSyncType.Float; break; + case VRCExpressionParameters.ValueType.Int: pst = ParameterSyncType.Int; break; + default: pst = ParameterSyncType.Float; break; + } + + if (!parameter.networkSynced) + { + pst = ParameterSyncType.NotSynced; + } + + target.parameters.Add(new ParameterConfig() + { + internalParameter = false, + nameOrPrefix = parameter.name, + isPrefix = false, + remapTo = "", + syncType = pst, + defaultValue = parameter.defaultValue, + saved = parameter.saved, + }); + } + } + } + private void DetectParameters() { var known = new HashSet(); diff --git a/Editor/Inspector/Parameters/ParameterConfigDrawer.cs b/Editor/Inspector/Parameters/ParameterConfigDrawer.cs index 09bff39d..878a1fda 100644 --- a/Editor/Inspector/Parameters/ParameterConfigDrawer.cs +++ b/Editor/Inspector/Parameters/ParameterConfigDrawer.cs @@ -81,6 +81,12 @@ namespace nadena.dev.modular_avatar.core.editor.Parameters updateRemapToPlaceholder(); + foreach (var elem in root.Query().Build()) + { + // Prevent keypresses from bubbling up + elem.RegisterCallback(evt => evt.StopPropagation(), TrickleDown.NoTrickleDown); + } + return root; } diff --git a/Editor/Inspector/Parameters/Parameters.uss b/Editor/Inspector/Parameters/Parameters.uss index 4d243bb1..80b51b48 100644 --- a/Editor/Inspector/Parameters/Parameters.uss +++ b/Editor/Inspector/Parameters/Parameters.uss @@ -1,5 +1,6 @@ #ListViewContainer { margin-top: 4px; + max-height: 500px; } .horizontal { diff --git a/Editor/Inspector/Parameters/ParametersMainUI.uxml b/Editor/Inspector/Parameters/ParametersMainUI.uxml index 4bb53140..e91178d4 100644 --- a/Editor/Inspector/Parameters/ParametersMainUI.uxml +++ b/Editor/Inspector/Parameters/ParametersMainUI.uxml @@ -12,7 +12,6 @@ show-border="true" show-foldout-header="false" name="Parameters" - item-height="100" binding-path="parameters" style="flex-grow: 1;" /> @@ -33,5 +32,7 @@ /> + + \ No newline at end of file diff --git a/Editor/Localization/en-US.json b/Editor/Localization/en-US.json index 07a5a565..e43aa771 100644 --- a/Editor/Localization/en-US.json +++ b/Editor/Localization/en-US.json @@ -51,6 +51,7 @@ "merge_parameter.ui.add_button": "Add", "merge_parameter.ui.details": "Parameter Configuration", "merge_parameter.ui.overrideAnimatorDefaults": "Override Animator Defaults", + "merge_parameter.ui.importFromAsset": "Import from asset", "merge_armature.merge_target": "Merge Target", "merge_armature.merge_target.tooltip": "The armature (or subtree) to merge this object into", "merge_armature.prefix": "Prefix",