2024-01-28 13:27:43 +08:00
|
|
|
|
using System.Globalization;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
|
|
|
|
|
|
namespace nadena.dev.modular_avatar.core.editor
|
|
|
|
|
{
|
|
|
|
|
internal class DefaultValueField : VisualElement
|
|
|
|
|
{
|
|
|
|
|
public new class UxmlFactory : UxmlFactory<DefaultValueField, UxmlTraits>
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-14 09:04:20 +08:00
|
|
|
|
private const string V_None = " ";
|
2024-08-12 09:09:20 +08:00
|
|
|
|
private const string V_True = "ON";
|
|
|
|
|
private const string V_False = "OFF";
|
2024-09-15 08:53:00 +08:00
|
|
|
|
|
2024-01-28 13:27:43 +08:00
|
|
|
|
private readonly FloatField _defaultValueField;
|
2024-09-15 08:53:00 +08:00
|
|
|
|
private readonly Toggle _hasExplicitDefaultValueField;
|
|
|
|
|
private readonly TextField _numberField;
|
2024-08-07 11:43:32 +08:00
|
|
|
|
private readonly DropdownField _boolField;
|
2024-09-15 08:53:00 +08:00
|
|
|
|
|
|
|
|
|
private ParameterSyncType _syncType;
|
2024-10-20 08:15:43 +08:00
|
|
|
|
private bool _hasInitialBinding;
|
|
|
|
|
|
2024-01-28 13:27:43 +08:00
|
|
|
|
public DefaultValueField()
|
|
|
|
|
{
|
|
|
|
|
// Hidden binding elements
|
|
|
|
|
_defaultValueField = new FloatField();
|
2024-09-15 08:53:00 +08:00
|
|
|
|
_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));
|
2024-08-07 11:43:32 +08:00
|
|
|
|
|
2024-09-15 08:53:00 +08:00
|
|
|
|
// Visible elements for input
|
|
|
|
|
_numberField = new TextField();
|
|
|
|
|
_numberField.isDelayed = true;
|
|
|
|
|
_numberField.RegisterValueChangedCallback(evt => OnUpdateNumberValue(evt.newValue));
|
|
|
|
|
_boolField = new DropdownField();
|
2024-09-14 09:04:20 +08:00
|
|
|
|
_boolField.choices.Add(V_None);
|
2024-08-12 09:09:20 +08:00
|
|
|
|
_boolField.choices.Add(V_True);
|
|
|
|
|
_boolField.choices.Add(V_False);
|
2024-09-15 08:53:00 +08:00
|
|
|
|
_boolField.RegisterValueChangedCallback(evt => OnUpdateBoolValue(evt.newValue));
|
2024-01-28 13:27:43 +08:00
|
|
|
|
|
2024-09-15 08:53:00 +08:00
|
|
|
|
Add(_defaultValueField);
|
|
|
|
|
Add(_hasExplicitDefaultValueField);
|
|
|
|
|
Add(_numberField);
|
|
|
|
|
Add(_boolField);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnUpdateSyncType(ParameterSyncType syncType)
|
|
|
|
|
{
|
|
|
|
|
_syncType = syncType;
|
2024-01-28 13:27:43 +08:00
|
|
|
|
|
2024-09-15 08:53:00 +08:00
|
|
|
|
if (syncType != ParameterSyncType.Bool)
|
2024-01-28 13:27:43 +08:00
|
|
|
|
{
|
2024-09-15 08:53:00 +08:00
|
|
|
|
_numberField.style.display = DisplayStyle.Flex;
|
|
|
|
|
_boolField.style.display = DisplayStyle.None;
|
2024-10-20 08:15:43 +08:00
|
|
|
|
OnUpdateNumberValue(_numberField.value, true);
|
2024-09-15 08:53:00 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_numberField.style.display = DisplayStyle.None;
|
|
|
|
|
_boolField.style.display = DisplayStyle.Flex;
|
2024-10-20 08:15:43 +08:00
|
|
|
|
OnUpdateBoolValue(_boolField.value, true);
|
2024-09-15 08:53:00 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-07 11:43:32 +08:00
|
|
|
|
|
2024-10-20 08:15:43 +08:00
|
|
|
|
private void OnUpdateNumberValue(string value, bool implicitUpdate = false)
|
2024-09-15 08:53:00 +08:00
|
|
|
|
{
|
2024-10-20 08:15:43 +08:00
|
|
|
|
// Upon initial creation, sometimes the OnUpdateSyncType fires before we receive the initial value event.
|
|
|
|
|
// In this case, suppress the update to avoid losing data.
|
|
|
|
|
if (implicitUpdate && !_hasInitialBinding) return;
|
|
|
|
|
|
|
|
|
|
var theValue = _defaultValueField.value;
|
2024-09-15 08:53:00 +08:00
|
|
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
|
|
|
{
|
2024-10-20 08:15:43 +08:00
|
|
|
|
if (!implicitUpdate)
|
|
|
|
|
{
|
|
|
|
|
_defaultValueField.value = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
theValue = _defaultValueField.value;
|
|
|
|
|
|
2024-09-15 08:53:00 +08:00
|
|
|
|
_hasExplicitDefaultValueField.value = false;
|
|
|
|
|
}
|
|
|
|
|
else if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed)
|
|
|
|
|
&& !float.IsNaN(parsed)
|
|
|
|
|
&& !float.IsInfinity(parsed))
|
2024-08-07 11:43:32 +08:00
|
|
|
|
{
|
2024-10-20 08:15:43 +08:00
|
|
|
|
theValue = _defaultValueField.value = _syncType switch
|
2024-09-15 08:53:00 +08:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
2024-08-07 11:43:32 +08:00
|
|
|
|
|
2024-10-20 08:15:43 +08:00
|
|
|
|
UpdateVisibleField(theValue, _hasExplicitDefaultValueField.value);
|
2024-01-28 13:27:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-10-20 08:15:43 +08:00
|
|
|
|
private void OnUpdateBoolValue(string value, bool implicitUpdate = false)
|
2024-01-28 13:27:43 +08:00
|
|
|
|
{
|
2024-10-20 08:15:43 +08:00
|
|
|
|
// Upon initial creation, sometimes the OnUpdateSyncType fires before we receive the initial value event.
|
|
|
|
|
// In this case, suppress the update to avoid losing data.
|
|
|
|
|
if (implicitUpdate && !_hasInitialBinding) return;
|
|
|
|
|
|
2024-09-15 08:53:00 +08:00
|
|
|
|
_defaultValueField.value = value == V_True ? 1 : 0;
|
|
|
|
|
_hasExplicitDefaultValueField.value = value != V_None;
|
|
|
|
|
|
|
|
|
|
UpdateVisibleField(_defaultValueField.value, _hasExplicitDefaultValueField.value);
|
2024-01-28 13:27:43 +08:00
|
|
|
|
}
|
2024-09-15 08:53:00 +08:00
|
|
|
|
|
2024-01-28 13:27:43 +08:00
|
|
|
|
private void UpdateVisibleField(float value, bool hasExplicitValue)
|
|
|
|
|
{
|
2024-10-20 08:15:43 +08:00
|
|
|
|
_hasInitialBinding = true;
|
|
|
|
|
|
2024-09-15 08:53:00 +08:00
|
|
|
|
if (hasExplicitValue || Mathf.Abs(value) > 0.0000001)
|
2024-01-28 13:27:43 +08:00
|
|
|
|
{
|
2024-09-15 08:53:00 +08:00
|
|
|
|
_numberField.SetValueWithoutNotify(value.ToString(CultureInfo.InvariantCulture));
|
|
|
|
|
_boolField.SetValueWithoutNotify(value != 0 ? V_True : V_False);
|
2024-01-28 13:27:43 +08:00
|
|
|
|
}
|
2024-08-07 11:43:32 +08:00
|
|
|
|
else
|
2024-09-15 08:53:00 +08:00
|
|
|
|
{
|
|
|
|
|
_numberField.SetValueWithoutNotify(string.Empty);
|
|
|
|
|
_boolField.SetValueWithoutNotify(V_None);
|
|
|
|
|
}
|
2024-01-28 13:27:43 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-15 08:53:00 +08:00
|
|
|
|
}
|