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

150 lines
4.0 KiB
C#
Raw Normal View History

2024-11-03 16:42:23 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Remoting.Contexts;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
using BITKit;
using Cysharp.Threading.Tasks;
namespace BITKit.UX.Internal
{
public class ContextMenu : IContextMenu
{
public virtual VisualElement GetVisualElement()
{
return new VisualElement();
}
}
public class Label : ContextMenu
{
public Label(string text)
{
this.text = text;
}
string text;
public override VisualElement GetVisualElement()
{
UnityEngine.UIElements.Label label = new(text);
return label;
}
}
[System.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)
{
this.text = text;
foreach (var x in actions)
{
action += x;
}
}
string text;
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.Excute));
return self;
}
}
public class ContextMenuBuilder
{
readonly List<IContextMenu> contexts = new();
public event Action OnExcuted;
private ContextMenuBuilder()
{
}
public static ContextMenuBuilder Create()
{
return new();
}
public void Build()
{
UXContextMenu.Singleton.Create(this);
}
internal void Excute()
{
OnExcuted?.Invoke();
}
public void Add(IContextMenu x) => contexts.Add(x);
public IEnumerable<IContextMenu> GetContextMenus() => contexts.ToArray();
}
public class UXContextMenu : MonoBehaviour
{
internal static UXContextMenu Singleton;
[SerializeField] private UIDocument document;
private VisualElement root;
private VisualElement container;
private void Awake()
{
Singleton = this;
root = document.rootVisualElement;
container = document.rootVisualElement[1];
root.Q("background-image").RegisterCallback<MouseDownEvent>(x =>
{
Close();
});
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.OnExcuted += Close;
}
void Close()
{
container.Clear();
root.SetActive(false);
}
}
}