207 lines
6.0 KiB
C#
207 lines
6.0 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using AYellowpaper.SerializedCollections;
|
|
using BITKit;
|
|
using BITKit.IData;
|
|
using BITKit.UX;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using Random = UnityEngine.Random;
|
|
|
|
namespace BITFactory.Cutting
|
|
{
|
|
public class UXCuttingToolService : MonoBehaviour
|
|
{
|
|
[SerializeField] private SerializedDictionary<string,Texture2D> brushIconDictionary;
|
|
|
|
[SerializeReference, SubclassSelector] private ICuttingToolService cuttingToolService;
|
|
|
|
[SerializeField] private VisualTreeAsset brushButtonTemplate;
|
|
|
|
[UXBindPath("cuttingBrush-container")]
|
|
private VisualElement _cuttingBrushContainer;
|
|
|
|
[UXBindPath("brush-info-label")]
|
|
private Label _brushInfoLabel;
|
|
[UXBindPath("brush-name-label")]
|
|
private Label _brushNameLabel;
|
|
[UXBindPath("brush-fields-container")]
|
|
private VisualElement _brushFieldsContainer;
|
|
|
|
private readonly ConcurrentDictionary<string, UXContainer> _brushes = new();
|
|
|
|
private async void Start()
|
|
{
|
|
UXUtils.Inject(this);
|
|
_cuttingBrushContainer.Clear();
|
|
|
|
var tips = _cuttingBrushContainer.Create<Label>();
|
|
tips.text = "正在初始化中...";
|
|
|
|
await UniTask.Delay(100);
|
|
|
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
|
|
|
if (cuttingToolService.StateDictionary.Count is 0)
|
|
{
|
|
throw new Exception("cuttingToolService.StateDictionary.Count is 0");
|
|
}
|
|
|
|
tips.RemoveFromHierarchy();
|
|
|
|
cuttingToolService.OnStateRegistered += Create;
|
|
cuttingToolService.OnStateUnRegistered += Remove;
|
|
foreach (var brush in cuttingToolService.StateDictionary.Values)
|
|
{
|
|
Create(brush);
|
|
}
|
|
|
|
cuttingToolService.OnStateChanged += OnStateChanged;
|
|
|
|
OnStateChanged(null,cuttingToolService.CurrentState);
|
|
}
|
|
|
|
private async void Remove(ICuttingToolBrush obj)
|
|
{
|
|
await UniTask.SwitchToMainThread();
|
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
|
if (_brushes.TryRemove(obj.Name, out var brush))
|
|
{
|
|
brush.visualElement.RemoveFromHierarchy();
|
|
}
|
|
}
|
|
|
|
private async void Create(ICuttingToolBrush brush)
|
|
{
|
|
await UniTask.SwitchToMainThread();
|
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
|
var container =
|
|
new UXContainer(_cuttingBrushContainer.Create<VisualElement>(brushButtonTemplate.CloneTree))
|
|
{
|
|
visualElement =
|
|
{
|
|
userData = brush
|
|
}
|
|
};
|
|
|
|
container.button.clicked += Clicked;
|
|
|
|
container.button.tooltip = brush.Name+"\n"+brush.Description;
|
|
|
|
if (brushIconDictionary.TryGetValue(brush.GetType().Name, out var sprite))
|
|
{
|
|
container.icon.style.backgroundImage = new StyleBackground(sprite);
|
|
}
|
|
|
|
_brushes.GetOrAdd(brush.Name, container);
|
|
|
|
return;
|
|
|
|
void Clicked()
|
|
{
|
|
cuttingToolService.TransitionState(brush);
|
|
}
|
|
}
|
|
|
|
private unsafe void OnStateChanged(ICuttingToolBrush arg1, ICuttingToolBrush arg2)
|
|
{
|
|
foreach (var x in _cuttingBrushContainer.Children())
|
|
{
|
|
x.SetEnabled(x.userData != arg2);
|
|
}
|
|
|
|
_brushNameLabel.text = arg2.Name;
|
|
_brushInfoLabel.text = arg2.Description;
|
|
|
|
_brushFieldsContainer.Clear();
|
|
|
|
var fields = arg2.GetType().GetFields(ReflectionHelper.Flags);
|
|
foreach (var fieldInfo in fields)
|
|
{
|
|
if (Attribute.IsDefined(fieldInfo, typeof(ExportAttribute)) is false) continue;
|
|
var exportAttribute = fieldInfo.GetCustomAttribute<ExportAttribute>();
|
|
|
|
// var runtimeFieldInfo = arg2.GetType().GetRuntimeField(fieldInfo.Name);
|
|
// runtimeFieldInfo= arg2.GetType().GetField(fieldInfo.Name);
|
|
//
|
|
// Debug.Log(runtimeFieldInfo);
|
|
// var _ref = TypedReference.MakeTypedReference(arg2, new []{runtimeFieldInfo});
|
|
|
|
var handler = UXDataBindingService.CreateBinding(arg2.GetExport(fieldInfo.Name),fieldInfo.GetValue(arg2));
|
|
|
|
//var handler = UXDataBindingService.CreateBinding(_ref);
|
|
|
|
_brushFieldsContainer.Add(handler.visualElement);
|
|
|
|
handler.visualElement.GetType().GetProperty("label")!.SetValue(handler.visualElement,
|
|
string.IsNullOrEmpty(exportAttribute.Name) ? fieldInfo.Name:exportAttribute.Name
|
|
);
|
|
|
|
//var handler = UXDataBindingService.CreateBinding(ref arg2.GetExport(fieldInfo.Name));
|
|
|
|
// switch (fieldInfo.GetValue(arg2))
|
|
// {
|
|
// case float _float:
|
|
// var floatField = _brushFieldsContainer.Create<FloatField>();
|
|
// floatField.label =string.IsNullOrEmpty(exportAttribute.Name) ? fieldInfo.Name:exportAttribute.Name;
|
|
// floatField.value = _float;
|
|
// floatField.RegisterValueChangedCallback(evt =>
|
|
// {
|
|
// fieldInfo.SetValue(arg2, evt.newValue);
|
|
// });
|
|
// break;
|
|
// case Vector3 _vector3:
|
|
// var vector3Field = _brushFieldsContainer.Create<Vector3Field>();
|
|
// vector3Field.label =string.IsNullOrEmpty(exportAttribute.Name) ? fieldInfo.Name:exportAttribute.Name;
|
|
// vector3Field.value = _vector3;
|
|
// vector3Field.RegisterValueChangedCallback(evt =>
|
|
// {
|
|
// fieldInfo.SetValue(arg2, evt.newValue);
|
|
// });
|
|
// break;
|
|
// }
|
|
}
|
|
|
|
foreach (var methodInfo in arg2.GetType().GetMethods(ReflectionHelper.Flags))
|
|
{
|
|
if (Attribute.IsDefined(methodInfo, typeof(ExportAttribute)) is false) continue;
|
|
var exportAttribute = methodInfo.GetCustomAttribute<ExportAttribute>();
|
|
|
|
var button = _brushFieldsContainer.Create<Button>();
|
|
button.text =string.IsNullOrEmpty(exportAttribute.Name) ? methodInfo.Name:exportAttribute.Name;
|
|
|
|
button.clicked += OnClicked;
|
|
|
|
return;
|
|
void OnClicked()
|
|
{
|
|
try
|
|
{
|
|
methodInfo.Invoke(arg2, 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|