Fix GUI traversal during child removal

This commit is contained in:
David Svez
2026-08-23 17:03:49 -05:00
committed by Wojtek Figat
parent b375b40736
commit 3fcad576a1
2 changed files with 56 additions and 14 deletions
@@ -26,6 +26,29 @@ namespace FlaxEngine.Tests
}
}
private sealed class RemovingControl : MyControl
{
private readonly Control[] _controlsToRemove;
public RemovingControl(float x, float y, float width, float height, params Control[] controlsToRemove)
: base(x, y, width, height)
{
_controlsToRemove = controlsToRemove;
}
public override void OnMouseEnter(Float2 location)
{
for (int i = 0; i < _controlsToRemove.Length; i++)
{
var control = _controlsToRemove[i];
if (control.Parent == Parent)
control.Parent = null;
}
base.OnMouseEnter(location);
}
}
[Test]
public void TestChildren()
{
@@ -53,6 +76,25 @@ namespace FlaxEngine.Tests
Assert.AreEqual(cc1.GetChildAt(new Vector2(15, 5)), cc2);
Assert.AreEqual(cc1.GetChildAtRecursive(new Vector2(35, 25)), c3);
}
[Test]
public void TestMouseMoveAllowsChildrenRemoval()
{
var container = new MyContainerControl(0, 0, 100, 100);
var first = new MyControl(0, 0, 100, 100);
var second = new MyControl(0, 0, 100, 100);
var removing = new RemovingControl(0, 0, 100, 100, first, second);
container.AddChild(first);
container.AddChild(second);
container.AddChild(removing);
// The top-most child removes multiple siblings during input dispatch.
// Traversal must not use the now-stale next index.
container.OnMouseMove(new Float2(50, 50));
Assert.AreEqual(1, container.ChildrenCount);
Assert.AreEqual(removing, container.GetChild(0));
}
}
}
#endif
+14 -14
View File
@@ -910,7 +910,7 @@ namespace FlaxEngine.GUI
return false;
}
}
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible)
@@ -928,7 +928,7 @@ namespace FlaxEngine.GUI
public override void OnMouseEnter(Float2 location)
{
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -948,7 +948,7 @@ namespace FlaxEngine.GUI
public override void OnMouseMove(Float2 location)
{
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -998,7 +998,7 @@ namespace FlaxEngine.GUI
public override bool OnMouseWheel(Float2 location, float delta)
{
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -1019,7 +1019,7 @@ namespace FlaxEngine.GUI
public override bool OnMouseDown(Float2 location, MouseButton button)
{
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -1040,7 +1040,7 @@ namespace FlaxEngine.GUI
public override bool OnMouseUp(Float2 location, MouseButton button)
{
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -1061,7 +1061,7 @@ namespace FlaxEngine.GUI
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -1096,7 +1096,7 @@ namespace FlaxEngine.GUI
/// <inheritdoc />
public override void OnTouchEnter(Float2 location, int pointerId)
{
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled && !child.IsTouchPointerOver(pointerId))
@@ -1114,7 +1114,7 @@ namespace FlaxEngine.GUI
/// <inheritdoc />
public override bool OnTouchDown(Float2 location, int pointerId)
{
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -1139,7 +1139,7 @@ namespace FlaxEngine.GUI
/// <inheritdoc />
public override void OnTouchMove(Float2 location, int pointerId)
{
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -1168,7 +1168,7 @@ namespace FlaxEngine.GUI
/// <inheritdoc />
public override bool OnTouchUp(Float2 location, int pointerId)
{
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled && child.IsTouchPointerOver(pointerId))
@@ -1250,7 +1250,7 @@ namespace FlaxEngine.GUI
var result = base.OnDragEnter(ref location, data);
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -1275,7 +1275,7 @@ namespace FlaxEngine.GUI
var result = base.OnDragMove(ref location, data);
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)
@@ -1333,7 +1333,7 @@ namespace FlaxEngine.GUI
var result = base.OnDragDrop(ref location, data);
// Check all children collisions with mouse and fire events for them
for (int i = _children.Count - 1; i >= 0 && _children.Count > 0; i--)
for (int i = _children.Count - 1; i >= 0 && i < _children.Count; i--)
{
var child = _children[i];
if (child.Visible && child.Enabled)