File size: 5,529 Bytes
18a519f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine.EventSystems;
namespace UnityEngine.UIElements
{
#if PACKAGE_UITOOLKIT
/// <summary>
/// A derived BaseRaycaster to raycast against UI Toolkit panel instances at runtime.
/// </summary>
[AddComponentMenu("UI Toolkit/Panel Raycaster (UI Toolkit)")]
public class PanelRaycaster : BaseRaycaster, IRuntimePanelComponent
{
private BaseRuntimePanel m_Panel;
/// <summary>
/// The panel that this component relates to. If panel is null, this component will have no effect.
/// Will be set to null automatically if panel is Disposed from an external source.
/// </summary>
public IPanel panel
{
get => m_Panel;
set
{
var newPanel = (BaseRuntimePanel)value;
if (m_Panel != newPanel)
{
UnregisterCallbacks();
m_Panel = newPanel;
RegisterCallbacks();
}
}
}
void RegisterCallbacks()
{
if (m_Panel != null)
{
m_Panel.destroyed += OnPanelDestroyed;
}
}
void UnregisterCallbacks()
{
if (m_Panel != null)
{
m_Panel.destroyed -= OnPanelDestroyed;
}
}
void OnPanelDestroyed()
{
panel = null;
}
private GameObject selectableGameObject => m_Panel?.selectableGameObject;
public override int sortOrderPriority => (int)(m_Panel?.sortingPriority ?? 0f);
public override int renderOrderPriority => ConvertFloatBitsToInt(m_Panel?.sortingPriority ?? 0f);
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
{
if (m_Panel == null)
return;
var eventPosition = Display.RelativeMouseAt(eventData.position);
var displayIndex = m_Panel.targetDisplay;
var originalEventPosition = eventPosition;
if (eventPosition != Vector3.zero)
{
// We support multiple display and display identification based on event position.
int eventDisplayIndex = (int)eventPosition.z;
// Discard events that are not part of this display so the user does not interact with multiple displays at once.
if (eventDisplayIndex != displayIndex)
return;
}
else
{
// The multiple display system is not supported on all platforms, when it is not supported the returned position
// will be all zeros so when the returned index is 0 we will default to the event data to be safe.
eventPosition = eventData.position;
#if UNITY_EDITOR
if (Display.activeEditorGameViewTarget != displayIndex)
return;
eventPosition.z = Display.activeEditorGameViewTarget;
#endif
// We don't really know in which display the event occurred. We will process the event assuming it occurred in our display.
}
var position = eventPosition;
var delta = eventData.delta;
float h = Screen.height;
if (displayIndex > 0 && displayIndex < Display.displays.Length)
{
h = Display.displays[displayIndex].systemHeight;
}
position.y = h - position.y;
delta.y = -delta.y;
var eventSystem = UIElementsRuntimeUtility.activeEventSystem as EventSystem;
if (eventSystem == null || eventSystem.currentInputModule == null)
return;
var pointerId = eventSystem.currentInputModule.ConvertUIToolkitPointerId(eventData);
var capturingElement = m_Panel.GetCapturingElement(pointerId);
if (capturingElement is VisualElement ve && ve.panel != m_Panel)
return;
var capturingPanel = PointerDeviceState.GetPressedButtons(pointerId) != 0 ?
PointerDeviceState.GetPlayerPanelWithSoftPointerCapture(pointerId) :
null;
if (capturingPanel != null && capturingPanel != m_Panel)
return;
if (capturingElement == null && capturingPanel == null)
{
if (!m_Panel.ScreenToPanel(position, delta, out var panelPosition, out _))
return;
var pick = m_Panel.Pick(panelPosition);
if (pick == null)
return;
}
resultAppendList.Add(new RaycastResult
{
gameObject = selectableGameObject,
module = this,
screenPosition = eventPosition,
displayIndex = m_Panel.targetDisplay,
});
}
public override Camera eventCamera => null;
[StructLayout(LayoutKind.Explicit, Size = sizeof(int))]
private struct FloatIntBits
{
[FieldOffset(0)]
public float f;
[FieldOffset(0)]
public int i;
}
private static int ConvertFloatBitsToInt(float f)
{
FloatIntBits bits = new FloatIntBits {f = f};
return bits.i;
}
}
#endif
}
|