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 : 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 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(); if(attribute != null) { Name = attribute.Name; VisualElement.GetType().GetProperty("label",ReflectionHelper.Flags)?.SetValue(VisualElement, Name); } if (fieldInfo.GetCustomAttribute() is not null) { VisualElement.SetEnabled(false); } if(VisualElement is INotifyValueChanged 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 { protected override VisualElement OnCreateUI() => new IntegerField(); } public sealed class UXFloatBinder:UXDataBinder { protected override VisualElement OnCreateUI() => new FloatField(); } public sealed class UXVector3Binder:UXDataBinder { protected override VisualElement OnCreateUI() => new Vector3Field(); } public sealed class UXVector2Binder:UXDataBinder { protected override VisualElement OnCreateUI() => new Vector2Field(); } public sealed class UXStringBinder:UXDataBinder { protected override VisualElement OnCreateUI() { if (this.fieldInfo.GetCustomAttribute() is not null) { return new Label(); } else { return new TextField() { isDelayed = true, multiline = true }; } } } public sealed class UXFloat3Binder:UXDataBinder { protected override VisualElement OnCreateUI() { var field = new Vector3Field { label = Name }; field.SetValueWithoutNotify(currentValue); field.RegisterCallback>(x => { fieldInfo.SetValue(target,(float3)x.newValue); }); return field; } protected override void OnValueChanged(float3 oldValue, float3 newValue) { currentValue = newValue; VisualElement.As>().SetValueWithoutNotify(newValue); } } }