using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Unity.Collections.LowLevel.Unsafe; using UnityEngine; using UnityEngine.UIElements; namespace BITKit.IData { public sealed class UXDataBindingHandler:IDisposable { internal unsafe UXDataBindingHandler(void* ptr, object value) { ValueObject = ptr; SafeValueObject = value; visualElement = value switch { Vector3 => new Vector3Field(), float => new FloatField(), int => new IntegerField(), _ => throw new InvalidCastException("未支持的数据类型"), }; switch (visualElement) { case INotifyValueChanged intField: intField.RegisterValueChangedCallback(evt => { //UnsafeUtility.AsRef(ValueObject) = evt.newValue; //Unsafe.Write(ValueObject,evt.newValue); UnsafeUtility.AsRef(ValueObject) = evt.newValue; }); break; case INotifyValueChanged floatField: floatField.RegisterValueChangedCallback(evt => { //Unsafe.Write(ValueObject,evt.newValue); UnsafeUtility.AsRef(ValueObject) = evt.newValue; }); break; case INotifyValueChanged vector3Field: vector3Field.RegisterValueChangedCallback(evt => { //Unsafe.Write(ValueObject,evt.newValue); UnsafeUtility.AsRef(ValueObject) = evt.newValue; }); break; } } internal readonly unsafe void* ValueObject; internal object SafeValueObject; public VisualElement visualElement { get; } public void Dispose() { visualElement.RemoveFromHierarchy(); } public unsafe void OnValueChanged() { SafeValueObject = SafeValueObject switch { int => UnsafeUtility.AsRef(ValueObject), float => UnsafeUtility.AsRef(ValueObject), Vector3 => UnsafeUtility.AsRef(ValueObject), _ => null }; switch (visualElement) { case INotifyValueChanged intField: intField.SetValueWithoutNotify((int)SafeValueObject); break; case INotifyValueChanged floatField: floatField.SetValueWithoutNotify((float)SafeValueObject); break; case INotifyValueChanged vector3Field: vector3Field.SetValueWithoutNotify((Vector3)SafeValueObject); break; } } } public class UXDataBindingService : MonoBehaviour { private static readonly List Handlers = new(); public static unsafe UXDataBindingHandler CreateBinding(void* ptr, object value) { var handler = new UXDataBindingHandler(ptr, value); Handlers.Add(handler); return handler; } public static unsafe UXDataBindingHandler CreateBinding(TypedReference typedReference) { UXDataBindingHandler handler = null; var value = TypedReference.ToObject(typedReference); switch (value) { case int: { ref var rawValue = ref __refvalue(typedReference, int); handler = new UXDataBindingHandler(UnsafeUtility.AddressOf(ref rawValue), value); } break; case float: { ref var rawValue = ref __refvalue(typedReference, float); handler = new UXDataBindingHandler(UnsafeUtility.AddressOf(ref rawValue), value); } break; case Vector3: { ref var rawValue = ref __refvalue(typedReference, Vector3); handler = new UXDataBindingHandler(UnsafeUtility.AddressOf(ref rawValue), value); } break; } // var handler = (value) switch // { // case int=> new UXDataBindingHandler(UnsafeUtility.AddressOf(ref value), value), // _ => throw new InvalidCastException("未支持的数据类型"), // }; //var handler = new UXDataBindingHandler(&value, __refvalue(typedReference, object)); Handlers.Add(handler); return handler; } [SerializeReference,SubclassSelector] private ITicker ticker; [SerializeField,ReadOnly] private int bindingCount; private void Start() { ticker.Add(OnTick); destroyCancellationToken.Register(() => { ticker.Remove(OnTick); }); } private void OnTick(float obj) { foreach (var handler in Handlers.ToArray()) { unsafe { if (handler.visualElement.parent is null) { Handlers.Remove(handler); continue; } object value = handler.SafeValueObject switch { int => UnsafeUtility.AsRef(handler.ValueObject), float => UnsafeUtility.AsRef(handler.ValueObject), Vector3 => UnsafeUtility.AsRef(handler.ValueObject), _ => null }; if (value != handler.SafeValueObject) { handler.OnValueChanged(); } } } bindingCount = Handlers.Count; } } }