Optimise + ensure propagation of non-layout flags

This commit is contained in:
smoogipoo
2020-04-10 18:56:32 +09:00
parent 54c9afff5e
commit 8de3fd0809
2 changed files with 53 additions and 4 deletions

View File

@@ -339,6 +339,49 @@ namespace osu.Framework.Tests.Layout
AddAssert("child size matches parent", () => child.DrawSize == parent.Size);
}
/// <summary>
/// Tests that non-alive children always receive non-layout invalidations (Parent & DrawNode).
/// </summary>
[Test]
public void TestNonAliveChildReceivesParentAndDrawNodeInvalidations()
{
Container parent = null;
bool invalidated = false;
AddStep("create test", () =>
{
Drawable child;
Child = parent = new Container
{
Size = new Vector2(200),
Child = child = new Box
{
RelativeSizeAxes = Axes.Both,
LifetimeStart = double.MaxValue
}
};
child.Invalidated += _ => invalidated = true;
});
AddStep("invalidate parent", () =>
{
invalidated = false;
parent.Invalidate(Invalidation.Parent);
});
AddAssert("child invalidated", () => invalidated);
AddStep("invalidate drawnode", () =>
{
invalidated = false;
parent.Invalidate(Invalidation.DrawNode);
});
AddAssert("child invalidated", () => invalidated);
}
private class TestBox1 : Box
{
public override bool RemoveWhenNotAlive => false;

View File

@@ -753,8 +753,8 @@ namespace osu.Framework.Graphics.Containers
ChildBecameAlive?.Invoke(child);
// Invalidations on non-alive children are blocked, so they must be invalidated once when they become alive.
child.Invalidate(source: InvalidationSource.Parent);
// Layout invalidations on non-alive children are blocked, so they must be invalidated once when they become alive.
child.Invalidate(Invalidation.Layout, InvalidationSource.Parent);
// Notify ourselves that a child has become alive.
Invalidate(Invalidation.Presence, InvalidationSource.Child);
@@ -966,9 +966,15 @@ namespace osu.Framework.Graphics.Containers
if (source == InvalidationSource.Child)
return anyInvalidated;
for (int i = 0; i < aliveInternalChildren.Count; ++i)
IReadOnlyList<Drawable> targetChildren = aliveInternalChildren;
// Non-layout flags must be propagated to all children. As such, it is simplest + quickest to propagate all other relevant flags along with them.
if ((invalidation & ~Invalidation.Layout) > 0)
targetChildren = internalChildren;
for (int i = 0; i < targetChildren.Count; ++i)
{
Drawable c = aliveInternalChildren[i];
Drawable c = targetChildren[i];
Invalidation childInvalidation = invalidation;
if ((invalidation & Invalidation.RequiredParentSizeToFit) > 0)