/// <summary>
 /// Updates the specified context.
 /// </summary>
 /// <param name="uv">The Ultraviolet context to update.</param>
 /// <param name="time">Time elapsed since the last update.</param>
 /// <returns><see langword="true"/> if the host should continue processing; otherwise, <see langword="false"/>.</returns>
 private Boolean UpdateContext(UltravioletContext uv, UltravioletTime time)
 {
     using (UltravioletProfiler.Section(UltravioletProfilerSections.Update))
     {
         uv.Update(time);
     }
     return(!uv.Disposed);
 }
示例#2
0
 /// <summary>
 /// Releases resources associated with the object.
 /// </summary>
 public void Dispose()
 {
     UltravioletProfiler.EndSection(name);
 }
        /// <summary>
        /// Advances the application state by one tick.
        /// </summary>
        public void RunOneTick()
        {
            var uv = host.Ultraviolet;

            if (!host.IsActive && InactiveSleepTime.TotalMilliseconds > 0)
            {
                Thread.Sleep(InactiveSleepTime);
            }

            var syncContext = SynchronizationContext.Current as UltravioletSynchronizationContext;

            if (syncContext != null)
            {
                syncContext.ProcessWorkItems();
            }

            if (IsFixedTimeStep)
            {
                if (tickTimer.Elapsed.TotalMilliseconds >= targetElapsedTime.TotalMilliseconds)
                {
                    tickTimer.Restart();
                    tickElapsed -= targetElapsedTime.TotalMilliseconds * (int)(tickElapsed / targetElapsedTime.TotalMilliseconds);

                    uv.HandleFrameStart();

                    const Double CatchUpThreshold = 1.05;
                    if (frameElapsed > 0 && frameElapsed > targetElapsedTime.TotalMilliseconds * CatchUpThreshold)
                    {
                        const Int32 RunningSlowlyFrameCount = 5;
                        runningSlowlyFrames = RunningSlowlyFrameCount;
                        isRunningSlowly     = true;

                        const Int32 CatchUpFrameLimit = 10;
                        var         catchUpUpdates    = Math.Min(CatchUpFrameLimit, (int)(frameElapsed / targetElapsedTime.TotalMilliseconds));

                        for (int i = 0; i < catchUpUpdates; i++)
                        {
                            timeTrackerUpdate.Increment(targetElapsedTime, isRunningSlowly);
                            timeTrackerDraw.Increment(targetElapsedTime, isRunningSlowly);
                            if (!UpdateContext(uv, timeTrackerUpdate.Time))
                            {
                                return;
                            }
                        }
                    }
                    else
                    {
                        if (isRunningSlowly)
                        {
                            runningSlowlyFrames--;
                            if (runningSlowlyFrames == 0)
                            {
                                isRunningSlowly = false;
                            }
                        }
                    }

                    frameTimer.Restart();

                    var uvTimeUpdate = timeTrackerUpdate.Increment(targetElapsedTime, isRunningSlowly);
                    if (!UpdateContext(uv, uvTimeUpdate))
                    {
                        return;
                    }

                    if (!host.IsSuspended)
                    {
                        var uvTimeDraw = timeTrackerDraw.Increment(targetElapsedTime, isRunningSlowly);
                        using (UltravioletProfiler.Section(UltravioletProfilerSections.Draw))
                        {
                            uv.Draw(uvTimeDraw);
                        }
                    }

                    uv.HandleFrameEnd();

                    frameElapsed = frameTimer.Elapsed.TotalMilliseconds;
                }
                else
                {
                    // NOTE: The precision of Sleep() can generally be assumed to be something like 10-15ms, so
                    // we only call it if we know we're going to be waiting a long time and there's no point
                    // in sucking up CPU cycles spinning our loop.
                    var frameDelay = (int)(targetElapsedTime.TotalMilliseconds - tickTimer.Elapsed.TotalMilliseconds);
                    if (frameDelay >= 10)
                    {
                        Thread.Sleep(frameDelay);
                    }
                }
            }
            else
            {
                var time = tickTimer.Elapsed.TotalMilliseconds;
                tickTimer.Restart();

                uv.HandleFrameStart();

                var uvTimeDelta  = TimeSpan.FromTicks((long)(time * TimeSpan.TicksPerMillisecond));
                var uvTimeUpdate = timeTrackerUpdate.Increment(uvTimeDelta, false);
                if (!UpdateContext(uv, uvTimeUpdate))
                {
                    return;
                }

                if (!host.IsSuspended)
                {
                    var uvTimeDraw = uvTimeUpdate;
                    using (UltravioletProfiler.Section(UltravioletProfilerSections.Draw))
                    {
                        uv.Draw(uvTimeDraw);
                    }
                }

                uv.HandleFrameEnd();
            }
        }