init
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user