From d2ab30e7a69bfe7efda63ae75812207377917bd3 Mon Sep 17 00:00:00 2001 From: miepzerino <o.skotnik@gmail.com> Date: Sun, 30 Mar 2025 18:50:27 +0000 Subject: [PATCH] Merge branch 'Flexalon-UI-Layouts' into develop --- Assets/Flexalon/Runtime/Interaction/FlexalonRaycaster.cs | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 104 insertions(+), 0 deletions(-) diff --git a/Assets/Flexalon/Runtime/Interaction/FlexalonRaycaster.cs b/Assets/Flexalon/Runtime/Interaction/FlexalonRaycaster.cs new file mode 100644 index 0000000..8db4421 --- /dev/null +++ b/Assets/Flexalon/Runtime/Interaction/FlexalonRaycaster.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Flexalon +{ + internal class FlexalonRaycaster + { + public Vector3 hitPosition; + + private int _raycastFrame = 0; + private FlexalonInteractable _hitInteractable; + private readonly Dictionary<GameObject, FlexalonInteractable> _handles = new Dictionary<GameObject, FlexalonInteractable>(); + +#if UNITY_UI + private List<UnityEngine.EventSystems.RaycastResult> _graphicRaycastResult = new List<UnityEngine.EventSystems.RaycastResult>(); +#endif + +#if UNITY_PHYSICS + private RaycastHit[] _raycastHits = new RaycastHit[10]; +#endif + + public void Register(FlexalonInteractable interactable) + { + _handles.Add(interactable.Handle, interactable); + } + + public void Unregister(FlexalonInteractable interactable) + { + _handles.Remove(interactable.Handle); + } + + public bool IsHit(Vector3 uiPointer, Ray ray, FlexalonInteractable interactable) + { + // Check if we've already casted this frame. + if (_raycastFrame != Time.frameCount) + { + _hitInteractable = null; + _raycastFrame = Time.frameCount; + float minDistance = float.MaxValue; + RaycastUI(uiPointer, ref minDistance); + RaycastPhysics(ray, ref minDistance); + } + + return _hitInteractable == interactable; + } + + private void RaycastUI(Vector3 uiPointer, ref float minDistance) + { +#if UNITY_UI + var eventSystem = UnityEngine.EventSystems.EventSystem.current; + if (eventSystem) + { + eventSystem.RaycastAll(new UnityEngine.EventSystems.PointerEventData(eventSystem) + { + position = uiPointer + }, _graphicRaycastResult); + + for (int i = 0; i < _graphicRaycastResult.Count; i++) + { + var hit = _graphicRaycastResult[i]; + if (hit.distance < minDistance) + { + if (_handles.TryGetValue(hit.gameObject, out var hitInteractable)) + { + _hitInteractable = hitInteractable; + minDistance = hit.distance; + + hitInteractable.UpdateCanvas(); + + if (hitInteractable.Canvas?.renderMode == UnityEngine.RenderMode.ScreenSpaceOverlay) + { + hitPosition = hit.screenPosition; + } + else + { + hitPosition = hit.worldPosition; + } + } + } + } + } +#endif + } + + private void RaycastPhysics(Ray ray, ref float minDistance) + { +#if UNITY_PHYSICS + int hits = Physics.RaycastNonAlloc(ray, _raycastHits, 1000); + + // Find the nearest hit interactable. + for (int i = 0; i < hits; i++) + { + var hit = _raycastHits[i]; + if (hit.distance < minDistance && _handles.TryGetValue(hit.collider.gameObject, out var hitInteractable)) + { + _hitInteractable = hitInteractable; + minDistance = hit.distance; + hitPosition = hit.point; + } + } +#endif + } + } +} \ No newline at end of file -- Gitblit v1.9.3