internal void Remove(pDrawable p) { if (p != null) { lock (SpriteLock) SpriteList.Remove(p); if (p.IsDisposable) { p.Dispose(); } p.IsVisible = false; } }
/// <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); }