A game framework written with osu! in mind.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Only invalidate alive children

+204 -2
+49
osu.Framework.Benchmarks/BenchmarkInvalidationWithManyNotAlive.cs
··· 1 + // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2 + // See the LICENCE file in the repository root for full licence text. 3 + 4 + using BenchmarkDotNet.Attributes; 5 + using NUnit.Framework; 6 + using osu.Framework.Graphics; 7 + using osu.Framework.Graphics.Containers; 8 + using osu.Framework.Graphics.Shapes; 9 + using osuTK; 10 + 11 + namespace osu.Framework.Benchmarks 12 + { 13 + public class BenchmarkInvalidationWithManyNotAlive : GameBenchmark 14 + { 15 + [Test] 16 + [Benchmark] 17 + public void RunFrame() => RunSingleFrame(); 18 + 19 + protected override Game CreateGame() => new TestGame(); 20 + 21 + private class TestGame : Game 22 + { 23 + protected override void LoadComplete() 24 + { 25 + base.LoadComplete(); 26 + 27 + var container = new FillFlowContainer 28 + { 29 + Anchor = Anchor.Centre, 30 + Origin = Anchor.Centre, 31 + RelativeSizeAxes = Axes.Both, 32 + }; 33 + 34 + for (int i = 0; i < 50000; i++) 35 + { 36 + container.Add(new Box 37 + { 38 + Size = new Vector2(10), 39 + LifetimeStart = i > 10000 ? double.MaxValue : double.MinValue 40 + }); 41 + } 42 + 43 + Add(container); 44 + 45 + container.Spin(200, RotationDirection.Clockwise); 46 + } 47 + } 48 + } 49 + }
+37
osu.Framework.Benchmarks/BenchmarkMakeChildAlive.cs
··· 1 + // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2 + // See the LICENCE file in the repository root for full licence text. 3 + 4 + using BenchmarkDotNet.Attributes; 5 + using NUnit.Framework; 6 + using osu.Framework.Graphics; 7 + using osu.Framework.Graphics.Shapes; 8 + 9 + namespace osu.Framework.Benchmarks 10 + { 11 + public class BenchmarkMakeChildAlive : GameBenchmark 12 + { 13 + [Test] 14 + [Benchmark] 15 + public void RunFrame() => RunSingleFrame(); 16 + 17 + protected override Game CreateGame() => new TestGame(); 18 + 19 + private class TestGame : Game 20 + { 21 + private readonly Box child; 22 + 23 + public TestGame() 24 + { 25 + child = new Box { RelativeSizeAxes = Axes.Both }; 26 + } 27 + 28 + protected override void Update() 29 + { 30 + base.Update(); 31 + 32 + Clear(false); 33 + Add(child); 34 + } 35 + } 36 + } 37 + }
+43
osu.Framework.Benchmarks/BenchmarkSpinningParentWithManyAlive.cs
··· 1 + // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2 + // See the LICENCE file in the repository root for full licence text. 3 + 4 + using BenchmarkDotNet.Attributes; 5 + using NUnit.Framework; 6 + using osu.Framework.Graphics; 7 + using osu.Framework.Graphics.Containers; 8 + using osu.Framework.Graphics.Shapes; 9 + using osuTK; 10 + 11 + namespace osu.Framework.Benchmarks 12 + { 13 + public class BenchmarkSpinningParentWithManyAlive : GameBenchmark 14 + { 15 + [Test] 16 + [Benchmark] 17 + public void RunFrame() => RunSingleFrame(); 18 + 19 + protected override Game CreateGame() => new TestGame(); 20 + 21 + private class TestGame : Game 22 + { 23 + protected override void LoadComplete() 24 + { 25 + base.LoadComplete(); 26 + 27 + var container = new FillFlowContainer 28 + { 29 + Anchor = Anchor.Centre, 30 + Origin = Anchor.Centre, 31 + RelativeSizeAxes = Axes.Both, 32 + }; 33 + 34 + for (int i = 0; i < 10000; i++) 35 + container.Add(new Box { Size = new Vector2(10) }); 36 + 37 + Add(container); 38 + 39 + container.Spin(200, RotationDirection.Clockwise); 40 + } 41 + } 42 + } 43 + }
+68
osu.Framework.Tests/Layout/TestSceneContainerLayout.cs
··· 271 271 AddAssert("parent only invalidated with size", () => invalidation == Invalidation.DrawSize); 272 272 } 273 273 274 + /// <summary> 275 + /// Tests that a child is not invalidated by its parent when not alive. 276 + /// </summary> 277 + [Test] 278 + public void TestChildNotInvalidatedWhenNotAlive() 279 + { 280 + Container parent = null; 281 + bool invalidated = false; 282 + 283 + AddStep("create test", () => 284 + { 285 + Drawable child; 286 + 287 + Child = parent = new Container 288 + { 289 + Size = new Vector2(200), 290 + Child = child = new Box 291 + { 292 + RelativeSizeAxes = Axes.Both, 293 + LifetimeStart = double.MaxValue 294 + } 295 + }; 296 + 297 + // Trigger a validation of draw size. 298 + Assert.That(child.DrawSize, Is.EqualTo(new Vector2(200))); 299 + 300 + child.Invalidated += _ => invalidated = true; 301 + }); 302 + 303 + AddStep("resize parent", () => parent.Size = new Vector2(400)); 304 + AddAssert("child not invalidated", () => !invalidated); 305 + } 306 + 307 + /// <summary> 308 + /// Tests that a loaded child is invalidated when it becomes alive. 309 + /// </summary> 310 + [Test] 311 + public void TestChildInvalidatedWhenMadeAlive() 312 + { 313 + Container parent = null; 314 + Drawable child = null; 315 + bool invalidated = false; 316 + 317 + AddStep("create test", () => 318 + { 319 + Child = parent = new Container 320 + { 321 + Size = new Vector2(200), 322 + Child = child = new Box { RelativeSizeAxes = Axes.Both } 323 + }; 324 + }); 325 + 326 + AddStep("make child dead", () => 327 + { 328 + child.LifetimeStart = double.MaxValue; 329 + child.Invalidated += _ => invalidated = true; 330 + }); 331 + 332 + // See above: won't cause an invalidation 333 + AddStep("resize parent", () => parent.Size = new Vector2(400)); 334 + 335 + AddStep("make child alive", () => child.LifetimeStart = double.MinValue); 336 + AddAssert("child invalidated", () => invalidated); 337 + 338 + // Final check to make sure that the correct invalidation occurred 339 + AddAssert("child size matches parent", () => child.DrawSize == parent.Size); 340 + } 341 + 274 342 private class TestBox1 : Box 275 343 { 276 344 public override bool RemoveWhenNotAlive => false;
+7 -2
osu.Framework/Graphics/Containers/CompositeDrawable.cs
··· 753 753 754 754 ChildBecameAlive?.Invoke(child); 755 755 756 + // Invalidations on non-alive children are blocked, so they must be invalidated once when they become alive. 757 + child.Invalidate(source: InvalidationSource.Parent); 758 + 759 + // Notify ourselves that a child has become alive. 756 760 Invalidate(Invalidation.Presence, InvalidationSource.Child); 757 761 } 758 762 ··· 785 789 removed = true; 786 790 } 787 791 792 + // Notify ourselves that a child has died. 788 793 Invalidate(Invalidation.Presence, InvalidationSource.Child); 789 794 790 795 return removed; ··· 961 966 if (source == InvalidationSource.Child) 962 967 return anyInvalidated; 963 968 964 - for (int i = 0; i < internalChildren.Count; ++i) 969 + for (int i = 0; i < aliveInternalChildren.Count; ++i) 965 970 { 966 - Drawable c = internalChildren[i]; 971 + Drawable c = aliveInternalChildren[i]; 967 972 968 973 Invalidation childInvalidation = invalidation; 969 974 if ((invalidation & Invalidation.RequiredParentSizeToFit) > 0)