Net.Like.Xue.Tokyo/Assets/BITKit/Unity/Scripts/UX/DataBind/UXIEnumerableBindingHandler.cs

194 lines
4.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit.IData
{
public abstract class UXIEnumerableBindingHandler<TDataType> : IUXDataBinder
{
public Type TargetType =>typeof(IEnumerable<TDataType>);
public VisualElement VisualElement { get;private set; }
protected object target { get; private set; }
protected FieldInfo fieldInfo{ get; private set; }
protected VisualElement container { get; private set; }
protected Button addButton;
protected readonly List<TDataType> interfaceList=new();
public VisualElement CreateUI(object target, FieldInfo fieldInfo)
{
if(VisualElement is not null){throw new InvalidOperationException($"已经创建了Inspector<{VisualElement.GetType().Name}>");}
var exportAttribute = fieldInfo.GetCustomAttribute<ExportAttribute>();
this.fieldInfo = fieldInfo;
this.target = target;
// VisualElement = new Foldout();
//
// VisualElement.Create<Label>().text = exportAttribute switch
// {
// not null when string.IsNullOrEmpty(exportAttribute.Name) is false => exportAttribute.Name,
// _=>fieldInfo.Name
// };
VisualElement = new Foldout()
{
text = exportAttribute switch
{
not null when string.IsNullOrEmpty(exportAttribute.Name) is false => exportAttribute.Name,
_=>fieldInfo.Name
}
};
VisualElement.AddToClassList("--button");
container = VisualElement.Create<VisualElement>();
addButton = VisualElement.Create<Button>();
addButton.text = "+";
addButton.clicked += Add;
Rebuild();
return VisualElement;
}
private void Add()
{
interfaceList.Add(default);
switch (fieldInfo.GetValue(target))
{
case List<TDataType> list:
list.Add(default);
break;
case TDataType[] array:
Array.Resize(ref array, array.Length + 1);
fieldInfo.SetValue(target, array);
break;
}
Rebuild();
}
protected void Rebuild()
{
interfaceList.Clear();
interfaceList.AddRange((IEnumerable<TDataType>)fieldInfo.GetValue(target));
container.Clear();
for (var index = 0; index < interfaceList.Count; index++)
{
var index1 = index;
var entryContainer = container.Create<VisualElement>();
entryContainer.style.flexDirection = FlexDirection.Row;
var x = interfaceList[index];
var textField = entryContainer.Create<TextField>();
textField.isDelayed = true;
if(x is not null)
textField.SetValueWithoutNotify(JsonConvert.SerializeObject(x));
textField.style.flexGrow = 1;
textField.style.marginLeft = 0;
textField.RegisterValueChangedCallback(OnTextFieldOnValueChanged);
var removeButton = entryContainer.Create<Button>();
//removeButton.text = $"-{index}";
//u know how to do
removeButton.style.marginTop = 0;
removeButton.AddToClassList("icon-remove");
removeButton.clicked += OnRemoveButtonOnClicked;
container.Add(entryContainer);
continue;
void OnRemoveButtonOnClicked()
{
switch (fieldInfo.GetValue(target))
{
case List<TDataType> list:
list.RemoveAt(index1);
break;
case TDataType[] array:
interfaceList.RemoveAt(index1);
fieldInfo.SetValue(target, interfaceList.ToArray());
break;
}
Rebuild();
}
void OnTextFieldOnValueChanged(ChangeEvent<string> evt)
{
Deserialize(textField,index1,evt.newValue);
}
}
}
public void OnTick(float deltaTime)
{
}
public void Dispose()
{
// TODO 在此释放托管资源
}
protected void Deserialize(TextField textField,int index,string value)
{
try
{
var newValue = (TDataType)JsonConvert.DeserializeObject(value, typeof(TDataType));
switch (fieldInfo.GetValue(target))
{
case List<TDataType> list:
list[index] = newValue;
break;
case TDataType[] array:
array[index] = newValue;
fieldInfo.SetValue(target, array);
break;
}
Rebuild();
textField.EnableInClassList("error",false);
}
catch (Exception e)
{
textField.Query<TextElement>().First().tooltip = e.Message;
textField.EnableInClassList("error",true);
}
}
}
public sealed class UXStringIEnumerableBindingHandler : UXIEnumerableBindingHandler<string>
{
}
public sealed class UXFloatIEnumerableBindingHandler : UXIEnumerableBindingHandler<float>
{
}
public sealed class UXIntIEnumerableBindingHandler : UXIEnumerableBindingHandler<int>
{
}
public sealed class UXVector3IEnumerableBindingHandler : UXIEnumerableBindingHandler<Vector3>
{
}
public sealed class UXFloat3IEnumerableBindingHandler : UXIEnumerableBindingHandler<float3>
{
}
}