// Remove a lost UserId
        public virtual int RemoveUser(ulong userId, KinectManager.UserDetectionOrder userDetectionOrder)
        {
            //int uidIndex = alUserIds.IndexOf(userId);
            int uidIndex = System.Array.IndexOf(aUserIndexIds, userId);

            // clear calibration data for this user
            if (playerCalibrationData.ContainsKey(userId))
            {
                playerCalibrationData.Remove(userId);
            }

            // clean up the outdated calibration data in the data dictionary
            List <ulong> alCalDataKeys = new List <ulong>(playerCalibrationData.Keys);

            foreach (ulong calUserID in alCalDataKeys)
            {
                KinectGestureManager.GestureData gestureData = playerCalibrationData[calUserID];

                if ((gestureData.timestamp + 60f) < Time.realtimeSinceStartup)
                {
                    playerCalibrationData.Remove(calUserID);
                }
            }

            alCalDataKeys.Clear();

            // remove user-id from the global users lists
            dictUserIdToIndex.Remove(userId);
            dictUserIdToTime.Remove(userId);
            alUserIds.Remove(userId);

            if (uidIndex >= 0)
            {
                FreeEmptyUserSlot(uidIndex, userDetectionOrder);
            }

            // if this was the primary user, update the primary user-id
            if (liPrimaryUserId == userId)
            {
                if (aUserIndexIds.Length > 0)
                {
                    liPrimaryUserId = aUserIndexIds[0];
                }
                else
                {
                    liPrimaryUserId = 0;
                }
            }

            if (alUserIds.Count == 0)
            {
                //Debug.Log("Waiting for users.");
            }

            return(uidIndex);
        }
        // check if the calibration pose is complete for given user
        protected virtual bool CheckForCalibrationPose(ulong UserId, int bodyIndex, GestureType calibrationGesture,
                                                       KinectGestureManager gestureManager, ref KinectInterop.BodyData[] alTrackedBodies)
        {
            if (calibrationGesture == GestureType.None)
            {
                return(true);
            }
            if (!gestureManager)
            {
                return(false);
            }

            KinectGestureManager.GestureData gestureData = playerCalibrationData.ContainsKey(UserId) ?
                                                           playerCalibrationData[UserId] : new KinectGestureManager.GestureData();

            // init gesture data if needed
            if (gestureData.userId != UserId)
            {
                gestureData.userId    = UserId;
                gestureData.gesture   = calibrationGesture;
                gestureData.state     = 0;
                gestureData.timestamp = Time.realtimeSinceStartup;
                gestureData.joint     = 0;
                gestureData.progress  = 0f;
                gestureData.complete  = false;
                gestureData.cancelled = false;
            }

            // get joint positions and tracking
            int iAllJointsCount = (int)KinectInterop.JointType.Count;

            bool[]    playerJointsTracked = new bool[iAllJointsCount];
            Vector3[] playerJointsPos     = new Vector3[iAllJointsCount];

            int[] aiNeededJointIndexes = gestureManager.GetNeededJointIndexes();
            int   iNeededJointsCount   = aiNeededJointIndexes.Length;

            for (int i = 0; i < iNeededJointsCount; i++)
            {
                int joint = aiNeededJointIndexes[i];

                if (joint >= 0)
                {
                    KinectInterop.JointData jointData = alTrackedBodies[bodyIndex].joint[joint];

                    playerJointsTracked[joint] = jointData.trackingState != KinectInterop.TrackingState.NotTracked;
                    playerJointsPos[joint]     = jointData.kinectPos;

                    if (!playerJointsTracked[joint] && (joint == (int)KinectInterop.JointType.Neck))
                    {
                        KinectInterop.JointData lShoulderData = alTrackedBodies[bodyIndex].joint[(int)KinectInterop.JointType.ShoulderLeft];
                        KinectInterop.JointData rShoulderData = alTrackedBodies[bodyIndex].joint[(int)KinectInterop.JointType.ShoulderRight];

                        if (lShoulderData.trackingState != KinectInterop.TrackingState.NotTracked && rShoulderData.trackingState != KinectInterop.TrackingState.NotTracked)
                        {
                            playerJointsTracked[joint] = true;
                            playerJointsPos[joint]     = (lShoulderData.kinectPos + rShoulderData.kinectPos) / 2f;
                        }
                    }
                }
            }

            // estimate the gesture progess
            gestureManager.CheckForGesture(UserId, ref gestureData, Time.realtimeSinceStartup,
                                           ref playerJointsPos, ref playerJointsTracked);
            playerCalibrationData[UserId] = gestureData;

            // check if gesture is complete
            if (gestureData.complete)
            {
                gestureData.userId            = 0;
                playerCalibrationData[UserId] = gestureData;

                return(true);
            }

            return(false);
        }