arenos-nexus/Arenos Nexus/Library/PackageCache/com.unity.ugui@38c58105e446/Runtime/UGUI/EventSystem/UIElements/UIToolkitInteroperabilityBridge.cs
Daniel 2e704cae70 init
Init Commit Unity
2025-09-25 22:01:28 +02:00

366 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine.EventSystems;
namespace UnityEngine.UIElements
{
// This code is disabled unless the com.unity.modules.uielements module is present.
// The UIElements module is always present in the Editor but it can be stripped from a project build if unused.
#if PACKAGE_UITOOLKIT
/// <summary>
/// Enables UI Toolkit interoperability with uGUI events.
/// </summary>
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;
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;
foreach (var panel in UIElementsRuntimeUtility.GetSortedPlayerPanels())
{
StartTrackingPanel(panel);
}
UIElementsRuntimeUtility.onCreatePanel += StartTrackingPanel;
m_IsTrackingPanels = true;
}
private readonly HashSet<BaseRuntimePanel> trackedPanels = new();
private void StartTrackingPanel(BaseRuntimePanel panel)
{
trackedPanels.Add(panel);
}
private void StopTrackingUIToolkitPanels()
{
if (!m_IsTrackingPanels) return;
UIElementsRuntimeUtility.onCreatePanel -= StartTrackingPanel;
m_IsTrackingPanels = false;
foreach (var panel in trackedPanels)
{
DestroyPanelGameObject(panel);
}
trackedPanels.Clear();
DestroyWorldSpacePanelGameObject();
}
private void UpdatePanelGameObject(BaseRuntimePanel panel)
{
var handlerType = panel.isFlat ? EventHandlerTypes.ScreenOverlay : EventHandlerTypes.WorldSpace;
if ((m_HandlerTypes & handlerType) != 0)
{
CreatePanelGameObject(panel);
}
else
{
DestroyPanelGameObject(panel);
}
}
private readonly Dictionary<BaseRuntimePanel, Action> destroyedActions = new();
private void CreatePanelGameObject(BaseRuntimePanel panel)
{
if (panel.selectableGameObject == null)
{
var go = new GameObject(panel.name, typeof(PanelEventHandler), typeof(PanelRaycaster));
go.transform.SetParent(m_EventSystem.transform);
panel.selectableGameObject = go;
var destroyed = destroyedActions[panel] = () => UIRUtility.Destroy(go);
panel.destroyed += destroyed;
}
}
private void DestroyPanelGameObject(BaseRuntimePanel panel)
{
var go = panel.selectableGameObject;
if (go != null)
{
if (!destroyedActions.Remove(panel, out var destroyed))
return; // this object wasn't created by us, so leave it untouched
panel.destroyed -= destroyed;
panel.selectableGameObject = null;
UIRUtility.Destroy(go);
}
}
private void CreateWorldSpacePanelGameObject()
{
// This will destroy m_WorldSpaceGo if raycaster components need to change.
ApplyCameraProperties();
if (m_WorldSpaceGo == null)
{
var go = new GameObject("WorldDocumentRaycaster");
go.transform.SetParent(m_EventSystem.transform);
if (m_InputSettings.defaultEventCameraIsMainCamera)
{
go.AddComponent<WorldDocumentRaycaster>();
}
else
{
foreach (var cam in m_InputSettings.eventCameras)
{
go.AddComponent<WorldDocumentRaycaster>().camera = cam;
}
}
m_WorldSpaceGo = go;
}
}
private void DestroyWorldSpacePanelGameObject()
{
var go = m_WorldSpaceGo;
m_WorldSpaceGo = null;
UIRUtility.Destroy(go);
}
public void Start()
{
m_Started = true;
StartTrackingUIToolkitPanels();
}
public void OnEnable()
{
if (m_Enabled) return;
m_Enabled = true;
if (PanelInputConfiguration.current != null)
Apply(PanelInputConfiguration.current);
PanelInputConfiguration.onApply += Apply;
if (m_Started)
StartTrackingUIToolkitPanels();
if (m_OverrideUIToolkitEvents)
UIElementsRuntimeUtility.RegisterEventSystem(m_EventSystem);
}
public void OnDisable()
{
if (!m_Enabled) return;
m_Enabled = false;
PanelInputConfiguration.onApply -= Apply;
StopTrackingUIToolkitPanels();
UIElementsRuntimeUtility.UnregisterEventSystem(m_EventSystem);
}
public void Update()
{
UpdatePanelGameObjects();
}
private PanelInputConfiguration.Settings m_InputSettings = PanelInputConfiguration.Settings.Default;
void Apply(PanelInputConfiguration input)
{
m_InputSettings = input != null ? input.settings : PanelInputConfiguration.Settings.Default;
m_OverrideUIToolkitEvents =
m_InputSettings.panelInputRedirection != PanelInputConfiguration.PanelInputRedirection.Never;
m_HandlerTypes = EventHandlerTypes.ScreenOverlay |
(m_InputSettings.processWorldSpaceInput ? EventHandlerTypes.WorldSpace : 0);
m_WorldPickingLayers = m_InputSettings.interactionLayers;
m_WorldPickingMaxDistance = m_InputSettings.maxInteractionDistance;
m_CreateDefaultPanelComponents = m_InputSettings.autoCreatePanelComponents;
ApplyOverrideUIToolkitEvents();
ApplyCameraProperties();
ApplyOtherProperties();
}
private bool m_OldOverrideUIToolkitEvents = true;
private EventHandlerTypes m_OldHandlerTypes = EventHandlerTypes.ScreenOverlay | EventHandlerTypes.WorldSpace;
private bool m_OldCreateDefaultPanelComponents = true;
private bool m_OldDefaultEventCameraIsMainCamera = true;
private long m_OldEventCamerasHash = 0;
private void ApplyOverrideUIToolkitEvents()
{
if (m_OldOverrideUIToolkitEvents == m_OverrideUIToolkitEvents) return;
m_OldOverrideUIToolkitEvents = m_OverrideUIToolkitEvents;
if (!m_Enabled) return;
if (m_OverrideUIToolkitEvents)
{
UIElementsRuntimeUtility.RegisterEventSystem(m_EventSystem);
}
else
{
UIElementsRuntimeUtility.UnregisterEventSystem(m_EventSystem);
}
UpdatePanelTracking();
}
private void ApplyCameraProperties()
{
bool dirty = false;
if (m_OldDefaultEventCameraIsMainCamera != m_InputSettings.defaultEventCameraIsMainCamera)
{
m_OldDefaultEventCameraIsMainCamera = m_InputSettings.defaultEventCameraIsMainCamera;
dirty = true;
}
if (!m_InputSettings.defaultEventCameraIsMainCamera)
{
var hashCode = 0;
foreach (var cam in m_InputSettings.eventCameras)
{
hashCode = (hashCode * 397) ^ cam.GetHashCode();
}
if (m_OldEventCamerasHash != hashCode)
{
m_OldEventCamerasHash = hashCode;
dirty = true;
}
}
else
{
m_OldEventCamerasHash = 0;
}
if (dirty)
DestroyWorldSpacePanelGameObject();
}
private void ApplyOtherProperties()
{
bool dirty = false;
if (m_OldHandlerTypes != m_HandlerTypes)
{
m_OldHandlerTypes = m_HandlerTypes;
dirty = true;
}
if (m_OldCreateDefaultPanelComponents != m_CreateDefaultPanelComponents)
{
m_OldCreateDefaultPanelComponents = m_CreateDefaultPanelComponents;
dirty = true;
}
if (dirty)
UpdatePanelTracking();
}
private void UpdatePanelTracking()
{
if (shouldTrackPanels)
{
StartTrackingUIToolkitPanels();
}
else
{
StopTrackingUIToolkitPanels();
}
}
private void UpdatePanelGameObjects()
{
if (!m_IsTrackingPanels) return;
bool isWorldSpaceActive = false;
foreach (var panel in trackedPanels)
{
UpdatePanelGameObject(panel);
isWorldSpaceActive |= !panel.isFlat;
}
if (isWorldSpaceActive && (m_HandlerTypes & EventHandlerTypes.WorldSpace) != 0)
{
CreateWorldSpacePanelGameObject();
}
else
{
DestroyWorldSpacePanelGameObject();
}
}
}
#endif
}