187 lines
5.3 KiB
C#
187 lines
5.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.Design;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using UnityEngine.InputSystem;
|
|
using BITKit.Mod;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace BITKit.UX.Internal
|
|
{
|
|
public class ContextMenu : IContextMenu
|
|
{
|
|
public virtual VisualElement GetVisualElement()
|
|
{
|
|
return new VisualElement();
|
|
}
|
|
}
|
|
public class Label : ContextMenu
|
|
{
|
|
public Label(string text)
|
|
{
|
|
_text = text;
|
|
}
|
|
private readonly string _text;
|
|
public override VisualElement GetVisualElement()
|
|
{
|
|
UnityEngine.UIElements.Label label = new(_text);
|
|
return label;
|
|
}
|
|
}
|
|
[Serializable]
|
|
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)
|
|
{
|
|
_text = text;
|
|
foreach (var x in actions)
|
|
{
|
|
_action += x;
|
|
}
|
|
}
|
|
|
|
private readonly string _text;
|
|
private readonly Action _action;
|
|
public override VisualElement GetVisualElement()
|
|
{
|
|
UnityEngine.UIElements.Button button = new();
|
|
button.clicked += _action;
|
|
button.text = _text;
|
|
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)
|
|
{
|
|
self.Add(new Internal.Button(text, action, self.Execute));
|
|
return self;
|
|
}
|
|
}
|
|
public class ContextMenuBuilder
|
|
{
|
|
private readonly List<IContextMenu> _contexts = new();
|
|
public event Action OnExecuted;
|
|
private ContextMenuBuilder()
|
|
{
|
|
|
|
}
|
|
public static ContextMenuBuilder Create()
|
|
{
|
|
return new();
|
|
}
|
|
public void Build()
|
|
{
|
|
UXContextMenu.Singleton.Create(this);
|
|
}
|
|
internal void Execute()
|
|
{
|
|
OnExecuted?.Invoke();
|
|
}
|
|
public void Add(IContextMenu x) => _contexts.Add(x);
|
|
public IEnumerable<IContextMenu> GetContextMenus() => _contexts.ToArray();
|
|
}
|
|
public class UXContextMenu:IDisposable
|
|
{
|
|
internal static UXContextMenu Singleton;
|
|
private readonly IUXService _uxService;
|
|
private VisualElement _root;
|
|
private VisualElement _container;
|
|
private bool _isInitialized = false;
|
|
public UXContextMenu(IUXService uxService)
|
|
{
|
|
_uxService = uxService;
|
|
Singleton = this;
|
|
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>("ui_context_menu");
|
|
|
|
_root = document.rootVisualElement;
|
|
_container = _root.Q<VisualElement>("menu-container");
|
|
_root.Q("background-image").RegisterCallback<MouseDownEvent>(_ =>
|
|
{
|
|
Close();
|
|
});
|
|
_isInitialized = true;
|
|
Close();
|
|
}
|
|
public void Create(ContextMenuBuilder builder)
|
|
{
|
|
var pos = Mouse.current.position.ReadValue();
|
|
pos.y = Screen.height - pos.y;
|
|
pos = RuntimePanelUtils.ScreenToPanel(_root.panel, pos);
|
|
|
|
_container.style.position = Position.Absolute;
|
|
_container.style.left = pos.x;
|
|
_container.style.top = pos.y;
|
|
_container.Clear();
|
|
|
|
_root.SetActive(true);
|
|
|
|
foreach (var context in builder.GetContextMenus())
|
|
{
|
|
_container.Add(context.GetVisualElement());
|
|
}
|
|
builder.OnExecuted += Close;
|
|
}
|
|
private void Close()
|
|
{
|
|
if(_isInitialized is false)return;
|
|
_container.Clear();
|
|
_root.SetActive(false);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_uxService.OnPanelChanged -= OnPanelChanged;
|
|
}
|
|
|
|
private void OnPanelChanged(IUXPanel arg1, IUXPanel arg2)
|
|
{
|
|
Close();
|
|
}
|
|
}
|
|
}
|