优化
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Ichni.RhythmGame;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class DynamicUISlider : DynamicUIElement
|
||||
{
|
||||
public Slider slider;
|
||||
public TMP_InputField valueInputField;
|
||||
public TMP_InputField minInputField;
|
||||
public TMP_InputField maxInputField;
|
||||
|
||||
private UnityAction<float> customAction;
|
||||
private bool updatingInternally; // 防止输入框和滑块互相递归更新
|
||||
|
||||
#region [初始化] Initialize
|
||||
|
||||
public override void Initialize(IBaseElement baseElement, string title, string parameterName)
|
||||
{
|
||||
Initialize(baseElement, title, parameterName, 0f, 1f, false);
|
||||
}
|
||||
|
||||
public void Initialize(IBaseElement baseElement, string title, string parameterName,
|
||||
float min, float max, bool wholeNumbers = false)
|
||||
{
|
||||
slider.minValue = min;
|
||||
slider.maxValue = max;
|
||||
slider.wholeNumbers = wholeNumbers;
|
||||
|
||||
// [对象池安全] 精准解绑业务代理
|
||||
slider.onValueChanged.RemoveListener(OnSliderValueChanged);
|
||||
valueInputField?.onEndEdit.RemoveListener(OnValueInputEndEdit);
|
||||
minInputField?.onEndEdit.RemoveListener(OnMinInputEndEdit);
|
||||
maxInputField?.onEndEdit.RemoveListener(OnMaxInputEndEdit);
|
||||
customAction = null;
|
||||
|
||||
base.Initialize(baseElement, title, parameterName);
|
||||
|
||||
if (parameterName != string.Empty)
|
||||
{
|
||||
var val = ReflectionHelper.GetDeepValue(connectedBaseElement, parameterName);
|
||||
if (val != null)
|
||||
{
|
||||
slider.SetValueWithoutNotify(System.Convert.ToSingle(val));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[DynamicUI] 尝试绑定 {title} ({parameterName}) 失败,由于其值或路径无效。");
|
||||
}
|
||||
slider.onValueChanged.AddListener(OnSliderValueChanged);
|
||||
}
|
||||
else
|
||||
{
|
||||
slider.onValueChanged.AddListener(OnSliderValueChanged);
|
||||
}
|
||||
|
||||
SyncAllInputFields();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [滑块变化回调] Slider Callback
|
||||
|
||||
private void OnSliderValueChanged(float value)
|
||||
{
|
||||
if (updatingInternally) return;
|
||||
updatingInternally = true;
|
||||
|
||||
UpdateValueInputText(value);
|
||||
if (parameterName != string.Empty)
|
||||
{
|
||||
ApplyParameters(value);
|
||||
}
|
||||
customAction?.Invoke(value);
|
||||
|
||||
updatingInternally = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [输入框回调] Input Field Callbacks
|
||||
|
||||
private void OnValueInputEndEdit(string text)
|
||||
{
|
||||
if (updatingInternally) return;
|
||||
if (!float.TryParse(text, out float val)) return;
|
||||
|
||||
val = Mathf.Clamp(val, slider.minValue, slider.maxValue);
|
||||
|
||||
updatingInternally = true;
|
||||
|
||||
slider.SetValueWithoutNotify(val);
|
||||
UpdateValueInputText(val);
|
||||
if (parameterName != string.Empty)
|
||||
{
|
||||
ApplyParameters(val);
|
||||
}
|
||||
customAction?.Invoke(val);
|
||||
|
||||
updatingInternally = false;
|
||||
}
|
||||
|
||||
private void OnMinInputEndEdit(string text)
|
||||
{
|
||||
if (updatingInternally) return;
|
||||
if (!float.TryParse(text, out float val)) return;
|
||||
|
||||
if (val >= slider.maxValue) val = slider.maxValue - 0.0001f;
|
||||
slider.minValue = val;
|
||||
|
||||
if (slider.value < val)
|
||||
{
|
||||
slider.value = val;
|
||||
}
|
||||
|
||||
UpdateMinMaxInputTexts();
|
||||
UpdateValueInputText(slider.value);
|
||||
}
|
||||
|
||||
private void OnMaxInputEndEdit(string text)
|
||||
{
|
||||
if (updatingInternally) return;
|
||||
if (!float.TryParse(text, out float val)) return;
|
||||
|
||||
if (val <= slider.minValue) val = slider.minValue + 0.0001f;
|
||||
slider.maxValue = val;
|
||||
|
||||
if (slider.value > val)
|
||||
{
|
||||
slider.value = val;
|
||||
}
|
||||
|
||||
UpdateMinMaxInputTexts();
|
||||
UpdateValueInputText(slider.value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [参数写入] Apply Parameters
|
||||
|
||||
private void ApplyParameters(float value)
|
||||
{
|
||||
object convertedValue;
|
||||
if (slider.wholeNumbers)
|
||||
{
|
||||
convertedValue = Mathf.RoundToInt(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
convertedValue = value;
|
||||
}
|
||||
Ichni.Editor.Commands.CommandManager.ExecuteCommand(
|
||||
new Ichni.Editor.Commands.ChangeValueCommand(connectedBaseElement, parameterName, convertedValue));
|
||||
connectedBaseElement.Refresh();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [UI 同步] UI Sync Helpers
|
||||
|
||||
private void SyncAllInputFields()
|
||||
{
|
||||
UpdateValueInputText(slider.value);
|
||||
UpdateMinMaxInputTexts();
|
||||
}
|
||||
|
||||
private void UpdateValueInputText(float value)
|
||||
{
|
||||
if (valueInputField != null)
|
||||
{
|
||||
valueInputField.SetTextWithoutNotify(slider.wholeNumbers
|
||||
? Mathf.RoundToInt(value).ToString()
|
||||
: value.ToString("F3"));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMinMaxInputTexts()
|
||||
{
|
||||
string FormatRangeVal(float v)
|
||||
{
|
||||
return slider.wholeNumbers ? Mathf.RoundToInt(v).ToString() : v.ToString("F3");
|
||||
}
|
||||
|
||||
if (minInputField != null)
|
||||
{
|
||||
minInputField.SetTextWithoutNotify(FormatRangeVal(slider.minValue));
|
||||
}
|
||||
if (maxInputField != null)
|
||||
{
|
||||
maxInputField.SetTextWithoutNotify(FormatRangeVal(slider.maxValue));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [Public API]
|
||||
|
||||
public void SetRange(float min, float max)
|
||||
{
|
||||
slider.minValue = min;
|
||||
slider.maxValue = max;
|
||||
UpdateMinMaxInputTexts();
|
||||
UpdateValueInputText(slider.value);
|
||||
}
|
||||
|
||||
public void SetWholeNumbers(bool wholeNumbers)
|
||||
{
|
||||
slider.wholeNumbers = wholeNumbers;
|
||||
SyncAllInputFields();
|
||||
}
|
||||
|
||||
public override DynamicUIElement AddListenerFunction(UnityAction action)
|
||||
{
|
||||
customAction += _ => action();
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user