mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 22:18:34 +01:00
Some more ui style improvements
This commit is contained in:
parent
3648352540
commit
ca89d03ca4
11 changed files with 64 additions and 42 deletions
|
@ -27,6 +27,8 @@ Improvements
|
||||||
- Exposed the epsilon value used by Element calculations
|
- Exposed the epsilon value used by Element calculations
|
||||||
- Made Image ScaleToImage take ui scale into account
|
- Made Image ScaleToImage take ui scale into account
|
||||||
- Added style properties for a lot of hardcoded default element styles
|
- Added style properties for a lot of hardcoded default element styles
|
||||||
|
- Allow style properties to set style values with a higher priority, which allows elements to style their default children
|
||||||
|
- Allow changing the entire ui style for a single element
|
||||||
|
|
||||||
Fixes
|
Fixes
|
||||||
- Fixed VerticalSpace height parameter being an integer
|
- Fixed VerticalSpace height parameter being an integer
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace Demos {
|
||||||
this.UiRoot.AddChild(this.root);
|
this.UiRoot.AddChild(this.root);
|
||||||
|
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a small demo for MLEM.Ui, a user interface library that is part of the MLEM Library for Extending MonoGame."));
|
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a small demo for MLEM.Ui, a user interface library that is part of the MLEM Library for Extending MonoGame."));
|
||||||
var image = this.root.AddChild(new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true, Padding = new Vector2(3)});
|
var image = this.root.AddChild(new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true, Padding = new Padding(3)});
|
||||||
// Setting the x or y coordinate of the size to 1 or a lower number causes the width or height to be a percentage of the parent's width or height
|
// Setting the x or y coordinate of the size to 1 or a lower number causes the width or height to be a percentage of the parent's width or height
|
||||||
// (for example, setting the size's x to 0.75 would make the element's width be 0.75*parentWidth)
|
// (for example, setting the size's x to 0.75 would make the element's width be 0.75*parentWidth)
|
||||||
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), "Toggle Grass Image", "This button shows a grass tile above it to show the automatic anchoring of objects.") {
|
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), "Toggle Grass Image", "This button shows a grass tile above it to show the automatic anchoring of objects.") {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Misc;
|
||||||
using MLEM.Textures;
|
using MLEM.Textures;
|
||||||
using MLEM.Ui.Style;
|
using MLEM.Ui.Style;
|
||||||
|
|
||||||
|
@ -81,7 +82,8 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <param name="tooltipText">The text that should be displayed in a <see cref="Tooltip"/> when hovering over this button</param>
|
/// <param name="tooltipText">The text that should be displayed in a <see cref="Tooltip"/> when hovering over this button</param>
|
||||||
public Button(Anchor anchor, Vector2 size, string text = null, string tooltipText = null) : base(anchor, size) {
|
public Button(Anchor anchor, Vector2 size, string text = null, string tooltipText = null) : base(anchor, size) {
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
this.Text = new Paragraph(Anchor.Center, 1, text, true) {Padding = new Vector2(1)};
|
this.Text = new Paragraph(Anchor.Center, 1, text, true);
|
||||||
|
this.Text.Padding.SetFromStyle(new Padding(1), 1);
|
||||||
this.AddChild(this.Text);
|
this.AddChild(this.Text);
|
||||||
}
|
}
|
||||||
if (tooltipText != null)
|
if (tooltipText != null)
|
||||||
|
|
|
@ -32,8 +32,17 @@ namespace MLEM.Ui.Elements {
|
||||||
internal set {
|
internal set {
|
||||||
this.system = value;
|
this.system = value;
|
||||||
this.Controls = value?.Controls;
|
this.Controls = value?.Controls;
|
||||||
if (this.system != null)
|
this.Style = value?.Style;
|
||||||
this.InitStyle(this.system.Style);
|
}
|
||||||
|
}
|
||||||
|
public UiStyle Style {
|
||||||
|
get => this.style;
|
||||||
|
set {
|
||||||
|
if (this.style != value) {
|
||||||
|
this.style = value;
|
||||||
|
if (value != null)
|
||||||
|
this.InitStyle(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -109,31 +118,13 @@ namespace MLEM.Ui.Elements {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector2 ScaledOffset => this.offset * this.Scale;
|
public Vector2 ScaledOffset => this.offset * this.Scale;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The padding that this element has.
|
|
||||||
/// The padding is subtracted from the element's <see cref="Size"/>, and it is an area that the element does not extend into. This means that this element's resulting <see cref="DisplayArea"/> does not include this padding.
|
|
||||||
/// </summary>
|
|
||||||
public Padding Padding;
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="Padding"/>, but with <see cref="Scale"/> applied.
|
/// The <see cref="Padding"/>, but with <see cref="Scale"/> applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Padding ScaledPadding => this.Padding * this.Scale;
|
public Padding ScaledPadding => this.Padding.Value * this.Scale;
|
||||||
/// <summary>
|
|
||||||
/// The child padding that this element has.
|
|
||||||
/// The child padding moves any <see cref="Children"/> added to this element inwards by the given amount in each direction.
|
|
||||||
/// </summary>
|
|
||||||
public Padding ChildPadding {
|
|
||||||
get => this.childPadding;
|
|
||||||
set {
|
|
||||||
if (this.childPadding == value)
|
|
||||||
return;
|
|
||||||
this.childPadding = value;
|
|
||||||
this.SetAreaDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="ChildPadding"/>, but with <see cref="Scale"/> applied.
|
/// The <see cref="ChildPadding"/>, but with <see cref="Scale"/> applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Padding ScaledChildPadding => this.childPadding * this.Scale;
|
public Padding ScaledChildPadding => this.ChildPadding.Value * this.Scale;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This element's current <see cref="Area"/>, but with <see cref="ScaledChildPadding"/> applied.
|
/// This element's current <see cref="Area"/>, but with <see cref="ScaledChildPadding"/> applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -260,6 +251,7 @@ namespace MLEM.Ui.Elements {
|
||||||
/// Stores whether this element is its <see cref="Root"/>'s <see cref="RootElement.SelectedElement"/>.
|
/// Stores whether this element is its <see cref="Root"/>'s <see cref="RootElement.SelectedElement"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsSelected { get; protected set; }
|
public bool IsSelected { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A style property that contains the selection indicator that is displayed on this element if it is the <see cref="RootElement.SelectedElement"/>
|
/// A style property that contains the selection indicator that is displayed on this element if it is the <see cref="RootElement.SelectedElement"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -272,6 +264,17 @@ namespace MLEM.Ui.Elements {
|
||||||
/// A style property that contains the sound effect that is played when this element's <see cref="OnSecondaryPressed"/> is called
|
/// A style property that contains the sound effect that is played when this element's <see cref="OnSecondaryPressed"/> is called
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public StyleProp<SoundEffectInfo> SecondActionSound;
|
public StyleProp<SoundEffectInfo> SecondActionSound;
|
||||||
|
/// <summary>
|
||||||
|
/// The padding that this element has.
|
||||||
|
/// The padding is subtracted from the element's <see cref="Size"/>, and it is an area that the element does not extend into. This means that this element's resulting <see cref="DisplayArea"/> does not include this padding.
|
||||||
|
/// </summary>
|
||||||
|
public StyleProp<Padding> Padding;
|
||||||
|
/// <summary>
|
||||||
|
/// The child padding that this element has.
|
||||||
|
/// The child padding moves any <see cref="Children"/> added to this element inwards by the given amount in each direction.
|
||||||
|
/// When setting this style after this element has already been added to a ui, <see cref="SetAreaDirty"/> should be called.
|
||||||
|
/// </summary>
|
||||||
|
public StyleProp<Padding> ChildPadding;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event that is called after this element is drawn, but before its children are drawn
|
/// Event that is called after this element is drawn, but before its children are drawn
|
||||||
|
@ -389,11 +392,11 @@ namespace MLEM.Ui.Elements {
|
||||||
private Anchor anchor;
|
private Anchor anchor;
|
||||||
private Vector2 size;
|
private Vector2 size;
|
||||||
private Vector2 offset;
|
private Vector2 offset;
|
||||||
private Padding childPadding;
|
|
||||||
private RectangleF area;
|
private RectangleF area;
|
||||||
private bool areaDirty;
|
private bool areaDirty;
|
||||||
private bool isHidden;
|
private bool isHidden;
|
||||||
private int priority;
|
private int priority;
|
||||||
|
private UiStyle style;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new element with the given anchor and size and sets up some default event reactions.
|
/// Creates a new element with the given anchor and size and sets up some default event reactions.
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using MLEM.Input;
|
using MLEM.Input;
|
||||||
|
using MLEM.Misc;
|
||||||
using MLEM.Textures;
|
using MLEM.Textures;
|
||||||
|
|
||||||
namespace MLEM.Ui.Elements {
|
namespace MLEM.Ui.Elements {
|
||||||
|
@ -22,7 +23,8 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <returns>An image button</returns>
|
/// <returns>An image button</returns>
|
||||||
public static Button ImageButton(Anchor anchor, Vector2 size, TextureRegion texture, string text = null, string tooltipText = null, float imagePadding = 2) {
|
public static Button ImageButton(Anchor anchor, Vector2 size, TextureRegion texture, string text = null, string tooltipText = null, float imagePadding = 2) {
|
||||||
var button = new Button(anchor, size, text, tooltipText);
|
var button = new Button(anchor, size, text, tooltipText);
|
||||||
var image = new Image(Anchor.CenterLeft, Vector2.One, texture) {Padding = new Vector2(imagePadding)};
|
var image = new Image(Anchor.CenterLeft, Vector2.One, texture);
|
||||||
|
image.Padding.SetFromStyle(new Padding(imagePadding), 1);
|
||||||
button.OnAreaUpdated += e => image.Size = new Vector2(e.Area.Height, e.Area.Height) / e.Scale;
|
button.OnAreaUpdated += e => image.Size = new Vector2(e.Area.Height, e.Area.Height) / e.Scale;
|
||||||
button.AddChild(image, 0);
|
button.AddChild(image, 0);
|
||||||
return button;
|
return button;
|
||||||
|
|
|
@ -71,8 +71,12 @@ namespace MLEM.Ui.Elements {
|
||||||
AutoHideWhenEmpty = autoHideScrollbar,
|
AutoHideWhenEmpty = autoHideScrollbar,
|
||||||
IsHidden = autoHideScrollbar
|
IsHidden = autoHideScrollbar
|
||||||
};
|
};
|
||||||
if (autoHideScrollbar)
|
if (autoHideScrollbar) {
|
||||||
this.ScrollBar.OnAutoHide += e => this.ChildPadding += new Padding(0, this.ScrollerSize.Value.X, 0, 0) * (e.IsHidden ? -1 : 1);
|
this.ScrollBar.OnAutoHide += e => {
|
||||||
|
this.ChildPadding += new Padding(0, this.ScrollerSize.Value.X, 0, 0) * (e.IsHidden ? -1 : 1);
|
||||||
|
this.SetAreaDirty();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// handle automatic element selection, the scroller needs to scroll to the right location
|
// handle automatic element selection, the scroller needs to scroll to the right location
|
||||||
this.OnSelectedElementChanged += (element, otherElement) => {
|
this.OnSelectedElementChanged += (element, otherElement) => {
|
||||||
|
@ -216,8 +220,7 @@ namespace MLEM.Ui.Elements {
|
||||||
this.Texture.SetFromStyle(style.PanelTexture);
|
this.Texture.SetFromStyle(style.PanelTexture);
|
||||||
this.StepPerScroll.SetFromStyle(style.PanelStepPerScroll);
|
this.StepPerScroll.SetFromStyle(style.PanelStepPerScroll);
|
||||||
this.ScrollerSize.SetFromStyle(style.PanelScrollerSize);
|
this.ScrollerSize.SetFromStyle(style.PanelScrollerSize);
|
||||||
if (this.ChildPadding == default)
|
this.ChildPadding.SetFromStyle(style.PanelChildPadding);
|
||||||
this.ChildPadding = style.PanelChildPadding;
|
|
||||||
this.SetScrollBarStyle();
|
this.SetScrollBarStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +238,7 @@ namespace MLEM.Ui.Elements {
|
||||||
var lowestChild = this.GetLowestChild(c => c != this.ScrollBar && !c.IsHidden);
|
var lowestChild = this.GetLowestChild(c => c != this.ScrollBar && !c.IsHidden);
|
||||||
// the max value of the scrollbar is the amount of non-scaled pixels taken up by overflowing components
|
// the max value of the scrollbar is the amount of non-scaled pixels taken up by overflowing components
|
||||||
var childrenHeight = lowestChild.Area.Bottom - firstChild.Area.Top;
|
var childrenHeight = lowestChild.Area.Bottom - firstChild.Area.Top;
|
||||||
this.ScrollBar.MaxValue = (childrenHeight - this.Area.Height) / this.Scale + this.ChildPadding.Height;
|
this.ScrollBar.MaxValue = (childrenHeight - this.Area.Height) / this.Scale + this.ChildPadding.Value.Height;
|
||||||
|
|
||||||
// update the render target
|
// update the render target
|
||||||
var targetArea = (Rectangle) this.GetRenderTargetArea();
|
var targetArea = (Rectangle) this.GetRenderTargetArea();
|
||||||
|
|
|
@ -79,10 +79,9 @@ namespace MLEM.Ui.Elements {
|
||||||
this.Texture.SetFromStyle(style.TooltipBackground);
|
this.Texture.SetFromStyle(style.TooltipBackground);
|
||||||
this.MouseOffset.SetFromStyle(style.TooltipOffset);
|
this.MouseOffset.SetFromStyle(style.TooltipOffset);
|
||||||
this.Delay.SetFromStyle(style.TooltipDelay);
|
this.Delay.SetFromStyle(style.TooltipDelay);
|
||||||
this.ChildPadding = style.TooltipChildPadding;
|
this.ChildPadding.SetFromStyle(style.TooltipChildPadding);
|
||||||
if (this.Paragraph != null) {
|
if (this.Paragraph != null) {
|
||||||
// we can't set from style here since it's a different element
|
this.Paragraph.TextColor.SetFromStyle(style.TooltipTextColor, 1);
|
||||||
this.Paragraph.TextColor.Set(style.TooltipTextColor);
|
|
||||||
this.Paragraph.Size = new Vector2(style.TooltipTextWidth, 0);
|
this.Paragraph.Size = new Vector2(style.TooltipTextWidth, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@ namespace MLEM.Ui.Style {
|
||||||
/// The currently applied style
|
/// The currently applied style
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T Value { get; private set; }
|
public T Value { get; private set; }
|
||||||
private bool isCustom;
|
private byte lastSetPriority;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new style property with the given custom style.
|
/// Creates a new style property with the given custom style.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The custom style to apply</param>
|
/// <param name="value">The custom style to apply</param>
|
||||||
public StyleProp(T value) {
|
public StyleProp(T value) {
|
||||||
this.isCustom = true;
|
this.lastSetPriority = byte.MaxValue;
|
||||||
this.Value = value;
|
this.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,9 +30,12 @@ namespace MLEM.Ui.Style {
|
||||||
/// This allows this property to be overridden by custom style settings using <see cref="Set"/>.
|
/// This allows this property to be overridden by custom style settings using <see cref="Set"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The style to apply</param>
|
/// <param name="value">The style to apply</param>
|
||||||
public void SetFromStyle(T value) {
|
/// <param name="priority">The priority that this style value has. Higher priority style values will override lower priority style values.</param>
|
||||||
if (!this.isCustom)
|
public void SetFromStyle(T value, byte priority = 0) {
|
||||||
|
if (priority >= this.lastSetPriority) {
|
||||||
this.Value = value;
|
this.Value = value;
|
||||||
|
this.lastSetPriority = priority;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -41,7 +44,7 @@ namespace MLEM.Ui.Style {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public void Set(T value) {
|
public void Set(T value) {
|
||||||
this.isCustom = true;
|
this.lastSetPriority = byte.MaxValue;
|
||||||
this.Value = value;
|
this.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +67,7 @@ namespace MLEM.Ui.Style {
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return $"{this.Value} (Custom: {this.isCustom})";
|
return this.Value?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -52,6 +52,14 @@ namespace MLEM.Misc {
|
||||||
this.Bottom = bottom;
|
this.Bottom = bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new padding with the specified value, which will be applied to each edge.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The padding to apply to each edge</param>
|
||||||
|
public Padding(float value) :
|
||||||
|
this(value, value) {
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new padding with the specified x and y values, applying them to both edges.
|
/// Creates a new padding with the specified x and y values, applying them to both edges.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -224,7 +224,7 @@ namespace Sandbox {
|
||||||
var button = loadPanel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) {
|
var button = loadPanel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) {
|
||||||
SetHeightBasedOnChildren = true,
|
SetHeightBasedOnChildren = true,
|
||||||
Padding = new Padding(0, 0, 0, 1),
|
Padding = new Padding(0, 0, 0, 1),
|
||||||
ChildPadding = new Vector2(3)
|
ChildPadding = new Padding(3)
|
||||||
});
|
});
|
||||||
button.AddChild(new Group(Anchor.AutoLeft, new Vector2(0.5F, 30), false) {
|
button.AddChild(new Group(Anchor.AutoLeft, new Vector2(0.5F, 30), false) {
|
||||||
CanBeMoused = false
|
CanBeMoused = false
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace Tests {
|
||||||
var button = panel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) {
|
var button = panel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) {
|
||||||
SetHeightBasedOnChildren = true,
|
SetHeightBasedOnChildren = true,
|
||||||
Padding = new Padding(0, 0, 0, 1),
|
Padding = new Padding(0, 0, 0, 1),
|
||||||
ChildPadding = new Vector2(3)
|
ChildPadding = new Padding(3)
|
||||||
});
|
});
|
||||||
button.AddChild(new Group(Anchor.AutoLeft, new Vector2(0.5F, 30), false) {
|
button.AddChild(new Group(Anchor.AutoLeft, new Vector2(0.5F, 30), false) {
|
||||||
CanBeMoused = false
|
CanBeMoused = false
|
||||||
|
|
Loading…
Reference in a new issue