174 lines
4.6 KiB
C#
174 lines
4.6 KiB
C#
|
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<int> intField:
|
||
|
intField.RegisterValueChangedCallback(evt =>
|
||
|
{
|
||
|
//UnsafeUtility.AsRef<int>(ValueObject) = evt.newValue;
|
||
|
//Unsafe.Write(ValueObject,evt.newValue);
|
||
|
UnsafeUtility.AsRef<int>(ValueObject) = evt.newValue;
|
||
|
});
|
||
|
break;
|
||
|
case INotifyValueChanged<float> floatField:
|
||
|
floatField.RegisterValueChangedCallback(evt =>
|
||
|
{
|
||
|
//Unsafe.Write(ValueObject,evt.newValue);
|
||
|
UnsafeUtility.AsRef<float>(ValueObject) = evt.newValue;
|
||
|
});
|
||
|
break;
|
||
|
case INotifyValueChanged<Vector3> vector3Field:
|
||
|
vector3Field.RegisterValueChangedCallback(evt =>
|
||
|
{
|
||
|
//Unsafe.Write(ValueObject,evt.newValue);
|
||
|
UnsafeUtility.AsRef<Vector3>(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<int>(ValueObject),
|
||
|
float => UnsafeUtility.AsRef<float>(ValueObject),
|
||
|
Vector3 => UnsafeUtility.AsRef<Vector3>(ValueObject),
|
||
|
_ => null
|
||
|
};
|
||
|
switch (visualElement)
|
||
|
{
|
||
|
case INotifyValueChanged<int> intField:
|
||
|
intField.SetValueWithoutNotify((int)SafeValueObject);
|
||
|
break;
|
||
|
case INotifyValueChanged<float> floatField:
|
||
|
floatField.SetValueWithoutNotify((float)SafeValueObject);
|
||
|
break;
|
||
|
case INotifyValueChanged<Vector3> vector3Field:
|
||
|
vector3Field.SetValueWithoutNotify((Vector3)SafeValueObject);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class UXDataBindingService : MonoBehaviour
|
||
|
{
|
||
|
private static readonly List<UXDataBindingHandler> 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<int>(handler.ValueObject),
|
||
|
float => UnsafeUtility.AsRef<float>(handler.ValueObject),
|
||
|
Vector3 => UnsafeUtility.AsRef<Vector3>(handler.ValueObject),
|
||
|
_ => null
|
||
|
};
|
||
|
|
||
|
if (value != handler.SafeValueObject)
|
||
|
{
|
||
|
handler.OnValueChanged();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
bindingCount = Handlers.Count;
|
||
|
}
|
||
|
}
|
||
|
}
|