Пример #1
0
        ControllerTracker HandleButtonDown(EControllerButton btn, EEventSet event_set)
        {
            if ((bitmask_buttons_down & (1U << (int)btn)) == 0)
            {
                return(null);    /* not actually pressing this button */
            }
            ControllerTracker tracker = FindHandler(event_set);

            if (tracker != null)
            {
                if (tracker == tracker_hover && btn != EControllerButton.Menu)
                {
                    tracker_hover_lock |= 1U << (int)btn;
                }

                ControllerEvent ev = null;
                switch (btn)
                {
                case EControllerButton.Trigger:  ev = tracker._i_onTriggerDown;    break;

                case EControllerButton.Grip:     ev = tracker._i_onGripDown;       break;

                case EControllerButton.Menu:     ev = tracker._i_onMenuClick;      break;
                }
                tracker._Call(ev, this);
            }
            return(tracker);
        }
Пример #2
0
 public void PickIfBetter(float priority, ref ControllerTracker current_best, ref float current_best_priority)
 {
     if (priority > current_best_priority ||
         (priority == current_best_priority && creation_order > current_best.creation_order))
     {
         current_best_priority = priority;
         current_best          = this;
     }
 }
Пример #3
0
        void LeaveNow()
        {
            ControllerTracker prev = tracker_hover;

            tracker_hover      = null;
            tracker_hover_lock = 0;
            prev._Call(prev._i_onLeave, this);
            SetPointer("");
        }
Пример #4
0
        void CallEnterEvents()
        {
            if (tracker_hover_next == null)
            {
                return;
            }

            if (tracker_hover == null)
            {
                tracker_hover = tracker_hover_next;
                tracker_hover._Call(tracker_hover._i_onEnter, this);
            }
            Debug.Assert(tracker_hover == tracker_hover_next);
        }
Пример #5
0
 public void ForceLeave(ControllerTracker single_tracker = null)
 {
     if (active_trigger != null && (single_tracker == null || single_tracker == active_trigger))
     {
         DeactivateTrigger();
     }
     if (active_grip != null && (single_tracker == null || single_tracker == active_grip))
     {
         DeactivateGrip();
     }
     if (active_touchpad != null && (single_tracker == null || single_tracker == active_touchpad))
     {
         DeactivateTouchpad();
     }
     if (tracker_hover != null && (single_tracker == null || single_tracker == tracker_hover))
     {
         LeaveNow();
     }
 }
Пример #6
0
        static ControllerTracker GetOrBuildTracker(MonoBehaviour tracker, bool is_hover)
        {
            Baroque._EnsureStarted();
            ControllerTracker ct;
            var these_trackers = is_hover ? hover_trackers : global_trackers;

            if (!these_trackers.TryGetValue(tracker, out ct))
            {
                ct = new ControllerTracker(tracker, is_hover);
                these_trackers[tracker] = ct;
            }

            if (--auto_free_trackers <= 0)
            {
                hover_trackers     = RemoveDeadTrackers(hover_trackers);
                global_trackers    = RemoveDeadTrackers(global_trackers);
                auto_free_trackers = (hover_trackers.Count + global_trackers.Count) / 2 + 16;
            }

            return(ct);
        }
Пример #7
0
        ControllerTracker FindHandler(EEventSet event_set)
        {
            /* returns either tracker_hover or a global tracker, but one
             * that can handle the event_set. */
            if (tracker_hover != null && (tracker_hover._event_sets & event_set) != 0)
            {
                return(tracker_hover);
            }
            else
            {
                /* look for global trackers */
                ControllerTracker best          = null;
                float             best_priority = float.NegativeInfinity;

                foreach (var ct in global_trackers.Values)
                {
                    if ((ct._event_sets & event_set) != 0 && ct.isActiveAndEnabled)
                    {
                        float priority = ct.computePriority(this);
                        if (priority != float.NegativeInfinity)
                        {
                            ct.PickIfBetter(priority, ref best, ref best_priority);
                        }
                    }
                }
                /* If it's a non-concurrent tracker and it is used by the other controller, cancel */
                if (best != null && !best.isConcurrent)
                {
                    foreach (var ctrl in Baroque.GetControllers())
                    {
                        if (ctrl != this && ctrl.ActiveWith(best))
                        {
                            return(null);
                        }
                    }
                }
                return(best);
            }
        }
Пример #8
0
 bool ActiveWith(ControllerTracker ct)
 {
     return(ct == tracker_hover || ct == active_trigger || ct == active_grip || ct == active_touchpad);
 }
Пример #9
0
        static void ResolveControllerConflicts(Controller[] controllers)
        {
            Debug.Assert(controllers.Length == 2);   /* for now, always exactly two */
            Controller        left_ctrl  = controllers[0];
            Controller        right_ctrl = controllers[1];
            ControllerTracker tracker    = left_ctrl.tracker_hover_next;

            if (tracker != null && tracker == right_ctrl.tracker_hover_next && !tracker.isConcurrent)
            {
                /* conflict: both controllers are inside the zone corresponding to
                 * the same, non-Concurrent, ControllerTracker */
                Controller forced_out;

                /* Heuristics, but will never pick whoever has got 'tracker_hover_lock & MANUAL_LOCK' */
                if ((right_ctrl.tracker_hover_lock & MANUAL_LOCK) != 0)
                {
                    forced_out = left_ctrl;
                }
                else if (left_ctrl.tracker_hover_lock != 0)
                {
                    forced_out = right_ctrl;
                }
                else if (right_ctrl.tracker_hover_lock != 0)
                {
                    forced_out = left_ctrl;
                }
                else if (right_ctrl.IsClickingNow())
                {
                    forced_out = left_ctrl;
                }
                else if (left_ctrl.IsClickingNow())
                {
                    forced_out = right_ctrl;
                }
                else if (right_ctrl.tracker_hover_next_priority > left_ctrl.tracker_hover_next_priority)
                {
                    forced_out = left_ctrl;
                }
                else if (right_ctrl.tracker_hover_next_priority < left_ctrl.tracker_hover_next_priority)
                {
                    forced_out = right_ctrl;
                }
                else if (left_ctrl.touchpadTouched)
                {
                    forced_out = right_ctrl;
                }
                else
                {
                    forced_out = left_ctrl;
                }

                /* Force one of the controllers "out" of the zone, and force a button deactivation if needed.
                 * In principle, afterwards, it is not possible that the tracker remains locked for both
                 * controllers, because tracker_hover_lock == MANUAL_LOCK can only be set if the tracker is
                 * the current hover in the first place and this tracker cannot be current for both. */
                if (forced_out.active_trigger == tracker)
                {
                    forced_out.DeactivateTrigger();
                }
                if (forced_out.active_grip == tracker)
                {
                    forced_out.DeactivateGrip();
                }
                if (forced_out.active_touchpad == tracker)
                {
                    forced_out.DeactivateTouchpad();
                }

                forced_out.tracker_hover_next = null;
            }
        }
Пример #10
0
        void ReadControllerState()
        {
            /* Updates the state fields; updates 'is_tracking' and 'bitmask_buttons';
             * /* may cause un-grabbing (deactivating) of buttons and so 'active_*' may be reset to null;
             * sets 'tracker_hover_next'.
             */
            if (!GetControllerState(ref controllerState))
            {
                bitmask_buttons      = 0;
                bitmask_buttons_down = 0;
                is_tracking_active   = false;
                tracker_hover_next   = null;
                tracker_hover_lock   = 0;
                ResetVelocityEstimates();
            }
            else
            {
                /* read the button state */
                uint prev_bitmask_buttons = bitmask_buttons;

                bool  trigclick = (controllerState.rAxis1.x > 0.999f);  /* == 1.0: the controller fully 'clicked' */
                ulong trigger   = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Trigger));
                ulong pad       = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Touchpad));
                ulong padtouch  = controllerState.ulButtonTouched & (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));

                /* the bit at 0x400000U means that the trigger was fully clicked during the
                 * previous frame.  If the bit is set but we are not fully clicking any more,
                 * then we consider the trigger to be already released even if trigger != 0
                 * right now (i.e. the trigger is still pressed a lot, just not fully any more).
                 */
                if ((bitmask_buttons & 0x400000U) != 0 && !trigclick && trigger != 0)
                {
                    trigclick = true;   /* keep the 0x400000U bit as long as we get trigger != 0 */
                    trigger   = 0;
                }

                uint b = 0;
                if (menu != 0)
                {
                    b |= (1U << (int)EControllerButton.Menu);
                }
                if (grip != 0)
                {
                    b |= (1U << (int)EControllerButton.Grip);
                }
                if (pad != 0)
                {
                    b |= (1U << (int)EControllerButton.Touchpad);
                }
                if (trigger != 0)
                {
                    b |= (1U << (int)EControllerButton.Trigger);
                }
                if (padtouch != 0)
                {
                    b |= (1U << (int)EControllerButton.TouchpadTouched);
                }
                if (trigclick)
                {
                    b |= 0x400000U;
                }
                bitmask_buttons      = b;
                bitmask_buttons_down = bitmask_buttons & ~prev_bitmask_buttons;


                /* ignore trigger click when grip is down and vice-versa */
                if (grip != 0)
                {
                    bitmask_buttons_down &= ~(1U << (int)EControllerButton.Trigger);
                }
                if (trigger != 0)
                {
                    bitmask_buttons_down &= ~(1U << (int)EControllerButton.Grip);
                }

                if (!is_tracking_active)
                {
                    bitmask_buttons_down = 0;
                    is_tracking_active   = true;
                }
            }

            /* un-grab */

            if (active_trigger != null && !triggerPressed)
            {
                DeactivateTrigger();
            }
            if (active_grip != null && !gripPressed)
            {
                DeactivateGrip();
            }
            if (active_touchpad != null &&
                (!touchpadTouched || (active_touchpad_state == ActiveTouchpadState.Action1 && !touchpadPressed)))
            {
                DeactivateTouchpad();
            }

            if (is_tracking_active)
            {
                /* read the position and rotation, and update the velocity estimates */
                current_position = ComputePosition();
                current_rotation = transform.rotation;
                UpdateVelocityEstimates();

                /* find the next BaseControllerTracker at that position, taking the highest
                 * priority one. */
                var potential = new HashSet <Transform>();

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

                float             best_priority = float.NegativeInfinity;
                ControllerTracker best          = null;
                overlapping_trackers.Clear();   /* should already be cleared, but better safe than sorry */

                foreach (Transform tr in potential)
                {
                    foreach (var tracker in tr.GetComponents <MonoBehaviour>())
                    {
                        ControllerTracker ct;
                        if (tracker == null || !hover_trackers.TryGetValue(tracker, out ct))
                        {
                            continue;
                        }

                        float priority = ct.computePriority(this);
                        if (priority == float.NegativeInfinity)
                        {
                            continue;
                        }

                        overlapping_trackers[ct] = priority;
                        ct.PickIfBetter(priority, ref best, ref best_priority);
                    }
                }

                /* If tracker_hover_lock is set, we keep tracker_hover.
                 * We still do the loop above in order to get 'overlapping_trackers'.
                 */
                if (tracker_hover_lock != 0)
                {
                    Debug.Assert(tracker_hover != null);
                    tracker_hover_next          = tracker_hover;
                    tracker_hover_next_priority = float.PositiveInfinity;
                }
                else
                {
                    tracker_hover_next          = best;
                    tracker_hover_next_priority = best_priority;
                }
            }
        }
Пример #11
0
        void CallButtonDown()
        {
            const float TOUCHPAD_CLICK_TIME = 0.25f;

            const EEventSet TouchpadAll = (EEventSet.TouchpadAction1 |
                                           EEventSet.TouchpadAction2 |
                                           EEventSet.TouchpadAction3);

            if (bitmask_buttons_down != 0)
            {
                if (active_trigger == null)
                {
                    active_trigger = HandleButtonDown(EControllerButton.Trigger, EEventSet.Trigger);
                }

                if (active_grip == null)
                {
                    active_grip = HandleButtonDown(EControllerButton.Grip, EEventSet.Grip);
                }

                HandleButtonDown(EControllerButton.Menu, EEventSet.Menu);

                /* == Handle the touchpad == */

                if ((bitmask_buttons_down & (1U << (int)EControllerButton.TouchpadTouched)) != 0)
                {
                    /* starting to touch: the only case is "released" => "small delay" */
                    touch_original_pos2 = touchpadPosition;

                    if (active_touchpad_state == ActiveTouchpadState.None)
                    {
                        Debug.Assert(active_touchpad == null);
                        active_touchpad = FindHandler(TouchpadAll);
                        if (active_touchpad != null)
                        {
                            if (active_touchpad == tracker_hover)
                            {
                                tracker_hover_lock |= 1U << (int)EControllerButton.Touchpad;
                            }

                            EEventSet es    = active_touchpad._event_sets;
                            int       count = ((es & EEventSet.TouchpadAction1) != 0 ? 1 : 0) +
                                              ((es & EEventSet.TouchpadAction2) != 0 ? 1 : 0) +
                                              ((es & EEventSet.TouchpadAction3) != 0 ? 1 : 0);
                            float delay = count >= 2 ? TOUCHPAD_CLICK_TIME : 1e-20f;
                            active_touchpad_state   = ActiveTouchpadState.SmallDelay;
                            active_touchpad_timeout = GetTime() + delay;
                            touch_original_pos3     = position;
                        }
                    }
                }

                if ((bitmask_buttons_down & (1U << (int)EControllerButton.Touchpad)) != 0)
                {
                    /* pressing: goes to "action 1" if the tracker handles it */
                    ControllerTracker cs = active_touchpad;
                    if (cs == null)
                    {
                        cs = HandleButtonDown(EControllerButton.Touchpad, EEventSet.TouchpadAction1);
                    }

                    if (cs != null && (cs._event_sets & EEventSet.TouchpadAction1) != 0)
                    {
                        StopTouchpadAction();
                        active_touchpad_state = ActiveTouchpadState.Action1;
                        active_touchpad       = cs;
                        active_touchpad._Call(active_touchpad._i_onTouchPressDown, this);
                    }
                }
            }

            /* == More touchpad handling == */

            if (touchpadTouched)
            {
                if (active_touchpad_state == ActiveTouchpadState.None || active_touchpad_state == ActiveTouchpadState.SmallDelay)
                {
                    const float TOUCHPAD_SCROLL_DISTANCE     = 0.22f;
                    const float TOUCHPAD_DRAG_SPACE_DISTANCE = 0.08f;

                    ControllerTracker cs = active_touchpad;
                    if (cs == null)
                    {
                        cs = FindHandler(EEventSet.TouchpadAction2 | EEventSet.TouchpadAction3);
                    }

                    if (cs != null)
                    {
                        if ((cs._event_sets & EEventSet.TouchpadAction2) != 0)
                        {
                            /* detect finger movement */
                            if (Vector2.Distance(touch_original_pos2, touchpadPosition) > TOUCHPAD_SCROLL_DISTANCE)
                            {
                                active_touchpad_timeout = 0;
                                active_touchpad_state   = ActiveTouchpadState.Action2;
                                active_touchpad         = cs;
                                if (active_touchpad == tracker_hover)
                                {
                                    tracker_hover_lock |= 1U << (int)EControllerButton.Touchpad;
                                }
                                scrollWheelVisible |= SWV_SCROLLING;
                                UpdateScrollWheel();
                            }
                        }
                        if (active_touchpad_state == ActiveTouchpadState.SmallDelay && (cs._event_sets & EEventSet.TouchpadAction3) != 0)
                        {
                            /* detect timeout or controller movement from the "small delay" state */
                            if (active_touchpad_timeout <= GetTime() ||
                                Vector3.Distance(touch_original_pos3, position) > TOUCHPAD_DRAG_SPACE_DISTANCE)
                            {
                                Vector3 saved = current_position;
                                active_touchpad_state = ActiveTouchpadState.Action3;
                                active_touchpad       = cs;
                                current_position      = touch_original_pos3;
                                active_touchpad._Call(active_touchpad._i_onTouchDown, this);
                                current_position = saved;
                            }
                        }
                    }
                }
            }
        }