Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jacobfdunbar/1a9842a1e5006500885e03a158117f46 to your computer and use it in GitHub Desktop.
Save jacobfdunbar/1a9842a1e5006500885e03a158117f46 to your computer and use it in GitHub Desktop.
UIToolkitRaycastChecker is a script for Unity UIElements to replicate the EventSystem.current.IsPointerOverGameObject() functionality for UI Elements.
using UnityEngine;
public class ExampleNonUIMonoBehaviour : MonoBehaviour
{
private void Start()
{
//Example of how to check for a position. This is the equivalent of EventSystem.current.IsPointerOverGameObject() except for UI Elements.
if (UIToolkitRaycastChecker.IsPointerOverUI())
{
//I'm under a part of the UI that's set to block raycasts! Don't try to raycast or something.
}
}
}
using UnityEngine;
using UnityEngine.UIElements;
public class ExampleUIController : MonoBehaviour
{
[SerializeField]
private UIDocument _document;
private VisualElement _root;
private void OnEnable()
{
_root = _document.rootVisualElement;
_rectangle = _root.Q<VisualElement>("Rectangle");
_root.BlockRaycasts(); //This optional extension method lets you register visual elements as if it were built in.
UIToolkitRaycastChecker.RegisterBlockingElement(_rectangle); // Same effect as the above code, but this is more explicit that you are registering your element to some system you'll need to unregister it from.
}
private void OnDisable()
{
//Counterparts to the above methods:
_root.AllowRaycasts();
UIToolkitRaycastChecker.UnregisterBlockingElement(_rectangle);
}
private void ExampleMethod() //You can check an element to see whether it's blocking raycasts or not.
{
if(_root.IsBlockingRaycasts())
{
//Do a thing
}
if(UIToolkitRaycastChecker.IsBlockingRaycasts(_rectangle))
{
//Do the same thing
}
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
#if UNITY_EDITOR
using UnityEditor;
#endif
public static class UIToolkitRaycastChecker
{
private static HashSet<VisualElement> _blockingElements = new HashSet<VisualElement>();
public static void RegisterBlockingElement(VisualElement blockingElement) =>
_blockingElements.Add(blockingElement);
public static void UnregisterBlockingElement(VisualElement blockingElement) =>
_blockingElements.Remove(blockingElement);
public static bool IsBlockingRaycasts(VisualElement element)
{
return _blockingElements.Contains(element) &&
element.visible &&
element.resolvedStyle.display == DisplayStyle.Flex;
}
public static bool IsPointerOverUI()
{
foreach (var element in _blockingElements)
{
if (IsBlockingRaycasts(element) == false)
continue;
if (ContainsMouse(element))
return true;
}
return false;
}
private static bool ContainsMouse(VisualElement element)
{
var mousePosition = Mouse.current.position.ReadValue();
var scaledMousePosition = new Vector2(mousePosition.x / Screen.width, mousePosition.y / Screen.height);
var flippedPosition = new Vector2(scaledMousePosition.x, 1 - scaledMousePosition.y);
var adjustedPosition = flippedPosition * element.panel.visualTree.layout.size;
var localPosition = element.WorldToLocal(adjustedPosition);
return element.ContainsPoint(localPosition);
}
#if UNITY_EDITOR
//This is used to reset the blocking elements set on playmode enter
//to fix a bug if you have the quick enter playmode settings turned on
//and don't unregister all your blocking elements before leaving playmode.
[InitializeOnEnterPlayMode]
private static void ResetBlockingElements()
{
_blockingElements = new HashSet<VisualElement>();
}
#endif
}
using UnityEngine.UIElements;
public static class VisualElementExtensions
{
public static void BlockRaycasts(this VisualElement element) =>
UIToolkitRaycastChecker.RegisterBlockingElement(element);
public static void AllowRaycasts(this VisualElement element) =>
UIToolkitRaycastChecker.UnregisterBlockingElement(element);
public static void IsBlockingRaycasts(this VisualElement element) =>
UIToolkitRaycastChecker.IsBlockingRaycasts(element);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment