//public Frame(long id, long timestamp, List<Hand> hands, List<Pointable> pointables, List<Finger> fingers, List<Tool> tools)
        //{
        //    Id = id;
        //    Timestamp = timestamp;
        //    Hands = hands;
        //    Pointables = pointables;
        //    Fingers = fingers;
        //    Tools = tools;
        //    foreach (Hand h in Hands)
        //        if (h.IsLeft)
        //            LeftHand = h;
        //        else if (h.IsRight)
        //            RightHand = h;
        //        else
        //            throw new Exception("Unknow hand");
        //}

        public Frame(Leap.Frame frame)
        {
            this.Id         = frame.Id;
            this.Timestamp  = frame.Timestamp;
            this.Hands      = new List <Hand>();
            this.Pointables = new List <Pointable>();
            this.Fingers    = new List <Finger>();
            this.Tools      = new List <Tool>();
            foreach (Leap.Hand lh in frame.Hands)
            {
                Hand h = new Hand(lh, this);
                this.Hands.Add(h);
                this.Pointables.AddRange(h.Pointables);
                this.Fingers.AddRange(h.Fingers);
                this.Tools.AddRange(h.Tools);
                if (h.IsLeft)
                {
                    LeftHand = h;
                }
                else if (h.IsRight)
                {
                    RightHand = h;
                }
                else
                {
                    throw new Exception("Unknow hand");
                }
            }

            this.Gestures = new List <Gesture>();
            foreach (Leap.Gesture g in frame.Gestures())
            {
                Gestures.Add(new Gesture(g, this, Hands, Pointables));
            }
        }
    // Update is called once per frame
    void Update()
    {
        mFrame = leapController.Frame ();
        int fingerCount = 0;
        if(numbersGestureRegistered || closeFistRegistered || openFistRegistered ||
                keytapGestureRegistered || twoFingerKeytapRegistered || threeFingerKeytapRegistered ||
                screentapGestureRegistered || twoFingerScreentapRegistered || threeFingerScreentapRegistered || steeringWheelRegistered)
            fingerCount = GetFingerCount();

        foreach(Leap.Gesture gesture in mFrame.Gestures ()) {
            switch(gesture.Type) {
                case Leap.Gesture.GestureType.TYPECIRCLE:
                    if(circleGestureRegistered) BuiltInGestureRecognised(gesture,EasyLeapGestureType.TYPECIRCLE);
                    break;
                case Leap.Gesture.GestureType.TYPESWIPE:
                    if(swipeGestureRegistered) BuiltInGestureRecognised(gesture,EasyLeapGestureType.TYPESWIPE);
                    break;
                case Leap.Gesture.GestureType.TYPEKEYTAP:
                    if(keytapGestureRegistered && fingerCount == 1) BuiltInGestureRecognised(gesture,EasyLeapGestureType.TYPEKEYTAP);
                    if(twoFingerKeytapRegistered && fingerCount == 2) BuiltInImprovedGestureRecognised(gesture,EasyLeapGestureType.TWO_FINGERS_KEYTAP);
                    if(threeFingerKeytapRegistered && fingerCount == 3) BuiltInImprovedGestureRecognised(gesture,EasyLeapGestureType.THREE_FINGERS_KEYTAP);
                    break;
                case Leap.Gesture.GestureType.TYPESCREENTAP:
                    if(screentapGestureRegistered && fingerCount == 1) BuiltInGestureRecognised(gesture,EasyLeapGestureType.TYPESCREENTAP);
                    if(twoFingerScreentapRegistered && fingerCount == 2) BuiltInImprovedGestureRecognised(gesture,EasyLeapGestureType.TWO_FINGERS_SCREENTAP);
                    if(threeFingerScreentapRegistered && fingerCount == 3) BuiltInImprovedGestureRecognised(gesture,EasyLeapGestureType.THREE_FINGERS_SCREENTAP);
                    break;
            }

        }
        if(mFrame.Gestures ().Count == 0) ClearDraggingGestures();

        if(numbersGestureRegistered || closeFistRegistered || openFistRegistered) {
            switch(fingerCount) {
                case 0:
                    // NO FINGERS
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.DEFAULT);
                    if(closeFistRegistered) {
                        if(mFrame.Hands.Count == 1) {
                            if(PalmIsHorizontal(mFrame.Hands[0])) CloseFistGestureRecognised(EasyLeapGestureState.STATESTOP);
                        }
                        else CloseFistGestureRecognised(EasyLeapGestureState.STATEINVALID);
                    }
                    if(openFistRegistered) {
                        if(mFrame.Hands.Count == 1) {
                            if(PalmIsHorizontal(mFrame.Hands[0])) OpenFistGestureRecognised(EasyLeapGestureState.STATESTART);
                        }
                        else OpenFistGestureRecognised(EasyLeapGestureState.STATEINVALID);
                    }
                    break;
                case 1:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.ONE);
                    break;
                case 2:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.TWO);
                    break;
                case 3:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.THREE);
                    break;
                case 4:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.FOUR);
                    break;
                case 5:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.FIVE);
                    if(closeFistRegistered && mFrame.Hands.Count == 1) CloseFistGestureRecognised(EasyLeapGestureState.STATESTART);
                    if(openFistRegistered) OpenFistGestureRecognised(EasyLeapGestureState.STATESTOP);
                    break;
                case 6:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.SIX);
                    break;
                case 7:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.SEVEN);
                    break;
                case 8:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.EIGHT);
                    break;
                case 9:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.NINE);
                    break;
                case 10:
                    if(numbersGestureRegistered) NumbersGestureRecognised(EasyLeapGestureType.TEN);
                    break;
            }
        }

        if(pushGestureRegistered || pullGestureRegistered) {
            if(mFrame.Hands.Count == 1) {
                if(pushGestureRegistered) {
                    if(mFrame.Hands[0].PalmVelocity.y < -EasyLeapGesture.MinPushPullVelocity) PushGestureRecognised(EasyLeapGestureState.STATESTART);
                    else PushGestureRecognised(EasyLeapGestureState.STATEINVALID);
                }
                if(pullGestureRegistered) {
                    if(mFrame.Hands[0].PalmVelocity.y > EasyLeapGesture.MinPushPullVelocity) PullGestureRecognised(EasyLeapGestureState.STATESTART);
                    else PullGestureRecognised(EasyLeapGestureState.STATEINVALID);
                }
            } else {
                PushGestureRecognised(EasyLeapGestureState.STATEINVALID);
                PullGestureRecognised(EasyLeapGestureState.STATEINVALID);
            }
        }

        if(doubleInwardsSwipeGestureRegistered || doubleOutwardsSwipeGestureRegistered) {
            if(mFrame.Hands.Count == 2) {
                bool leftHandSwipeIn = (PalmIsHorizontal(mFrame.Hands.Leftmost)) && mFrame.Hands.Leftmost.PalmVelocity.x > EasyLeapGesture.MinSwipeVelocity;
                bool rightHandSwipeIn = (PalmIsHorizontal(mFrame.Hands.Rightmost)) && mFrame.Hands.Rightmost.PalmVelocity.x < -EasyLeapGesture.MinSwipeVelocity;
                if(doubleInwardsSwipeGestureRegistered && (leftHandSwipeIn && rightHandSwipeIn)) {
                    if(mFrame.Hands[0].StabilizedPalmPosition.DistanceTo(mFrame.Hands[1].StabilizedPalmPosition) < EasyLeapGesture.MaxPalmDistance) DoubleInwardsSwipeRecognised(EasyLeapGestureState.STATESTART);
                } else DoubleInwardsSwipeRecognised(EasyLeapGestureState.STATEINVALID);
                bool leftHandSwipeOut = (PalmIsHorizontal(mFrame.Hands.Leftmost)) && mFrame.Hands.Leftmost.PalmVelocity.x < -EasyLeapGesture.MinSwipeVelocity;
                bool rightHandSwipeOut = (PalmIsHorizontal(mFrame.Hands.Rightmost)) && mFrame.Hands.Rightmost.PalmVelocity.x > EasyLeapGesture.MinSwipeVelocity;
                if(doubleOutwardsSwipeGestureRegistered && leftHandSwipeOut && rightHandSwipeOut) {
                    if(mFrame.Hands[0].StabilizedPalmPosition.DistanceTo(mFrame.Hands[1].StabilizedPalmPosition) > EasyLeapGesture.MaxPalmDistance) DoubleOutwardsSwipeRecognised(EasyLeapGestureState.STATESTART);
                } else DoubleOutwardsSwipeRecognised(EasyLeapGestureState.STATEINVALID);
            }
        }

        if(clapGestureRegistered) {
            if(mFrame.Hands.Count == 2) {
                bool leftHandSwipeIn = (!PalmIsHorizontal(mFrame.Hands.Leftmost)) && mFrame.Hands.Leftmost.PalmVelocity.x > EasyLeapGesture.MinClapVelocity;
                bool rightHandSwipeIn = (!PalmIsHorizontal(mFrame.Hands.Rightmost)) && mFrame.Hands.Rightmost.PalmVelocity.x < -EasyLeapGesture.MinClapVelocity;
                if(leftHandSwipeIn && rightHandSwipeIn) {
                    if(mFrame.Hands[0].StabilizedPalmPosition.DistanceTo(mFrame.Hands[1].StabilizedPalmPosition) < EasyLeapGesture.MaxPalmClapDistance) ClapRecognised(EasyLeapGestureState.STATESTART);
                } else ClapRecognised(EasyLeapGestureState.STATEINVALID);
            }
        }

        if(steeringWheelRegistered) {
            float palmsAngle = (mFrame.Hands.Leftmost.PalmNormal.AngleTo(mFrame.Hands.Rightmost.PalmNormal)*Mathf.Rad2Deg);
            if(mFrame.Hands.Count >= 1 && fingerCount < 2 && (palmsAngle > 110 || palmsAngle < 70)) {
                Leap.Vector leftMost = mFrame.Hands.Leftmost.StabilizedPalmPosition;
                Leap.Vector rightMost = mFrame.Hands.Rightmost.StabilizedPalmPosition;
                Leap.Vector steerVector = (leftMost - rightMost).Normalized;
                //steerVector.z = 0;
                float angle = steerVector.AngleTo(Leap.Vector.Left)*Mathf.Rad2Deg * (leftMost.y > rightMost.y ? 1 : -1);
                SteeringWheelRecognised(angle, Mathf.Abs (leftMost.z) - Mathf.Abs (rightMost.z));
            }
        }

        // Send gestures detected to all registered gesture listeners
        SendGesturesToListeners();
    }
        public override void OnFrame(Leap.Controller controller)
        {
            Leap.Frame frame = controller.Frame();

            Leap.InteractionBox interactionBox = frame.InteractionBox;
            _pointerPosition =
                interactionBox.NormalizePoint(frame.Pointables.Frontmost.TipPosition);

            _standardGestures = frame.Gestures();

            foreach (Leap.Gesture gesture in _standardGestures)
            {
                if (gesture.State.Equals(Leap.Gesture.GestureState.STATESTOP))
                {
                    if (gesture.Type.Equals(Leap.Gesture.GestureType.TYPESWIPE))
                    {
                        Print("Finger Swipe Detected");
                        Leap.SwipeGesture       swipe      = new Leap.SwipeGesture(gesture);
                        Events.FingerSwipeEvent swipeEvent = new Events.FingerSwipeEvent(swipe);
                        OnFingerSwipeDetected(swipeEvent);
                    }

                    if (gesture.Type.Equals(Leap.Gesture.GestureType.TYPE_CIRCLE))
                    {
                        Print("Circle Gesture Detected");
                        Leap.CircleGesture circle      = new Leap.CircleGesture(gesture);
                        Events.CircleEvent circleEvent = new Events.CircleEvent(circle);
                        OnCircleDetected(circleEvent);
                    }

                    if (gesture.Type.Equals(Leap.Gesture.GestureType.TYPE_SCREEN_TAP))
                    {
                        Print("Screen Tap Detected");
                        Leap.ScreenTapGesture screenTap      = new Leap.ScreenTapGesture(gesture);
                        Events.ScreenTapEvent screenTapEvent = new Events.ScreenTapEvent(screenTap);
                        OnScreenTapDetected(screenTapEvent);
                    }
                }
            }

            Gestures.HandSwipe handSwipe = Gestures.HandSwipe.IsHandSwipe(frame);
            if (handSwipe != null)
            {
                if (handSwipe.State.Equals(Gestures.GestureState.END))
                {
                    Print("Hand Swipe Detected");

                    Events.HandSwipeEvent swipeEvent = new Events.HandSwipeEvent(handSwipe);
                    OnHandSwipeDetected(swipeEvent);
                }
            }

            Gestures.ZoomIn zoomIn = Gestures.ZoomIn.IsZoomIn(frame);
            if (zoomIn != null)
            {
                if (zoomIn.State.Equals(Gestures.GestureState.END))
                {
                    Print("ZoomIn Detected");

                    Events.ZoomInEvent zoomInEvent = new Events.ZoomInEvent(zoomIn);
                    OnZoomInDetected(zoomInEvent);
                }
            }

            Gestures.ZoomOut zoomOut = Gestures.ZoomOut.IsZoomOut(frame);
            if (zoomOut != null)
            {
                if (zoomOut.State.Equals(Gestures.GestureState.END))
                {
                    Print("ZoomOut Detected");

                    Events.ZoomOutEvent zoomOutEvent = new Events.ZoomOutEvent(zoomOut);
                    OnZoomOutDetected(zoomOutEvent);
                }
            }
        }