1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-26 14:38:34 +01:00

added SpriteBatchContext

This commit is contained in:
Ell 2022-04-25 15:25:58 +02:00
parent c78bafd000
commit 6393d879d9
14 changed files with 211 additions and 42 deletions

View file

@ -12,6 +12,7 @@ Jump to version:
### MLEM ### MLEM
Additions Additions
- Added consuming variants of IsPressed methods to InputHandler - Added consuming variants of IsPressed methods to InputHandler
- Added SpriteBatchContext struct and extensions
### MLEM.Ui ### MLEM.Ui
Additions Additions
@ -19,12 +20,16 @@ Additions
Improvements Improvements
- Ensure that Element.IsMouseOver is always accurate by making it an auto-property - Ensure that Element.IsMouseOver is always accurate by making it an auto-property
- Started using SpriteBatchContext for Draw and DrawTransformed methods
Fixes Fixes
- Fixed auto-nav tooltip displaying on the selected element even when not in auto-nav mode - Fixed auto-nav tooltip displaying on the selected element even when not in auto-nav mode
- Fixed radio buttons not unchecking all other radio buttons with the same root element - Fixed radio buttons not unchecking all other radio buttons with the same root element
- Fixed elements not being deselected when removed through RemoveChild - Fixed elements not being deselected when removed through RemoveChild
Removals
- Marked old Draw and DrawTransformed overloads as obsolete in favor of SpriteBatchContext ones
## 5.3.0 ## 5.3.0
### MLEM ### MLEM
Additions Additions

View file

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Graphics;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
using MLEM.Ui.Style; using MLEM.Ui.Style;
@ -92,7 +93,7 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
var tex = this.Texture; var tex = this.Texture;
var color = (Color) this.NormalColor * alpha; var color = (Color) this.NormalColor * alpha;
if (this.IsDisabled) { if (this.IsDisabled) {
@ -103,7 +104,7 @@ namespace MLEM.Ui.Elements {
color = (Color) this.HoveredColor * alpha; color = (Color) this.HoveredColor * alpha;
} }
batch.Draw(tex, this.DisplayArea, color, this.Scale); batch.Draw(tex, this.DisplayArea, color, this.Scale);
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} }
/// <inheritdoc /> /// <inheritdoc />

View file

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Graphics;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
using MLEM.Ui.Style; using MLEM.Ui.Style;
@ -108,7 +109,7 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
var tex = this.Texture; var tex = this.Texture;
var color = Color.White * alpha; var color = Color.White * alpha;
if (this.IsDisabled) { if (this.IsDisabled) {
@ -123,7 +124,7 @@ namespace MLEM.Ui.Elements {
batch.Draw(tex, boxDisplayArea, color, this.Scale); batch.Draw(tex, boxDisplayArea, color, this.Scale);
if (this.Checked) if (this.Checked)
batch.Draw(this.Checkmark, boxDisplayArea, Color.White * alpha); batch.Draw(this.Checkmark, boxDisplayArea, Color.White * alpha);
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} }
/// <inheritdoc /> /// <inheritdoc />

View file

@ -7,6 +7,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using MLEM.Extensions; using MLEM.Extensions;
using MLEM.Graphics;
using MLEM.Input; using MLEM.Input;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
@ -234,7 +235,7 @@ namespace MLEM.Ui.Elements {
public virtual bool PreventParentSpill { get; set; } public virtual bool PreventParentSpill { get; set; }
/// <summary> /// <summary>
/// The transparency (alpha value) that this element is rendered with. /// The transparency (alpha value) that this element is rendered with.
/// Note that, when <see cref="Draw"/> is called, this alpha value is multiplied with the <see cref="Parent"/>'s alpha value and passed down to this element's <see cref="Children"/>. /// Note that, when <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> is called, this alpha value is multiplied with the <see cref="Parent"/>'s alpha value and passed down to this element's <see cref="Children"/>.
/// </summary> /// </summary>
public virtual float DrawAlpha { get; set; } = 1; public virtual float DrawAlpha { get; set; } = 1;
/// <summary> /// <summary>
@ -916,7 +917,7 @@ namespace MLEM.Ui.Elements {
} }
/// <summary> /// <summary>
/// Draws this element by calling <see cref="Draw"/> internally. /// Draws this element by calling <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> internally.
/// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <see cref="SpriteBatch.Begin"/> call is also started. /// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <see cref="SpriteBatch.Begin"/> call is also started.
/// </summary> /// </summary>
/// <param name="time">The game's time</param> /// <param name="time">The game's time</param>
@ -927,25 +928,37 @@ namespace MLEM.Ui.Elements {
/// <param name="effect">The effect that is used for drawing</param> /// <param name="effect">The effect that is used for drawing</param>
/// <param name="depthStencilState">The depth stencil state that is used for drawing</param> /// <param name="depthStencilState">The depth stencil state that is used for drawing</param>
/// <param name="matrix">The transformation matrix that is used for drawing</param> /// <param name="matrix">The transformation matrix that is used for drawing</param>
[Obsolete("Use DrawTransformed that takes a SpriteBatchContext instead")]
public void DrawTransformed(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public void DrawTransformed(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
this.DrawTransformed(time, batch, alpha, new SpriteBatchContext(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, matrix));
}
/// <summary>
/// Draws this element by calling <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> internally.
/// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <see cref="SpriteBatch.Begin"/> call is also started.
/// </summary>
/// <param name="time">The game's time</param>
/// <param name="batch">The sprite batch to use for drawing</param>
/// <param name="alpha">The alpha to draw this element and its children with</param>
/// <param name="context">The sprite batch context to use for drawing</param>
public void DrawTransformed(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
#pragma warning disable CS0618 #pragma warning disable CS0618
var customDraw = this.BeginImpl != null || this.Transform != Matrix.Identity; var customDraw = this.BeginImpl != null || this.Transform != Matrix.Identity;
var mat = this.Transform * matrix; var transformed = context;
transformed.TransformMatrix = this.Transform * transformed.TransformMatrix;
// TODO ending and beginning again when the matrix changes isn't ideal (https://github.com/MonoGame/MonoGame/issues/3156) // TODO ending and beginning again when the matrix changes isn't ideal (https://github.com/MonoGame/MonoGame/issues/3156)
if (customDraw) { if (customDraw) {
// end the usual draw so that we can begin our own // end the usual draw so that we can begin our own
batch.End(); batch.End();
// begin our own draw call // begin our own draw call
if (this.BeginImpl != null) { batch.Begin(transformed);
this.BeginImpl(this, time, batch, alpha, blendState, samplerState, depthStencilState, effect, mat);
} else {
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, mat);
}
} }
#pragma warning restore CS0618 #pragma warning restore CS0618
// draw content in custom begin call // draw content in custom begin call
this.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, mat); #pragma warning disable CS0618
this.Draw(time, batch, alpha, transformed.BlendState, transformed.SamplerState, transformed.DepthStencilState, transformed.Effect, transformed.TransformMatrix);
#pragma warning restore CS0618
if (this.System != null) if (this.System != null)
this.System.Metrics.Draws++; this.System.Metrics.Draws++;
@ -953,7 +966,7 @@ namespace MLEM.Ui.Elements {
// end our draw // end our draw
batch.End(); batch.End();
// begin the usual draw again for other elements // begin the usual draw again for other elements
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, matrix); batch.Begin(context);
} }
} }
@ -969,14 +982,30 @@ namespace MLEM.Ui.Elements {
/// <param name="effect">The effect that is used for drawing</param> /// <param name="effect">The effect that is used for drawing</param>
/// <param name="depthStencilState">The depth stencil state that is used for drawing</param> /// <param name="depthStencilState">The depth stencil state that is used for drawing</param>
/// <param name="matrix">The transformation matrix that is used for drawing</param> /// <param name="matrix">The transformation matrix that is used for drawing</param>
[Obsolete("Use Draw that takes a SpriteBatchContext instead")]
public virtual void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public virtual void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
this.Draw(time, batch, alpha, new SpriteBatchContext(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, matrix));
}
/// <summary>
/// Draws this element and all of its children. Override this method to draw the content of custom elements.
/// Note that, when this is called, <see cref="SpriteBatch.Begin"/> has already been called with custom <see cref="Transform"/> etc. applied.
/// </summary>
/// <param name="time">The game's time</param>
/// <param name="batch">The sprite batch to use for drawing</param>
/// <param name="alpha">The alpha to draw this element and its children with</param>
/// <param name="context">The sprite batch context to use for drawing</param>
public virtual void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
this.System.InvokeOnElementDrawn(this, time, batch, alpha); this.System.InvokeOnElementDrawn(this, time, batch, alpha);
if (this.IsSelected) if (this.IsSelected)
this.System.InvokeOnSelectedElementDrawn(this, time, batch, alpha); this.System.InvokeOnSelectedElementDrawn(this, time, batch, alpha);
foreach (var child in this.GetRelevantChildren()) { foreach (var child in this.GetRelevantChildren()) {
if (!child.IsHidden) if (!child.IsHidden) {
child.DrawTransformed(time, batch, alpha * child.DrawAlpha, blendState, samplerState, depthStencilState, effect, matrix); #pragma warning disable CS0618
child.DrawTransformed(time, batch, alpha * child.DrawAlpha, context.BlendState, context.SamplerState, context.DepthStencilState, context.Effect, context.TransformMatrix);
#pragma warning restore CS0618
}
} }
} }
@ -1131,7 +1160,7 @@ namespace MLEM.Ui.Elements {
public delegate void OtherElementCallback(Element thisElement, Element otherElement); public delegate void OtherElementCallback(Element thisElement, Element otherElement);
/// <summary> /// <summary>
/// A delegate used inside of <see cref="Element.Draw"/> /// A delegate used inside of <see cref="Element.Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/>
/// </summary> /// </summary>
/// <param name="element">The element that is being drawn</param> /// <param name="element">The element that is being drawn</param>
/// <param name="time">The game's time</param> /// <param name="time">The game's time</param>

View file

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Graphics;
namespace MLEM.Ui.Elements { namespace MLEM.Ui.Elements {
/// <summary> /// <summary>
@ -20,10 +21,10 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
// since the group never accesses its own area when drawing, we have to update it manually // since the group never accesses its own area when drawing, we have to update it manually
this.UpdateAreaIfDirty(); this.UpdateAreaIfDirty();
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} }
} }

View file

@ -1,6 +1,7 @@
using System; using System;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Graphics;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
using MLEM.Ui.Style; using MLEM.Ui.Style;
@ -103,7 +104,7 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
if (this.Texture == null) if (this.Texture == null)
return; return;
var center = new Vector2(this.Texture.Width / 2F, this.Texture.Height / 2F); var center = new Vector2(this.Texture.Width / 2F, this.Texture.Height / 2F);
@ -116,7 +117,7 @@ namespace MLEM.Ui.Elements {
var scale = new Vector2(1F / this.Texture.Width, 1F / this.Texture.Height) * this.DisplayArea.Size; var scale = new Vector2(1F / this.Texture.Width, 1F / this.Texture.Height) * this.DisplayArea.Size;
batch.Draw(this.Texture, this.DisplayArea.Location + center * scale, color, this.ImageRotation, center, scale * this.ImageScale, this.ImageEffects, 0); batch.Draw(this.Texture, this.DisplayArea.Location + center * scale, color, this.ImageRotation, center, scale * this.ImageScale, this.ImageEffects, 0);
} }
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} }
/// <summary> /// <summary>

View file

@ -4,6 +4,7 @@ using System.Linq;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Extensions; using MLEM.Extensions;
using MLEM.Graphics;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
using MLEM.Ui.Style; using MLEM.Ui.Style;
@ -167,7 +168,7 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
// draw children onto the render target if we have one // draw children onto the render target if we have one
if (this.scrollOverflow && this.renderTarget != null) { if (this.scrollOverflow && this.renderTarget != null) {
this.UpdateAreaIfDirty(); this.UpdateAreaIfDirty();
@ -179,21 +180,22 @@ namespace MLEM.Ui.Elements {
batch.GraphicsDevice.Clear(Color.Transparent); batch.GraphicsDevice.Clear(Color.Transparent);
// offset children by the render target's location // offset children by the render target's location
var area = this.GetRenderTargetArea(); var area = this.GetRenderTargetArea();
var trans = Matrix.CreateTranslation(-area.X, -area.Y, 0);
// do the usual draw, but within the render target // do the usual draw, but within the render target
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, trans); var trans = context;
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, trans); trans.TransformMatrix = Matrix.CreateTranslation(-area.X, -area.Y, 0);
batch.Begin(trans);
base.Draw(time, batch, alpha, trans);
batch.End(); batch.End();
} }
batch.GraphicsDevice.PresentationParameters.RenderTargetUsage = lastUsage; batch.GraphicsDevice.PresentationParameters.RenderTargetUsage = lastUsage;
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, matrix); batch.Begin(context);
} }
if (this.Texture.HasValue()) if (this.Texture.HasValue())
batch.Draw(this.Texture, this.DisplayArea, this.DrawColor.OrDefault(Color.White) * alpha, this.Scale); batch.Draw(this.Texture, this.DisplayArea, this.DrawColor.OrDefault(Color.White) * alpha, this.Scale);
// if we handle overflow, draw using the render target in DrawUnbound // if we handle overflow, draw using the render target in DrawUnbound
if (!this.scrollOverflow || this.renderTarget == null) { if (!this.scrollOverflow || this.renderTarget == null) {
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} else { } else {
// draw the actual render target (don't apply the alpha here because it's already drawn onto with alpha) // draw the actual render target (don't apply the alpha here because it's already drawn onto with alpha)
batch.Draw(this.renderTarget, this.GetRenderTargetArea(), Color.White); batch.Draw(this.renderTarget, this.GetRenderTargetArea(), Color.White);

View file

@ -6,6 +6,7 @@ using MLEM.Extensions;
using MLEM.Font; using MLEM.Font;
using MLEM.Formatting; using MLEM.Formatting;
using MLEM.Formatting.Codes; using MLEM.Formatting.Codes;
using MLEM.Graphics;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Ui.Style; using MLEM.Ui.Style;
@ -144,12 +145,12 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
var pos = this.DisplayArea.Location + new Vector2(this.GetAlignmentOffset(), 0); var pos = this.DisplayArea.Location + new Vector2(this.GetAlignmentOffset(), 0);
var sc = this.TextScale * this.TextScaleMultiplier * this.Scale; var sc = this.TextScale * this.TextScaleMultiplier * this.Scale;
var color = this.TextColor.OrDefault(Color.White) * alpha; var color = this.TextColor.OrDefault(Color.White) * alpha;
this.TokenizedText.Draw(time, batch, pos, this.RegularFont, color, sc, 0); this.TokenizedText.Draw(time, batch, pos, this.RegularFont, color, sc, 0);
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} }
/// <inheritdoc /> /// <inheritdoc />

View file

@ -2,6 +2,7 @@ using System;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Extensions; using MLEM.Extensions;
using MLEM.Graphics;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
using MLEM.Ui.Style; using MLEM.Ui.Style;
@ -73,7 +74,7 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
batch.Draw(this.Texture, this.DisplayArea, (Color) this.Color * alpha, this.Scale); batch.Draw(this.Texture, this.DisplayArea, (Color) this.Color * alpha, this.Scale);
var percentage = this.CurrentValue / this.MaxValue; var percentage = this.CurrentValue / this.MaxValue;
@ -106,7 +107,7 @@ namespace MLEM.Ui.Elements {
} else { } else {
batch.Draw(batch.GetBlankTexture(), offsetArea, (Color) this.ProgressColor * alpha); batch.Draw(batch.GetBlankTexture(), offsetArea, (Color) this.ProgressColor * alpha);
} }
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} }
/// <inheritdoc /> /// <inheritdoc />

View file

@ -3,6 +3,7 @@ using System.Linq;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch; using Microsoft.Xna.Framework.Input.Touch;
using MLEM.Graphics;
using MLEM.Input; using MLEM.Input;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
@ -205,13 +206,13 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
batch.Draw(this.Background, this.DisplayArea, Color.White * alpha, this.Scale); batch.Draw(this.Background, this.DisplayArea, Color.White * alpha, this.Scale);
if (this.MaxValue > 0) { if (this.MaxValue > 0) {
var scrollerRect = new RectangleF(this.ScrollerPosition, this.ScrollerSize * this.Scale); var scrollerRect = new RectangleF(this.ScrollerPosition, this.ScrollerSize * this.Scale);
batch.Draw(this.ScrollerTexture, scrollerRect, Color.White * alpha, this.Scale); batch.Draw(this.ScrollerTexture, scrollerRect, Color.White * alpha, this.Scale);
} }
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} }
/// <inheritdoc /> /// <inheritdoc />

View file

@ -7,6 +7,7 @@ using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using MLEM.Extensions; using MLEM.Extensions;
using MLEM.Font; using MLEM.Font;
using MLEM.Graphics;
using MLEM.Input; using MLEM.Input;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
@ -285,7 +286,7 @@ namespace MLEM.Ui.Elements {
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) { public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
var tex = this.Texture; var tex = this.Texture;
var color = Color.White * alpha; var color = Color.White * alpha;
if (this.IsMouseOver) { if (this.IsMouseOver) {
@ -314,7 +315,7 @@ namespace MLEM.Ui.Elements {
this.Font.Value.DrawString(batch, this.PlaceholderText, textPos, this.PlaceholderColor.OrDefault(Color.Gray) * alpha, 0, Vector2.Zero, this.TextScale * this.Scale, SpriteEffects.None, 0); this.Font.Value.DrawString(batch, this.PlaceholderText, textPos, this.PlaceholderColor.OrDefault(Color.Gray) * alpha, 0, Vector2.Zero, this.TextScale * this.Scale, SpriteEffects.None, 0);
} }
} }
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix); base.Draw(time, batch, alpha, context);
} }
/// <summary> /// <summary>

View file

@ -33,12 +33,12 @@ namespace MLEM.Ui {
public uint Updates { get; internal set; } public uint Updates { get; internal set; }
/// <summary> /// <summary>
/// The amount of time that <see cref="Element.Draw"/> took. /// The amount of time that <see cref="Element.Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> took.
/// Can be divided by <see cref="Draws"/> to get an average per draw. /// Can be divided by <see cref="Draws"/> to get an average per draw.
/// </summary> /// </summary>
public TimeSpan DrawTime { get; internal set; } public TimeSpan DrawTime { get; internal set; }
/// <summary> /// <summary>
/// The amount of times that <see cref="Element.Draw"/> was called. /// The amount of times that <see cref="Element.Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> was called.
/// </summary> /// </summary>
public uint Draws { get; internal set; } public uint Draws { get; internal set; }

View file

@ -7,6 +7,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MLEM.Formatting; using MLEM.Formatting;
using MLEM.Formatting.Codes; using MLEM.Formatting.Codes;
using MLEM.Graphics;
using MLEM.Input; using MLEM.Input;
using MLEM.Misc; using MLEM.Misc;
using MLEM.Textures; using MLEM.Textures;
@ -77,23 +78,32 @@ namespace MLEM.Ui {
/// <summary> /// <summary>
/// The blend state that this ui system and all of its elements draw with /// The blend state that this ui system and all of its elements draw with
/// </summary> /// </summary>
[Obsolete("Set this through SpriteBatchContext instead")]
public BlendState BlendState; public BlendState BlendState;
/// <summary> /// <summary>
/// The sampler state that this ui system and all of its elements draw with. /// The sampler state that this ui system and all of its elements draw with.
/// The default is <see cref="Microsoft.Xna.Framework.Graphics.SamplerState.PointClamp"/>, as that is the one that works best with pixel graphics. /// The default is <see cref="Microsoft.Xna.Framework.Graphics.SamplerState.PointClamp"/>, as that is the one that works best with pixel graphics.
/// </summary> /// </summary>
public SamplerState SamplerState = SamplerState.PointClamp; [Obsolete("Set this through SpriteBatchContext instead")]
public SamplerState SamplerState;
/// <summary> /// <summary>
/// The depth stencil state that this ui system and all of its elements draw with. /// The depth stencil state that this ui system and all of its elements draw with.
/// The default is <see cref="Microsoft.Xna.Framework.Graphics.DepthStencilState.None"/>, which is also the default for <see cref="SpriteBatch.Begin"/>. /// The default is <see cref="Microsoft.Xna.Framework.Graphics.DepthStencilState.None"/>, which is also the default for <see cref="SpriteBatch.Begin"/>.
/// </summary> /// </summary>
public DepthStencilState DepthStencilState = DepthStencilState.None; [Obsolete("Set this through SpriteBatchContext instead")]
public DepthStencilState DepthStencilState;
/// <summary> /// <summary>
/// The effect that this ui system and all of its elements draw with. /// The effect that this ui system and all of its elements draw with.
/// The default is null, which means that no custom effect will be used. /// The default is null, which means that no custom effect will be used.
/// </summary> /// </summary>
[Obsolete("Set this through SpriteBatchContext instead")]
public Effect Effect; public Effect Effect;
/// <summary> /// <summary>
/// The spriteb atch context that this ui system and all of its elements should draw with.
/// The default <see cref="MLEM.Graphics.SpriteBatchContext.SamplerState"/> is <see cref="Microsoft.Xna.Framework.Graphics.SamplerState.PointClamp"/>, as that is the one that works best with pixel graphics.
/// </summary>
public SpriteBatchContext SpriteBatchContext = new SpriteBatchContext(samplerState: SamplerState.PointClamp);
/// <summary>
/// The <see cref="TextFormatter"/> that this ui system's <see cref="Paragraph"/> elements format their text with. /// The <see cref="TextFormatter"/> that this ui system's <see cref="Paragraph"/> elements format their text with.
/// To add new formatting codes to the ui system, add them to this formatter. /// To add new formatting codes to the ui system, add them to this formatter.
/// </summary> /// </summary>
@ -296,9 +306,24 @@ namespace MLEM.Ui {
foreach (var root in this.rootElements) { foreach (var root in this.rootElements) {
if (root.Element.IsHidden) if (root.Element.IsHidden)
continue; continue;
batch.Begin(SpriteSortMode.Deferred, this.BlendState, this.SamplerState, this.DepthStencilState, null, this.Effect, root.Transform); var context = this.SpriteBatchContext;
var alpha = this.DrawAlpha * root.Element.DrawAlpha; context.TransformMatrix = root.Transform * context.TransformMatrix;
root.Element.DrawTransformed(time, batch, alpha, this.BlendState, this.SamplerState, this.DepthStencilState, this.Effect, root.Transform);
#pragma warning disable CS0618
if (this.BlendState != null)
context.BlendState = this.BlendState;
if (this.SamplerState != null)
context.SamplerState = this.SamplerState;
if (this.DepthStencilState != null)
context.DepthStencilState = this.DepthStencilState;
if (this.Effect != null)
context.Effect = this.Effect;
#pragma warning restore CS0618
batch.Begin(context);
#pragma warning disable CS0618
root.Element.DrawTransformed(time, batch, this.DrawAlpha * root.Element.DrawAlpha, context.BlendState, context.SamplerState, context.DepthStencilState, context.Effect, context.TransformMatrix);
#pragma warning restore CS0618
batch.End(); batch.End();
} }

View file

@ -0,0 +1,100 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MLEM.Graphics {
/// <summary>
/// A sprite batch context is a set of information for a <see cref="SpriteBatch"/> to use, which encapsulates all of the information usually passed directly to <see cref="SpriteBatch.Begin"/>.
/// To use a sprite batch context effectively, the extension methods in <see cref="SpriteBatchContextExtensions"/> should be used.
/// </summary>
public struct SpriteBatchContext {
/// <summary>
/// The drawing order for sprite and text drawing.
/// </summary>
public SpriteSortMode SortMode;
/// <summary>
/// State of the blending.
/// </summary>
public BlendState BlendState;
/// <summary>
/// State of the sampler.
/// </summary>
public SamplerState SamplerState;
/// <summary>
/// State of the depth-stencil buffer.
/// </summary>
public DepthStencilState DepthStencilState;
/// <summary>
/// State of the rasterization.
/// </summary>
public RasterizerState RasterizerState;
/// <summary>
/// A custom <see cref="T:Microsoft.Xna.Framework.Graphics.Effect" /> to override the default sprite effect.
/// </summary>
public Effect Effect;
/// <summary>
/// An optional matrix used to transform the sprite geometry.
/// </summary>
public Matrix TransformMatrix;
/// <summary>
/// Creates a new sprite batch context with the given parameters.
/// </summary>
/// <param name="sortMode">The drawing order for sprite and text drawing. <see cref="F:Microsoft.Xna.Framework.Graphics.SpriteSortMode.Deferred" /> by default.</param>
/// <param name="blendState">State of the blending. Uses <see cref="F:Microsoft.Xna.Framework.Graphics.BlendState.AlphaBlend" /> if null.</param>
/// <param name="samplerState">State of the sampler. Uses <see cref="F:Microsoft.Xna.Framework.Graphics.SamplerState.LinearClamp" /> if null.</param>
/// <param name="depthStencilState">State of the depth-stencil buffer. Uses <see cref="F:Microsoft.Xna.Framework.Graphics.DepthStencilState.None" /> if null.</param>
/// <param name="rasterizerState">State of the rasterization. Uses <see cref="F:Microsoft.Xna.Framework.Graphics.RasterizerState.CullCounterClockwise" /> if null.</param>
/// <param name="effect">A custom <see cref="T:Microsoft.Xna.Framework.Graphics.Effect" /> to override the default sprite effect.</param>
/// <param name="transformMatrix">An optional matrix used to transform the sprite geometry. Uses <see cref="P:Microsoft.Xna.Framework.Matrix.Identity" /> if null.</param>
public SpriteBatchContext(SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState blendState = null, SamplerState samplerState = null, DepthStencilState depthStencilState = null, RasterizerState rasterizerState = null, Effect effect = null, Matrix? transformMatrix = null) {
this.SortMode = sortMode;
this.BlendState = blendState ?? BlendState.AlphaBlend;
this.SamplerState = samplerState ?? SamplerState.LinearClamp;
this.DepthStencilState = depthStencilState ?? DepthStencilState.None;
this.RasterizerState = rasterizerState ?? RasterizerState.CullCounterClockwise;
this.Effect = effect;
this.TransformMatrix = transformMatrix ?? Matrix.Identity;
}
/// <summary>
/// Creates a new sprite batch context from the passed <see cref="GraphicsDevice"/>'s current information.
/// This can be useful to retrieve some information about drawing right after a <see cref="SpriteBatch.End"/> call has occured.
/// </summary>
/// <param name="device">The graphics device to query data from.</param>
/// <param name="sortMode">The drawing order for sprite and text drawing. <see cref="F:Microsoft.Xna.Framework.Graphics.SpriteSortMode.Deferred" /> by default.</param>
/// <param name="effect">A custom <see cref="T:Microsoft.Xna.Framework.Graphics.Effect" /> to override the default sprite effect.</param>
/// <param name="transformMatrix">An optional matrix used to transform the sprite geometry. Uses <see cref="P:Microsoft.Xna.Framework.Matrix.Identity" /> if null.</param>
/// <returns>A new sprite batch context from the <paramref name="device"/>'s current information.</returns>
public static SpriteBatchContext Current(GraphicsDevice device, SpriteSortMode sortMode = SpriteSortMode.Deferred, Effect effect = null, Matrix? transformMatrix = null) {
return new SpriteBatchContext(sortMode, device.BlendState, device.SamplerStates[0], device.DepthStencilState, device.RasterizerState, effect, transformMatrix);
}
}
/// <summary>
/// A set of extensions for <see cref="SpriteBatchContext"/>.
/// </summary>
public static class SpriteBatchContextExtensions {
/// <summary>
/// Begins a new sprite and text batch with the specified <see cref="SpriteBatchContext"/>
/// </summary>
/// <param name="batch">The sprite batch to use for drawing.</param>
/// <param name="context">The sprite batch context to use.</param>
public static void Begin(this SpriteBatch batch, SpriteBatchContext context) {
batch.Begin(context.SortMode, context.BlendState, context.SamplerState, context.DepthStencilState, context.RasterizerState, context.Effect, context.TransformMatrix);
}
/// <summary>
/// Draws the given batch's content onto the <see cref="GraphicsDevice"/>'s current render target (or the back buffer) with the given settings.
/// Note that this method should not be called while a regular <see cref="SpriteBatch"/> is currently active.
/// </summary>
/// <param name="batch">The static sprite batch to use for drawing.</param>
/// <param name="context">The sprite batch context to use.</param>
public static void Draw(this StaticSpriteBatch batch, SpriteBatchContext context) {
batch.Draw(context.BlendState, context.SamplerState, context.DepthStencilState, context.RasterizerState, context.Effect, context.TransformMatrix);
}
}
}