169 lines
5.5 KiB
C#
169 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.UIElements;
|
|
using PlayerInputManager = VOID.Generic.Player.Input.PlayerInputManager;
|
|
using ShortcutsInputManager = VOID.Generic.Player.Input.ShortcutsInputManager;
|
|
|
|
namespace VOID.UserInterface.Game.Util
|
|
{
|
|
[Serializable]
|
|
public class WindowUI : MonoBehaviour
|
|
{
|
|
public static List<WindowUI> openWindows = new();
|
|
|
|
// UI Visual Elements
|
|
private VisualElement _parentElement;
|
|
private VisualElement _rootElement;
|
|
private Button _windowCloseButton;
|
|
private VisualElement _headerElement;
|
|
private Label _titleLabel;
|
|
|
|
// Events
|
|
public event Action OnClose;
|
|
public event Action OnOpen;
|
|
|
|
// References
|
|
private PlayerInputManager _playerInputManager;
|
|
private GameUI _gameUI;
|
|
|
|
// Toggle
|
|
private bool _isOpen;
|
|
private bool _isOverHeader;
|
|
private bool _isDragging;
|
|
|
|
// Offset - relative position from window position to cursor
|
|
private Vector2 _draggingOffset;
|
|
|
|
private void Awake()
|
|
{
|
|
var uiDocument = gameObject.GetComponent<UIDocument>();
|
|
var templateElement = uiDocument.rootVisualElement;
|
|
|
|
// Find all visual elements
|
|
_rootElement = templateElement.Q("root-window");
|
|
_parentElement = _rootElement.parent.parent;
|
|
_headerElement = _rootElement.Q("header");
|
|
_titleLabel = _headerElement.Q<Label>("title");
|
|
_windowCloseButton = _rootElement.Q<Button>("close");
|
|
|
|
// Close backpack when "x" pressed
|
|
_windowCloseButton.clicked += Close;
|
|
|
|
// Make window active if pressed
|
|
_parentElement.RegisterCallback(new EventCallback<MouseDownEvent>(_ => SetActiveWindow()), TrickleDown.TrickleDown);
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
_gameUI = GameUI.current;
|
|
_playerInputManager = PlayerInputManager.current;
|
|
_playerInputManager.OnDraggingPrepare += PrepareDragging;
|
|
_playerInputManager.OnDraggingStart += StartDragging;
|
|
_playerInputManager.OnDraggingEnd += EndDragging;
|
|
}
|
|
|
|
public void SetTitle(string title)
|
|
{
|
|
_titleLabel.text = title;
|
|
}
|
|
|
|
public void Toggle()
|
|
{
|
|
if (_isOpen)
|
|
{
|
|
Close();
|
|
}
|
|
else
|
|
{
|
|
Open();
|
|
}
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
// Hide element
|
|
_parentElement.style.display = DisplayStyle.None;
|
|
|
|
// Reset element position styles
|
|
_parentElement.style.right = StyleKeyword.Null;
|
|
_parentElement.style.top = StyleKeyword.Null;
|
|
_parentElement.style.bottom = StyleKeyword.Null;
|
|
_parentElement.style.left = StyleKeyword.Null;
|
|
|
|
_isOpen = false;
|
|
OnClose?.Invoke();
|
|
openWindows.Remove(this);
|
|
}
|
|
|
|
public void Open()
|
|
{
|
|
// Show Element
|
|
_parentElement.style.display = DisplayStyle.Flex;
|
|
|
|
_isOpen = true;
|
|
OnOpen?.Invoke();
|
|
openWindows.Add(this);
|
|
SetActiveWindow();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!_isDragging) return;
|
|
|
|
var mousePos = _gameUI.cursorPositionOnUI;
|
|
_parentElement.style.top = new StyleLength(mousePos.y - Mathf.Abs(_draggingOffset.y));
|
|
_parentElement.style.left = new StyleLength(mousePos.x - Mathf.Abs(_draggingOffset.x));
|
|
}
|
|
|
|
private void PrepareDragging()
|
|
{
|
|
// Check if dragging started at window's title header...
|
|
_isOverHeader = GameUI.current.elementsUnderCursor.Contains(_headerElement);
|
|
|
|
// ...Only dragging by TITLE element allows to drag whole window
|
|
if (!_isOverHeader) return;
|
|
|
|
// Calculate offset from mouse position to window position
|
|
var windowPos = new Vector2(_parentElement.worldBound.x,_parentElement.worldBound.y);
|
|
var mousePos = _gameUI.cursorPositionOnUI;
|
|
_draggingOffset = windowPos - mousePos;
|
|
}
|
|
|
|
private void StartDragging()
|
|
{
|
|
if (!_isOverHeader) return;
|
|
|
|
_isDragging = true;
|
|
_parentElement.style.right = new StyleLength(StyleKeyword.Auto);
|
|
_parentElement.style.bottom = new StyleLength(StyleKeyword.Auto);
|
|
}
|
|
|
|
public void EndDragging()
|
|
{
|
|
_isDragging = false;
|
|
_isOverHeader = false;
|
|
}
|
|
|
|
public void SetActiveWindow()
|
|
{
|
|
openWindows.Remove(this);
|
|
openWindows = openWindows.Prepend(this).ToList();
|
|
UpdateDocumentUIOrder();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculating sorting order for all windows (in which order they will be rendered)
|
|
/// </summary>
|
|
public static void UpdateDocumentUIOrder()
|
|
{
|
|
openWindows.ForEach(window =>
|
|
{
|
|
var sortingOrder = openWindows.Count - openWindows.IndexOf(window);
|
|
window.GetComponent<UIDocument>().sortingOrder = sortingOrder;
|
|
});
|
|
}
|
|
}
|
|
} |