mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-22 20:58:34 +01:00
move CustomDrawGroup behavior into Element, allowing any element to inherit it
This commit is contained in:
parent
98937ee83f
commit
f1d686f0c0
4 changed files with 99 additions and 81 deletions
|
@ -138,9 +138,8 @@ namespace Demos {
|
||||||
this.root.AddChild(slider);
|
this.root.AddChild(slider);
|
||||||
|
|
||||||
// Check the WobbleButton method for an explanation of how this button works
|
// Check the WobbleButton method for an explanation of how this button works
|
||||||
var group = this.root.AddChild(new CustomDrawGroup(Anchor.AutoLeft, new Vector2(1, 0)));
|
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Wobble Me", "This button wobbles around visually when clicked, but this doesn't affect its actual size and positioning") {
|
||||||
group.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Wobble Me", "This button wobbles around visually when clicked, but this doesn't affect its actual size and positioning") {
|
OnPressed = element => CoroutineHandler.Start(WobbleButton(element)),
|
||||||
OnPressed = element => CoroutineHandler.Start(WobbleButton(group)),
|
|
||||||
PositionOffset = new Vector2(0, 1)
|
PositionOffset = new Vector2(0, 1)
|
||||||
});
|
});
|
||||||
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Transform Ui", "This button causes the entire ui to be transformed (both in positioning, rotation and scale)") {
|
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Transform Ui", "This button causes the entire ui to be transformed (both in positioning, rotation and scale)") {
|
||||||
|
@ -200,20 +199,20 @@ namespace Demos {
|
||||||
|
|
||||||
// This method is used by the wobbling button (see above)
|
// This method is used by the wobbling button (see above)
|
||||||
// Note that this particular example makes use of the Coroutine package, which is not required but makes demonstration easier
|
// Note that this particular example makes use of the Coroutine package, which is not required but makes demonstration easier
|
||||||
private static IEnumerator<Wait> WobbleButton(CustomDrawGroup group) {
|
private static IEnumerator<Wait> WobbleButton(Element button) {
|
||||||
var counter = 0F;
|
var counter = 0F;
|
||||||
while (counter < 4 * Math.PI) {
|
while (counter < 4 * Math.PI) {
|
||||||
// A custom draw group allows the implementation of any sort of custom rendering for all of its child components
|
// Every element allows the implementation of any sort of custom rendering for itself and all of its child components
|
||||||
// This includes simply changing the transform matrix like here, but also applying custom effects and doing
|
// This includes simply changing the transform matrix like here, but also applying custom effects and doing
|
||||||
// anything else that can be done in the SpriteBatch's Begin call.
|
// anything else that can be done in the SpriteBatch's Begin call.
|
||||||
// Note that changing visual features like this
|
// Note that changing visual features like this
|
||||||
// has no effect on the ui's actual interaction behavior (mouse position interpretation, for example), but it can
|
// has no effect on the ui's actual interaction behavior (mouse position interpretation, for example), but it can
|
||||||
// be a great way to accomplish feedback animations for buttons and so on.
|
// be a great way to accomplish feedback animations for buttons and so on.
|
||||||
group.Transform = Matrix.CreateTranslation((float) Math.Sin(counter / 2) * 10 * group.Scale, 0, 0);
|
button.Transform = Matrix.CreateTranslation((float) Math.Sin(counter / 2) * 10 * button.Scale, 0, 0);
|
||||||
counter += 0.1F;
|
counter += 0.1F;
|
||||||
yield return new Wait(0.01F);
|
yield return new Wait(0.01F);
|
||||||
}
|
}
|
||||||
group.Transform = Matrix.Identity;
|
button.Transform = Matrix.Identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerator<Wait> WobbleProgressBar(ProgressBar bar) {
|
private static IEnumerator<Wait> WobbleProgressBar(ProgressBar bar) {
|
||||||
|
|
|
@ -1,42 +1,23 @@
|
||||||
|
using System;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace MLEM.Ui.Elements {
|
namespace MLEM.Ui.Elements {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="Group"/> that can have custom drawing parameters.
|
/// A <see cref="Group"/> that can have custom drawing parameters.
|
||||||
/// Custom drawing parameters include a <see cref="Transform"/> matrix, as well as a custom <see cref="SpriteBatch.Begin"/> call.
|
/// Custom drawing parameters include a <see cref="Element.Transform"/> matrix, as well as a custom <see cref="SpriteBatch.Begin"/> call.
|
||||||
/// All <see cref="Element.Children"/> of the custom draw group will be drawn with the custom parameters.
|
/// All <see cref="Element.Children"/> of the custom draw group will be drawn with the custom parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("CustomDrawGroup mechanics have been moved down to Element, which means custom draw groups are no longer necessary.")]
|
||||||
public class CustomDrawGroup : Group {
|
public class CustomDrawGroup : Group {
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This custom draw group's transform matrix
|
|
||||||
/// </summary>
|
|
||||||
public Matrix? Transform;
|
|
||||||
/// <summary>
|
|
||||||
/// A callback for retrieving this group's <see cref="Transform"/> automatically
|
|
||||||
/// </summary>
|
|
||||||
public TransformCallback TransformGetter;
|
|
||||||
private BeginDelegate beginImpl;
|
|
||||||
private bool isDefaultBegin;
|
|
||||||
/// <summary>
|
|
||||||
/// The call that this custom draw group should make to <see cref="SpriteBatch"/> to begin drawing.
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new custom draw group with the given settings
|
/// Creates a new custom draw group with the given settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="anchor">The group's anchor</param>
|
/// <param name="anchor">The group's anchor</param>
|
||||||
/// <param name="size">The group's size</param>
|
/// <param name="size">The group's size</param>
|
||||||
/// <param name="transformGetter">The group's <see cref="TransformGetter"/></param>
|
/// <param name="transformGetter">The group's <see cref="Element.TransformGetter"/></param>
|
||||||
/// <param name="beginImpl">The group's <see cref="BeginImpl"/></param>
|
/// <param name="beginImpl">The group's <see cref="Element.BeginImpl"/></param>
|
||||||
/// <param name="setHeightBasedOnChildren">Whether this group should automatically calculate its height based on its children</param>
|
/// <param name="setHeightBasedOnChildren">Whether this group should automatically calculate its height based on its children</param>
|
||||||
public CustomDrawGroup(Anchor anchor, Vector2 size, TransformCallback transformGetter = null, BeginDelegate beginImpl = null, bool setHeightBasedOnChildren = true) :
|
public CustomDrawGroup(Anchor anchor, Vector2 size, TransformCallback transformGetter = null, BeginDelegate beginImpl = null, bool setHeightBasedOnChildren = true) :
|
||||||
base(anchor, size, setHeightBasedOnChildren) {
|
base(anchor, size, setHeightBasedOnChildren) {
|
||||||
|
@ -44,54 +25,11 @@ namespace MLEM.Ui.Elements {
|
||||||
this.BeginImpl = beginImpl;
|
this.BeginImpl = beginImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
///<inheritdoc cref="Element.ScaleTransform"/>
|
||||||
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
|
[Obsolete("Use ScaleTransform instead")]
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Scales this custom draw group's <see cref="Transform"/> matrix based on the given scale and origin.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="scale">The scale to use</param>
|
|
||||||
/// <param name="origin">The origin to use for scaling, or null to use this element's center point</param>
|
|
||||||
public void ScaleOrigin(float scale, Vector2? origin = null) {
|
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));
|
this.ScaleTransform(scale, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A delegate method used for <see cref="CustomDrawGroup.BeginImpl"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="element">The custom draw group</param>
|
|
||||||
/// <param name="time">The game's time</param>
|
|
||||||
/// <param name="batch">The sprite batch used for drawing</param>
|
|
||||||
/// <param name="alpha">This element's draw alpha</param>
|
|
||||||
/// <param name="blendState">The blend state used for drawing</param>
|
|
||||||
/// <param name="samplerState">The sampler state used for drawing</param>
|
|
||||||
/// <param name="matrix">The transform matrix used for drawing</param>
|
|
||||||
public delegate void BeginDelegate(CustomDrawGroup element, GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A delegate method used for <see cref="CustomDrawGroup.TransformGetter"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="element">The element whose transform to get</param>
|
|
||||||
/// <param name="time">The game's time</param>
|
|
||||||
/// <param name="matrix">The regular transform matrix</param>
|
|
||||||
public delegate Matrix TransformCallback(CustomDrawGroup element, GameTime time, Matrix matrix);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -225,6 +225,22 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This element's transform matrix.
|
||||||
|
/// Can easily be scaled using <see cref="ScaleTransform"/>.
|
||||||
|
/// Note that, when this is non-null, a new <see cref="SpriteBatch.Begin"/> call is used for this element.
|
||||||
|
/// </summary>
|
||||||
|
public Matrix? Transform;
|
||||||
|
/// <summary>
|
||||||
|
/// A callback for retrieving this element's <see cref="Transform"/> automatically.
|
||||||
|
/// </summary>
|
||||||
|
public TransformCallback TransformGetter = (e, time, m) => Matrix.Identity;
|
||||||
|
/// <summary>
|
||||||
|
/// The call that this element should make to <see cref="SpriteBatch"/> to begin drawing.
|
||||||
|
/// Note that, when this is non-null, a new <see cref="SpriteBatch.Begin"/> call is used for this element.
|
||||||
|
/// </summary>
|
||||||
|
public BeginDelegate BeginImpl;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set this field to false to disallow the element from being selected.
|
/// Set this field to false to disallow the element from being selected.
|
||||||
/// An unselectable element is skipped by automatic navigation and its <see cref="OnSelected"/> callback will never be called.
|
/// An unselectable element is skipped by automatic navigation and its <see cref="OnSelected"/> callback will never be called.
|
||||||
|
@ -379,6 +395,8 @@ namespace MLEM.Ui.Elements {
|
||||||
this.anchor = anchor;
|
this.anchor = anchor;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
|
||||||
|
// force BeginImpl to be reset to the default
|
||||||
|
this.BeginImpl = null;
|
||||||
this.OnMouseEnter += element => this.IsMouseOver = true;
|
this.OnMouseEnter += element => this.IsMouseOver = true;
|
||||||
this.OnMouseExit += element => this.IsMouseOver = false;
|
this.OnMouseExit += element => this.IsMouseOver = false;
|
||||||
this.OnTouchEnter += element => this.IsMouseOver = true;
|
this.OnTouchEnter += element => this.IsMouseOver = true;
|
||||||
|
@ -806,8 +824,42 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws this element and all of its <see cref="GetRelevantChildren"/>
|
/// Draws this element by calling <see cref="Draw"/> internally.
|
||||||
/// Note that, when this is called, <see cref="SpriteBatch.Begin"/> has already been called.
|
/// 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="blendState">The blend state that is used for drawing</param>
|
||||||
|
/// <param name="samplerState">The sampler state that is used for drawing</param>
|
||||||
|
/// <param name="matrix">The transformation matrix that is used for drawing</param>
|
||||||
|
public void DrawAll(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
|
||||||
|
var transform = this.Transform ?? this.TransformGetter(this, time, matrix);
|
||||||
|
var customDraw = this.BeginImpl != null || transform != Matrix.Identity;
|
||||||
|
var mat = matrix * transform;
|
||||||
|
if (customDraw) {
|
||||||
|
// end the usual draw so that we can begin our own
|
||||||
|
batch.End();
|
||||||
|
// begin our own draw call
|
||||||
|
if (this.BeginImpl != null) {
|
||||||
|
this.BeginImpl(this, time, batch, alpha, blendState, samplerState, mat);
|
||||||
|
} else {
|
||||||
|
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, null, null, null, mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// draw content in custom begin call
|
||||||
|
this.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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>
|
/// </summary>
|
||||||
/// <param name="time">The game's time</param>
|
/// <param name="time">The game's time</param>
|
||||||
/// <param name="batch">The sprite batch to use for drawing</param>
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
|
@ -822,7 +874,7 @@ namespace MLEM.Ui.Elements {
|
||||||
|
|
||||||
foreach (var child in this.GetRelevantChildren()) {
|
foreach (var child in this.GetRelevantChildren()) {
|
||||||
if (!child.IsHidden)
|
if (!child.IsHidden)
|
||||||
child.Draw(time, batch, alpha * child.DrawAlpha, blendState, samplerState, matrix);
|
child.DrawAll(time, batch, alpha * child.DrawAlpha, blendState, samplerState, matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,6 +940,15 @@ namespace MLEM.Ui.Elements {
|
||||||
this.Children.Reverse(index, count ?? this.Children.Count);
|
this.Children.Reverse(index, count ?? this.Children.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scales this element's <see cref="Transform"/> matrix based on the given scale and origin.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scale">The scale to use</param>
|
||||||
|
/// <param name="origin">The origin to use for scaling, or null to use this element's center point</param>
|
||||||
|
public void ScaleTransform(float scale, Vector2? origin = null) {
|
||||||
|
this.Transform = Matrix.CreateScale(scale, scale, 1) * Matrix.CreateTranslation(new Vector3((1 - scale) * (origin ?? this.DisplayArea.Center), 0));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes this element's <see cref="StyleProp{T}"/> instances using the ui system's <see cref="UiStyle"/>.
|
/// Initializes this element's <see cref="StyleProp{T}"/> instances using the ui system's <see cref="UiStyle"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -949,5 +1010,25 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <param name="usualNext">The element that is considered to be the next element by default</param>
|
/// <param name="usualNext">The element that is considered to be the next element by default</param>
|
||||||
public delegate Element GamepadNextElementCallback(Direction2 dir, Element usualNext);
|
public delegate Element GamepadNextElementCallback(Direction2 dir, Element usualNext);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate method used for <see cref="CustomDrawGroup.BeginImpl"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">The custom draw group</param>
|
||||||
|
/// <param name="time">The game's time</param>
|
||||||
|
/// <param name="batch">The sprite batch used for drawing</param>
|
||||||
|
/// <param name="alpha">This element's draw alpha</param>
|
||||||
|
/// <param name="blendState">The blend state used for drawing</param>
|
||||||
|
/// <param name="samplerState">The sampler state used for drawing</param>
|
||||||
|
/// <param name="matrix">The transform matrix used for drawing</param>
|
||||||
|
public delegate void BeginDelegate(Element element, GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate method used for <see cref="CustomDrawGroup.TransformGetter"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">The element whose transform to get</param>
|
||||||
|
/// <param name="time">The game's time</param>
|
||||||
|
/// <param name="matrix">The regular transform matrix</param>
|
||||||
|
public delegate Matrix TransformCallback(Element element, GameTime time, Matrix matrix);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -260,7 +260,7 @@ namespace MLEM.Ui {
|
||||||
continue;
|
continue;
|
||||||
batch.Begin(SpriteSortMode.Deferred, this.BlendState, this.SamplerState, null, null, null, root.Transform);
|
batch.Begin(SpriteSortMode.Deferred, this.BlendState, this.SamplerState, null, null, null, root.Transform);
|
||||||
var alpha = this.DrawAlpha * root.Element.DrawAlpha;
|
var alpha = this.DrawAlpha * root.Element.DrawAlpha;
|
||||||
root.Element.Draw(time, batch, alpha, this.BlendState, this.SamplerState, root.Transform);
|
root.Element.DrawAll(time, batch, alpha, this.BlendState, this.SamplerState, root.Transform);
|
||||||
batch.End();
|
batch.End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue