Skip to content

Commit 5af6036

Browse files
committed
revert experimental changes, #2 :(
Revert "potentially cleaner version of our experrimental changes" This reverts commit 618584c. Revert "combine panel changes with the "more robust" approach" This reverts commit ef3bd12.
1 parent ef3bd12 commit 5af6036

File tree

4 files changed

+28
-69
lines changed

4 files changed

+28
-69
lines changed

CHANGELOG.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ MLEM uses [semantic versioning](https://semver.org/). Potentially breaking chang
77
Additions
88
- Added UiSystem.OnElementAreaDirty and Element.OnAreaDirty events
99
- Added Element.DebugName to allow describing ui elements in ToString
10-
- Added ILayoutItem.OnLayoutRecursionSettled which is called when recursive ui layouting has finished
1110

1211
Improvements
1312
- Made the exception thrown after the element recursion limit is reached more helpful
14-
- **Implemented a more robust UiLayouter recursion tracking system**
1513

1614
Fixes
1715
- Fixed undrawn elements not updating their area correctly even if their children are drawn or accessed

MLEM.Ui/Elements/Element.cs

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ protected IList<Element> SortedChildren {
555555
private bool treatSizeAsMinimum;
556556
private bool treatSizeAsMaximum;
557557
private bool preventParentSpill;
558-
private (int, int) layoutRecursion;
558+
private int layoutRecursion;
559559
private bool parentPotentiallyDirty;
560560

561561
/// <summary>
@@ -1104,32 +1104,6 @@ public Vector2 TransformInverseAll(Vector2 position) {
11041104
return this.TransformInverse(position);
11051105
}
11061106

1107-
/// <summary>
1108-
/// A method called by <see cref="UiLayouter.Layout{T}"/> when a layout item's size is being recalculated based on its children.
1109-
/// </summary>
1110-
/// <param name="recursion">The current recursion depth.</param>
1111-
/// <param name="relevantChild">The child that triggered the layout recursion. May be <see langword="null"/> in case the source of the layout recursion is unknown.</param>
1112-
protected virtual void OnLayoutRecursion(int recursion, ILayoutItem relevantChild) {
1113-
this.System.Metrics.SummedRecursionDepth++;
1114-
if (recursion > this.System.Metrics.MaxRecursionDepth)
1115-
this.System.Metrics.MaxRecursionDepth = recursion;
1116-
1117-
if (recursion >= Element.RecursionLimit) {
1118-
var exceptionText = $"The area of {this} has recursively updated more often than the configured Element.RecursionLimit. This issue may occur due to this element or one of its children containing conflicting auto-sizing settings, a custom element setting its area dirty too frequently, or this element being part of a complex layout tree that should be split up into multiple groups.";
1119-
if (relevantChild != null)
1120-
exceptionText += $" Does its child {relevantChild} contain any conflicting auto-sizing settings?";
1121-
throw new ArithmeticException(exceptionText);
1122-
}
1123-
}
1124-
1125-
/// <summary>
1126-
/// A method called by <see cref="UiLayouter.Layout{T}"/> when a layout item's size is being calculated, but recursive calculations have settled.
1127-
/// Also see <see cref="OnLayoutRecursion"/>, which is called for every recursive operation during element layouting.
1128-
/// </summary>
1129-
/// <param name="totalRecursion">The total reached recursion depth.</param>
1130-
/// <param name="elementInternal"><see langword="true"/> if the settled recursive operation was element-internal (ie related to properties like <see cref="SetWidthBasedOnChildren"/> and <see cref="SetHeightBasedOnChildren"/>); <see langword="false"/> if the settled recursive operation was related to recursively updated children or parents of this element.</param>
1131-
protected virtual void OnLayoutRecursionSettled(int totalRecursion, bool elementInternal) {}
1132-
11331107
/// <summary>
11341108
/// Called when this element is added to a <see cref="UiSystem"/> and, optionally, a given <see cref="RootElement"/>.
11351109
/// This method is called in <see cref="AddChild{T}"/> for a parent whose <see cref="System"/> is set, as well as <see cref="UiSystem.Add"/>.
@@ -1157,11 +1131,16 @@ protected internal virtual void RemovedFromUi() {
11571131
}
11581132

11591133
void ILayoutItem.OnLayoutRecursion(int recursion, ILayoutItem relevantChild) {
1160-
this.OnLayoutRecursion(recursion, relevantChild);
1161-
}
1134+
this.System.Metrics.SummedRecursionDepth++;
1135+
if (recursion > this.System.Metrics.MaxRecursionDepth)
1136+
this.System.Metrics.MaxRecursionDepth = recursion;
11621137

1163-
void ILayoutItem.OnLayoutRecursionSettled(int totalRecursion, bool elementInternal) {
1164-
this.OnLayoutRecursionSettled(totalRecursion, elementInternal);
1138+
if (recursion >= Element.RecursionLimit) {
1139+
var exceptionText = $"The area of {this} has recursively updated more often than the configured Element.RecursionLimit. This issue may occur due to this element or one of its children containing conflicting auto-sizing settings, a custom element setting its area dirty too frequently, or this element being part of a complex layout tree that should be split up into multiple groups.";
1140+
if (relevantChild != null)
1141+
exceptionText += $" Does its child {relevantChild} contain any conflicting auto-sizing settings?";
1142+
throw new ArithmeticException(exceptionText);
1143+
}
11651144
}
11661145

11671146
Vector2 ILayoutItem.CalcActualSize(RectangleF parentArea) {

MLEM.Ui/Elements/Panel.cs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,11 @@ public override void RemoveChildren(Func<Element, bool> condition = null) {
172172
}
173173

174174
/// <inheritdoc />
175-
protected override void OnLayoutRecursionSettled(int totalRecursion, bool elementInternal) {
176-
base.OnLayoutRecursionSettled(totalRecursion, elementInternal);
177-
if (!elementInternal)
178-
this.scrollBarMaxHistory.Clear();
175+
public override void Update(GameTime time) {
176+
// reset the scroll bar's max history when an update happens, at which point we know that any scroll bar recursion has "settled"
177+
// (this reset ensures that the max history is recursion-internal and old values aren't reused when elements get modified later)
178+
this.scrollBarMaxHistory.Clear();
179+
base.Update(time);
179180
}
180181

181182
/// <inheritdoc />
@@ -335,13 +336,12 @@ protected virtual void ScrollSetup() {
335336
var scrollBarMax = Math.Max(0, (childrenHeight - this.ChildPaddedArea.Height) / this.Scale);
336337
// avoid an infinite show/hide oscillation that occurs while updating our area by simply using the maximum recent height in that case
337338
if (this.scrollBarMaxHistory.Count(v => v.Equals(scrollBarMax, Element.Epsilon)) >= 2)
338-
scrollBarMax = Math.Max(scrollBarMax, this.scrollBarMaxHistory.Max());
339+
scrollBarMax = this.scrollBarMaxHistory.Max();
339340
if (!this.ScrollBar.MaxValue.Equals(scrollBarMax, Element.Epsilon)) {
340341
this.scrollBarMaxHistory.Add(scrollBarMax);
341342
if (this.scrollBarMaxHistory.Count > 8)
342343
this.scrollBarMaxHistory.RemoveAt(0);
343344

344-
var wasHidden = this.ScrollBar.IsHidden;
345345
this.ScrollBar.MaxValue = scrollBarMax;
346346
this.relevantChildrenDirty = true;
347347

@@ -353,11 +353,6 @@ protected virtual void ScrollSetup() {
353353
this.ChildPadding += new Padding(0, childOffsetDelta, 0, 0);
354354
}
355355

356-
// if we know we'll have to update our area, do it now so that the UiLayouter recursion tracker counts this change as "recursion-internal"
357-
// (we use our child padded area below when changing the scroll bar's scroller size, so force update before that!)
358-
if (this.ScrollBar.IsHidden != wasHidden || !childOffsetDelta.Equals(0, Element.Epsilon))
359-
this.ForceUpdateArea();
360-
361356
// 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
362357
var scrollerHeight = Math.Min(this.ChildPaddedArea.Height / childrenHeight / this.Scale, 1) * this.ScrollBar.Area.Height;
363358
this.ScrollBar.ScrollerSize = new Vector2(this.ScrollerSize.Value.X, Math.Max(this.ScrollerSize.Value.Y, scrollerHeight));

MLEM.Ui/UiLayouter.cs

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,20 @@ public static class UiLayouter {
1515
/// Lays out the given <paramref name="item"/> based on the information specified in its <see cref="ILayoutItem"/> interface.
1616
/// </summary>
1717
/// <param name="item">The item to lay out.</param>
18-
/// <param name="recursionTracker">A reference to a field in the <paramref name="item"/> that is used by the layouter to track recursion counts across <see cref="Layout"/> calls.</param>
18+
/// <param name="layoutRecursionTracker">A reference to a field in the <paramref name="item"/> that is used by the layouter to track recursion counts across <see cref="Layout"/> calls.</param>
1919
/// <param name="epsilon">An epsilon value used in layout item size, position and resulting area calculations to mitigate floating point rounding inaccuracies.</param>
2020
/// <typeparam name="T"></typeparam>
21-
public static void Layout<T>(T item, ref (int Layer, int Depth) recursionTracker, float epsilon = 0) where T : class, ILayoutItem {
22-
if (recursionTracker.Depth > 0)
23-
item.OnLayoutRecursion(recursionTracker.Depth, null);
24-
recursionTracker.Layer++;
25-
recursionTracker.Depth++;
21+
public static void Layout<T>(T item, ref int layoutRecursionTracker, float epsilon = 0) where T : class, ILayoutItem {
22+
var initiatedLayouting = layoutRecursionTracker <= 0;
23+
if (!initiatedLayouting)
24+
item.OnLayoutRecursion(layoutRecursionTracker, null);
25+
layoutRecursionTracker++;
2626

2727
var internalRecursion = 0;
2828
UpdateDisplayArea();
29-
item.OnLayoutRecursionSettled(internalRecursion, true);
3029

31-
recursionTracker.Layer--;
32-
if (recursionTracker.Layer <= 0) {
33-
item.OnLayoutRecursionSettled(recursionTracker.Depth, false);
34-
recursionTracker.Layer = 0;
35-
recursionTracker.Depth = 0;
36-
}
30+
if (initiatedLayouting)
31+
layoutRecursionTracker = 0;
3732

3833
void UpdateDisplayArea(Vector2? overrideSize = null) {
3934
var parentArea = item.ParentArea;
@@ -381,10 +376,11 @@ public interface ILayoutItem {
381376
bool CanAutoAnchorsAttach { get; }
382377

383378
/// <summary>
384-
/// Calculates the actual total size that this element should take up.
379+
/// Calculates the actual size that this layout item should take up, based on the area that its parent encompasses.
380+
/// By default, this is based on the information specified in <see cref="System.Drawing.Size"/>'s documentation.
385381
/// </summary>
386-
/// <param name="parentArea">This parent's area, or the ui system's viewport if it has no parent.</param>
387-
/// <returns>The actual size of this element.</returns>
382+
/// <param name="parentArea">This parent's area, or the ui system's viewport if it has no parent</param>
383+
/// <returns>The actual size of this layout item, any scaling into account</returns>
388384
Vector2 CalcActualSize(RectangleF parentArea);
389385

390386
/// <summary>
@@ -405,19 +401,10 @@ public interface ILayoutItem {
405401

406402
/// <summary>
407403
/// A method called by <see cref="UiLayouter.Layout{T}"/> when a layout item's size is being recalculated based on its children.
408-
/// Also see <see cref="OnLayoutRecursionSettled"/>, which is called after recursive operations during element layouting have completed.
409404
/// </summary>
410405
/// <param name="recursion">The current recursion depth.</param>
411406
/// <param name="relevantChild">The child that triggered the layout recursion. May be <see langword="null"/> in case the source of the layout recursion is unknown.</param>
412407
void OnLayoutRecursion(int recursion, ILayoutItem relevantChild);
413408

414-
/// <summary>
415-
/// A method called by <see cref="UiLayouter.Layout{T}"/> when a layout item's size is being calculated, but recursive calculations have settled.
416-
/// Also see <see cref="OnLayoutRecursion"/>, which is called for every recursive operation during element layouting.
417-
/// </summary>
418-
/// <param name="totalRecursion">The total reached recursion depth.</param>
419-
/// <param name="elementInternal"><see langword="true"/> if the settled recursive operation was element-internal (ie related to properties like <see cref="SetWidthBasedOnChildren"/> and <see cref="SetHeightBasedOnChildren"/>); <see langword="false"/> if the settled recursive operation was related to recursively updated children or parents of this element.</param>
420-
void OnLayoutRecursionSettled(int totalRecursion, bool elementInternal);
421-
422409
}
423410
}

0 commit comments

Comments
 (0)