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

154 lines
4.0 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BITKit.UX;
using Newtonsoft.Json;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.UIElements;
using Cursor = UnityEngine.UIElements.Cursor;
namespace BITKit.IData
{
public interface IUXDataBinder:IDisposable
{
Type TargetType { get; }
void OnTick(float deltaTime);
VisualElement CreateUI(object target,FieldInfo fieldInfo);
VisualElement VisualElement { get; }
}
public abstract class UXDataBinder<TDataType> : IUXDataBinder
{
public Type TargetType => typeof(TDataType);
public VisualElement VisualElement { get; private set; }
protected object target{ get; private set; }
protected TDataType currentValue { get; set; }
protected FieldInfo fieldInfo{ get; private set; }
protected string Name { get; private set; }
public virtual void OnTick(float deltaTime)
{
var newValue = (TDataType)fieldInfo.GetValue(target);
if(Equals(newValue,currentValue))return;
OnValueChanged(currentValue,newValue);
}
protected virtual void OnValueChanged(TDataType oldValue,TDataType newValue)
{
currentValue = newValue;
fieldInfo.SetValue(target,currentValue);
if (VisualElement is INotifyValueChanged<TDataType> notifyValueChanged)
notifyValueChanged.SetValueWithoutNotify(newValue);
}
public virtual void Dispose()
{
target = null;
fieldInfo = null;
VisualElement.RemoveFromHierarchy();
VisualElement = null;
}
public VisualElement CreateUI(object target, FieldInfo fieldInfo)
{
this.target = target;
this.fieldInfo = fieldInfo;
currentValue = (TDataType)fieldInfo.GetValue(target);
VisualElement = OnCreateUI();
var attribute = fieldInfo.GetCustomAttribute<ExportAttribute>();
if(attribute != null)
{
Name = attribute.Name;
VisualElement.GetType().GetProperty("label",ReflectionHelper.Flags)?.SetValue(VisualElement, Name);
}
if (fieldInfo.GetCustomAttribute<ReadOnlyAttribute>() is not null)
{
VisualElement.SetEnabled(false);
}
if(VisualElement is INotifyValueChanged<TDataType> notifyValueChanged)
{
notifyValueChanged.SetValueWithoutNotify(currentValue);
notifyValueChanged.RegisterValueChangedCallback(x =>
{
fieldInfo.SetValue(target,x.newValue);
currentValue = x.newValue;
});
}
return VisualElement;
}
protected abstract VisualElement OnCreateUI();
}
public sealed class UXIntBinder:UXDataBinder<int>
{
protected override VisualElement OnCreateUI() => new IntegerField();
}
public sealed class UXFloatBinder:UXDataBinder<float>
{
protected override VisualElement OnCreateUI() => new FloatField();
}
public sealed class UXVector3Binder:UXDataBinder<Vector3>
{
protected override VisualElement OnCreateUI() => new Vector3Field();
}
public sealed class UXVector2Binder:UXDataBinder<Vector2>
{
protected override VisualElement OnCreateUI() => new Vector2Field();
}
public sealed class UXStringBinder:UXDataBinder<string>
{
protected override VisualElement OnCreateUI()
{
if (this.fieldInfo.GetCustomAttribute<ReadOnlyAttribute>() is not null)
{
return new Label();
}
else
{
return new TextField()
{
isDelayed = true,
multiline = true
};
}
}
}
public sealed class UXFloat3Binder:UXDataBinder<float3>
{
protected override VisualElement OnCreateUI()
{
var field = new Vector3Field
{
label = Name
};
field.SetValueWithoutNotify(currentValue);
field.RegisterCallback<ChangeEvent<Vector3>>(x =>
{
fieldInfo.SetValue(target,(float3)x.newValue);
});
return field;
}
protected override void OnValueChanged(float3 oldValue, float3 newValue)
{
currentValue = newValue;
VisualElement.As<INotifyValueChanged<Vector3>>().SetValueWithoutNotify(newValue);
}
}
}