A game framework written with osu! in mind.
at master 165 lines 5.1 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; 5using osu.Framework.Graphics; 6using osu.Framework.Graphics.Containers; 7using osu.Framework.Graphics.Shapes; 8using osu.Framework.Graphics.Sprites; 9using osu.Framework.Input.Events; 10using osu.Framework.Timing; 11using osuTK; 12using osuTK.Graphics; 13 14namespace osu.Framework.Tests.Visual.Clocks 15{ 16 public abstract class TestSceneClock : FrameworkTestScene 17 { 18 private readonly FillFlowContainer fill; 19 20 protected TestSceneClock() 21 { 22 Child = fill = new FillFlowContainer 23 { 24 Spacing = new Vector2(5), 25 Direction = FillDirection.Full, 26 RelativeSizeAxes = Axes.Both, 27 }; 28 29 AddStep("clear all", () => 30 { 31 fill.Clear(); 32 lastClock = null; 33 AddClock(Clock); 34 }); 35 } 36 37 private IClock lastClock; 38 39 protected IClock AddClock(IClock clock) 40 { 41 if (lastClock != null && clock is ISourceChangeableClock framed) 42 framed.ChangeSource(lastClock); 43 44 fill.Add(new VisualClock(lastClock = clock)); 45 46 return clock; 47 } 48 49 public class VisualClock : CompositeDrawable 50 { 51 private readonly IClock clock; 52 private readonly SpriteText time; 53 private readonly SpriteText rate; 54 55 private bool zeroed = true; 56 57 private const float width = 200; 58 59 private readonly Box bg; 60 private readonly Box hand; 61 62 public VisualClock(IClock clock) 63 { 64 this.clock = clock; 65 66 Size = new Vector2(width); 67 CornerRadius = width / 2; 68 Masking = true; 69 70 BorderColour = Color4.White; 71 BorderThickness = 5; 72 73 InternalChildren = new Drawable[] 74 { 75 bg = new Box 76 { 77 Colour = clock is IAdjustableClock ? Color4.Tomato : Color4.Navy, 78 RelativeSizeAxes = Axes.Both, 79 }, 80 new SpriteText 81 { 82 Text = clock.GetType().Name, 83 Anchor = Anchor.Centre, 84 Origin = Anchor.Centre, 85 Y = -25, 86 }, 87 time = new SpriteText 88 { 89 Anchor = Anchor.Centre, 90 Origin = Anchor.Centre, 91 Y = 25, 92 }, 93 rate = new SpriteText 94 { 95 Anchor = Anchor.Centre, 96 Origin = Anchor.Centre, 97 Font = new FontUsage(size: 14), 98 Y = 40, 99 }, 100 hand = new Box 101 { 102 Colour = Color4.White, 103 Anchor = Anchor.Centre, 104 Origin = Anchor.BottomCentre, 105 Size = new Vector2(2, width / 2) 106 }, 107 }; 108 } 109 110 protected override bool OnClick(ClickEvent e) 111 { 112 if (clock is IAdjustableClock adjustable) 113 { 114 if (adjustable.IsRunning) 115 adjustable.Stop(); 116 else 117 adjustable.Start(); 118 } 119 120 return true; 121 } 122 123 protected override bool OnScroll(ScrollEvent e) 124 { 125 if (clock is IAdjustableClock adjustable) 126 adjustable.Rate += e.ScrollDelta.Y / 1000; 127 128 return base.OnScroll(e); 129 } 130 131 protected override void Update() 132 { 133 base.Update(); 134 135 var lastTime = clock.CurrentTime; 136 137 (clock as IFrameBasedClock)?.ProcessFrame(); 138 139 var timespan = TimeSpan.FromMilliseconds(clock.CurrentTime); 140 time.Text = $"{timespan.Minutes:00}:{timespan.Seconds:00}:{timespan.Milliseconds:00}"; 141 rate.Text = $"{clock.Rate:N2}x"; 142 143 if (clock.CurrentTime != lastTime) 144 BorderColour = clock.CurrentTime >= lastTime ? Color4.White : Color4.Red; 145 146 Colour = clock.IsRunning ? Color4.White : Color4.Gray; 147 148 hand.Rotation = (float)(clock.CurrentTime / 1000) * 360 % 360; 149 150 if (hand.Rotation < 180) 151 { 152 if (!zeroed) 153 { 154 zeroed = true; 155 bg.FlashColour(Color4.White, 500, Easing.OutQuint); 156 } 157 } 158 else 159 { 160 zeroed = false; 161 } 162 } 163 } 164 } 165}