mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 05:58:35 +01:00
Compare commits
2 commits
dc6c472b84
...
c880c3e011
Author | SHA1 | Date | |
---|---|---|---|
c880c3e011 | |||
a143aef67c |
6 changed files with 57 additions and 29 deletions
|
@ -35,14 +35,13 @@ Improvements
|
||||||
- Avoid unnecessary panel updates by using an Epsilon comparison when scrolling children
|
- Avoid unnecessary panel updates by using an Epsilon comparison when scrolling children
|
||||||
- Allow setting a default text alignment for paragraphs in UiStyle
|
- Allow setting a default text alignment for paragraphs in UiStyle
|
||||||
- Made custom values of Element.Style persist when a new ui style is set
|
- Made custom values of Element.Style persist when a new ui style is set
|
||||||
- Use a scissor rectangle for panels instead of a render target
|
- Update elements less aggressively when changing a ui system's style
|
||||||
|
|
||||||
Fixes
|
Fixes
|
||||||
- Fixed paragraph links having incorrect hover locations when using special text alignments
|
- Fixed paragraph links having incorrect hover locations when using special text alignments
|
||||||
|
|
||||||
Removals
|
Removals
|
||||||
- Marked StyleProp equality members as obsolete
|
- Marked StyleProp equality members as obsolete
|
||||||
- Marked UiSystem.DrawEarly and Element.DrawEarly as obsolete
|
|
||||||
|
|
||||||
### MLEM.Extended
|
### MLEM.Extended
|
||||||
Improvements
|
Improvements
|
||||||
|
|
|
@ -22,6 +22,9 @@ protected override void Update(GameTime gameTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Draw(GameTime gameTime) {
|
protected override void Draw(GameTime gameTime) {
|
||||||
|
// DrawEarly needs to be called before clearing your graphics context
|
||||||
|
this.UiSystem.DrawEarly(gameTime, this.SpriteBatch);
|
||||||
|
|
||||||
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||||
// Do your regular game drawing here
|
// Do your regular game drawing here
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ namespace MLEM.Startup {
|
||||||
this.PreDraw?.Invoke(this, gameTime);
|
this.PreDraw?.Invoke(this, gameTime);
|
||||||
CoroutineHandler.RaiseEvent(CoroutineEvents.PreDraw);
|
CoroutineHandler.RaiseEvent(CoroutineEvents.PreDraw);
|
||||||
|
|
||||||
|
this.UiSystem.DrawEarly(gameTime, this.SpriteBatch);
|
||||||
this.DoDraw(gameTime);
|
this.DoDraw(gameTime);
|
||||||
this.UiSystem.Draw(gameTime, this.SpriteBatch);
|
this.UiSystem.Draw(gameTime, this.SpriteBatch);
|
||||||
|
|
||||||
|
|
|
@ -985,7 +985,6 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <param name="effect">The effect that is used for drawing</param>
|
/// <param name="effect">The effect that is used for drawing</param>
|
||||||
/// <param name="depthStencilState">The depth stencil state that is used for drawing</param>
|
/// <param name="depthStencilState">The depth stencil state that is used for drawing</param>
|
||||||
/// <param name="matrix">The transformation matrix that is used for drawing</param>
|
/// <param name="matrix">The transformation matrix that is used for drawing</param>
|
||||||
[Obsolete("DrawEarly has been deprecated. There is no replacement, and all drawing code should be placed in Draw.")]
|
|
||||||
public virtual void DrawEarly(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
|
public virtual void DrawEarly(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
|
||||||
foreach (var child in this.GetRelevantChildren()) {
|
foreach (var child in this.GetRelevantChildren()) {
|
||||||
if (!child.IsHidden)
|
if (!child.IsHidden)
|
||||||
|
|
|
@ -13,15 +13,10 @@ namespace MLEM.Ui.Elements {
|
||||||
/// A panel element to be used inside of a <see cref="UiSystem"/>.
|
/// A panel element to be used inside of a <see cref="UiSystem"/>.
|
||||||
/// The panel is a complex element that displays a box as a background to all of its child elements.
|
/// The panel is a complex element that displays a box as a background to all of its child elements.
|
||||||
/// Additionally, a panel can be set to <see cref="scrollOverflow"/> on construction, which causes all elements that don't fit into the panel to be hidden until scrolled to using a <see cref="ScrollBar"/>.
|
/// Additionally, a panel can be set to <see cref="scrollOverflow"/> on construction, which causes all elements that don't fit into the panel to be hidden until scrolled to using a <see cref="ScrollBar"/>.
|
||||||
|
/// As this behavior is accomplished using a <see cref="RenderTarget2D"/>, scrolling panels need to have their <see cref="DrawEarly"/> methods called using <see cref="UiSystem.DrawEarly"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Panel : Element {
|
public class Panel : Element {
|
||||||
|
|
||||||
private static readonly RasterizerState ScissorRasterizer = new RasterizerState {
|
|
||||||
// use the default cull mode from SpriteBatch, but with scissor test enabled
|
|
||||||
CullMode = CullMode.CullCounterClockwiseFace,
|
|
||||||
ScissorTestEnable = true
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The scroll bar that this panel contains.
|
/// The scroll bar that this panel contains.
|
||||||
/// This is only nonnull if <see cref="scrollOverflow"/> is true.
|
/// This is only nonnull if <see cref="scrollOverflow"/> is true.
|
||||||
|
@ -56,6 +51,7 @@ namespace MLEM.Ui.Elements {
|
||||||
private readonly List<Element> relevantChildren = new List<Element>();
|
private readonly List<Element> relevantChildren = new List<Element>();
|
||||||
private readonly bool scrollOverflow;
|
private readonly bool scrollOverflow;
|
||||||
|
|
||||||
|
private RenderTarget2D renderTarget;
|
||||||
private bool relevantChildrenDirty;
|
private bool relevantChildrenDirty;
|
||||||
private float scrollBarChildOffset;
|
private float scrollBarChildOffset;
|
||||||
|
|
||||||
|
@ -174,32 +170,44 @@ namespace MLEM.Ui.Elements {
|
||||||
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
|
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
|
||||||
if (this.Texture.HasValue())
|
if (this.Texture.HasValue())
|
||||||
batch.Draw(this.Texture, this.DisplayArea, this.DrawColor.OrDefault(Color.White) * alpha, this.Scale);
|
batch.Draw(this.Texture, this.DisplayArea, this.DrawColor.OrDefault(Color.White) * alpha, this.Scale);
|
||||||
// if we handle overflow, draw using a scissor rectangle
|
// if we handle overflow, draw using the render target in DrawUnbound
|
||||||
if (this.scrollOverflow) {
|
if (!this.scrollOverflow || this.renderTarget == null) {
|
||||||
batch.End();
|
|
||||||
batch.GraphicsDevice.ScissorRectangle = (Rectangle) this.GetInnerArea();
|
|
||||||
|
|
||||||
// do the usual draw, but with the scissor rectangle applied
|
|
||||||
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, ScissorRasterizer, effect, matrix);
|
|
||||||
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix);
|
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix);
|
||||||
batch.End();
|
|
||||||
|
|
||||||
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, matrix);
|
|
||||||
} else {
|
} else {
|
||||||
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix);
|
// draw the actual render target (don't apply the alpha here because it's already drawn onto with alpha)
|
||||||
|
batch.Draw(this.renderTarget, this.GetRenderTargetArea(), Color.White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void DrawEarly(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
|
||||||
|
this.UpdateAreaIfDirty();
|
||||||
|
if (this.scrollOverflow && this.renderTarget != null) {
|
||||||
|
// draw children onto the render target
|
||||||
|
using (batch.GraphicsDevice.WithRenderTarget(this.renderTarget)) {
|
||||||
|
batch.GraphicsDevice.Clear(Color.Transparent);
|
||||||
|
// offset children by the render target's location
|
||||||
|
var area = this.GetRenderTargetArea();
|
||||||
|
var trans = Matrix.CreateTranslation(-area.X, -area.Y, 0);
|
||||||
|
// do the usual draw, but within the render target
|
||||||
|
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, trans);
|
||||||
|
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, trans);
|
||||||
|
batch.End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.DrawEarly(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Element GetElementUnderPos(Vector2 position) {
|
public override Element GetElementUnderPos(Vector2 position) {
|
||||||
// if overflow is handled, don't propagate mouse checks to hidden children
|
// if overflow is handled, don't propagate mouse checks to hidden children
|
||||||
var transformed = this.TransformInverse(position);
|
var transformed = this.TransformInverse(position);
|
||||||
if (this.scrollOverflow && !this.GetInnerArea().Contains(transformed))
|
if (this.scrollOverflow && !this.GetRenderTargetArea().Contains(transformed))
|
||||||
return !this.IsHidden && this.CanBeMoused && this.DisplayArea.Contains(transformed) ? this : null;
|
return !this.IsHidden && this.CanBeMoused && this.DisplayArea.Contains(transformed) ? this : null;
|
||||||
return base.GetElementUnderPos(position);
|
return base.GetElementUnderPos(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RectangleF GetInnerArea() {
|
private RectangleF GetRenderTargetArea() {
|
||||||
var area = this.ChildPaddedArea;
|
var area = this.ChildPaddedArea;
|
||||||
area.X = this.DisplayArea.X;
|
area.X = this.DisplayArea.X;
|
||||||
area.Width = this.DisplayArea.Width;
|
area.Width = this.DisplayArea.Width;
|
||||||
|
@ -250,6 +258,26 @@ namespace MLEM.Ui.Elements {
|
||||||
// the scroller height has the same relation to the scroll bar height as the visible area has to the total height of the panel's content
|
// the scroller height has the same relation to the scroll bar height as the visible area has to the total height of the panel's content
|
||||||
var scrollerHeight = Math.Min(this.ChildPaddedArea.Height / childrenHeight / this.Scale, 1) * this.ScrollBar.Area.Height;
|
var scrollerHeight = Math.Min(this.ChildPaddedArea.Height / childrenHeight / this.Scale, 1) * this.ScrollBar.Area.Height;
|
||||||
this.ScrollBar.ScrollerSize = new Vector2(this.ScrollerSize.Value.X, Math.Max(this.ScrollerSize.Value.Y, scrollerHeight));
|
this.ScrollBar.ScrollerSize = new Vector2(this.ScrollerSize.Value.X, Math.Max(this.ScrollerSize.Value.Y, scrollerHeight));
|
||||||
|
|
||||||
|
// update the render target
|
||||||
|
var targetArea = (Rectangle) this.GetRenderTargetArea();
|
||||||
|
if (targetArea.Width <= 0 || targetArea.Height <= 0)
|
||||||
|
return;
|
||||||
|
if (this.renderTarget == null || targetArea.Width != this.renderTarget.Width || targetArea.Height != this.renderTarget.Height) {
|
||||||
|
if (this.renderTarget != null)
|
||||||
|
this.renderTarget.Dispose();
|
||||||
|
this.renderTarget = targetArea.IsEmpty ? null : new RenderTarget2D(this.System.Game.GraphicsDevice, targetArea.Width, targetArea.Height);
|
||||||
|
this.relevantChildrenDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Dispose() {
|
||||||
|
if (this.renderTarget != null) {
|
||||||
|
this.renderTarget.Dispose();
|
||||||
|
this.renderTarget = null;
|
||||||
|
}
|
||||||
|
base.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetScrollBarStyle() {
|
private void SetScrollBarStyle() {
|
||||||
|
@ -263,7 +291,7 @@ namespace MLEM.Ui.Elements {
|
||||||
private void ForceUpdateRelevantChildren() {
|
private void ForceUpdateRelevantChildren() {
|
||||||
this.relevantChildrenDirty = false;
|
this.relevantChildrenDirty = false;
|
||||||
this.relevantChildren.Clear();
|
this.relevantChildren.Clear();
|
||||||
var visible = this.GetInnerArea();
|
var visible = this.GetRenderTargetArea();
|
||||||
foreach (var child in this.SortedChildren) {
|
foreach (var child in this.SortedChildren) {
|
||||||
if (child.Area.Intersects(visible)) {
|
if (child.Area.Intersects(visible)) {
|
||||||
this.relevantChildren.Add(child);
|
this.relevantChildren.Add(child);
|
||||||
|
|
|
@ -59,10 +59,8 @@ namespace MLEM.Ui {
|
||||||
get => this.style;
|
get => this.style;
|
||||||
set {
|
set {
|
||||||
this.style = value;
|
this.style = value;
|
||||||
foreach (var root in this.rootElements) {
|
foreach (var root in this.rootElements)
|
||||||
root.Element.AndChildren(e => e.System = this);
|
root.Element.AndChildren(e => e.Style = e.Style.OrStyle(value));
|
||||||
root.Element.ForceUpdateArea();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -264,7 +262,6 @@ namespace MLEM.Ui {
|
||||||
/// </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>
|
||||||
[Obsolete("DrawEarly has been deprecated. There is no replacement, so only Draw has to be called.")]
|
|
||||||
public void DrawEarly(GameTime time, SpriteBatch batch) {
|
public void DrawEarly(GameTime time, SpriteBatch batch) {
|
||||||
this.Metrics.ResetDraws();
|
this.Metrics.ResetDraws();
|
||||||
this.Stopwatch.Restart();
|
this.Stopwatch.Restart();
|
||||||
|
@ -281,6 +278,7 @@ namespace MLEM.Ui {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws any <see cref="Element"/>s onto the screen.
|
/// Draws any <see cref="Element"/>s onto the screen.
|
||||||
|
/// Note that, when using <see cref="Panel"/>s with a scroll bar, <see cref="DrawEarly"/> needs to be called as well.
|
||||||
/// </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>
|
||||||
|
|
Loading…
Reference in a new issue