mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 22:18:34 +01:00
fixed stack overflow with nested auto-sized children
This commit is contained in:
parent
3e20aaf6c5
commit
79ba6864e7
2 changed files with 52 additions and 22 deletions
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
@ -524,27 +525,10 @@ namespace MLEM.Ui.Elements {
|
|||
var parentArea = this.Parent != null ? this.Parent.ChildPaddedArea : (RectangleF) this.system.Viewport;
|
||||
var parentCenterX = parentArea.X + parentArea.Width / 2;
|
||||
var parentCenterY = parentArea.Y + parentArea.Height / 2;
|
||||
|
||||
var actualSize = this.CalcActualSize(parentArea);
|
||||
UpdateDisplayArea(actualSize);
|
||||
|
||||
if (this.Children.Count > 0) {
|
||||
var autoSize = this.DisplayArea.Size;
|
||||
if (this.SetHeightBasedOnChildren) {
|
||||
var lowest = this.GetLowestChild(e => !e.IsHidden);
|
||||
if (lowest != null)
|
||||
autoSize.Y = lowest.UnscrolledArea.Bottom - this.DisplayArea.Y + this.ScaledChildPadding.Bottom;
|
||||
}
|
||||
if (this.SetWidthBasedOnChildren) {
|
||||
var rightmost = this.GetRightmostChild(e => !e.IsHidden);
|
||||
if (rightmost != null)
|
||||
autoSize.X = rightmost.UnscrolledArea.Right - this.DisplayArea.X + this.ScaledChildPadding.Right;
|
||||
}
|
||||
if (this.TreatSizeAsMinimum)
|
||||
autoSize = Vector2.Max(autoSize, actualSize);
|
||||
if (autoSize != this.DisplayArea.Size)
|
||||
UpdateDisplayArea(autoSize);
|
||||
}
|
||||
var recursion = 0;
|
||||
UpdateDisplayArea(actualSize);
|
||||
|
||||
void UpdateDisplayArea(Vector2 newSize) {
|
||||
var pos = new Vector2();
|
||||
|
@ -639,9 +623,38 @@ namespace MLEM.Ui.Elements {
|
|||
this.System.OnElementAreaUpdated?.Invoke(this);
|
||||
|
||||
foreach (var child in this.Children)
|
||||
child.SetAreaDirty();
|
||||
// clear the dirty flag again in case our children just set us dirty
|
||||
this.areaDirty = false;
|
||||
child.ForceUpdateArea();
|
||||
|
||||
if (this.Children.Count > 0) {
|
||||
Element foundChild = null;
|
||||
var autoSize = this.Area.Size;
|
||||
if (this.SetHeightBasedOnChildren) {
|
||||
var lowest = this.GetLowestChild(e => !e.IsHidden);
|
||||
var newY = lowest?.UnscrolledArea.Bottom - pos.Y + this.ScaledChildPadding.Bottom;
|
||||
if (newY != null && autoSize.Y != newY) {
|
||||
autoSize.Y = newY.Value;
|
||||
foundChild = lowest;
|
||||
}
|
||||
}
|
||||
if (this.SetWidthBasedOnChildren) {
|
||||
var rightmost = this.GetRightmostChild(e => !e.IsHidden);
|
||||
var newX = rightmost?.UnscrolledArea.Right - pos.X + this.ScaledChildPadding.Right;
|
||||
if (newX != null && autoSize.X != newX) {
|
||||
autoSize.X = newX.Value;
|
||||
foundChild = rightmost;
|
||||
}
|
||||
}
|
||||
if (this.TreatSizeAsMinimum)
|
||||
autoSize = Vector2.Max(autoSize, actualSize);
|
||||
if (autoSize != this.Area.Size) {
|
||||
recursion++;
|
||||
if (recursion >= 16) {
|
||||
throw new ArithmeticException($"The area of {this} with root {this.Root?.Name} has recursively updated too often. Does its child {foundChild} contain any conflicting auto-sizing settings?");
|
||||
} else {
|
||||
UpdateDisplayArea(autoSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ using MLEM.Ui;
|
|||
using MLEM.Ui.Elements;
|
||||
using MLEM.Ui.Style;
|
||||
using MonoGame.Extended.Tiled;
|
||||
using Group = MLEM.Ui.Elements.Group;
|
||||
|
||||
namespace Sandbox {
|
||||
public class GameImpl : MlemGame {
|
||||
|
@ -205,6 +206,22 @@ namespace Sandbox {
|
|||
invalidPanel.AddChild(new Paragraph(Anchor.AutoRight, 1, "This is some test text!", true));
|
||||
invalidPanel.AddChild(new VerticalSpace(1));
|
||||
this.UiSystem.Add("Invalid", invalidPanel);*/
|
||||
|
||||
var loadGroup = new Group(Anchor.TopLeft, Vector2.One, false);
|
||||
var loadPanel = loadGroup.AddChild(new Panel(Anchor.Center, new Vector2(150, 150), Vector2.Zero, false, true, new Point(5, 10), false) {
|
||||
ChildPadding = new Padding(5, 10, 5, 5)
|
||||
});
|
||||
for (var i = 0; i < 1; i++) {
|
||||
var button = loadPanel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) {
|
||||
SetHeightBasedOnChildren = true,
|
||||
Padding = new Padding(0, 0, 0, 1),
|
||||
ChildPadding = new Vector2(3)
|
||||
});
|
||||
button.AddChild(new Group(Anchor.AutoLeft, new Vector2(0.5F, 30), false) {
|
||||
CanBeMoused = false
|
||||
});
|
||||
}
|
||||
this.UiSystem.Add("Load", loadGroup);
|
||||
}
|
||||
|
||||
protected override void DoUpdate(GameTime gameTime) {
|
||||
|
|
Loading…
Reference in a new issue