150 lines
4.0 KiB
C#
150 lines
4.0 KiB
C#
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|