using System;
using System.Collections.Generic;
using UnityEngine.EventSystems;
namespace UnityEngine.UIElements
{
// This code is disabled unless the com.unity.modules.uielements module is activated in the package manager.
#if PACKAGE_UITOOLKIT
///
/// Enables UI Toolkit interoperability with uGUI events.
///
internal class UIToolkitInteroperabilityBridge
{
[Flags]
public enum EventHandlerTypes
{
ScreenOverlay = 1,
WorldSpace = 2,
}
private EventSystem m_EventSystem;
internal EventSystem eventSystem
{
get => m_EventSystem;
set
{
if (m_EventSystem == value) return;
Debug.Assert(!m_Started && !m_Enabled, "Expect EventSystem set before OnEnable and Start");
m_EventSystem = value;
}
}
private bool m_OverrideUIToolkitEvents = true;
private EventHandlerTypes m_HandlerTypes = EventHandlerTypes.ScreenOverlay | EventHandlerTypes.WorldSpace;
private LayerMask m_WorldPickingLayers = Physics.DefaultRaycastLayers;
private float m_WorldPickingMaxDistance = Mathf.Infinity;
private bool m_CreateDefaultPanelComponents = true;
private bool m_Started;
private bool m_Enabled;
private bool m_IsTrackingPanels;
private GameObject m_WorldSpaceGo;
private bool m_PendingRegistration; // True if we need to retry registration when utility becomes available
public bool overrideUIToolkitEvents
{
get => m_OverrideUIToolkitEvents;
internal set
{
m_OverrideUIToolkitEvents = value;
ApplyOverrideUIToolkitEvents();
}
}
public EventHandlerTypes handlerTypes
{
get => m_HandlerTypes;
internal set
{
m_HandlerTypes = value;
ApplyOtherProperties();
}
}
public int worldPickingLayers
{
get => m_WorldPickingLayers;
internal set => m_WorldPickingLayers = value;
}
public float worldPickingMaxDistance
{
get => m_WorldPickingMaxDistance;
internal set => m_WorldPickingMaxDistance = value;
}
public bool createDefaultPanelComponents
{
get => m_CreateDefaultPanelComponents;
internal set
{
m_CreateDefaultPanelComponents = value;
ApplyOtherProperties();
}
}
private bool shouldTrackPanels => overrideUIToolkitEvents && createDefaultPanelComponents &&
m_Started && m_Enabled;
private void StartTrackingUIToolkitPanels()
{
if (m_IsTrackingPanels || !shouldTrackPanels) return;
// Can be null if runtime panels have not been created yet; mark for retry in Update()
if (IRuntimePanel.uIElementsRuntimeUtility == null)
{
m_PendingRegistration = true;
return;
}
foreach (var panel in IRuntimePanel.uIElementsRuntimeUtility.GetSortedPlayerPanelsInternal())
{
StartTrackingPanel(panel);
}
IRuntimePanel.uIElementsRuntimeUtility.AddOnCreatePanelAction( StartTrackingPanel);
m_IsTrackingPanels = true;
}
// Use object storage to prevent generic type parameter from preserving BaseRuntimePanel during code stripping
private readonly HashSet trackedPanels = new();
private void StartTrackingPanel(IRuntimePanel panel)
{
trackedPanels.Add(panel);
}
private void StopTrackingUIToolkitPanels()
{
if (!m_IsTrackingPanels) return;
// Can be null if runtime panels have not been created or UI Toolkit is stripped
IRuntimePanel.uIElementsRuntimeUtility?.RemoveOnCreatePanelAction( StartTrackingPanel);
m_IsTrackingPanels = false;
foreach (var panelObj in trackedPanels)
{
DestroyPanelGameObject(panelObj);
}
trackedPanels.Clear();
DestroyWorldSpacePanelGameObject();
}
private void UpdatePanelGameObject(IRuntimePanel panel)
{
var handlerType = panel.isFlat ? EventHandlerTypes.ScreenOverlay : EventHandlerTypes.WorldSpace;
if ((m_HandlerTypes & handlerType) != 0)
{
CreatePanelGameObject(panel);
}
else
{
DestroyPanelGameObject(panel);
}
}
// Use interface storage to prevent generic type parameter from preserving BaseRuntimePanel during code stripping
private readonly Dictionary