From faa8d210f24a8d4b399e58e9032d6de28507035b Mon Sep 17 00:00:00 2001 From: nekobako Date: Sun, 15 Sep 2024 09:53:00 +0900 Subject: [PATCH] Enhance default value field (#1125) * feat: enhance default value field input * fix: format default value when update type or value on parameters inspector * fix: don't accept NaN and Infinity for default value setting --- .../Inspector/Parameters/DefaultValueField.cs | 147 +++++++++--------- .../Parameters/ParameterConfigDrawer.cs | 22 +-- Editor/Inspector/Parameters/Parameters.uss | 20 +-- 3 files changed, 87 insertions(+), 102 deletions(-) diff --git a/Editor/Inspector/Parameters/DefaultValueField.cs b/Editor/Inspector/Parameters/DefaultValueField.cs index d044a9b1..6ba6cd22 100644 --- a/Editor/Inspector/Parameters/DefaultValueField.cs +++ b/Editor/Inspector/Parameters/DefaultValueField.cs @@ -1,6 +1,4 @@ using System.Globalization; -using UnityEditor; -using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; @@ -15,95 +13,104 @@ namespace nadena.dev.modular_avatar.core.editor private const string V_None = " "; private const string V_True = "ON"; private const string V_False = "OFF"; - - private readonly TextField _visibleField; + private readonly FloatField _defaultValueField; + private readonly Toggle _hasExplicitDefaultValueField; + private readonly TextField _numberField; private readonly DropdownField _boolField; - private readonly Toggle _hasExplicitDefaultSetField; + + private ParameterSyncType _syncType; public DefaultValueField() { // Hidden binding elements _defaultValueField = new FloatField(); - _hasExplicitDefaultSetField = new Toggle(); - _boolField = new DropdownField(); + _defaultValueField.style.display = DisplayStyle.None; + _defaultValueField.bindingPath = nameof(ParameterConfig.defaultValue); + _defaultValueField.RegisterValueChangedCallback(evt => UpdateVisibleField(evt.newValue, _hasExplicitDefaultValueField.value)); + _hasExplicitDefaultValueField = new Toggle(); + _hasExplicitDefaultValueField.style.display = DisplayStyle.None; + _hasExplicitDefaultValueField.bindingPath = nameof(ParameterConfig.hasExplicitDefaultValue); + _hasExplicitDefaultValueField.RegisterValueChangedCallback(evt => UpdateVisibleField(_defaultValueField.value, evt.newValue)); + // Visible elements for input + _numberField = new TextField(); + _numberField.isDelayed = true; + _numberField.RegisterValueChangedCallback(evt => OnUpdateNumberValue(evt.newValue)); + _boolField = new DropdownField(); _boolField.choices.Add(V_None); _boolField.choices.Add(V_True); _boolField.choices.Add(V_False); + _boolField.RegisterValueChangedCallback(evt => OnUpdateBoolValue(evt.newValue)); - _defaultValueField.RegisterValueChangedCallback( - evt => UpdateVisibleField(evt.newValue, _hasExplicitDefaultSetField.value)); - _defaultValueField.bindingPath = nameof(ParameterConfig.defaultValue); - - _hasExplicitDefaultSetField.RegisterValueChangedCallback( - evt => UpdateVisibleField(_defaultValueField.value, evt.newValue)); - _hasExplicitDefaultSetField.bindingPath = nameof(ParameterConfig.hasExplicitDefaultValue); - - _visibleField = new TextField(); - _visibleField.RegisterValueChangedCallback(evt => - { - if (string.IsNullOrWhiteSpace(evt.newValue)) - { - _hasExplicitDefaultSetField.value = false; - _defaultValueField.value = 0; - } - else - { - _hasExplicitDefaultSetField.value = true; - _defaultValueField.value = float.Parse(evt.newValue, CultureInfo.InvariantCulture); - } - }); - - _defaultValueField.style.width = 0; - _defaultValueField.SetEnabled(false); - _hasExplicitDefaultSetField.style.width = 0; - _hasExplicitDefaultSetField.SetEnabled(false); - - _boolField.RegisterValueChangedCallback(evt => - { - if (evt.newValue == V_True) - _defaultValueField.value = 1; - else - _defaultValueField.value = 0; - - _hasExplicitDefaultSetField.value = evt.newValue != V_None; - }); - - - style.flexDirection = FlexDirection.Row; - - Add(_visibleField); - Add(_boolField); Add(_defaultValueField); - Add(_hasExplicitDefaultSetField); + Add(_hasExplicitDefaultValueField); + Add(_numberField); + Add(_boolField); } - public void ManualBindProperty(SerializedProperty property) + public void OnUpdateSyncType(ParameterSyncType syncType) { - _defaultValueField.BindProperty(property); - _hasExplicitDefaultSetField.BindProperty(property); + _syncType = syncType; + + if (syncType != ParameterSyncType.Bool) + { + _numberField.style.display = DisplayStyle.Flex; + _boolField.style.display = DisplayStyle.None; + OnUpdateNumberValue(_numberField.value); + } + else + { + _numberField.style.display = DisplayStyle.None; + _boolField.style.display = DisplayStyle.Flex; + OnUpdateBoolValue(_boolField.value); + } } - + + private void OnUpdateNumberValue(string value) + { + if (string.IsNullOrWhiteSpace(value)) + { + _defaultValueField.value = 0; + _hasExplicitDefaultValueField.value = false; + } + else if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed) + && !float.IsNaN(parsed) + && !float.IsInfinity(parsed)) + { + _defaultValueField.value = _syncType switch + { + ParameterSyncType.Int => Mathf.FloorToInt(Mathf.Clamp(parsed, 0, 255)), + ParameterSyncType.Float => Mathf.Clamp(parsed, -1, 1), + ParameterSyncType.Bool => parsed != 0 ? 1 : 0, + _ => parsed, + }; + _hasExplicitDefaultValueField.value = true; + } + + UpdateVisibleField(_defaultValueField.value, _hasExplicitDefaultValueField.value); + } + + private void OnUpdateBoolValue(string value) + { + _defaultValueField.value = value == V_True ? 1 : 0; + _hasExplicitDefaultValueField.value = value != V_None; + + UpdateVisibleField(_defaultValueField.value, _hasExplicitDefaultValueField.value); + } + private void UpdateVisibleField(float value, bool hasExplicitValue) { - if (Mathf.Abs(value) > 0.0000001) + if (hasExplicitValue || Mathf.Abs(value) > 0.0000001) { - hasExplicitValue = true; + _numberField.SetValueWithoutNotify(value.ToString(CultureInfo.InvariantCulture)); + _boolField.SetValueWithoutNotify(value != 0 ? V_True : V_False); } - - var str = hasExplicitValue ? value.ToString(CultureInfo.InvariantCulture) : ""; - _visibleField.SetValueWithoutNotify(str); - - string boolStr; - if (!hasExplicitValue) - boolStr = V_None; - else if (value > 0.5) - boolStr = V_True; else - boolStr = V_False; - - _boolField.SetValueWithoutNotify(boolStr); + { + _numberField.SetValueWithoutNotify(string.Empty); + _boolField.SetValueWithoutNotify(V_None); + } } } -} \ No newline at end of file +} diff --git a/Editor/Inspector/Parameters/ParameterConfigDrawer.cs b/Editor/Inspector/Parameters/ParameterConfigDrawer.cs index 32b9ddf2..09bff39d 100644 --- a/Editor/Inspector/Parameters/ParameterConfigDrawer.cs +++ b/Editor/Inspector/Parameters/ParameterConfigDrawer.cs @@ -20,14 +20,14 @@ namespace nadena.dev.modular_avatar.core.editor.Parameters Localization.UI.Localize(root); root.styleSheets.Add(uss); - var type_field = root.Q("f-type"); - - var f_sync_type = root.Q("f-sync-type"); + var f_type = root.Q("f-type"); + var f_sync_type = root.Q("f-sync-type"); + var f_is_prefix = root.Q("f-is-prefix"); SetupPairedDropdownField( root, - type_field, + f_type, f_sync_type, - root.Q("f-is-prefix"), + f_is_prefix, ("Bool", "False", "params.syncmode.Bool"), ("Float", "False", "params.syncmode.Float"), ("Int", "False", "params.syncmode.Int"), @@ -35,15 +35,9 @@ namespace nadena.dev.modular_avatar.core.editor.Parameters (null, "True", "params.syncmode.PhysBonesPrefix") ); - f_sync_type.Q().RegisterValueChangedCallback(evt => - { - var is_anim_only = evt.newValue == "Not Synced"; - - if (is_anim_only) - root.AddToClassList("st-anim-only"); - else - root.RemoveFromClassList("st-anim-only"); - }); + var f_default = root.Q(); + f_default.OnUpdateSyncType((ParameterSyncType)f_sync_type.index); + f_sync_type.RegisterValueChangedCallback(evt => f_default.OnUpdateSyncType((ParameterSyncType)f_sync_type.index)); var f_synced = root.Q("f-synced"); var f_local_only = root.Q("f-local-only"); diff --git a/Editor/Inspector/Parameters/Parameters.uss b/Editor/Inspector/Parameters/Parameters.uss index 5449835c..4d243bb1 100644 --- a/Editor/Inspector/Parameters/Parameters.uss +++ b/Editor/Inspector/Parameters/Parameters.uss @@ -30,7 +30,7 @@ display: none; } -.st-anim-only .st-anim-only__hide { +.st-ty-Not-Synced .st-anim-only__hide { display: none; } @@ -79,28 +79,12 @@ margin: 0; } -DefaultValueField TextField { - display: flex; +DefaultValueField > * { width: 60px; height: 100%; margin: 0; } -DefaultValueField DropdownField { - display: none; - width: 60px; - height: 100%; - margin: 0; -} - -.st-ty-Bool DefaultValueField TextField { - display: none; -} - -.st-ty-Bool DefaultValueField DropdownField { - display: flex; -} - #f-local-only { display: none; }