/// <inheritdoc />
        public override void OnPostSceneQuery()
        {
            base.OnPostSceneQuery();

            LineBase.enabled = IsInteractionEnabled;
            BaseCursor?.SetVisibility(IsInteractionEnabled);

            if (!LineBase.enabled)
            {
                return;
            }

            // The distance the ray travels through the world before it hits something. Measured in world-units (as opposed to normalized distance).
            float    clearWorldLength;
            Gradient lineColor = LineColorNoTarget;

            if (Result?.CurrentPointerTarget != null)
            {
                // We hit something
                clearWorldLength = Result.Details.RayDistance;
                lineColor        = LineColorValid;
            }
            else
            {
                clearWorldLength = DefaultPointerExtent;
                lineColor        = IsSelectPressed ? LineColorSelected : LineColorNoTarget;
            }

            if (IsFocusLocked)
            {
                lineColor = LineColorLockFocus;
            }

            int maxClampLineSteps = LineCastResolution;

            foreach (BaseMixedRealityLineRenderer lineRenderer in lineRenderers)
            {
                // Renderers are enabled by default if line is enabled
                maxClampLineSteps      = Mathf.Max(maxClampLineSteps, lineRenderer.LineStepCount);
                lineRenderer.LineColor = lineColor;
            }

            // Used to ensure the line doesn't extend beyond the cursor
            float cursorOffsetWorldLength = (BaseCursor != null) ? BaseCursor.SurfaceCursorDistance : 0;

            // If focus is locked, we're sticking to the target
            // So don't clamp the world length
            if (IsFocusLocked && IsTargetPositionLockedOnFocusLock)
            {
                float cursorOffsetLocalLength = LineBase.GetNormalizedLengthFromWorldLength(cursorOffsetWorldLength);
                LineBase.LineEndClamp = 1 - cursorOffsetLocalLength;
            }
            else
            {
                // Otherwise clamp the line end by the clear distance
                float clearLocalLength = lineBase.GetNormalizedLengthFromWorldLength(clearWorldLength - cursorOffsetWorldLength, maxClampLineSteps);
                LineBase.LineEndClamp = clearLocalLength;
            }
        }
        /// <inheritdoc />
        public override void OnPostSceneQuery()
        {
            if (IsSelectPressed)
            {
                MixedRealityToolkit.InputSystem.RaisePointerDragged(this, MixedRealityInputAction.None, Handedness);
            }

            Gradient lineColor = LineColorNoTarget;
            BaseMixedRealityLineRenderer contextRenderer = null;

            if (!IsActive)
            {
                LineBase.enabled = false;
                BaseCursor?.SetVisibility(false);
                return;
            }

            contextRenderer  = lineRendererNoTarget;
            LineBase.enabled = true;
            BaseCursor?.SetVisibility(true);

            float clearWorldLength;
            float cursorOffsetWorldLength = (BaseCursor != null) ? BaseCursor.SurfaceCursorDistance : 0;

            // If we hit something
            if (Result?.CurrentPointerTarget != null)
            {
                clearWorldLength = Result.Details.RayDistance;

                lineColor       = LineColorValid;
                contextRenderer = lineRendererSelected;
            }
            else
            {
                clearWorldLength = DefaultPointerExtent;

                lineColor       = IsSelectPressed ? LineColorSelected : LineColorNoTarget;
                contextRenderer = IsSelectPressed ? lineRendererSelected : lineRendererNoTarget;
            }

            if (IsFocusLocked)
            {
                lineColor       = LineColorLockFocus;
                contextRenderer = lineRendererSelected;
            }

            int maxClampLineSteps = LineCastResolution;

            foreach (BaseMixedRealityLineRenderer lineRenderer in LineRenderers)
            {
                // Otherwise, enable the renderer we chose
                if (lineRenderer == contextRenderer)
                {
                    lineRenderer.enabled = true;
                    maxClampLineSteps    = Mathf.Max(maxClampLineSteps, lineRenderer.LineStepCount);
                }
                else
                {
                    lineRenderer.enabled = false;
                }

                // Set colors on all line renderers regardless of context
                lineRenderer.LineColor = lineColor;
            }

            // If focus and target point is locked, we're sticking to the target
            // So don't clamp the world length
            if (IsFocusLocked && IsTargetPositionLockedOnFocusLock)
            {
                float cursorOffsetLocalLength = LineBase.GetNormalizedLengthFromWorldLength(cursorOffsetWorldLength);
                LineBase.LineEndClamp = 1 - cursorOffsetLocalLength;
            }
            else
            {
                // Otherwise clamp the line end by the clear distance
                float clearLocalLength = LineBase.GetNormalizedLengthFromWorldLength(clearWorldLength - cursorOffsetWorldLength, maxClampLineSteps);
                LineBase.LineEndClamp = clearLocalLength;
            }
        }
        public override void OnPostRaycast()
        {
            // Use the results from the last update to set our NavigationResult
            float clearWorldLength = 0f;

            TeleportSurfaceResult    = TeleportSurfaceResult.None;
            GravityDistorter.enabled = false;

            if (IsInteractionEnabled)
            {
                LineBase.enabled = true;

                // If we hit something
                if (Result.CurrentPointerTarget != null)
                {
                    // Check if it's in our valid layers
                    if (((1 << Result.CurrentPointerTarget.layer) & ValidLayers.value) != 0)
                    {
                        // See if it's a hot spot
                        if (TeleportHotSpot != null && TeleportHotSpot.IsActive)
                        {
                            TeleportSurfaceResult = TeleportSurfaceResult.HotSpot;
                            // Turn on gravity, point it at hotspot
                            GravityDistorter.WorldCenterOfGravity = TeleportHotSpot.Position;
                            GravityDistorter.enabled = true;
                        }
                        else
                        {
                            // If it's NOT a hotspot, check if the hit normal is too steep
                            // (Hotspots override dot requirements)
                            TeleportSurfaceResult = Vector3.Dot(Result.Details.LastRaycastHit.normal, Vector3.up) > upDirectionThreshold
                                ? TeleportSurfaceResult.Valid
                                : TeleportSurfaceResult.Invalid;
                        }
                    }
                    else if (((1 << Result.CurrentPointerTarget.layer) & InvalidLayers) != 0)
                    {
                        TeleportSurfaceResult = TeleportSurfaceResult.Invalid;
                    }
                    else
                    {
                        TeleportSurfaceResult = TeleportSurfaceResult.None;
                    }

                    // Use the step index to determine the length of the hit
                    for (int i = 0; i <= Result.RayStepIndex; i++)
                    {
                        if (i == Result.RayStepIndex)
                        {
                            if (MixedRealityRaycaster.DebugEnabled)
                            {
                                Color debugColor = TeleportSurfaceResult != TeleportSurfaceResult.None
                                    ? Color.yellow
                                    : Color.cyan;

                                Debug.DrawLine(Result.StartPoint + Vector3.up * 0.1f, Result.StartPoint + Vector3.up * 0.1f, debugColor);
                            }

                            // Only add the distance between the start point and the hit
                            clearWorldLength += Vector3.Distance(Result.StartPoint, Result.Details.Point);
                        }
                        else if (i < Result.RayStepIndex)
                        {
                            // Add the full length of the step to our total distance
                            clearWorldLength += Rays[i].Length;
                        }
                    }

                    // Clamp the end of the parabola to the result hit's point
                    LineBase.LineEndClamp = LineBase.GetNormalizedLengthFromWorldLength(clearWorldLength, LineCastResolution);
                    BaseCursor?.SetVisibility(TeleportSurfaceResult == TeleportSurfaceResult.Valid || TeleportSurfaceResult == TeleportSurfaceResult.HotSpot);
                }
                else
                {
                    BaseCursor?.SetVisibility(false);
                    LineBase.LineEndClamp = 1f;
                }

                // Set the line color
                for (int i = 0; i < LineRenderers.Length; i++)
                {
                    LineRenderers[i].LineColor = GetLineGradient(TeleportSurfaceResult);
                }
            }
            else
            {
                LineBase.enabled = false;
            }
        }
        public override void OnPostSceneQuery()
        {
            // Use the results from the last update to set our NavigationResult
            float clearWorldLength = 0f;

            TeleportSurfaceResult    = TeleportSurfaceResult.None;
            GravityDistorter.enabled = false;

            if (IsInteractionEnabled)
            {
                LineBase.enabled = true;

                // If we hit something
                if (Result.CurrentPointerTarget != null)
                {
                    // Check if it's in our valid layers
                    if (((1 << Result.CurrentPointerTarget.layer) & ValidLayers.value) != 0)
                    {
                        // See if it's a hot spot
                        if (TeleportHotSpot != null && TeleportHotSpot.IsActive)
                        {
                            TeleportSurfaceResult = TeleportSurfaceResult.HotSpot;
                            // Turn on gravity, point it at hotspot
                            GravityDistorter.WorldCenterOfGravity = TeleportHotSpot.Position;
                            GravityDistorter.enabled = true;
                        }
                        else
                        {
                            // If it's NOT a hotspot, check if the hit normal is too steep
                            // (Hotspots override dot requirements)
                            TeleportSurfaceResult = Vector3.Dot(Result.Details.LastRaycastHit.normal, Vector3.up) > upDirectionThreshold
                                ? TeleportSurfaceResult.Valid
                                : TeleportSurfaceResult.Invalid;
                        }
                    }
                    else if (((1 << Result.CurrentPointerTarget.layer) & InvalidLayers) != 0)
                    {
                        TeleportSurfaceResult = TeleportSurfaceResult.Invalid;
                    }
                    else
                    {
                        TeleportSurfaceResult = TeleportSurfaceResult.None;
                    }

                    clearWorldLength = Result.Details.RayDistance;

                    // Clamp the end of the parabola to the result hit's point
                    LineBase.LineEndClamp = LineBase.GetNormalizedLengthFromWorldLength(clearWorldLength, LineCastResolution);
                    BaseCursor?.SetVisibility(TeleportSurfaceResult == TeleportSurfaceResult.Valid || TeleportSurfaceResult == TeleportSurfaceResult.HotSpot);
                }
                else
                {
                    BaseCursor?.SetVisibility(false);
                    LineBase.LineEndClamp = 1f;
                }

                // Set the line color
                for (int i = 0; i < LineRenderers.Length; i++)
                {
                    LineRenderers[i].LineColor = GetLineGradient(TeleportSurfaceResult);
                }
            }
            else
            {
                LineBase.enabled = false;
            }
        }