diff --git a/Demos/UiDemo.cs b/Demos/UiDemo.cs index c57b146..f9ef3e5 100644 --- a/Demos/UiDemo.cs +++ b/Demos/UiDemo.cs @@ -8,6 +8,7 @@ using MLEM.Extensions; using MLEM.Font; using MLEM.Formatting; using MLEM.Input; +using MLEM.Misc; using MLEM.Startup; using MLEM.Textures; using MLEM.Ui; @@ -173,6 +174,17 @@ namespace Demos { PositionOffset = new Vector2(0, 1) }); + root.AddChild(new VerticalSpace(3)); + root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Progress bars in multiple orientations:")); + var bar1 = root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Right, 10) {PositionOffset = new Vector2(0, 1)}); + CoroutineHandler.Start(this.WobbleProgressBar(bar1)); + var bar2 = root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Left, 10) {PositionOffset = new Vector2(0, 1)}); + CoroutineHandler.Start(this.WobbleProgressBar(bar2)); + var bar3 = root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(8, 30), Direction2.Down, 10) {PositionOffset = new Vector2(0, 1)}); + CoroutineHandler.Start(this.WobbleProgressBar(bar3)); + var bar4 = root.AddChild(new ProgressBar(Anchor.AutoInline, new Vector2(8, 30), Direction2.Up, 10) {PositionOffset = new Vector2(1, 1)}); + CoroutineHandler.Start(this.WobbleProgressBar(bar4)); + root.AddChild(new VerticalSpace(3)); root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "There are also some additional \"components\" which are created as combinations of other components. You can find all of them in the ElementHelper class. Here are some examples:")); root.AddChild(ElementHelper.NumberField(Anchor.AutoLeft, new Vector2(1, 10))).PositionOffset = new Vector2(0, 1); @@ -226,6 +238,22 @@ namespace Demos { group.Transform = Matrix.Identity; } + private IEnumerator WobbleProgressBar(ProgressBar bar) { + var reducing = false; + while (bar.Root != null) { + if (reducing) { + bar.CurrentValue -= 0.1F; + if (bar.CurrentValue <= 0) + reducing = false; + } else { + bar.CurrentValue += 0.1F; + if (bar.CurrentValue >= bar.MaxValue) + reducing = true; + } + yield return new WaitSeconds(0.01F); + } + } + public override void Clear() { this.UiSystem.Remove("Test"); this.UiSystem.Remove("TestTooltip"); diff --git a/MLEM.Ui/Elements/Element.cs b/MLEM.Ui/Elements/Element.cs index e3634ad..bee99b8 100644 --- a/MLEM.Ui/Elements/Element.cs +++ b/MLEM.Ui/Elements/Element.cs @@ -66,15 +66,7 @@ namespace MLEM.Ui.Elements { this.SetAreaDirty(); } } - public Rectangle ChildPaddedArea { - get { - var padded = this.UnscrolledArea; - padded.Location += this.ScaledChildPadding; - padded.Width -= this.ScaledChildPadding.X * 2; - padded.Height -= this.ScaledChildPadding.Y * 2; - return padded; - } - } + public Rectangle ChildPaddedArea => this.UnscrolledArea.Shrink(this.ScaledChildPadding); public Point ScaledChildPadding => this.childPadding.Multiply(this.Scale); public GenericCallback OnPressed; @@ -131,15 +123,7 @@ namespace MLEM.Ui.Elements { public Rectangle Area => this.UnscrolledArea.OffsetCopy(this.ScaledScrollOffset); public Point ScrollOffset; public Point ScaledScrollOffset => this.ScrollOffset.Multiply(this.Scale); - public Rectangle DisplayArea { - get { - var padded = this.Area; - padded.Location += this.ScaledPadding; - padded.Width -= this.ScaledPadding.X * 2; - padded.Height -= this.ScaledPadding.Y * 2; - return padded; - } - } + public Rectangle DisplayArea => this.Area.Shrink(this.ScaledPadding); private int priority; public int Priority { get => this.priority; diff --git a/MLEM.Ui/Elements/ProgressBar.cs b/MLEM.Ui/Elements/ProgressBar.cs new file mode 100644 index 0000000..028ee77 --- /dev/null +++ b/MLEM.Ui/Elements/ProgressBar.cs @@ -0,0 +1,78 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MLEM.Extensions; +using MLEM.Misc; +using MLEM.Textures; +using MLEM.Ui.Style; + +namespace MLEM.Ui.Elements { + public class ProgressBar : Element { + + public NinePatch Texture; + public Color Color; + public Point ProgressPadding; + public NinePatch ProgressTexture; + public Color ProgressColor; + + public Direction2 Direction; + public float MaxValue; + private float currentValue; + public float CurrentValue { + get => this.currentValue; + set => this.currentValue = MathHelper.Clamp(value, 0, this.MaxValue); + } + + public ProgressBar(Anchor anchor, Vector2 size, Direction2 direction, float maxValue, float currentValue = 0) : base(anchor, size) { + if (!direction.IsAdjacent()) + throw new NotSupportedException("Progress bars only support Up, Down, Left and Right directions"); + this.Direction = direction; + this.MaxValue = maxValue; + this.currentValue = currentValue; + } + + public override void Draw(GameTime time, SpriteBatch batch, float alpha) { + batch.Draw(this.Texture, this.DisplayArea, this.Color * alpha, this.Scale); + + var percentage = this.CurrentValue / this.MaxValue; + var width = (percentage * this.DisplayArea.Width).Floor(); + var height = (percentage * this.DisplayArea.Height).Floor(); + Rectangle progressArea; + switch (this.Direction) { + case Direction2.Up: + progressArea = new Rectangle(this.DisplayArea.X, + this.DisplayArea.Y + (this.DisplayArea.Height - height), + this.DisplayArea.Width, height); + break; + case Direction2.Down: + progressArea = new Rectangle(this.DisplayArea.Location, new Point(this.DisplayArea.Width, height)); + break; + case Direction2.Left: + progressArea = new Rectangle( + this.DisplayArea.X + (this.DisplayArea.Width - width), + this.DisplayArea.Y, width, this.DisplayArea.Height); + break; + default: // Right + progressArea = new Rectangle(this.DisplayArea.Location, new Point(width, this.DisplayArea.Height)); + break; + } + var offsetArea = progressArea.Shrink(this.ProgressPadding.Multiply(this.Scale)); + if (this.ProgressTexture != null) { + batch.Draw(this.ProgressTexture, offsetArea, this.ProgressColor * alpha, this.Scale); + } else { + batch.Draw(batch.GetBlankTexture(), offsetArea, this.ProgressColor * alpha); + } + base.Draw(time, batch, alpha); + } + + protected override void InitStyle(UiStyle style) { + base.InitStyle(style); + this.Texture = style.ProgressBarTexture; + this.Color = style.ProgressBarColor; + this.ProgressPadding = style.ProgressBarProgressPadding; + this.ProgressTexture = style.ProgressBarProgressTexture; + this.ProgressColor = style.ProgressBarProgressColor; + } + + } +} \ No newline at end of file diff --git a/MLEM.Ui/Style/UiStyle.cs b/MLEM.Ui/Style/UiStyle.cs index c4358bc..1ed6438 100644 --- a/MLEM.Ui/Style/UiStyle.cs +++ b/MLEM.Ui/Style/UiStyle.cs @@ -25,6 +25,11 @@ namespace MLEM.Ui.Style { public TextureRegion RadioCheckmark; public NinePatch TooltipBackground; public Color TooltipBackgroundColor; + public NinePatch ProgressBarTexture; + public Color ProgressBarColor; + public Point ProgressBarProgressPadding; + public NinePatch ProgressBarProgressTexture; + public Color ProgressBarProgressColor; public IGenericFont Font; public IGenericFont BoldFont; public IGenericFont ItalicFont; diff --git a/MLEM.Ui/Style/UntexturedStyle.cs b/MLEM.Ui/Style/UntexturedStyle.cs index b436b7d..9d49954 100644 --- a/MLEM.Ui/Style/UntexturedStyle.cs +++ b/MLEM.Ui/Style/UntexturedStyle.cs @@ -25,6 +25,10 @@ namespace MLEM.Ui.Style { this.RadioCheckmark = GenerateTexture(batch, Color.CornflowerBlue).Region; this.TooltipBackground = GenerateTexture(batch, Color.DarkGray); this.TooltipBackgroundColor = new Color(Color.Black, 0.65F); + this.ProgressBarTexture = GenerateTexture(batch, Color.RoyalBlue); + this.ProgressBarColor = Color.White; + this.ProgressBarProgressPadding = new Point(1); + this.ProgressBarProgressColor = Color.Red; this.Font = new EmptyFont(); } diff --git a/MLEM/Extensions/NumberExtensions.cs b/MLEM/Extensions/NumberExtensions.cs index 8ebd503..a3b9132 100644 --- a/MLEM/Extensions/NumberExtensions.cs +++ b/MLEM/Extensions/NumberExtensions.cs @@ -44,5 +44,13 @@ namespace MLEM.Extensions { return rect; } + public static Rectangle Shrink(this Rectangle rect, Point padding) { + rect.X += padding.X; + rect.Y += padding.Y; + rect.Width -= padding.X * 2; + rect.Height -= padding.Y * 2; + return rect; + } + } } \ No newline at end of file