This commit is contained in:
CortexCore
2024-04-16 04:15:06 +08:00
parent b673a9438d
commit 0362b2c606
183 changed files with 5695 additions and 1453 deletions

View File

@@ -1,9 +1,14 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using BITKit.UX;
using Newtonsoft.Json;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.UIElements;
@@ -11,163 +16,126 @@ 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)
[RuntimeInitializeOnLoadMethod]
private static void Reload()
{
var handler = new UXDataBindingHandler(ptr, value);
Handlers.Add(handler);
return handler;
_Binders.Clear();
_Instances.Clear();
}
public static unsafe UXDataBindingHandler CreateBinding(TypedReference typedReference)
private static readonly Dictionary<Type,IUXDataBinder> _Binders = new();
private static readonly CacheList<IUXDataBinder> _Instances = new();
public static VisualElement Create(object target)
{
UXDataBindingHandler handler = null;
var value = TypedReference.ToObject(typedReference);
var visualElement = new VisualElement();
var fields = target.GetType().GetFields(ReflectionHelper.Flags);
foreach (var fieldInfo in fields.Where(x=>x.GetCustomAttribute<ExportAttribute>() is not null))
{
var handler = UXDataBindingService.Create(target,fieldInfo);
var ui = handler.CreateUI(target, fieldInfo);
visualElement.Add(ui);
}
foreach (var methodInfo in target.GetType().GetMethods(ReflectionHelper.Flags))
{
if (Attribute.IsDefined(methodInfo, typeof(ExportAttribute)) is false) continue;
var exportAttribute = methodInfo.GetCustomAttribute<ExportAttribute>();
var button = visualElement.Create<Button>();
button.text =string.IsNullOrEmpty(exportAttribute.Name) ? methodInfo.Name:exportAttribute.Name;
button.clicked += OnClicked;
continue;
void OnClicked()
{
try
{
methodInfo.Invoke(target, null);
}
catch (TargetInvocationException targetInvocationException)
{
if (targetInvocationException.InnerException is InGameException e is false) return;
switch (e)
{
case {InnerException:not null}:
Alert.Print(e.Message,e.InnerException.Message);
break;
default:
Alert.Print(e.Message,e.Source);
break;
}
}
}
}
return visualElement;
}
public static IUXDataBinder Create(object target,FieldInfo fieldInfo)
{
var value = fieldInfo.GetValue(target);
var type = value?.GetType() ?? fieldInfo.FieldType;
// if (value is IEnumerable)
// {
// //type = typeof(IEnumerable<>).MakeGenericType(fieldInfo.FieldType.GetElementType());
// //type = typeof(IEnumerable<>).MakeGenericType(type.GetGenericArguments());
// }
switch (value)
{
case int:
{
ref var rawValue = ref __refvalue(typedReference, int);
handler = new UXDataBindingHandler(UnsafeUtility.AddressOf(ref rawValue), value);
}
case Array:
type = typeof(IEnumerable<>).MakeGenericType(fieldInfo.FieldType.GetElementType());
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);
}
case IList:
type = typeof(IEnumerable<>).MakeGenericType(type.GetGenericArguments());
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;
if (_Binders.TryGetValue(type, out var binder) is false)
throw new NotImplementedException($"未支持的类型:{type.Name}");
var instance = (IUXDataBinder)Activator.CreateInstance(binder.GetType());
_Instances.Add(instance);
return instance;
}
[SerializeReference, SubclassSelector] private ITicker ticker;
[SerializeReference,SubclassSelector] private ITicker ticker;
[SerializeField,ReadOnly] private int bindingCount;
private void Start()
private async void Start()
{
ticker.Add(OnTick);
destroyCancellationToken.Register(() => { ticker.Remove(OnTick); });
}
var binders = await ReflectionHelper.GetTypes<IUXDataBinder>();
if(destroyCancellationToken.IsCancellationRequested)return;
private void OnTick(float obj)
{
foreach (var handler in Handlers.ToArray())
foreach (var x in binders)
{
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();
}
}
var instance = (IUXDataBinder)Activator.CreateInstance(x);
if (_Binders.TryAdd(instance.TargetType, instance)) ;
}
ticker.Add(OnTick);
destroyCancellationToken.Register(() =>
{
ticker.Remove(OnTick);
});
}
private static void OnTick(float obj)
{
var array = _Instances.ValueArray;
foreach (var x in array)
{
if (x.VisualElement.panel is null)
{
_Instances.Remove(x);
continue;
}
x.OnTick(obj);
}
bindingCount = Handlers.Count;
}
}
}