private void TransformArmData(ref LeapArmData arm)
    {
        LeapForearmData forearm = arm.forearm;
        LeapHandData    hand    = arm.hand;

        LeapFingerData[] fingers = hand.fingers;

        // Fingers
        for (int i = 0; i < fingers.Length; ++i)
        {
            LeapFingerData finger = fingers[i];
            finger.TipPosition           = TransformVector(finger.TipPosition);
            finger.StabilizedTipPosition = TransformVector(finger.StabilizedTipPosition);
            finger.FingerDirection       = TransformVector(finger.FingerDirection);
            finger.TipVelocity           = TransformVector(finger.TipVelocity);
        }

        // Hand
        hand.PalmPosition           = TransformVector(hand.PalmPosition);
        hand.StabilizedPalmPosition = TransformVector(hand.StabilizedPalmPosition);
        hand.PalmNormal             = TransformVector(hand.PalmNormal);
        hand.PalmVelocity           = TransformVector(hand.PalmVelocity);
        hand.PalmToFingersDirection = TransformVector(hand.PalmToFingersDirection);

        // Forearm
        forearm.WristPosition    = TransformVector(forearm.WristPosition);
        forearm.ForearmDirection = TransformVector(forearm.ForearmDirection);
        forearm.ElbowPosition    = TransformVector(forearm.ElbowPosition);
    }
    LeapFrameTransformer(
        [Inject(Id = "Frame stream")]                Subject <LeapFrameData> frameStream,
        [Inject(Id = "Transformed frame stream")]   Subject <LeapFrameData> transformedFrameStream,
        [Inject(Id = "Leap to locatable camera")]   Subject <Matrix4x4> leapToLocatableCamera)
    {
        _transformedFrameStream = transformedFrameStream;

        leapToLocatableCamera.Subscribe(trans =>
        {
            _leapToLocatableCamera = trans;
        });

        frameStream.ObserveOn(Scheduler.MainThread).SubscribeOn(Scheduler.MainThread).Subscribe(frame =>
        {
            if (frame != null)
            {
                LeapArmData leftArm  = frame.left_arm;
                LeapArmData rightArm = frame.right_arm;

                // Left arm
                if (leftArm != null)
                {
                    TransformArmData(ref leftArm);
                }

                // Right arm
                if (rightArm != null)
                {
                    TransformArmData(ref rightArm);
                }

                _transformedFrameStream.OnNext(frame);
            }
        });
    }
    private void UpdateArm(LeapArmData data, Side side)
    {
        // Check if the arm's visibility has changed
        bool isVisible = data != null;

        if (isVisible != _isVisible[(int)side])
        {
            SwitchHandVisibility(side);
        }
        _isVisible[(int)side] = isVisible;

        // If the arm is visible then update the position of the visualizations
        if (isVisible)
        {
            SetFingerPosition(side, FingerType.THUMB, data.hand.Thumb.TipPosition);
            SetFingerPosition(side, FingerType.INDEX, data.hand.IndexFinger.TipPosition);
            SetFingerPosition(side, FingerType.MIDDLE, data.hand.MiddleFinger.TipPosition);
            SetFingerPosition(side, FingerType.RING, data.hand.RingFinger.TipPosition);
            SetFingerPosition(side, FingerType.PINKY, data.hand.Pinky.TipPosition);
        }
    }