1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-25 05:58:35 +01:00

Compare commits

...

3 commits

5 changed files with 41 additions and 39 deletions

View file

@ -69,10 +69,12 @@ Fixes
- Fixed children of Panel scroll bars also being scrolled - Fixed children of Panel scroll bars also being scrolled
- Fixed RootElement.CanSelectContent and Element.IsSelected returning incorrect results when CanBeSelected changes - Fixed RootElement.CanSelectContent and Element.IsSelected returning incorrect results when CanBeSelected changes
- Fixed dropdowns with some non-selectable children failing to navigate when using gamepad controls - Fixed dropdowns with some non-selectable children failing to navigate when using gamepad controls
- Fixed UiMetrics.ForceAreaUpdateTime being inaccurate for nested elements
Removals Removals
- Marked StyleProp equality members as obsolete - Marked StyleProp equality members as obsolete
- Marked BeginDelegate and BeginImpl as obsolete - Marked Element.BeginDelegate and Element.BeginImpl as obsolete
- Marked Element.DrawEarly and UiSystem.DrawEarly as obsolete
### MLEM.Extended ### MLEM.Extended
Improvements Improvements

View file

@ -22,9 +22,6 @@ 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

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
@ -184,7 +185,7 @@ namespace MLEM.Ui.Elements {
/// Note that, when this is non-null, a new <see cref="SpriteBatch.Begin"/> call is used for this element. /// Note that, when this is non-null, a new <see cref="SpriteBatch.Begin"/> call is used for this element.
/// </summary> /// </summary>
#pragma warning disable CS0618 #pragma warning disable CS0618
[Obsolete("BeginImpl is deprecated. You can create a custom element class and override DrawEarly or Draw instead.")] [Obsolete("BeginImpl is deprecated. You can create a custom element class and override Draw instead.")]
public BeginDelegate BeginImpl; public BeginDelegate BeginImpl;
#pragma warning restore CS0618 #pragma warning restore CS0618
/// <summary> /// <summary>
@ -409,6 +410,7 @@ namespace MLEM.Ui.Elements {
protected RectangleF ParentArea => this.Parent?.ChildPaddedArea ?? (RectangleF) this.system.Viewport; protected RectangleF ParentArea => this.Parent?.ChildPaddedArea ?? (RectangleF) this.system.Viewport;
private readonly List<Element> children = new List<Element>(); private readonly List<Element> children = new List<Element>();
private readonly Stopwatch stopwatch = new Stopwatch();
private bool sortedChildrenDirty; private bool sortedChildrenDirty;
private IList<Element> sortedChildren; private IList<Element> sortedChildren;
private UiSystem system; private UiSystem system;
@ -559,7 +561,7 @@ namespace MLEM.Ui.Elements {
// which would cause our ForceUpdateArea code to be run twice, so we only update our parent instead // which would cause our ForceUpdateArea code to be run twice, so we only update our parent instead
if (this.Parent != null && this.Parent.UpdateAreaIfDirty()) if (this.Parent != null && this.Parent.UpdateAreaIfDirty())
return; return;
this.System.Stopwatch.Restart(); this.stopwatch.Restart();
var parentArea = this.ParentArea; var parentArea = this.ParentArea;
var parentCenterX = parentArea.X + parentArea.Width / 2; var parentCenterX = parentArea.X + parentArea.Width / 2;
@ -569,8 +571,8 @@ namespace MLEM.Ui.Elements {
var recursion = 0; var recursion = 0;
UpdateDisplayArea(actualSize); UpdateDisplayArea(actualSize);
this.System.Stopwatch.Stop(); this.stopwatch.Stop();
this.System.Metrics.ForceAreaUpdateTime += this.System.Stopwatch.Elapsed; this.System.Metrics.ForceAreaUpdateTime += this.stopwatch.Elapsed;
this.System.Metrics.ForceAreaUpdates++; this.System.Metrics.ForceAreaUpdates++;
void UpdateDisplayArea(Vector2 newSize) { void UpdateDisplayArea(Vector2 newSize) {
@ -988,6 +990,7 @@ 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 is deprecated. For custom implementations, see Panel.Draw for how to replace this method.")]
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)
@ -1166,7 +1169,7 @@ namespace MLEM.Ui.Elements {
/// <param name="effect">The effect used for drawing</param> /// <param name="effect">The effect used for drawing</param>
/// <param name="depthStencilState">The depth stencil state used for drawing</param> /// <param name="depthStencilState">The depth stencil state used for drawing</param>
/// <param name="matrix">The transform matrix used for drawing</param> /// <param name="matrix">The transform matrix used for drawing</param>
[Obsolete("BeginDelegate is deprecated. You can create a custom element class and override DrawEarly or Draw instead.")] [Obsolete("BeginDelegate is deprecated. You can create a custom element class and override Draw instead.")]
public delegate void BeginDelegate(Element element, GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix); public delegate void BeginDelegate(Element element, GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix);
} }

View file

@ -13,7 +13,6 @@ 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 {
@ -169,22 +168,13 @@ namespace MLEM.Ui.Elements {
/// <inheritdoc /> /// <inheritdoc />
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()) // draw children onto the render target if we have one
batch.Draw(this.Texture, this.DisplayArea, this.DrawColor.OrDefault(Color.White) * alpha, this.Scale);
// if we handle overflow, draw using the render target in DrawUnbound
if (!this.scrollOverflow || this.renderTarget == null) {
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix);
} else {
// 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) { if (this.scrollOverflow && this.renderTarget != null) {
// draw children onto the render target this.UpdateAreaIfDirty();
batch.End();
// force render target usage to preserve so that previous content isn't cleared
var lastUsage = batch.GraphicsDevice.PresentationParameters.RenderTargetUsage;
batch.GraphicsDevice.PresentationParameters.RenderTargetUsage = RenderTargetUsage.PreserveContents;
using (batch.GraphicsDevice.WithRenderTarget(this.renderTarget)) { using (batch.GraphicsDevice.WithRenderTarget(this.renderTarget)) {
batch.GraphicsDevice.Clear(Color.Transparent); batch.GraphicsDevice.Clear(Color.Transparent);
// offset children by the render target's location // offset children by the render target's location
@ -195,8 +185,19 @@ namespace MLEM.Ui.Elements {
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, trans); base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, trans);
batch.End(); batch.End();
} }
batch.GraphicsDevice.PresentationParameters.RenderTargetUsage = lastUsage;
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, matrix);
}
if (this.Texture.HasValue())
batch.Draw(this.Texture, this.DisplayArea, this.DrawColor.OrDefault(Color.White) * alpha, this.Scale);
// if we handle overflow, draw using the render target in DrawUnbound
if (!this.scrollOverflow || this.renderTarget == null) {
base.Draw(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix);
} else {
// 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);
} }
base.DrawEarly(time, batch, alpha, blendState, samplerState, depthStencilState, effect, matrix);
} }
/// <inheritdoc /> /// <inheritdoc />

View file

@ -105,7 +105,7 @@ namespace MLEM.Ui {
public UiControls Controls; public UiControls Controls;
/// <summary> /// <summary>
/// The update and rendering statistics to be used for runtime debugging and profiling. /// The update and rendering statistics to be used for runtime debugging and profiling.
/// The metrics are reset accordingly every frame: <see cref="UiMetrics.ResetUpdates"/> is called at the start of <see cref="Update"/>, and <see cref="UiMetrics.ResetDraws"/> is called at the start of <see cref="DrawEarly"/>, or at the start of <see cref="Draw"/> if <see cref="DrawEarly"/> was not called. /// The metrics are reset accordingly every frame: <see cref="UiMetrics.ResetUpdates"/> is called at the start of <see cref="Update"/>, and <see cref="UiMetrics.ResetDraws"/> is called at the start of <see cref="Draw"/>.
/// </summary> /// </summary>
public UiMetrics Metrics; public UiMetrics Metrics;
@ -182,9 +182,8 @@ namespace MLEM.Ui {
/// </summary> /// </summary>
public event RootCallback OnRootRemoved; public event RootCallback OnRootRemoved;
internal readonly Stopwatch Stopwatch = new Stopwatch();
private readonly List<RootElement> rootElements = new List<RootElement>(); private readonly List<RootElement> rootElements = new List<RootElement>();
private readonly Stopwatch stopwatch = new Stopwatch();
private float globalScale = 1; private float globalScale = 1;
private bool drewEarly; private bool drewEarly;
private UiStyle style; private UiStyle style;
@ -253,14 +252,14 @@ namespace MLEM.Ui {
/// <param name="time">The game's time</param> /// <param name="time">The game's time</param>
public override void Update(GameTime time) { public override void Update(GameTime time) {
this.Metrics.ResetUpdates(); this.Metrics.ResetUpdates();
this.Stopwatch.Restart(); this.stopwatch.Restart();
this.Controls.Update(); this.Controls.Update();
for (var i = this.rootElements.Count - 1; i >= 0; i--) for (var i = this.rootElements.Count - 1; i >= 0; i--)
this.rootElements[i].Element.Update(time); this.rootElements[i].Element.Update(time);
this.Stopwatch.Stop(); this.stopwatch.Stop();
this.Metrics.UpdateTime += this.Stopwatch.Elapsed; this.Metrics.UpdateTime += this.stopwatch.Elapsed;
} }
/// <summary> /// <summary>
@ -269,30 +268,30 @@ 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 is deprecated. Calling it is not required anymore, and there is no replacement.")]
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();
foreach (var root in this.rootElements) { foreach (var root in this.rootElements) {
if (!root.Element.IsHidden) if (!root.Element.IsHidden)
root.Element.DrawEarly(time, batch, this.DrawAlpha * root.Element.DrawAlpha, this.BlendState, this.SamplerState, this.DepthStencilState, this.Effect, root.Transform); root.Element.DrawEarly(time, batch, this.DrawAlpha * root.Element.DrawAlpha, this.BlendState, this.SamplerState, this.DepthStencilState, this.Effect, root.Transform);
} }
this.Stopwatch.Stop(); this.stopwatch.Stop();
this.Metrics.DrawTime += this.Stopwatch.Elapsed; this.Metrics.DrawTime += this.stopwatch.Elapsed;
this.drewEarly = true; this.drewEarly = true;
} }
/// <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>
public void Draw(GameTime time, SpriteBatch batch) { public void Draw(GameTime time, SpriteBatch batch) {
if (!this.drewEarly) if (!this.drewEarly)
this.Metrics.ResetDraws(); this.Metrics.ResetDraws();
this.Stopwatch.Restart(); this.stopwatch.Restart();
foreach (var root in this.rootElements) { foreach (var root in this.rootElements) {
if (root.Element.IsHidden) if (root.Element.IsHidden)
@ -303,8 +302,8 @@ namespace MLEM.Ui {
batch.End(); batch.End();
} }
this.Stopwatch.Stop(); this.stopwatch.Stop();
this.Metrics.DrawTime += this.Stopwatch.Elapsed; this.Metrics.DrawTime += this.stopwatch.Elapsed;
this.drewEarly = false; this.drewEarly = false;
} }