using System; using System.Collections.Generic; using System.Reflection; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UIElements; namespace DanieleMarotta.RiversongCodeShowcase { [RequireComponent(typeof(UIDocument))] public class UIRoot : MonoBehaviour, IUIRoot { private UIDocument _document; private Dictionary _views = new(); public VisualElement RootVisualElement { get; private set; } public event Action ElementClicked; private void Awake() { _document = GetComponent(); } public async UniTask Initialize(UIService uiService) { RootVisualElement = _document.rootVisualElement; await DiscoverViewsAsync(uiService); InitializeDragging(); RootVisualElement.RegisterCallback(OnClick); } public void Dispose() { foreach (var view in _views.Values) view.Dispose(); RootVisualElement.UnregisterCallback(OnClick); } private void OnClick(ClickEvent evt) { ElementClicked?.Invoke(evt); } private async UniTask DiscoverViewsAsync(UIService uiService) { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) foreach (var type in assembly.GetTypes()) { var viewAttribute = type.GetCustomAttribute(); if (viewAttribute == null) continue; var element = RootVisualElement.Q(className: viewAttribute.UssClassName); var view = await uiService.CreateView(type, element); _views.Add(type, view); } } private void InitializeDragging() { var targets = RootVisualElement.Query(className: "drag-target").ToList(); foreach (var target in targets) MakeDraggable(target); } public void MakeDraggable(VisualElement target) { var handle = target.Q(className: "drag-handle") ?? target; handle.AddManipulator(new DraggableManipulator(target)); } public T GetView() where T : UIView { return _views.TryGetValue(typeof(T), out var view) ? (T)view : null; } } }