private static bool IsObjectPartOfTouchable(GameObject targetObject, BaseNearInteractionTouchable touchable)
 {
     return(targetObject != null && touchable != null &&
            (targetObject == touchable.gameObject ||
             // Descendant game objects are touchable as well. In particular, this is needed to be able to send
             // touch events to Unity UI control elements.
             (targetObject.transform != null && touchable.gameObject.transform != null &&
              targetObject.transform.IsChildOf(touchable.gameObject.transform))));
 }
        public override void OnPreSceneQuery()
        {
            if (Rays == null)
            {
                Rays = new RayStep[1];
            }

            closestNormal = Rotation * Vector3.forward;

            var layerMasks = PrioritizedLayerMasksOverride ?? PokeLayerMasks;

            // Find closest touchable
            BaseNearInteractionTouchable newClosestTouchable = null;

            foreach (var layerMask in layerMasks)
            {
                if (FindClosestTouchableForLayerMask(layerMask, out newClosestTouchable, out closestDistance, out closestNormal))
                {
                    break;
                }
            }

            if (newClosestTouchable != null)
            {
                // Build ray (poke from in front to the back of the pointer position)
                // We make a very long ray if we are touching a touchable volume to ensure that we actually
                // hit the volume when we are inside of the volume, which could be very large.
                var lengthOfPointerRay = newClosestTouchable is NearInteractionTouchableVolume ?
                                         maximumTouchableVolumeSize : touchableDistance;
                Vector3 start = Position + lengthOfPointerRay * closestNormal;
                Vector3 end   = Position - lengthOfPointerRay * closestNormal;
                Rays[0].UpdateRayStep(ref start, ref end);

                line.SetPosition(0, Position);
                line.SetPosition(1, end);
            }

            // Check if the currently touched object is still part of the new touchable.
            if (currentTouchableObjectDown != null)
            {
                if (!IsObjectPartOfTouchable(currentTouchableObjectDown, newClosestTouchable))
                {
                    TryRaisePokeUp();
                }
            }

            // Set new touchable only now: If we have to raise a poke-up event for the previous touchable object,
            // we need to do so using the previous touchable in TryRaisePokeUp().
            closestProximityTouchable = newClosestTouchable;

            visuals.SetActive(IsActive);
        }
Example #3
0
        public override void OnPreSceneQuery()
        {
            if (Rays == null)
            {
                Rays = new RayStep[1];
            }

            closestNormal = Rotation * Vector3.forward;

            var layerMasks = PrioritizedLayerMasksOverride ?? PokeLayerMasks;

            // Find closest touchable
            BaseNearInteractionTouchable newClosestTouchable = null;

            foreach (var layerMask in layerMasks)
            {
                if (FindClosestTouchableForLayerMask(layerMask, out newClosestTouchable, out closestDistance, out closestNormal))
                {
                    break;
                }
            }

            if (newClosestTouchable != null)
            {
                // Build ray (poke from in front to the back of the pointer position)
                Vector3 start = Position - newClosestTouchable.PokeThreshold * -closestNormal;
                Vector3 end   = Position + touchableDistance * -closestNormal;
                Rays[0].UpdateRayStep(ref start, ref end);

                line.SetPosition(0, Position);
                line.SetPosition(1, end);
            }

            // Check if the currently touched object is still part of the new touchable.
            if (currentTouchableObjectDown != null)
            {
                if (!IsObjectPartOfTouchable(currentTouchableObjectDown, newClosestTouchable))
                {
                    TryRaisePokeUp(Result.CurrentPointerTarget, Position);
                }
            }

            // Set new touchable only now: If we have to raise a poke-up event for the previous touchable object,
            // we need to do so using the previous touchable in TryRaisePokeUp().
            closestProximityTouchable = newClosestTouchable;

            visuals.SetActive(IsActive);
        }
        private bool FindClosestTouchableForLayerMask(LayerMask layerMask, out BaseNearInteractionTouchable closest, out float closestDistance, out Vector3 closestNormal)
        {
            closest         = null;
            closestDistance = float.PositiveInfinity;
            closestNormal   = Vector3.zero;

            int numColliders = UnityEngine.Physics.OverlapSphereNonAlloc(Position, touchableDistance, queryBuffer, layerMask, triggerInteraction);

            if (numColliders == queryBuffer.Length)
            {
                Debug.LogWarning($"Maximum number of {numColliders} colliders found in PokePointer overlap query. Consider increasing the query buffer size in the input system settings.");
            }

            for (int i = 0; i < numColliders; ++i)
            {
                var touchable = queryBuffer[i].GetComponent <BaseNearInteractionTouchable>();
                if (touchable)
                {
                    float distance = touchable.DistanceToTouchable(Position, out Vector3 normal);
                    if (distance < closestDistance)
                    {
                        closest         = touchable;
                        closestDistance = distance;
                        closestNormal   = normal;
                    }
                }
            }

            // Unity UI does not provide an equivalent broad-phase test to Physics.OverlapSphere,
            // so we have to use a static instances list to test all NearInteractionTouchableUnityUI
            for (int i = 0; i < NearInteractionTouchableUnityUI.Instances.Count; i++)
            {
                NearInteractionTouchableUnityUI touchable = NearInteractionTouchableUnityUI.Instances[i];
                float distance = touchable.DistanceToTouchable(Position, out Vector3 normal);
                if (distance <= touchableDistance && distance < closestDistance)
                {
                    closest         = touchable;
                    closestDistance = distance;
                    closestNormal   = normal;
                }
            }

            return(closest != null);
        }