Exemplo n.º 1
0
        public IEnumerator RayInteractorSamplePointsContinuesThroughGeometry([ValueSource(nameof(s_LineTypes))] XRRayInteractor.LineType lineType)
        {
            TestUtilities.CreateInteractionManager();
            TestUtilities.CreateXRRig();
            var interactor = TestUtilities.CreateRayInteractor();

            interactor.xrController.enabled = false;
            interactor.transform.position   = Vector3.zero;
            interactor.transform.rotation   = Quaternion.Euler(-45f, 0f, 0f);
            const int sampleFrequency = 5;

            interactor.sampleFrequency    = sampleFrequency;
            interactor.maxRaycastDistance = 20f;
            // These produce a curve that is the rough equivalent of the default projectile curve
            // in order to keep the assertions the same between the test cases.
            interactor.controlPointHeight   = 0f;
            interactor.controlPointDistance = 22.6f;
            interactor.endPointHeight       = -38.9f;
            interactor.endPointDistance     = 45.2f;
            interactor.lineType             = lineType;

            var lineVisual = interactor.GetComponent <XRInteractorLineVisual>();

            Assert.That(lineVisual, Is.Not.Null);
            Assert.That(lineVisual.enabled, Is.True);
            lineVisual.overrideInteractorLineLength = false;
            lineVisual.stopLineAtFirstRaycastHit    = false;

            var lineRenderer = interactor.GetComponent <LineRenderer>();

            Assert.That(lineRenderer, Is.Not.Null);
            Assert.That(lineRenderer.enabled, Is.True);

            yield return(null);

            Vector3[] samplePoints = null;
            var       isValid      = interactor.GetLinePoints(ref samplePoints, out var samplePointsCount);

            Assert.That(isValid, Is.True);
            Assert.That(samplePoints, Is.Not.Null);
            Assert.That(samplePointsCount, Is.EqualTo(lineType == XRRayInteractor.LineType.StraightLine ? 2 : sampleFrequency));
            Assert.That(samplePoints.Length, Is.GreaterThanOrEqualTo(samplePointsCount));

            // Verify that the Ray Interactor is not hitting anything
            var isHitInfoValid = interactor.TryGetHitInfo(out _, out _, out var hitPositionInLine, out var isValidTarget);

            Assert.That(isHitInfoValid, Is.False);
            Assert.That(isValidTarget, Is.False);
            Assert.That(hitPositionInLine, Is.EqualTo(0));

            yield return(null);

            // The Line Renderer should match
            Assert.That(lineVisual.enabled, Is.True);
            Assert.That(lineRenderer.enabled, Is.True);
            var lineRendererPositions = new Vector3[samplePointsCount];

            // LineRenderer.GetPositions always returns 0 when running with the -batchmode flag
            if (!Application.isBatchMode)
            {
                var lineRendererPositionsCount = lineRenderer.GetPositions(lineRendererPositions);
                Assert.That(lineRendererPositionsCount, Is.EqualTo(samplePointsCount));
                Assert.That(lineRendererPositions, Is.EquivalentTo(samplePoints).Using(Vector3ComparerWithEqualsOperator.Instance));
                Assert.That(lineRenderer.positionCount, Is.EqualTo(samplePointsCount));
            }

            // Create and place a plane between sample index 1 and 2
            var plane = GameObject.CreatePrimitive(PrimitiveType.Plane);

            plane.transform.localPosition = new Vector3(0f, 0f, 13f);
            plane.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f);
            plane.transform.localScale    = new Vector3(10f, 1f, 10f);

            // Wait for Physics update for hit and onBeforeRender callback to be invoked in XRInteractorLineVisual
            yield return(new WaitForFixedUpdate());

            yield return(null);

            yield return(null);

            // Verify that the Ray Interactor is hitting the plane
            isHitInfoValid = interactor.TryGetHitInfo(out var hitPosition, out var hitNormal, out hitPositionInLine, out isValidTarget);

            Assert.That(isHitInfoValid, Is.True);
            Assert.That(isValidTarget, Is.False);
            Assert.That(hitPositionInLine, Is.EqualTo(lineType == XRRayInteractor.LineType.StraightLine ? 1 : 2));
            Assert.That(hitPosition.z, Is.EqualTo(plane.transform.position.z).Using(FloatEqualityComparer.Instance));
            Assert.That(hitNormal, Is.EqualTo(plane.transform.up).Using(Vector3ComparerWithEqualsOperator.Instance));

            // The sample points should continue beyond the hit to allow the
            // Line Visual behavior to render them
            Vector3[] samplePointsWithPlane = null;
            isValid = interactor.GetLinePoints(ref samplePointsWithPlane, out var samplePointsCountWithPlane);

            Assert.That(isValid, Is.True);
            Assert.That(samplePointsWithPlane, Is.Not.Null);
            Assert.That(samplePointsCountWithPlane, Is.EqualTo(lineType == XRRayInteractor.LineType.StraightLine ? 2 : sampleFrequency));
            Assert.That(samplePointsWithPlane.Length, Is.GreaterThanOrEqualTo(samplePointsCountWithPlane));
            Assert.That(samplePointsWithPlane, Is.EquivalentTo(samplePoints).Using(Vector3ComparerWithEqualsOperator.Instance));

            // The Line Renderer should still match
            Assert.That(lineVisual.enabled, Is.True);
            Assert.That(lineRenderer.enabled, Is.True);
            if (!Application.isBatchMode)
            {
                var lineRendererPositionsCount = lineRenderer.GetPositions(lineRendererPositions);
                Assert.That(lineRendererPositionsCount, Is.EqualTo(samplePointsCount));
                Assert.That(lineRendererPositions, Is.EquivalentTo(samplePoints).Using(Vector3ComparerWithEqualsOperator.Instance));
                Assert.That(lineRenderer.positionCount, Is.EqualTo(samplePointsCount));
            }

            lineVisual.stopLineAtFirstRaycastHit = true;

            // Wait for onBeforeRender callback to be invoked in XRInteractorLineVisual
            yield return(null);

            yield return(null);

            // The Line Renderer should now stop at the first hit
            Assert.That(lineVisual.enabled, Is.True);
            Assert.That(lineRenderer.enabled, Is.True);
            if (!Application.isBatchMode)
            {
                var lineRendererPositionsCount = lineRenderer.GetPositions(lineRendererPositions);
                Assert.That(lineRendererPositionsCount, Is.EqualTo(hitPositionInLine + 1));
                var expectedLineRendererPositions = samplePoints.Take(hitPositionInLine).ToList();
                expectedLineRendererPositions.Add(hitPosition);
                Assert.That(lineRendererPositions.Take(hitPositionInLine + 1), Is.EquivalentTo(expectedLineRendererPositions).Using(Vector3ComparerWithEqualsOperator.Instance));
                Assert.That(lineRenderer.positionCount, Is.EqualTo(hitPositionInLine + 1));
            }
        }
Exemplo n.º 2
0
        public IEnumerator RayInteractorHitsAllAlongCurve([ValueSource(nameof(s_LineTypes))] XRRayInteractor.LineType lineType)
        {
            TestUtilities.CreateInteractionManager();
            TestUtilities.CreateXRRig();
            var interactor = TestUtilities.CreateRayInteractor();

            interactor.xrController.enabled = false;
            const int sampleFrequency = 5;

            interactor.sampleFrequency = sampleFrequency;
            interactor.hitClosestOnly  = false;
            interactor.lineType        = lineType;

            yield return(null);

            // Get the Sample Points to determine where to place the Interactable Planes in different segments
            Vector3[] samplePoints = null;
            var       isValid      = interactor.GetLinePoints(ref samplePoints, out var samplePointsCount);

            Assert.That(isValid, Is.True);
            Assert.That(samplePoints, Is.Not.Null);
            Assert.That(samplePointsCount, Is.EqualTo(lineType == XRRayInteractor.LineType.StraightLine ? 2 : sampleFrequency));
            Assert.That(samplePoints.Length, Is.GreaterThanOrEqualTo(samplePointsCount));

            // Verify that valid targets and hover targets is empty
            var targets = new List <XRBaseInteractable>();

            interactor.GetValidTargets(targets);

            Assert.That(targets, Is.Empty);

            interactor.GetHoverTargets(targets);

            Assert.That(targets, Is.Empty);

            // Create two Interactable Planes such that they are within two separate line segments of the curve
            // (although for Straight Line, there is only the one line segment).
            // Add Interactable Plane near the end of the curve
            var from            = samplePoints[samplePointsCount - 2];
            var to              = samplePoints[samplePointsCount - 1];
            var farInteractable = CreatePlaneInteractable(Vector3.Lerp(from, to, 0.75f));

            // Add Interactable Plane near the start of the curve
            from = samplePoints[0];
            to   = samplePoints[1];
            var nearInteractable = CreatePlaneInteractable(Vector3.Lerp(from, to, 0.25f));

            // Wait for Physics update for hit
            yield return(new WaitForFixedUpdate());

            yield return(null);

            // Verify that both Interactable Planes are hit
            interactor.GetValidTargets(targets);

            Assert.That(targets, Is.EqualTo(new[] { nearInteractable, farInteractable }));

            interactor.GetHoverTargets(targets);

            Assert.That(targets, Is.EqualTo(new[] { nearInteractable, farInteractable }));

            XRBaseInteractable CreatePlaneInteractable(Vector3 position)
            {
                var planeGO      = GameObject.CreatePrimitive(PrimitiveType.Plane);
                var interactable = planeGO.AddComponent <XRSimpleInteractable>();

                planeGO.transform.localPosition = position;
                planeGO.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f);
                planeGO.transform.localScale    = new Vector3(100f, 1f, 100f);
                return(interactable);
            }
        }