Skip to content

Commit 422f2c5

Browse files
committed
Fixed undrawn elements not updating their area correctly even if their children are drawn or accessed
(potentially not final)
1 parent 272b6f5 commit 422f2c5

File tree

5 files changed

+37
-23
lines changed

5 files changed

+37
-23
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ Additions
1111
Improvements
1212
- Made the exception thrown after the element recursion limit is reached more helpful
1313

14+
Fixes
15+
- Fixed undrawn elements not updating their area correctly even if their children are drawn or accessed
16+
1417
## 8.0.0
1518

1619
### MLEM

MLEM.Ui/Elements/Element.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ protected IList<Element> SortedChildren {
556556
private bool treatSizeAsMaximum;
557557
private bool preventParentSpill;
558558
private int layoutRecursion;
559+
private bool parentPotentiallyDirty = true;
559560

560561
/// <summary>
561562
/// Creates a new element with the given anchor and size and sets up some default event reactions.
@@ -664,13 +665,22 @@ public void SetAreaDirty() {
664665
this.AreaDirty = true;
665666
this.System?.InvokeOnElementAreaDirty(this);
666667
this.Parent?.OnChildAreaDirty(this, false);
668+
foreach (var child in this.Children)
669+
child.OnParentAreaDirty(this, false);
667670
}
668671

669672
/// <summary>
670673
/// Updates this element's <see cref="Area"/> and all of its <see cref="Children"/> by calling <see cref="ForceUpdateArea"/> if <see cref="AreaDirty"/> is true.
671674
/// </summary>
672675
/// <returns>Whether <see cref="AreaDirty"/> was true and <see cref="ForceUpdateArea"/> was called</returns>
673676
public bool UpdateAreaIfDirty() {
677+
// ensure we are positioned correctly in our parent by updating its area if it is dirty.
678+
// this ensures that area updates are correctly propagated even for elements that don't access their own areas while drawing or updating.
679+
// if the parent's area was dirty and updated our area, our AreaDirty will have already been set to false before we reach the code below.
680+
if (this.parentPotentiallyDirty) {
681+
this.parentPotentiallyDirty = false;
682+
this.Parent?.UpdateAreaIfDirty();
683+
}
674684
if (this.AreaDirty) {
675685
this.ForceUpdateArea();
676686
return true;
@@ -688,6 +698,7 @@ public virtual void ForceUpdateArea() {
688698
return;
689699
// if the parent's area is dirty, it would get updated anyway when querying its ChildPaddedArea,
690700
// which would cause our ForceUpdateArea code to be run twice, so we only update our parent instead
701+
this.parentPotentiallyDirty = false;
691702
if (this.Parent != null && this.Parent.UpdateAreaIfDirty())
692703
return;
693704
this.stopwatch.Restart();
@@ -1055,6 +1066,13 @@ protected virtual void OnChildAreaDirty(Element child, bool grandchild) {
10551066
this.Parent?.OnChildAreaDirty(child, true);
10561067
}
10571068

1069+
protected virtual void OnParentAreaDirty(Element parent, bool grandparent) {
1070+
if (!grandparent)
1071+
this.parentPotentiallyDirty = true;
1072+
foreach (var child in this.Children)
1073+
child.OnParentAreaDirty(parent, true);
1074+
}
1075+
10581076
/// <summary>
10591077
/// Transforms the given <paramref name="position"/> by the inverse of this element's <see cref="Transform"/> matrix.
10601078
/// </summary>

MLEM.Ui/Elements/Group.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,5 @@ public Group(Anchor anchor, Vector2 size, bool setWidthBasedOnChildren, bool set
3131
base.CanBeSelected = false;
3232
}
3333

34-
/// <inheritdoc />
35-
public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
36-
// TODO since the group never accesses its own area when drawing, we have to update it manually :/
37-
// this is a little terrible but removing it causes a lot of issues when it comes to location updates for grouped elements
38-
// & this is a pretty good sign that we really need to streamline the element dirtying & updating order
39-
this.UpdateAreaIfDirty();
40-
base.Draw(time, batch, alpha, context);
41-
}
42-
4334
}
4435
}

MLEM.Ui/Elements/SquishingGroup.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,6 @@ public override void SetAreaAndUpdateChildren(RectangleF area) {
3030
}
3131
}
3232

33-
/// <inheritdoc />
34-
public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
35-
// be sure to update our area before drawing since our children may not have been squished yet
36-
this.UpdateAreaIfDirty();
37-
base.Draw(time, batch, alpha, context);
38-
}
39-
40-
/// <inheritdoc />
41-
public override Element GetElementUnderPos(Vector2 position) {
42-
// be sure to update our area before since our children may not have been squished yet
43-
this.UpdateAreaIfDirty();
44-
return base.GetElementUnderPos(position);
45-
}
46-
4733
/// <inheritdoc />
4834
protected override void OnChildAreaDirty(Element child, bool grandchild) {
4935
base.OnChildAreaDirty(child, grandchild);

Tests/UiTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,22 @@ public void TestToString() {
281281
Assert.AreEqual(button.ToString(), "Test Button 0 @ Test Group 0 @ Panel Test");
282282
}
283283

284+
[Test]
285+
public void TestGroupDirtyPropagation() {
286+
var group = new Group(Anchor.BottomRight, Vector2.One) {SetWidthBasedOnChildren = true};
287+
var btn = group.AddChild(new Button(Anchor.AutoInlineBottomIgnoreOverflow, new Vector2(12)));
288+
var panel = group.AddChild(new Panel(Anchor.AutoRight, new Vector2(120, 175), Vector2.Zero, false, true) {PositionOffset = new Vector2(0, 1)});
289+
290+
this.AddAndUpdate(group, out _, out _);
291+
Assert.AreEqual(btn.System.Viewport.Height - 175 - 1 - 12, btn.DisplayArea.Y);
292+
293+
// hiding the panel should update the button's display area,
294+
// but due to elements that don't draw themselves previously not propagating updates correctly,
295+
// this was not the case
296+
panel.IsHidden = true;
297+
Assert.AreEqual(btn.System.Viewport.Height - 12, btn.DisplayArea.Y);
298+
}
299+
284300
private void AddAndUpdate(Element element, out TimeSpan addTime, out TimeSpan updateTime) {
285301
foreach (var root in this.Game.UiSystem.GetRootElements())
286302
this.Game.UiSystem.Remove(root.Name);

0 commit comments

Comments
 (0)