예제 #1
0
        void CallEnterEvents()
        {
            if (tracker_hover_next == null)
            {
                return;
            }

            if (tracker_hover == null)
            {
                tracker_hover_next.OnEnter(this);
                tracker_hover = tracker_hover_next;
            }
            Debug.Assert(tracker_hover == tracker_hover_next);

            if (is_clicking_now && !is_grabbing)
            {
                switch (clicking_button)
                {
                case EControllerButton.Trigger:
                    tracker_hover.OnTriggerDown(this);
                    break;

                case EControllerButton.Grip:
                    tracker_hover.OnGripDown(this);
                    break;
                }
                grabbing_button = clicking_button;
                is_grabbing     = true;
            }
        }
예제 #2
0
 void CallLeaveEvents()
 {
     if (tracker_hover != null && tracker_hover != tracker_hover_next)
     {
         BaseControllerTracker prev = tracker_hover;
         tracker_hover = null;
         prev.OnLeave(this);
         SetPointer(null);
     }
 }
예제 #3
0
        static void CallControllerMoves(Controller[] controllers)
        {
            Debug.Assert(controllers.Length == 2);   /* for now, always exactly two */
            BaseControllerTracker left_tracker  = controllers[0].tracker_hover;
            BaseControllerTracker right_tracker = controllers[1].tracker_hover;

            if (left_tracker == right_tracker)
            {
                if (left_tracker == null)
                {
                    return;     /* both controllers are nowhere */
                }
                if (left_tracker is ConcurrentControllerTracker)
                {
                    /* both controllers are over the same ConcurrentControllerTracker */
                    (left_tracker as ConcurrentControllerTracker).OnMove(FilterNotLeaving(controllers));
                    return;
                }
            }

            foreach (var ctrl in controllers)
            {
                BaseControllerTracker tracker = ctrl.tracker_hover;
                if (tracker is ControllerTracker)
                {
                    if (ctrl.is_grabbing)
                    {
                        switch (ctrl.grabbing_button)
                        {
                        case EControllerButton.Trigger:
                            (tracker as ControllerTracker).OnTriggerDrag(ctrl);
                            break;

                        case EControllerButton.Grip:
                            (tracker as ControllerTracker).OnGripDrag(ctrl);
                            break;
                        }
                    }
                    else
                    {
                        (tracker as ControllerTracker).OnMoveOver(ctrl);
                    }
                }
                else if (tracker is ConcurrentControllerTracker)
                {
                    (tracker as ConcurrentControllerTracker).OnMove(FilterNotLeaving(new Controller[] { ctrl }));
                }
            }
        }
예제 #4
0
        void ReadControllerState()
        {
            /* updates the state fields; updates 'is_tracking' and 'is_clicking_now';
             * may cause un-grabbing and so 'is_grabbing' may be reset to false;
             * sets 'tracker_hover_next'. */

            is_clicking_now = false;

            var system = OpenVR.System;

            if (system == null || !isActiveAndEnabled ||
                !system.GetControllerState((uint)trackedObject.index, ref controllerState,
                                           (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t))))
            {
                tracker_hover_next = null;
                bitmask_buttons    = 0;

                if (is_tracking)
                {
                    if (is_grabbing)
                    {
                        UnGrab();
                    }
                    is_tracking = false;
                    ResetVelocityEstimates();
                }
            }
            else
            {
                is_tracking = true;

                /* read the button state */
                ulong trigger = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Trigger));
                ulong pad     = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Touchpad));
                ulong grip    = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_Grip));
                ulong menu    = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_ApplicationMenu));

                uint b = 0;
                if (menu != 0)
                {
                    b |= (1U << (int)EControllerButton.Menu);
                }
                if (grip != 0)
                {
                    if (!GetButton(EControllerButton.Grip))
                    {
                        is_clicking_now = true; clicking_button = EControllerButton.Grip;
                    }
                    b |= (1U << (int)EControllerButton.Grip);
                }
                if (pad != 0)
                {
                    b |= (1U << (int)EControllerButton.Touchpad);
                }
                if (trigger != 0)
                {
                    if (!GetButton(EControllerButton.Trigger))
                    {
                        is_clicking_now = true;  clicking_button = EControllerButton.Trigger;
                    }
                    b |= (1U << (int)EControllerButton.Trigger);
                }
                bitmask_buttons = b;

                if (is_grabbing && grabbing_button.HasValue && !GetButton(grabbing_button.Value))
                {
                    UnGrab();
                }

                /* read the position/rotation and update the velocity estimation */
                current_position = transform.position + transform.rotation * POS_TO_CURSOR;
                current_rotation = transform.rotation;
                UpdateVelocityEstimates();

                /* find the next BaseControllerTracker at that position, taking the highest
                 * priority one.  If is_grabbing, then keep the current one instead.
                 */
                if (is_grabbing)
                {
                    tracker_hover_next          = tracker_hover;
                    tracker_hover_next_priority = float.PositiveInfinity;
                }
                else
                {
                    Collider[] lst = Physics.OverlapSphere(current_position, 0.02f, Physics.AllLayers,
                                                           QueryTriggerInteraction.Collide);
                    var potential = new HashSet <Transform>();

                    foreach (var coll in lst)
                    {
                        Transform tr = coll.transform;
                        while (tr != null)
                        {
                            if (!potential.Add(tr))
                            {
                                break;     /* already in the set */
                            }
                            tr = tr.parent;
                        }
                    }

                    float best_priority        = float.NegativeInfinity;
                    BaseControllerTracker best = null;

                    foreach (Transform tr in potential)
                    {
                        foreach (var tracker in tr.GetComponents <BaseControllerTracker>())
                        {
                            if (tracker is ControllerTracker && !Matches((tracker as ControllerTracker).selectableControllers))
                            {
                                continue;
                            }

                            float priority = tracker.GetPriority(this);
                            if (priority == float.NegativeInfinity)
                            {
                                continue;
                            }
                            Debug.Assert(priority < float.PositiveInfinity);

                            if (priority > best_priority || (priority == best_priority && tracker.creation_order > best.creation_order))
                            {
                                best_priority = priority;
                                best          = tracker;
                            }
                        }
                    }
                    tracker_hover_next          = best;
                    tracker_hover_next_priority = best_priority;
                }

                /* sanity check */
                if (is_grabbing)
                {
                    Debug.Assert(tracker_hover);
                }
            }
        }
예제 #5
0
        void Update()
        {
            if (active_controller == null)
            {
                foreach (var ctrl in BaroqueUI.GetControllers())
                {
                    if (ctrl.Matches(controllerSelection) && ctrl.GetButton(controllerButton))
                    {
                        BaseControllerTracker tracker = ctrl.HoverControllerTracker();
                        if (tracker == null || tracker.CanStartTeleportAction(ctrl))
                        {
                            arc.Show();
                            active_controller = ctrl;
                            break;
                        }
                    }
                }
                if (active_controller == null)
                {
                    return;
                }
            }

            if (active_controller.GetButton(controllerButton))
            {
                bool saved = Physics.queriesHitTriggers;
                try
                {
                    Physics.queriesHitTriggers = false;

                    Transform tr = active_controller.transform;
                    arc.SetArcData(tr.position, tr.TransformDirection(new Vector3(0, beamUpVelocity, beamForwardVelocity)), true, false);

                    destination_valid = false;
                    bool       show_invalid = false;
                    RaycastHit hitInfo;
                    if (arc.DrawArc(out hitInfo))
                    {
                        /* The teleport destination is accepted if we fit a capsule here.  More precisely:
                         * the capsule starts at ABOVE_GROUND above the hit point of the beam; on top
                         * of that we check the capsule.  The height of that capsule above around is thus
                         * from ABOVE_GROUND to ABOVE_GROUND + RADIUS + DISTANCE + RADIUS.  The parameters
                         * are chosen so that planes of above ~30° cannot be teleported to, because the
                         * bottom of the capsule always intersects that plane.
                         */
                        const float ABOVE_GROUND = 0.1f, RADIUS = 0.32f, DISTANCE = 1.1f;

                        if (Physics.CheckCapsule(hitInfo.point + (ABOVE_GROUND + RADIUS) * Vector3.up,
                                                 hitInfo.point + (ABOVE_GROUND + RADIUS + DISTANCE) * Vector3.up,
                                                 RADIUS, traceLayerMask, QueryTriggerInteraction.Ignore))
                        {
                            /* invalid position */
                            invalid_reticle.position = hitInfo.point;
                            invalid_reticle.rotation = Quaternion.LookRotation(hitInfo.normal) * Quaternion.Euler(90, 0, 0);
                            show_invalid             = true;
                        }
                        else
                        {
                            /* valid position */
                            invalid_reticle.gameObject.SetActive(false);
                            destination_reticle.position = destination_position = hitInfo.point;
                            destination_valid            = true;
                        }
                    }
                    invalid_reticle.gameObject.SetActive(show_invalid);
                    destination_reticle.gameObject.SetActive(destination_valid);
                    arc.SetColor(destination_valid ? validArcColor : invalidArcColor);
                }
                finally
                {
                    Physics.queriesHitTriggers = saved;
                }
            }
            else
            {
                active_controller = null;
                arc.Hide();
                invalid_reticle.gameObject.SetActive(false);
                destination_reticle.gameObject.SetActive(false);

                if (destination_valid)
                {
                    StartTeleporting();
                }
            }
        }