Example #1
0
    /// Once you have that information, it's simply a matter of placing a
    /// window off to the side of the hand! The palm pose Right direction
    /// points to different sides of each hand, so a different X offset
    /// is required for each hand.
    public static void DrawHandMenu(Handed handed)
    {
        if (!HandFacingHead(handed))
        {
            return;
        }

        // Decide the size and offset of the menu
        Vec2  size   = new Vec2(4, 16);
        float offset = handed == Handed.Left ? -2 - size.x : 2 + size.x;

        // Position the menu relative to the side of the hand
        Hand hand   = Input.Hand(handed);
        Vec3 at     = hand[FingerId.Little, JointId.KnuckleMajor].position;
        Vec3 down   = hand[FingerId.Little, JointId.Root].position;
        Vec3 across = hand[FingerId.Index, JointId.KnuckleMajor].position;

        Pose menuPose = new Pose(
            at,
            Quat.LookAt(at, across, at - down) * Quat.FromAngles(0, handed == Handed.Left ? 90 : -90, 0));

        menuPose.position += menuPose.Right * offset * U.cm;
        menuPose.position += menuPose.Up * (size.y / 2) * U.cm;

        // And make a menu!
        UI.WindowBegin("HandMenu", ref menuPose, size * U.cm, UIWin.Empty);
        UI.Button("Test");
        UI.Button("That");
        UI.Button("Hand");
        UI.WindowEnd();
    }
Example #2
0
        public void Step(Handed handed, Color color, float thickness)
        {
            // We'll make the whole painting the child of an affordance, so we can
            // move the painting around while we work with it! Affordances and
            // Windows both push a transform onto the Hierarchy stack, so all
            // subsequent locations are then relative to that transform.
            UI.AffordanceBegin("PaintingRoot", ref _pose, new Bounds(Vec3.One * 5 * Units.cm2m), true);

            UpdateInput(handed, color, thickness);
            Draw();

            UI.AffordanceEnd();
        }
Example #3
0
        /// :CodeDoc: Guides Using Hands
        /// ## Hand Menu
        ///
        /// Lets imagine you want to make a hand menu, you might need to know
        /// if the user is looking at the palm of their hand! Here's a quick
        /// example of using the palm's pose and the dot product to determine
        /// this.
        static bool HandFacingHead(Handed handed)
        {
            Hand hand = Input.Hand(handed);

            if (!hand.IsTracked)
            {
                return(false);
            }

            Vec3 palmDirection   = (hand.palm.Forward).Normalized();
            Vec3 directionToHead = (Input.Head.position - hand.palm.position).Normalized();

            return(Vec3.Dot(palmDirection, directionToHead) > 0.5f);
        }
Example #4
0
        void Draw(Handed handed)
        {
            Hand hand = Input.Hand(handed);
            Vec3 tip  = Vec3.Lerp(prevTip, hand.pinchPt, 0.3f);

            if (hand.IsJustPinched && !UI.IsInteracting(handed))
            {
                if (drawPoints.Count > 0)
                {
                    drawList.Add(drawPoints.ToArray());
                }
                drawPoints.Clear();
                drawPoints.Add(new LinePoint(tip, activeColor, lineSize));
                drawPoints.Add(new LinePoint(tip, activeColor, lineSize));
                prevTip  = tip;
                painting = true;
            }
            if (hand.IsJustUnpinched)
            {
                painting = false;
            }

            if (painting && drawPoints.Count > 1)
            {
                Vec3      prev  = drawPoints[drawPoints.Count - 2].pt;
                Vec3      dir   = (prev - (drawPoints.Count > 2 ? drawPoints[drawPoints.Count - 3].pt : drawPoints[drawPoints.Count - 1].pt)).Normalized;
                float     dist  = Vec3.Distance(prev, tip);
                float     speed = Vec3.Distance(tip, prevTip) * Time.Elapsedf;
                LinePoint here  = new LinePoint(tip, activeColor, Math.Max(1 - speed / 0.0003f, 0.1f) * lineSize);

                if ((Vec3.Dot(dir, (tip - prev).Normalized) < 0.99f && dist > 0.01f) || dist > 0.05f)
                {
                    drawPoints.Add(here);
                }
                else
                {
                    drawPoints[drawPoints.Count - 1] = here;
                }
            }

            Lines.Add(drawPoints.ToArray());
            for (int i = 0; i < drawList.Count; i++)
            {
                Lines.Add(drawList[i]);
            }
            prevTip = tip;
        }
Example #5
0
        void Draw(Handed handed)
        {
            Hand hand = Input.Hand(handed);
            Vec3 tip  = hand[FingerId.Index, JointId.Tip].position;

            tip = prevTip + (tip - prevTip) * 0.3f;
            const float minDist = 2 * Units.cm2m;

            if (hand.IsJustPinched && !UI.IsInteracting(handed))
            {
                if (drawPoints.Count > 0)
                {
                    drawList.Add(drawPoints.ToArray());
                }
                drawPoints.Clear();
                drawPoints.Add(new LinePoint(tip, activeColor, lineSize));
                drawPoints.Add(new LinePoint(tip, activeColor, lineSize));
                prevTip  = tip;
                painting = true;
            }
            if (hand.IsJustUnpinched)
            {
                painting = false;
            }

            if (painting && drawPoints.Count > 1)
            {
                Vec3      prev  = drawPoints[drawPoints.Count - 2].pt;
                Vec3      dir   = (prev - (drawPoints.Count > 2 ? drawPoints[drawPoints.Count - 3].pt : drawPoints[drawPoints.Count - 1].pt)).Normalized();
                float     dist  = (prev - tip).Magnitude;
                float     speed = (tip - prevTip).Magnitude * Time.Elapsedf;
                LinePoint here  = new LinePoint(tip, activeColor, Math.Max(1 - speed / 0.0003f, 0.1f) * lineSize);
                drawPoints[drawPoints.Count - 1] = here;

                if ((Vec3.Dot(dir, (tip - prev).Normalized()) < 0.99f && dist > 0.01f) || dist > 0.05f)
                {
                    drawPoints.Add(here);
                }
            }

            Lines.Add(drawPoints.ToArray());
            for (int i = 0; i < drawList.Count; i++)
            {
                Lines.Add(drawList[i]);
            }
            prevTip = tip;
        }
Example #6
0
    //set new weapon, used to change the hand positions
    public void SetWeapon(Weapon weapon)
    {
        if (weapon == null)
        {
            return;
        }

        handed = weapon.handed;

        renderGun.sprite = weapon.sprite;

        originLHand = new Vector3(weapon.LHandOffset.x, weapon.LHandOffset.y, -0.0001f);
        renderLHand.transform.localPosition = originLHand;
        originGun    = weapon.spriteOffset;
        originBarrel = weapon.barrelOffset;

        ChangeHandPosition();
    }
    void UpdateInput(Handed handed, Color color, float thickness)
    {
        // Get the hand's fingertip, convert it to local space, and smooth
        // it out to reduce any jagged noise! The hand's location data is
        // always provided in world space, but since we're inside of an
        // Affordance which uses the Hierarchy stack, we need to convert the
        // fingertip's coordinates into Heirarchy local coordinates before we
        // can work with it.
        Hand hand      = Input.Hand(handed);
        Vec3 fingertip = hand[FingerId.Index, JointId.Tip].position;

        fingertip = Hierarchy.ToLocal(fingertip);
        fingertip = Vec3.Lerp(_prevFingertip, fingertip, 0.3f);

        // If the user just made a pinching motion, and is not interacting
        // with the UI, we'll begin a paint stroke!
        if (hand.IsJustPinched && !UI.IsInteracting(handed))
        {
            BeginStroke(fingertip, color, thickness);
            _isDrawing = true;
        }
        // If we're drawing a paint stroke, then lets update it with the
        // current steps information!
        if (_isDrawing)
        {
            UpdateStroke(fingertip, color, thickness);
        }
        // And when they cease the pinching motion, we'll end whatever stroke
        // we started.
        if (_isDrawing && hand.IsJustUnpinched)
        {
            EndStroke();
            _isDrawing = false;
        }

        _prevFingertip = fingertip;
    }
Example #8
0
        /// Once you have that information, it's simply a matter of placing a
        /// window off to the side of the hand! The palm pose Right direction
        /// points to different sides of each hand, so a different X offset
        /// is required for each hand.
        public static void DrawHandMenu(Handed handed)
        {
            if (!HandFacingHead(handed))
            {
                return;
            }

            // Decide the size and offset of the menu
            Vec2  size   = new Vec2(4, 16);
            float offset = handed == Handed.Left ? -4 - size.x : 6 + size.x;

            // Position the menu relative to the palm
            Pose menuPose = Input.Hand(handed).palm;

            menuPose.position += menuPose.Right * offset * U.cm;
            menuPose.position += menuPose.Up * (size.y / 2) * U.cm;

            // And make a menu!
            UI.WindowBegin("HandMenu", ref menuPose, size * U.cm, UIWin.Empty);
            UI.Button("Test");
            UI.Button("That");
            UI.Button("Hand");
            UI.WindowEnd();
        }
Example #9
0
 [DllImport(NativeLib.DllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr  input_hand(Handed hand);
Example #10
0
 /// <summary>Set the Material used to render the hand! The default
 /// material uses an offset of 10 to ensure it gets drawn overtop of
 /// other elements.</summary>
 /// <param name="hand">>If Handed.Max, this will set the value for
 /// both hands.</param>
 /// <param name="material">The new Material!</param>
 public static void HandMaterial(Handed hand, Material material)
 => NativeAPI.input_hand_material(hand, material._inst);
Example #11
0
 /// <summary>Does StereoKit register the hand with the physics
 /// system? By default, this is true. Right now this is just a single
 /// block collider, but later will involve per-joint colliders!
 /// </summary>
 /// <param name="hand">If Handed.Max, this will set the value for
 /// both hands.</param>
 /// <param name="solid">True? Physics! False? No physics.</param>
 public static void HandSolid(Handed hand, bool solid)
 => NativeAPI.input_hand_solid(hand, solid);
Example #12
0
 /// <summary>Sets whether or not StereoKit should render the hand for
 /// you. Turn this to false if you're going to render your own, or
 /// don't need the hand itself to be visible.</summary>
 /// <param name="hand">If Handed.Max, this will set the value for
 /// both hands.</param>
 /// <param name="visible">True, StereoKit renders this. False, it
 /// doesn't.</param>
 public static void HandVisible(Handed hand, bool visible)
 => NativeAPI.input_hand_visible(hand, visible);
Example #13
0
 /// <summary>Clear out the override status from Input.HandOverride,
 /// and restore the user's control over it again.</summary>
 /// <param name="hand">Which hand are we clearing the override on?
 /// </param>
 public static void HandClearOverride(Handed hand)
 => NativeAPI.input_hand_override(hand, IntPtr.Zero);
Example #14
0
 /// <summary>This allows you to completely override the hand's pose
 /// information! It is still treated like the user's hand, so this is
 /// great for simulating input for testing purposes. It will remain
 /// overridden until you call Input.HandClearOverride.</summary>
 /// <param name="hand">Which hand should be overridden?</param>
 /// <param name="joints">A 2D array of 25 joints that should be used
 /// as StereoKit's hand information. See `Hand.fingers` for more
 /// information.</param>
 public static void HandOverride(Handed hand, in HandJoint[] joints)
Example #15
0
 /// <summary>Retreives all the information about the user's hand!
 /// StereoKit will always provide hand information, however sometimes
 /// that information is simulated, like in the case of a mouse, or
 /// controllers.
 ///
 /// Note that this is a copy of the hand information, and it's a good
 /// chunk of data, so it's a good idea to grab it once and keep it
 /// around for the frame, or at least function, rather than asking
 /// for it again and again each time you want to touch something.
 /// </summary>
 /// <param name="handed">Do you want the left or the right hand?
 /// </param>
 /// <returns>A copy of the entire set of hand data!</returns>
 public static Hand Hand(Handed handed)
 => Marshal.PtrToStructure <Hand>(NativeAPI.input_hand(handed));
Example #16
0
 /// <summary>Retreives all the information about the user's hand!
 /// StereoKit will always provide hand information, however sometimes
 /// that information is simulated, like in the case of a mouse, or
 /// controllers.
 ///
 /// Note that this is a copy of the hand information, and it's a good
 /// chunk of data, so it's a good idea to grab it once and keep it
 /// around for the frame, or at least function, rather than asking
 /// for it again and again each time you want to touch something.
 /// </summary>
 /// <param name="handed">Do you want the left or the right hand?
 /// </param>
 /// <returns>A copy of the entire set of hand data!</returns>
 public static Hand Hand(Handed handed)
 {
     Marshal.PtrToStructure(NativeAPI.input_hand(handed), hands[(int)handed]);
     return(hands[(int)handed]);
 }
Example #17
0
 /// <summary>Gets raw controller input data from the system. Note that
 /// not all buttons provided here are guaranteed to be present on the
 /// user's physical controller. Controllers are also not guaranteed to
 /// be available on the system, and are never simulated.</summary>
 /// <param name="handed">The handedness of the controller to get the
 /// state of.</param>
 /// <returns>A reference to a class that contains state information
 /// about the indicated controller.</returns>
 public static Controller Controller(Handed handed)
 {
     Marshal.PtrToStructure(NativeAPI.input_controller(handed), controllers[(int)handed]);
     return(controllers[(int)handed]);
 }
Example #18
0
 [DllImport(NativeLib.DllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern void    input_hand_solid(Handed hand, int solid);
Example #19
0
 /// <summary>Tells if the user is currently interacting with a UI element! This will be true
 /// if the hand has an active or focused UI element.</summary>
 /// <param name="hand">Which hand is interacting?</param>
 /// <returns>True if the hand has an active or focused UI element. False otherwise.</returns>
 public static bool IsInteracting(Handed hand)
 => NativeAPI.ui_is_interacting(hand);
Example #20
0
        /// :CodeSample: Controller Input.Controller TrackState Input.ControllerMenuButton Controller.IsTracked Controller.trackedPos Controller.trackedRot Controller.IsX1Pressed Controller.IsX2Pressed Controller.IsStickClicked Controller.stick Controller.aim Controller.grip Controller.trigger Controller.pose
        /// ### Controller Debug Visualizer
        /// This function shows a debug visualization of the current state of
        /// the controller! It's not something you'd show to users, but it's
        /// nice for just seeing how the API works, or as a temporary
        /// visualization.
        void ShowController(Handed hand)
        {
            Controller c = Input.Controller(hand);

            if (!c.IsTracked)
            {
                return;
            }

            Hierarchy.Push(c.pose.ToMatrix());
            // Pick the controller color based on trackin info state
            Color color = Color.Black;

            if (c.trackedPos == TrackState.Inferred)
            {
                color.g = 0.5f;
            }
            if (c.trackedPos == TrackState.Known)
            {
                color.g = 1;
            }
            if (c.trackedRot == TrackState.Inferred)
            {
                color.b = 0.5f;
            }
            if (c.trackedRot == TrackState.Known)
            {
                color.b = 1;
            }
            Default.MeshCube.Draw(Default.Material, Matrix.S(new Vec3(3, 3, 8) * U.cm), color);

            // Show button info on the back of the controller
            Hierarchy.Push(Matrix.TR(0, 1.6f * U.cm, 0, Quat.LookAt(Vec3.Zero, new Vec3(0, 1, 0), new Vec3(0, 0, -1))));

            // Show the tracking states as text
            Text.Add(c.trackedPos == TrackState.Known?"(pos)":(c.trackedPos == TrackState.Inferred?"~pos~":"pos"), Matrix.TS(0, -0.03f, 0, 0.25f));
            Text.Add(c.trackedRot == TrackState.Known?"(rot)":(c.trackedRot == TrackState.Inferred?"~rot~":"rot"), Matrix.TS(0, -0.02f, 0, 0.25f));

            // Show the controller's buttons
            Text.Add(Input.ControllerMenuButton.IsActive()?"(menu)":"menu", Matrix.TS(0, -0.01f, 0, 0.25f));
            Text.Add(c.IsX1Pressed?"(X1)":"X1", Matrix.TS(0, 0.00f, 0, 0.25f));
            Text.Add(c.IsX2Pressed?"(X2)":"X2", Matrix.TS(0, 0.01f, 0, 0.25f));

            // Show the analog stick's information
            Vec3 stickAt = new Vec3(0, 0.03f, 0);

            Lines.Add(stickAt, stickAt + c.stick.XY0 * 0.01f, Color.White, 0.001f);
            if (c.IsStickClicked)
            {
                Text.Add("O", Matrix.TS(stickAt, 0.25f));
            }

            // And show the trigger and grip buttons
            Default.MeshCube.Draw(Default.Material, Matrix.TS(0, -0.015f, -0.005f, new Vec3(0.01f, 0.04f, 0.01f)) * Matrix.TR(new Vec3(0, 0.02f, 0.03f), Quat.FromAngles(-45 + c.trigger * 40, 0, 0)));
            Default.MeshCube.Draw(Default.Material, Matrix.TS(0.0149f * (hand == Handed.Right?1:-1), 0, 0.015f, new Vec3(0.01f * (1 - c.grip), 0.04f, 0.01f)));

            Hierarchy.Pop();
            Hierarchy.Pop();

            // And show the pointer
            Default.MeshCube.Draw(Default.Material, c.aim.ToMatrix(new Vec3(1, 1, 4) * U.cm), Color.HSV(0, 0.5f, 0.8f).ToLinear());
        }
Example #21
0
 [DllImport(NativeLib.DllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern void    input_hand_material(Handed hand, IntPtr material);
Example #22
0
 /// <summary>This watches a volume of space for pinch interaction
 /// events! If a hand is inside the space indicated by the bounds,
 /// this function will return that hand's pinch state, as well as
 /// indicate which hand did it through the out parameter.
 ///
 /// Note that since this only provides the hand's pinch state, it
 /// won't give you JustActive and JustInactive notifications for
 /// when the hand enters or leaves the volume.</summary>
 /// <param name="bounds">A UI hierarchy space bounding volume.</param>
 /// <param name="hand">This will be the last hand that provides a
 /// pinch state within this volume. That means that if both hands are
 /// pinching in this volume, it will provide the Right hand.</param>
 /// <returns>This will be the pinch state of the last hand that
 /// provides a pinch state within this volume. That means that if
 /// both hands are pinching in this volume, it will provide the pinch
 /// state of the Right hand.</returns>
 public static BtnState InteractVolume(Bounds bounds, out Handed hand)
 => NativeAPI.ui_interact_volume_at(bounds, out hand);