/// <summary>Executes some code with a given scissor rectangle (drawing will be limited to the rectangle)</summary> /// <param name="batch">The <see cref="SpriteBatch"/> being used for drawing calls</param> /// <param name="scissorRect">The rectangle to limit drawing to</param> /// <param name="action">The function to execute with the given scissor rectangle</param> /// <param name="respectExistingScissor">Whether to limit the new scissor rectangle to a subrectangle of the current scissor rectangle</param> public static void WithScissorRect(this SpriteBatch batch, XnaRectangle scissorRect, Action <SpriteBatch> action, bool respectExistingScissor = true) { // Stop the old drawing code batch.End(); // Keep track of the old scissor rectangle (this needs to come after End() so they're applied to the GraphicsDevice) XnaRectangle oldScissor = batch.GraphicsDevice.ScissorRectangle; BlendState oldBlendState = batch.GraphicsDevice.BlendState; DepthStencilState oldStencilState = batch.GraphicsDevice.DepthStencilState; RasterizerState oldRasterizerState = batch.GraphicsDevice.RasterizerState; // Trim current scissor to the existing one if necessary if (respectExistingScissor) { scissorRect = scissorRect.Intersection(oldScissor) ?? new XnaRectangle(0, 0, 0, 0); } // Draw with the new scissor rectangle using (RasterizerState rasterizerState = new RasterizerState { ScissorTestEnable = true }) { batch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, rasterizerState); // Set scissor rectangle batch.GraphicsDevice.ScissorRectangle = scissorRect; // Perform the action action(batch); // Draw the batch batch.End(); } // Reset scissor rectangle batch.GraphicsDevice.ScissorRectangle = oldScissor; // Return to last state batch.Begin(SpriteSortMode.BackToFront, oldBlendState, SamplerState.PointClamp, oldStencilState, oldRasterizerState); }
/// <summary> /// Zeichenauruf für das Control (SpriteBatch ist bereits aktiviert) /// </summary> /// <param name="batch">Spritebatch</param> /// <param name="gameTime">Vergangene Spielzeit</param> public void Draw(SpriteBatch batch, Rectangle renderMask, GameTime gameTime) { if (!Visible) return; // Controlgröße ermitteln Rectangle controlArea = new Rectangle(AbsolutePosition, ActualSize); Rectangle localRenderMask = controlArea.Intersection(renderMask); // Scissor-Filter aktivieren batch.GraphicsDevice.ScissorRectangle = localRenderMask.Transform(AbsoluteTransformation); batch.Begin(rasterizerState: new RasterizerState() { ScissorTestEnable = true }, samplerState: SamplerState.LinearWrap, transformMatrix: AbsoluteTransformation); OnDraw(batch, controlArea, gameTime); batch.End(); foreach (var child in Children.AgainstZOrdner()) { Rectangle clientArea = ActualClientArea; clientArea.Location += AbsolutePosition; Rectangle clientRenderMask = clientArea.Intersection(renderMask); child.Draw(batch, clientRenderMask, gameTime); } invalidDrawing = false; }