Exemple #1
0
 void EndDisplayOfMenu()
 {
     s_ControllingSpatialMenu                 = null; // Allow another SpatialMenu to own control of the SpatialMenuUI
     m_CurrentSpatialActionMapInput           = null;
     m_TotalShowMenuCircularInputRotation     = 0;
     m_HighlightedTopLevelMenuElementPosition = -1;
     m_HighlightedSubLevelMenuElementPosition = -1;
     this.SetManipulatorsVisible(this, true);
     this.SetRayOriginEnabled(m_RayOrigin, true);
     visible = false;
 }
Exemple #2
0
        public void ProcessInput(ActionMapInput input, ConsumeControlDelegate consumeControl)
        {
            m_CurrentSpatialActionMapInput = (SpatialMenuInput)input;
            if (s_ControllingSpatialMenu != null && s_ControllingSpatialMenu != this)
            {
                this.SetRayOriginEnabled(m_RayOrigin, true);

                // Perform custom logic for proxies (driving a SpatialMenuController) that didn't initiate the display of the SpatialMenu
                // Though they may need their input actions to drive certain SpatialMenu functionality
                var cancelJustPressed = CancelWasJustPressedTest(consumeControl);
                if (!cancelJustPressed) // Only process selection testing if cancel was not just pressed
                {
                    SelectJustPressedTest(consumeControl, false);
                }

                return;
            }

            var showMenuInputAction                  = m_CurrentSpatialActionMapInput.showMenu;
            var showMenuInputActionVector2           = showMenuInputAction.vector2;
            var showMenuInputActionVector2Normalized = showMenuInputAction.vector2.normalized;
            var positiveYInputAction                 = showMenuInputAction.positiveY;

            // count how long the input value has been default and thus is in deadzone or lifted
            if (showMenuInputAction.vector2 == default(Vector2))
            {
                m_IdleAtCenterDuration += Time.unscaledDeltaTime;
            }
            else
            {
                m_IdleAtCenterDuration = 0f;
            }

            // release after the input has been default for a few frames. This almost entirely prevents
            // the case where having your thumb in the middle of the pad causes default value and thus release
            if (m_IdleAtCenterDuration >= 0.05f)
            {
                m_SpatialInputHold = false;
                EndDisplayOfMenu();
            }

            // Detect the initial activation of the relevant Spatial input, in order to display menu and own control with this SpatialMenuController
            if (positiveYInputAction.wasJustPressed && Mathf.Approximately(m_TotalShowMenuCircularInputRotation, 0))
            {
                s_ControllingSpatialMenu = this;
                m_OriginalShowMenuCircularInputDirection = showMenuInputActionVector2Normalized;
                m_UpdatingShowMenuCircularInputDirection = m_OriginalShowMenuCircularInputDirection;
                m_ShowMenuCircularInputCrossedRotationThresholdForSelection = false;

                m_SpatialInputHold = true;
                ConsumeControls(m_CurrentSpatialActionMapInput, consumeControl); // Select should only be consumed upon activation, so other UI can receive select events

#if UNITY_EDITOR
                // Hide the scene view Gizmo UI that draws SpatialMenu outlines and
                sceneViewGizmosVisible = false;
#endif

                // Alternatively, SpatialMenu's state could be a single static state
                // As opposed to passing the SpatialMenu instance's delegate when a new SpatialMenu instance initiates display of the menu
                s_SpatialMenuUI.changeMenuState = ChangeMenuState;

                spatialMenuState = SpatialMenuState.NavigatingTopLevel;
                s_SpatialMenuUI.spatialInterfaceInputMode = SpatialUIView.SpatialInterfaceInputMode.Neutral;

                foreach (var data in k_SpatialMenuData)
                {
                    foreach (var element in data.spatialMenuElements)
                    {
                        // When the SpatialMenu is displayed, assign its node as the controllerNode to all SpatialMenuElements
                        // This node is used as a fallback, if the element isn't currently being hovered by a proxy/ray
                        // This allows for a separate proxy/device, other than that which is the active SpatialMenuController,
                        // to have node-specific operations performed on the hovering node (adding tools, etc), rather than the controlling Menu node
                        if (element.VisualElement != null)
                        {
                            element.VisualElement.spatialMenuActiveControllerNode = node;
                        }
                    }
                }

                return;
            }

            // Trigger + continued/held circular-input, when beyond a threshold, allow for element selection cycling
            // If the magnitude of showMenu is below 0.5, consider the finger to have left the thumbstick/trackpad outer edge; close the menu
            if (positiveYInputAction.wasJustPressed || showMenuInputActionVector2.magnitude > 0.5f)
            {
                Vector3 facing = showMenuInputActionVector2Normalized;
                if (!m_ShowMenuCircularInputCrossedRotationThresholdForSelection)
                {
                    // Calculate rotation difference only in cases where the threshold has yet to be crossed
                    var rotationDifference = Vector2.Dot(m_OriginalShowMenuCircularInputDirection, showMenuInputActionVector2Normalized);
                    if (rotationDifference < -0.5)
                    {
                        // Show Menu Rotation Input can now be cycled forward/backward to select menu elements
                        s_SpatialMenuUI.spatialInterfaceInputMode = SpatialUIView.SpatialInterfaceInputMode.TriggerAffordanceRotation;
                        m_ShowMenuCircularInputCrossedRotationThresholdForSelection = true;
                    }
                }
                else
                {
                    if (m_CurrentSpatialActionMapInput.select.wasJustPressed)
                    {
                        s_SpatialMenuUI.SelectCurrentlyHighlightedElement(node, true);
                    }
                    else if (m_CircularTriggerSelectionCyclingCoroutine == null)
                    {
                        // Only allow selection if there has been a suitable amount of time since the previous selection
                        // Show menu input rotation is held, and has crossed the necessary threshold to allow for menu element cycling
                        // Positive is rotating to the right circularly, Negative is rotating to the left circularly
                        var circularRotationDirection = Vector3.Cross(facing, m_UpdatingShowMenuCircularInputDirection).z;
                        if (circularRotationDirection > 0.05f) // rotating to the right circularly
                        {
                            this.RestartCoroutine(ref m_CircularTriggerSelectionCyclingCoroutine, TimedCircularTriggerSelection());
                        }
                        else if (circularRotationDirection < -0.05f) // rotating to the left circularly
                        {
                            this.RestartCoroutine(ref m_CircularTriggerSelectionCyclingCoroutine, TimedCircularTriggerSelection(false));
                        }
                    }
                }

                var angle = Vector3.Angle(m_UpdatingShowMenuCircularInputDirection, facing);
                m_TotalShowMenuCircularInputRotation    += angle;
                m_UpdatingShowMenuCircularInputDirection = facing;
            }

            // isHeld goes false when you go below 0.5.  this is the check for 'up-click' on the pad / stick
            if ((positiveYInputAction.isHeld || m_SpatialInputHold) && s_SpatialMenuState != SpatialMenuState.Hidden)
            {
                // Individual axes can reset to 0, so always consume controls to pick them back up
                consumeControl(m_CurrentSpatialActionMapInput.leftStickX);
                consumeControl(m_CurrentSpatialActionMapInput.leftStickY);

                // If the ray IS pointing at the spatialMenu, then set the mode to reflect external ray input
                var atLeastOneInputDeviceIsAimingAtSpatialMenu = IsAimingAtUI();
                if (atLeastOneInputDeviceIsAimingAtSpatialMenu) // Ray-based interaction takes precedence over other input types
                {
                    s_SpatialMenuUI.spatialInterfaceInputMode = SpatialUIView.SpatialInterfaceInputMode.Ray;
                }
                else if (s_SpatialMenuUI.spatialInterfaceInputMode == SpatialUIView.SpatialInterfaceInputMode.Ray)
                {
                    s_SpatialMenuUI.ReturnToPreviousInputMode();
                }

                this.SetRayOriginEnabled(m_RayOrigin, false);
                this.SetManipulatorsVisible(this, false);
                visible = true;

                if (s_SpatialMenuState == SpatialMenuState.NavigatingSubMenuContent)
                {
                    var cancelJustPressed = CancelWasJustPressedTest(consumeControl);
                    if (cancelJustPressed)
                    {
                        return;
                    }
                }

                return;
            }

            if (!positiveYInputAction.isHeld && !m_SpatialInputHold)
            {
                EndDisplayOfMenu();
            }
        }