Net.Like.Xue.Tokyo/Assets/BITKit/Unity/Scripts/UX/ContextMenu/UXContextMenu.cs

187 lines
5.3 KiB
C#
Raw Normal View History

2024-11-03 16:42:23 +08:00
using System;
using System.Collections.Generic;
2024-11-13 17:47:45 +08:00
using System.ComponentModel.Design;
2024-11-03 16:42:23 +08:00
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
2024-11-13 17:47:45 +08:00
using BITKit.Mod;
using Object = UnityEngine.Object;
2024-11-03 16:42:23 +08:00
namespace BITKit.UX.Internal
{
public class ContextMenu : IContextMenu
{
public virtual VisualElement GetVisualElement()
{
return new VisualElement();
}
}
public class Label : ContextMenu
{
public Label(string text)
{
2024-11-13 17:47:45 +08:00
_text = text;
2024-11-03 16:42:23 +08:00
}
2024-11-13 17:47:45 +08:00
private readonly string _text;
2024-11-03 16:42:23 +08:00
public override VisualElement GetVisualElement()
{
2024-11-13 17:47:45 +08:00
UnityEngine.UIElements.Label label = new(_text);
2024-11-03 16:42:23 +08:00
return label;
}
}
2024-11-13 17:47:45 +08:00
[Serializable]
2024-11-03 16:42:23 +08:00
public class TestContextMenu
{
public void Execute()
{
ContextMenuBuilder
.Create()
.BuildText("Tools")
.BuildAction("Log", () => Debug.Log(nameof(ContextMenu)))
.Build();
}
}
public class Button : ContextMenu
{
public Button(string text, params Action[] actions)
{
2024-11-13 17:47:45 +08:00
_text = text;
2024-11-03 16:42:23 +08:00
foreach (var x in actions)
{
2024-11-13 17:47:45 +08:00
_action += x;
2024-11-03 16:42:23 +08:00
}
}
2024-11-13 17:47:45 +08:00
private readonly string _text;
private readonly Action _action;
2024-11-03 16:42:23 +08:00
public override VisualElement GetVisualElement()
{
UnityEngine.UIElements.Button button = new();
2024-11-13 17:47:45 +08:00
button.clicked += _action;
button.text = _text;
2024-11-03 16:42:23 +08:00
return button;
}
}
}
namespace BITKit.UX
{
public interface IContextMenu
{
VisualElement GetVisualElement();
}
public static class ContextMenuBuilderExtensions
{
public static ContextMenuBuilder BuildText(this ContextMenuBuilder self, string text)
{
self.Add(new Internal.Label(text));
return self;
}
public static ContextMenuBuilder BuildAction(this ContextMenuBuilder self, string text, Action action)
{
2024-11-13 17:47:45 +08:00
self.Add(new Internal.Button(text, action, self.Execute));
2024-11-03 16:42:23 +08:00
return self;
}
}
public class ContextMenuBuilder
{
2024-11-13 17:47:45 +08:00
private readonly List<IContextMenu> _contexts = new();
public event Action OnExecuted;
2024-11-03 16:42:23 +08:00
private ContextMenuBuilder()
{
}
public static ContextMenuBuilder Create()
{
return new();
}
public void Build()
{
UXContextMenu.Singleton.Create(this);
}
2024-11-13 17:47:45 +08:00
internal void Execute()
2024-11-03 16:42:23 +08:00
{
2024-11-13 17:47:45 +08:00
OnExecuted?.Invoke();
2024-11-03 16:42:23 +08:00
}
2024-11-13 17:47:45 +08:00
public void Add(IContextMenu x) => _contexts.Add(x);
public IEnumerable<IContextMenu> GetContextMenus() => _contexts.ToArray();
2024-11-03 16:42:23 +08:00
}
2024-11-13 17:47:45 +08:00
public class UXContextMenu:IDisposable
2024-11-03 16:42:23 +08:00
{
internal static UXContextMenu Singleton;
2024-11-13 17:47:45 +08:00
private readonly IUXService _uxService;
private VisualElement _root;
private VisualElement _container;
private bool _isInitialized = false;
public UXContextMenu(IUXService uxService)
2024-11-03 16:42:23 +08:00
{
2024-11-13 17:47:45 +08:00
_uxService = uxService;
2024-11-03 16:42:23 +08:00
Singleton = this;
2024-11-13 17:47:45 +08:00
uxService.OnPanelChanged += OnPanelChanged;
InitializeAsync();
}
private async void InitializeAsync()
{
var go = new GameObject(nameof(UXContextMenu));
Object.DontDestroyOnLoad(go);
var document = go.AddComponent<UIDocument>();
document.sortingOrder = 1;
try
{
var panelSettings =await ModService.LoadAsset<PanelSettings>("ux_panel_settings");
document.panelSettings = panelSettings;
}
catch (Exception)
{
BIT4Log.Warning<UXService>("未找到ux_panel_settings");
throw;
}
document.visualTreeAsset = await ModService.LoadAsset<VisualTreeAsset>("ux_context_menu");
_root = document.rootVisualElement;
_container = _root.Q<VisualElement>("menu-container");
_root.Q("background-image").RegisterCallback<MouseDownEvent>(_ =>
2024-11-03 16:42:23 +08:00
{
Close();
});
2024-11-13 17:47:45 +08:00
_isInitialized = true;
2024-11-03 16:42:23 +08:00
Close();
}
public void Create(ContextMenuBuilder builder)
{
var pos = Mouse.current.position.ReadValue();
pos.y = Screen.height - pos.y;
2024-11-13 17:47:45 +08:00
pos = RuntimePanelUtils.ScreenToPanel(_root.panel, pos);
2024-11-03 16:42:23 +08:00
2024-11-13 17:47:45 +08:00
_container.style.position = Position.Absolute;
_container.style.left = pos.x;
_container.style.top = pos.y;
_container.Clear();
2024-11-03 16:42:23 +08:00
2024-11-13 17:47:45 +08:00
_root.SetActive(true);
2024-11-03 16:42:23 +08:00
foreach (var context in builder.GetContextMenus())
{
2024-11-13 17:47:45 +08:00
_container.Add(context.GetVisualElement());
2024-11-03 16:42:23 +08:00
}
2024-11-13 17:47:45 +08:00
builder.OnExecuted += Close;
}
private void Close()
{
if(_isInitialized is false)return;
_container.Clear();
_root.SetActive(false);
}
public void Dispose()
{
_uxService.OnPanelChanged -= OnPanelChanged;
2024-11-03 16:42:23 +08:00
}
2024-11-13 17:47:45 +08:00
private void OnPanelChanged(IUXPanel arg1, IUXPanel arg2)
2024-11-03 16:42:23 +08:00
{
2024-11-13 17:47:45 +08:00
Close();
2024-11-03 16:42:23 +08:00
}
}
}