using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MLEM.Ui.Elements {
///
/// A that can have custom drawing parameters.
/// Custom drawing parameters include a matrix, as well as a custom call.
/// All of the custom draw group will be drawn with the custom parameters.
///
public class CustomDrawGroup : Group {
///
/// This custom draw group's transform matrix
///
public Matrix? Transform;
///
/// A callback for retrieving this group's automatically
///
public TransformCallback TransformGetter;
private BeginDelegate beginImpl;
private bool isDefaultBegin;
///
/// The call that this custom draw group should make to to begin drawing.
///
public BeginDelegate BeginImpl {
get => this.beginImpl;
set {
this.beginImpl = value ?? ((element, time, batch, alpha, blendState, samplerState, matrix) => batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, null, null, null, matrix));
this.isDefaultBegin = value == null;
}
}
///
/// Creates a new custom draw group with the given settings
///
/// The group's anchor
/// The group's size
/// The group's
/// The group's
/// Whether this group should automatically calculate its height based on its children
public CustomDrawGroup(Anchor anchor, Vector2 size, TransformCallback transformGetter = null, BeginDelegate beginImpl = null, bool setHeightBasedOnChildren = true) :
base(anchor, size, setHeightBasedOnChildren) {
this.TransformGetter = transformGetter ?? ((element, time, matrix) => Matrix.Identity);
this.BeginImpl = beginImpl;
}
///
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
var transform = this.Transform ?? this.TransformGetter(this, time, matrix);
var customDraw = !this.isDefaultBegin || transform != Matrix.Identity;
var mat = matrix * transform;
if (customDraw) {
// end the usual draw so that we can begin our own
batch.End();
this.BeginImpl(this, time, batch, alpha, blendState, samplerState, mat);
}
// draw child components in custom begin call
base.Draw(time, batch, alpha, blendState, samplerState, mat);
if (customDraw) {
// end our draw
batch.End();
// begin the usual draw again for other elements
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, null, null, null, matrix);
}
}
///
/// Scales this custom draw group's matrix based on the given scale and origin.
///
/// The scale to use
/// The origin to use for scaling, or null to use this element's center point
public void ScaleOrigin(float scale, Vector2? origin = null) {
this.Transform = Matrix.CreateScale(scale, scale, 0) * Matrix.CreateTranslation(new Vector3((1 - scale) * (origin ?? this.DisplayArea.Center), 0));
}
///
/// A delegate method used for
///
/// The custom draw group
/// The game's time
/// The sprite batch used for drawing
/// This element's draw alpha
/// The blend state used for drawing
/// The sampler state used for drawing
/// The transform matrix used for drawing
public delegate void BeginDelegate(CustomDrawGroup element, GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix);
///
/// A delegate method used for
///
/// The element whose transform to get
/// The game's time
/// The regular transform matrix
public delegate Matrix TransformCallback(CustomDrawGroup element, GameTime time, Matrix matrix);
}
}