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, 1) * 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); } }