366 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			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
 | |
| }
 |