From 8fdc3546c65601d371504ca6a40f95b837718d48 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Thu, 30 May 2024 13:24:35 +0200 Subject: [PATCH] Added the ScissorGroup element --- CHANGELOG.md | 1 + MLEM.Ui/Elements/Element.cs | 1 + MLEM.Ui/Elements/ScissorGroup.cs | 61 ++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 MLEM.Ui/Elements/ScissorGroup.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index d055aff..2645c33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Improvements Additions - Added the ability to set the anchor that should be used when a tooltip attaches to an element or the mouse - Added the ability to display tooltips using the auto-nav style even when using the mouse +- Added the ScissorGroup element, which applies a scissor rectangle when drawing its content Improvements - **Include the SpriteBatchContext in OnDrawn, OnElementDrawn and OnSelectedElementDrawn** diff --git a/MLEM.Ui/Elements/Element.cs b/MLEM.Ui/Elements/Element.cs index 08d0245..56746a0 100644 --- a/MLEM.Ui/Elements/Element.cs +++ b/MLEM.Ui/Elements/Element.cs @@ -1387,6 +1387,7 @@ namespace MLEM.Ui.Elements { /// The game's time /// The sprite batch used for drawing /// The alpha this element is drawn with + /// The sprite batch context to use for drawing public delegate void DrawCallback(Element element, GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context); /// diff --git a/MLEM.Ui/Elements/ScissorGroup.cs b/MLEM.Ui/Elements/ScissorGroup.cs new file mode 100644 index 0000000..2330d0d --- /dev/null +++ b/MLEM.Ui/Elements/ScissorGroup.cs @@ -0,0 +1,61 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MLEM.Extensions; +using MLEM.Graphics; + +namespace MLEM.Ui.Elements { + /// + /// A scissor group is a that sets the before drawing its content (and thus, its ), preventing them from being drawn outside of this group's 's bounds. + /// + public class ScissorGroup : Group { + + /// + /// The rasterizer state that this scissor group should use when drawing. + /// By default, is set to in accordance with 's default behavior, and is set to . + /// + public readonly RasterizerState Rasterizer = new RasterizerState { + // use the default cull mode from SpriteBatch, but with scissor test enabled + CullMode = CullMode.CullCounterClockwiseFace, + ScissorTestEnable = true + }; + + /// + /// Creates a new scissor group with the given settings + /// + /// The group's anchor + /// The group's size + /// Whether the group's height should be based on its children's height, see . + public ScissorGroup(Anchor anchor, Vector2 size, bool setHeightBasedOnChildren = true) : base(anchor, size, setHeightBasedOnChildren) {} + + /// + /// Creates a new scissor group with the given settings + /// + /// The group's anchor + /// The group's size + /// Whether the group's width should be based on its children's width, see . + /// Whether the group's height should be based on its children's height, see . + public ScissorGroup(Anchor anchor, Vector2 size, bool setWidthBasedOnChildren, bool setHeightBasedOnChildren) : base(anchor, size, setWidthBasedOnChildren, setHeightBasedOnChildren) {} + + /// + public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) { + batch.End(); + + // apply our scissor rectangle + var lastScissor = batch.GraphicsDevice.ScissorRectangle; + batch.GraphicsDevice.ScissorRectangle = (Rectangle) this.DisplayArea.OffsetCopy(context.TransformMatrix.Translation.ToVector2()); + + // enable scissor test + var localContext = context; + localContext.RasterizerState = this.Rasterizer; + batch.Begin(localContext); + + base.Draw(time, batch, alpha, localContext); + + // revert back to previous behavior + batch.End(); + batch.GraphicsDevice.ScissorRectangle = lastScissor; + batch.Begin(context); + } + + } +}