A game framework written with osu! in mind.
at master 204 lines 6.2 kB view raw
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 4using System.Threading; 5using NUnit.Framework; 6using osu.Framework.Allocation; 7using osu.Framework.Graphics; 8using osu.Framework.Graphics.Containers; 9using osu.Framework.Graphics.Shapes; 10using osu.Framework.Graphics.Sprites; 11using osuTK; 12using osuTK.Graphics; 13 14namespace osu.Framework.Tests.Visual.Drawables 15{ 16 public class TestSceneModelBackedDrawableWithLoading : FrameworkTestScene 17 { 18 private TestModelBackedDrawable backedDrawable; 19 20 private void createModelBackedDrawable(bool immediate) => 21 Child = backedDrawable = new TestModelBackedDrawable(immediate) 22 { 23 Anchor = Anchor.Centre, 24 Origin = Anchor.Centre, 25 Size = new Vector2(200), 26 }; 27 28 [Test] 29 public void TestNonImmediateTransform() 30 { 31 AddStep("setup", () => createModelBackedDrawable(false)); 32 addUsageSteps(); 33 } 34 35 [Test] 36 public void TestTransformImmediately() 37 { 38 AddStep("setup", () => createModelBackedDrawable(true)); 39 addUsageSteps(); 40 } 41 42 private void addUsageSteps() 43 { 44 TestDrawableModel drawableModel = null; 45 46 AddStep("load first model", () => backedDrawable.Model = new TestModel(drawableModel = new TestDrawableModel())); 47 AddWaitStep("wait a bit", 5); 48 AddStep("finish load", () => drawableModel.AllowLoad.Set()); 49 AddWaitStep("wait a bit", 5); 50 AddStep("load second model", () => backedDrawable.Model = new TestModel(drawableModel = new TestDrawableModel())); 51 AddWaitStep("wait a bit", 5); 52 AddStep("finish load", () => drawableModel.AllowLoad.Set()); 53 } 54 55 private class TestModelBackedDrawable : ModelBackedDrawable<TestModel> 56 { 57 public new TestModel Model 58 { 59 set => base.Model = value; 60 } 61 62 private readonly bool immediate; 63 private readonly Drawable spinner; 64 65 public TestModelBackedDrawable(bool immediate) 66 { 67 this.immediate = immediate; 68 69 CornerRadius = 5; 70 Masking = true; 71 72 AddRangeInternal(new[] 73 { 74 new Box 75 { 76 Colour = new Color4(0.1f, 0.1f, 0.1f, 1), 77 RelativeSizeAxes = Axes.Both, 78 Depth = float.MaxValue 79 }, 80 spinner = new LoadingSpinner 81 { 82 Anchor = Anchor.Centre, 83 Origin = Anchor.Centre, 84 Size = new Vector2(20), 85 Alpha = 0, 86 Depth = float.MinValue 87 } 88 }); 89 } 90 91 protected override bool TransformImmediately => immediate; 92 93 protected override double TransformDuration => 500; 94 95 protected override Drawable CreateDrawable(TestModel model) => model?.Drawable; 96 97 protected override void OnLoadStarted() 98 { 99 base.OnLoadStarted(); 100 101 if (!immediate) 102 DisplayedDrawable?.FadeTo(0, 300, Easing.OutQuint); 103 104 spinner.FadeIn(300, Easing.OutQuint); 105 } 106 107 protected override void OnLoadFinished() 108 { 109 base.OnLoadFinished(); 110 111 spinner.FadeOut(250, Easing.OutQuint); 112 } 113 } 114 115 private class TestModel 116 { 117 public readonly Drawable Drawable; 118 119 public TestModel(TestDrawableModel drawable) 120 { 121 Drawable = drawable; 122 } 123 } 124 125 private class TestDrawableModel : CompositeDrawable 126 { 127 private static int id = 1; 128 129 public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(); 130 131 protected Color4 BackgroundColour 132 { 133 get 134 { 135 switch (id % 5) 136 { 137 default: 138 return Color4.SkyBlue; 139 140 case 1: 141 return Color4.Tomato; 142 143 case 2: 144 return Color4.DarkGreen; 145 146 case 3: 147 return Color4.MediumPurple; 148 149 case 4: 150 return Color4.DarkOrchid; 151 } 152 } 153 } 154 155 public TestDrawableModel() 156 { 157 RelativeSizeAxes = Axes.Both; 158 159 InternalChildren = new Drawable[] 160 { 161 new Box 162 { 163 RelativeSizeAxes = Axes.Both, 164 Colour = BackgroundColour 165 }, 166 new SpriteText 167 { 168 Anchor = Anchor.Centre, 169 Origin = Anchor.Centre, 170 Text = $"Model {id++}" 171 } 172 }; 173 } 174 175 [BackgroundDependencyLoader] 176 private void load() 177 { 178 AllowLoad.Wait(); 179 } 180 } 181 182 private class LoadingSpinner : CompositeDrawable 183 { 184 private readonly SpriteIcon icon; 185 186 public LoadingSpinner() 187 { 188 InternalChild = icon = new SpriteIcon 189 { 190 Anchor = Anchor.Centre, 191 Origin = Anchor.Centre, 192 RelativeSizeAxes = Axes.Both, 193 Icon = FontAwesome.Solid.Spinner 194 }; 195 } 196 197 protected override void LoadComplete() 198 { 199 base.LoadComplete(); 200 icon.Spin(2000, RotationDirection.Clockwise); 201 } 202 } 203 } 204}