예제 #1
0
        internal void Remove(pDrawable p)
        {
            if (p != null)
            {
                lock (SpriteLock)
                    SpriteList.Remove(p);

                if (p.IsDisposable)
                {
                    p.Dispose();
                }

                p.IsVisible = false;
            }
        }
예제 #2
0
        /// <summary>
        ///   Draws this instance.
        /// </summary>
        internal bool Draw()
        {
            lock (SpriteLock)
            {
                if (FirstDraw)
                {
                    HandleFirstDraw();
                }

                int spriteListCount = SpriteList.Count;
                PixelsDrawn = 0;

                //Setup view rectangle
                if (viewRectangleCustom)
                {
                    ViewRectangleScaled =
                        new RectangleF(
                            (float)Math.Floor((WidescreenAutoOffset ? GameBase.WindowManager.NonWidescreenOffsetX : 0) + ViewRectangle.X * GameBase.WindowManager.Ratio),
                            (float)Math.Floor(ViewRectangle.Y * GameBase.WindowManager.Ratio),
                            (float)Math.Ceiling(ViewRectangle.Width * GameBase.WindowManager.Ratio),
                            (float)Math.Ceiling(ViewRectangle.Height * GameBase.WindowManager.Ratio));
                }
                else if (WidescreenAutoOffset)
                {
                    ViewRectangleScaled = new RectangleF(
                        GameBase.WindowManager.NonWidescreenOffsetX + ViewRectangle43.X * GameBase.WindowManager.Ratio,
                        ViewRectangle43.Y * GameBase.WindowManager.Ratio,
                        ViewRectangle43.Width * GameBase.WindowManager.Ratio, ViewRectangle43.Height * GameBase.WindowManager.Ratio);
                }
                else
                {
                    ViewRectangleScaled = new RectangleF(ViewRectangleCurrent.X * GameBase.WindowManager.Ratio,
                                                         ViewRectangleCurrent.Y * GameBase.WindowManager.Ratio,
                                                         ViewRectangleCurrent.Width * GameBase.WindowManager.Ratio,
                                                         ViewRectangleCurrent.Height * GameBase.WindowManager.Ratio);
                }

                ClipRectangle = new Rectangle((int)ViewRectangleScaled.X, (int)ViewRectangleScaled.Y, (int)Math.Ceiling(ViewRectangleScaled.Width), (int)Math.Ceiling(ViewRectangleScaled.Height));

                if (spriteListCount == 0 && !ForwardPlayOptimisations)
                {
                    return(false);
                }

                if (Alpha < 0.01f || Bypass)
                {
                    for (int m = 0; m < spriteListCount; m++)
                    {
                        SpriteList[m].IsVisible = false;
                    }
                    return(false);
                }

                LastFrameRendered = GameBase.TotalFramesRendered;

                if (BlacknessTarget >= 0)
                {
                    if (BlacknessTarget > Blackness)
                    {
                        Blackness = Math.Min(BlacknessTarget, Blackness + 0.018f * (float)GameBase.FrameRatio);
                    }
                    else if (BlacknessTarget < Blackness)
                    {
                        Blackness = Math.Max(BlacknessTarget, Blackness - 0.018f * (float)GameBase.FrameRatio);
                    }
                }

                int gameTime  = GameBase.Time;
                int audioTime = AudioEngine.Time;

                if (ForwardPlayOptimisations)
                {
                    while (forwardPlayQueue.Count > 0)
                    {
                        pDrawable i = forwardPlayQueue.Peek();
                        if (i.Transformations.Count > 0 && i.Transformations[0].Time1 > (i.Clock == Clocks.Game ? gameTime : audioTime))
                        {
                            break;
                        }

                        if (i.Transformations.Count == 0)
                        {
                            forwardPlayQueue.Dequeue().Dispose();
                            continue;
                        }

                        Add(forwardPlayQueue.Dequeue());
                        spriteListCount++;
                    }

                    if (AudioEngine.SeekedBackwards)
                    {
                        //if we are seeking backwards, re-add any previousyl removed items.
                        while (forwardPlayPast.Count > 0)
                        {
                            pDrawable i = forwardPlayPast.Peek();
                            if (i.Transformations.Count > 0)
                            {
                                int lastTransform = i.Transformations[i.Transformations.Count - 1].Time2;
                                if (lastTransform < audioTime)
                                {
                                    if (audioTime - lastTransform > 5000)
                                    {
                                        break; //allowance for out-of-order additions to this queue.
                                    }
                                }
                            }

                            i = forwardPlayPast.Pop();

                            //if (i.Clock != Clocks.AudioOnce)
                            {
                                Add(i);
                                spriteListCount++;
                            }
                        }
                    }
                }

                startBatch();

#if !DEBUG
                try
                {
#endif
                bool firstDraw = true;

                //Keep track of the OGL rectangle
                Rectangle currentClipRectangle = Masking ? ClipRectangle : OsuGlControl.ViewportZeroBased;

                //In most cases we won't be clipping more than at a spritemanager level
                //so we can save on rectangle copies/ogl calls by resetting the initial scissor rectangle here
                OsuGlControl.ResetScissor(new System.Drawing.Rectangle(OsuGlControl.Viewport.Left + currentClipRectangle.Left, OsuGlControl.Viewport.Top + GameBase.WindowManager.Height - currentClipRectangle.Bottom, currentClipRectangle.Width, currentClipRectangle.Height));

                if (SpriteBatch != null)
                {
                    SpriteBatch.ResetCounters();
                }

                for (int m = 0; m < spriteListCount; m++)
                {
                    pDrawable s = SpriteList[m];

                    if (s.Bypass)
                    {
                        continue;
                    }

#if DEBUG
                    TotalSprites++;
#endif

                    switch (s.Update())
                    {
                    case UpdateResult.Discard:
                        SpriteList.RemoveAt(m--);
                        spriteListCount--;

                        if (ForwardPlayOptimisations && s.Clock != Clocks.Game && AllowRewind)
                        {
                            forwardPlayPast.Push(s);
                        }
                        else
                        {
                            s.Dispose();
                        }
                        break;

                    case UpdateResult.NotVisible:
                        break;

                    case UpdateResult.Visible:
#if DEBUG
                        TotalSpritesVisible++;
#endif

                        if (!s.UsesSpriteBatch)
                        {
                            endBatch();
                        }

                        if (currentClipRectangle != s.ClipRectangleScaled)
                        {
                            SpriteBatch.Draw();
                            currentClipRectangle = s.ClipRectangleScaled;
                            OsuGlControl.ResetScissor(new System.Drawing.Rectangle(OsuGlControl.Viewport.Left + currentClipRectangle.Left, OsuGlControl.Viewport.Top + GameBase.WindowManager.Height - currentClipRectangle.Bottom, currentClipRectangle.Width, currentClipRectangle.Height));
                        }

                        s.Draw();
                        firstDraw = false;
                        break;
                    }
                }

                if (hasBegun)
                {
                    //there's an occasional case where blending mode is transferred outside of SpriteBatches (DirectX only).
                    //this is a safety call to reset to alpha blending.
                    SetBlending(false);
                }

                endBatch(true);

                OsuGlControl.ResetScissor();
#if !DEBUG
                exceptionCount = 0;
            }
            catch (Exception e)
            {
                /* TODO: Figure out why dialog popups are causing XNA exceptions
                 * See https://gist.github.com/324f5de475b438f48416. */

                try
                {
                    endBatch(true);
                }
                catch { }

                if (!(e is InvalidOperationException) || ++exceptionCount > 1)
                {
                    throw;
                }
            }
#endif
            }


            return(true);
        }