1
This commit is contained in:
193
Src/Unity/Scripts/UX/DataBind/UXIEnumerableBindingHandler.cs
Normal file
193
Src/Unity/Scripts/UX/DataBind/UXIEnumerableBindingHandler.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
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>
|
||||
{
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user