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);
+ }
+
+ }
+}