/// <summary>
        /// Performs this animation in a completely event-driven way.
        /// </summary>
        public EventDrivenPassInfo CalculateEventDriven()
        {
            this.PreCheckExecutionInternal();
            try
            {
                int countSteps = 0;

                PrecalculateAnimations();

                // Create shared UpdateState object
                UpdateState updateState = new UpdateState(TimeSpan.Zero);

                // Perform whole animation in an event-driven way
                List <EventDrivenStepInfo> steps = new List <EventDrivenStepInfo>(12);
                while (this.CountRunningAnimations > 0)
                {
                    // Store some values for measurement
                    int countAnimationsBegin = this.CountRunningAnimations;

                    // Perform animation calculation
                    TimeSpan timeTillNext = this.TimeTillCurrentAnimationStepFinished;
                    updateState.Reset(timeTillNext);
                    AnimationUpdateResult updateResult = this.Update(updateState);
                    countSteps++;

                    // Generate resport data
                    steps.Add(new EventDrivenStepInfo()
                    {
                        AnimationCount = updateResult.CountFinishedAnimations,
                        UpdateTime     = timeTillNext
                    });
                }

                return(new EventDrivenPassInfo(steps));
            }
            finally
            {
                this.PostCheckExecutionInternal();
            }
        }
        /// <summary>
        /// Called for each update step of this animation.
        /// </summary>
        /// <param name="updateState">The current state of the update pass.</param>
        /// <param name="animationState">The current state of the animation.</param>
        public AnimationUpdateResult Update(IAnimationUpdateState updateState, AnimationState animationState)
        {
            int  countAnimationsFinished = 0;
            bool prevIgnorePauseState    = updateState.IgnorePauseState;

            PreCheckExecutionInternal();
            try
            {
                // Execute all pre-update actions
                if (m_preUpdateActionsCount > 0)
                {
                    PerformPreupdateActionsInternal();
                }

                // Cancel here if there are no animations at all
                if ((m_runningAnimationsCount == 0) &&
                    (m_runningSecondaryAnimationsCount == 0))
                {
                    m_timeTillNextPartFinished = Constants.UPDATE_STATE_MAX_TIME;
                    return(AnimationUpdateResult.Empty);
                }

                // Check collection counters for plausibility
                if ((m_runningAnimationsCount < 0) ||
                    (m_runningSecondaryAnimationsCount < 0) ||
                    (m_preUpdateActionsCount < 0))
                {
                    throw new SeeingSharpGraphicsException("Internal error: Invalid animation count errors in Animation handler!");
                }

                bool anySubAnimationFinishedOrCanceled = false;

                // Animation update loop for primary animations
                if (m_runningAnimationsCount > 0)
                {
                    anySubAnimationFinishedOrCanceled |= UpdateQueueInternal(updateState, animationState, m_runningAnimations);
                }

                // Animation update loop for secondary animations
                if (m_runningSecondaryAnimationsCount > 0)
                {
                    foreach (Queue <IAnimation> actSecondaryQueue in m_runningSecondaryAnimations)
                    {
                        anySubAnimationFinishedOrCanceled |= UpdateQueueInternal(updateState, animationState, actSecondaryQueue);
                    }
                }

                // Dequeue all finished animations
                // Do also calculate time till next finished animation here
                while (anySubAnimationFinishedOrCanceled && (m_runningAnimationsCount > 0))
                {
                    if (m_runningAnimations.First().IsFinishedOrCanceled())
                    {
                        anySubAnimationFinishedOrCanceled = true;
                        countAnimationsFinished++;
                        IAnimation currentAnimation = m_runningAnimations.Dequeue();
                        if (currentAnimation != null)
                        {
                            Interlocked.Decrement(ref m_runningAnimationsCount);
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                if (anySubAnimationFinishedOrCanceled && (m_runningSecondaryAnimationsCount > 0))
                {
                    foreach (Queue <IAnimation> actSecondaryQueue in m_runningSecondaryAnimations)
                    {
                        while (actSecondaryQueue.Count > 0)
                        {
                            if (actSecondaryQueue.Peek().IsFinishedOrCanceled())
                            {
                                anySubAnimationFinishedOrCanceled = true;
                                countAnimationsFinished++;
                                actSecondaryQueue.Dequeue();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }

                // Clear all secondary animations which are finished completely
                while ((m_runningSecondaryAnimationsCount > 0) &&
                       (m_runningSecondaryAnimations.Peek().Count == 0))
                {
                    Queue <IAnimation> dummy = m_runningSecondaryAnimations.Dequeue();
                    Interlocked.Decrement(ref m_runningSecondaryAnimationsCount);
                }

                // Calculate time till next partial animation step
                if (anySubAnimationFinishedOrCanceled)
                {
                    UpdateTimeTillNextPartFinished();
                }
                else
                {
                    m_timeTillNextPartFinished = m_timeTillNextPartFinished - updateState.UpdateTime;
                    if (m_timeTillNextPartFinished < m_defaultCycleTime)
                    {
                        m_timeTillNextPartFinished = m_defaultCycleTime;
                    }
                }
            }
            finally
            {
                updateState.IgnorePauseState = prevIgnorePauseState;

                PostCheckExecutionInternal();
            }

            // Return some diagnostics about the executed animation
            AnimationUpdateResult result = new AnimationUpdateResult();

            result.CountFinishedAnimations = countAnimationsFinished;
            return(result);
        }