private void SetEngagedUserTrackingId(int newId, EventQueueSection section)
        {
            int oldId = this.EngagedUserTrackingId;
            this.EngagedUserTrackingId = newId;

            if (oldId != newId)
            {
                section.Enqueue(
                    () =>
                        {
                            if (this.EngagedUserChanged != null)
                            {
                                var args = new UserTrackingIdChangedEventArgs(oldId, newId);
                                this.EngagedUserChanged(this, args);
                            }
                        });
            }
        }
 private void SendTrackedUsersChanged(EventQueueSection section)
 {
     section.Enqueue(
         () =>
             {
                 if (this.TrackedUsersChanged != null)
                 {
                     this.TrackedUsersChanged(this, EventArgs.Empty);
                 }
             });
 }
        internal void SetPrimaryUserTrackingId(int newId, EventQueueSection section)
        {
            int oldId = this.PrimaryUserTrackingId;
            this.PrimaryUserTrackingId = newId;

            if (oldId != newId)
            {
                section.Enqueue(
                    () =>
                    {
                        if (this.PrimaryUserChanged != null)
                        {
                            var args = new UserTrackingIdChangedEventArgs(oldId, newId);
                            this.PrimaryUserChanged(this, args);
                        }
                    });

                // If the new primary user is the same as the engaged user, then there is no candidate user.
                // Otherwise, we have a new candidate user as long as the new primary user is a valid user.
                this.SetCandidateUserTrackingId(
                    (this.EngagedUserTrackingId != InvalidUserTrackingId) && (this.EngagedUserTrackingId == newId)
                        ? InvalidUserTrackingId
                        : newId,
                    section);
            }
        }
        /// <summary>
        /// Called whenever the set of tracked hand pointers has changed.
        /// </summary>
        /// <param name="trackedHandPointers">
        /// Hand pointers from which we'll update the set of tracked users and the primary user.
        /// </param>
        public void UpdateHandPointers(IEnumerable<HandPointer> trackedHandPointers)
        {
            bool foundEngagedUser = false;
            bool foundCandidateUser = false;
            int primaryUserTrackingId = InvalidUserTrackingId;

            using (var section = new EventQueueSection())
            {
                this.TrackedUserTrackingIds.Clear();

                foreach (var handPointer in trackedHandPointers)
                {
                    if (handPointer.IsTracked && (handPointer.TrackingId != InvalidUserTrackingId))
                    {
                        // Only consider valid user tracking ids
                        this.TrackedUserTrackingIds.Add(handPointer.TrackingId);

                        if (this.EngagedUserTrackingId == handPointer.TrackingId)
                        {
                            foundEngagedUser = true;
                        }

                        if (this.CandidateUserTrackingId == handPointer.TrackingId)
                        {
                            foundCandidateUser = true;
                        }

                        if (handPointer.IsPrimaryUser)
                        {
                            primaryUserTrackingId = handPointer.TrackingId;
                        }
                    }
                }

                this.SendTrackedUsersChanged(section);

                // If engaged user was not found in list of candidate users, engaged user has become invalid.
                if (!foundEngagedUser)
                {
                    this.SetEngagedUserTrackingId(InvalidUserTrackingId, section);
                }

                // If candidate user was not found in list of candidate users, candidate user has become invalid.
                if (!foundCandidateUser)
                {
                    this.SetCandidateUserTrackingId(InvalidUserTrackingId, section);
                }

                this.SetPrimaryUserTrackingId(primaryUserTrackingId, section);
            }
        }
 /// <summary>
 /// Resets all state to the initial state, with no users remembered as engaged or tracked.
 /// </summary>
 public void Reset()
 {
     using (var section = new EventQueueSection())
     {
         this.activityMeter.Clear();
         this.TrackedUserTrackingIds.Clear();
         this.PrimaryUserTrackingId = InvalidUserTrackingId;
         this.SetCandidateUserTrackingId(InvalidUserTrackingId, section);
         this.SetEngagedUserTrackingId(InvalidUserTrackingId, section);
         this.SendTrackedUsersChanged(section);
     }
 }
        /// <summary>
        /// Promote candidate user to be the engaged user.
        /// </summary>
        /// <param name="candidateTrackingId">
        /// Tracking Id of user to be promoted to engaged user.
        /// If tracking Id does not match the Id of current candidate user,
        /// no action is taken.
        /// </param>
        /// <returns>
        /// True if specified candidate could be confirmed as the new engaged user,
        /// false otherwise.
        /// </returns>
        public bool ConfirmCandidateEngagement(int candidateTrackingId)
        {
            bool isConfirmed = false;

            if ((candidateTrackingId != InvalidUserTrackingId) && (candidateTrackingId == this.CandidateUserTrackingId))
            {
                using (var section = new EventQueueSection())
                {
                    this.SetCandidateUserTrackingId(InvalidUserTrackingId, section);
                    this.SetEngagedUserTrackingId(candidateTrackingId, section);
                }

                isConfirmed = true;
            }

            return isConfirmed;
        }