From 8be500535d651e0ed17e4ab996cbb063773b4634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Sch=C3=BCrz?= Date: Mon, 30 Dec 2024 03:13:22 +0100 Subject: [PATCH 1/4] Speed up metronome when holding control --- .../Screens/Edit/Timing/MetronomeDisplay.cs | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs index 29e730c865..44553a92d4 100644 --- a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Framework.Timing; using osu.Framework.Utils; @@ -232,6 +233,19 @@ namespace osu.Game.Screens.Edit.Timing private ScheduledDelegate? latchDelegate; + private bool divisorChanged; + + private void setDivisor(int divisor) + { + if (divisor == Divisor) + return; + + divisorChanged = true; + + Divisor = divisor; + metronomeTick.Divisor = divisor; + } + protected override void LoadComplete() { base.LoadComplete(); @@ -250,13 +264,13 @@ namespace osu.Game.Screens.Edit.Timing timingPoint = BeatSyncSource.ControlPoints.TimingPointAt(BeatSyncSource.Clock.CurrentTime); - if (beatLength != timingPoint.BeatLength) + if (beatLength != timingPoint.BeatLength || divisorChanged) { beatLength = timingPoint.BeatLength; EarlyActivationMilliseconds = timingPoint.BeatLength / 2; - float bpmRatio = (float)Interpolation.ApplyEasing(Easing.OutQuad, Math.Clamp((timingPoint.BPM - 30) / 480, 0, 1)); + float bpmRatio = (float)Interpolation.ApplyEasing(Easing.OutQuad, Math.Clamp((timingPoint.BPM - 30) / 480 * Divisor, 0, 1)); weight.MoveToY((float)Interpolation.Lerp(0.1f, 0.83f, bpmRatio), 600, Easing.OutQuint); this.TransformBindableTo(interpolatedBpm, (int)Math.Round(timingPoint.BPM), 600, Easing.OutQuint); @@ -286,6 +300,8 @@ namespace osu.Game.Screens.Edit.Timing latchDelegate = Schedule(() => sampleLatch?.Play()); } } + + divisorChanged = false; } protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) @@ -316,6 +332,22 @@ namespace osu.Game.Screens.Edit.Timing stick.FlashColour(overlayColourProvider.Content1, beatLength, Easing.OutQuint); } + protected override bool OnKeyDown(KeyDownEvent e) + { + updateDivisorFromKey(e); + + return base.OnKeyDown(e); + } + + protected override void OnKeyUp(KeyUpEvent e) + { + base.OnKeyUp(e); + + updateDivisorFromKey(e); + } + + private void updateDivisorFromKey(UIEvent e) => setDivisor(e.ControlPressed ? 2 : 1); + private partial class MetronomeTick : BeatSyncedContainer { public bool EnableClicking; From aa6763785c00a50d1624b1aebe2a400d63273fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Sch=C3=BCrz?= Date: Mon, 30 Dec 2024 03:21:52 +0100 Subject: [PATCH 2/4] Use 3x speed instead when beat snap divisor is divisible by 3 --- osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs index 44553a92d4..553eacab46 100644 --- a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs @@ -42,6 +42,9 @@ namespace osu.Game.Screens.Edit.Timing [Resolved] private OverlayColourProvider overlayColourProvider { get; set; } = null!; + [Resolved] + private BindableBeatDivisor beatDivisor { get; set; } = null!; + public bool EnableClicking { get => metronomeTick.EnableClicking; @@ -233,10 +236,17 @@ namespace osu.Game.Screens.Edit.Timing private ScheduledDelegate? latchDelegate; + private bool spedUp; + private bool divisorChanged; - private void setDivisor(int divisor) + private void updateDivisor() { + int divisor = 1; + + if (spedUp) + divisor = beatDivisor.Value % 3 == 0 ? 3 : 2; + if (divisor == Divisor) return; @@ -264,6 +274,8 @@ namespace osu.Game.Screens.Edit.Timing timingPoint = BeatSyncSource.ControlPoints.TimingPointAt(BeatSyncSource.Clock.CurrentTime); + updateDivisor(); + if (beatLength != timingPoint.BeatLength || divisorChanged) { beatLength = timingPoint.BeatLength; @@ -346,7 +358,7 @@ namespace osu.Game.Screens.Edit.Timing updateDivisorFromKey(e); } - private void updateDivisorFromKey(UIEvent e) => setDivisor(e.ControlPressed ? 2 : 1); + private void updateDivisorFromKey(UIEvent e) => spedUp = e.ControlPressed; private partial class MetronomeTick : BeatSyncedContainer { From 9ea7afb38edb455f07771191481bd47e53bf9c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Sch=C3=BCrz?= Date: Mon, 30 Dec 2024 03:59:54 +0100 Subject: [PATCH 3/4] Use return value instead of field to force weight position update --- osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs index 553eacab46..58d461b3a5 100644 --- a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs @@ -238,9 +238,7 @@ namespace osu.Game.Screens.Edit.Timing private bool spedUp; - private bool divisorChanged; - - private void updateDivisor() + private bool updateDivisor() { int divisor = 1; @@ -248,12 +246,12 @@ namespace osu.Game.Screens.Edit.Timing divisor = beatDivisor.Value % 3 == 0 ? 3 : 2; if (divisor == Divisor) - return; - - divisorChanged = true; + return false; Divisor = divisor; metronomeTick.Divisor = divisor; + + return true; } protected override void LoadComplete() @@ -274,9 +272,7 @@ namespace osu.Game.Screens.Edit.Timing timingPoint = BeatSyncSource.ControlPoints.TimingPointAt(BeatSyncSource.Clock.CurrentTime); - updateDivisor(); - - if (beatLength != timingPoint.BeatLength || divisorChanged) + if (updateDivisor() || beatLength != timingPoint.BeatLength) { beatLength = timingPoint.BeatLength; @@ -312,8 +308,6 @@ namespace osu.Game.Screens.Edit.Timing latchDelegate = Schedule(() => sampleLatch?.Play()); } } - - divisorChanged = false; } protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) From 0641d2b51000b953628cbad480f7b50cf251d4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Sch=C3=BCrz?= Date: Mon, 30 Dec 2024 19:12:21 +0100 Subject: [PATCH 4/4] Remove turboweird function and update displayed bpm text --- .../Screens/Edit/Timing/MetronomeDisplay.cs | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs index 58d461b3a5..5e5b740b62 100644 --- a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs @@ -226,7 +226,7 @@ namespace osu.Game.Screens.Edit.Timing Clock = new FramedClock(metronomeClock = new StopwatchClock(true)); } - private double beatLength; + private double effectiveBeatLength; private TimingControlPoint timingPoint = null!; @@ -238,27 +238,24 @@ namespace osu.Game.Screens.Edit.Timing private bool spedUp; - private bool updateDivisor() + private int computeSpedUpDivisor() { - int divisor = 1; + if (!spedUp) + return 1; - if (spedUp) - divisor = beatDivisor.Value % 3 == 0 ? 3 : 2; + if (beatDivisor.Value % 3 == 0) + return 3; + if (beatDivisor.Value % 2 == 0) + return 2; - if (divisor == Divisor) - return false; - - Divisor = divisor; - metronomeTick.Divisor = divisor; - - return true; + return 1; } protected override void LoadComplete() { base.LoadComplete(); - interpolatedBpm.BindValueChanged(bpm => bpmText.Text = bpm.NewValue.ToLocalisableString()); + interpolatedBpm.BindValueChanged(_ => bpmText.Text = interpolatedBpm.Value.ToLocalisableString()); } protected override void Update() @@ -272,16 +269,20 @@ namespace osu.Game.Screens.Edit.Timing timingPoint = BeatSyncSource.ControlPoints.TimingPointAt(BeatSyncSource.Clock.CurrentTime); - if (updateDivisor() || beatLength != timingPoint.BeatLength) + Divisor = metronomeTick.Divisor = computeSpedUpDivisor(); + + if (effectiveBeatLength != timingPoint.BeatLength / Divisor) { - beatLength = timingPoint.BeatLength; + effectiveBeatLength = timingPoint.BeatLength / Divisor; EarlyActivationMilliseconds = timingPoint.BeatLength / 2; - float bpmRatio = (float)Interpolation.ApplyEasing(Easing.OutQuad, Math.Clamp((timingPoint.BPM - 30) / 480 * Divisor, 0, 1)); + double effectiveBpm = 60000 / effectiveBeatLength; + + float bpmRatio = (float)Interpolation.ApplyEasing(Easing.OutQuad, Math.Clamp((effectiveBpm - 30) / 480, 0, 1)); weight.MoveToY((float)Interpolation.Lerp(0.1f, 0.83f, bpmRatio), 600, Easing.OutQuint); - this.TransformBindableTo(interpolatedBpm, (int)Math.Round(timingPoint.BPM), 600, Easing.OutQuint); + this.TransformBindableTo(interpolatedBpm, (int)Math.Round(effectiveBpm), 600, Easing.OutQuint); } if (!BeatSyncSource.Clock.IsRunning && isSwinging) @@ -327,7 +328,7 @@ namespace osu.Game.Screens.Edit.Timing float currentAngle = swing.Rotation; float targetAngle = currentAngle > 0 ? -angle : angle; - swing.RotateTo(targetAngle, beatLength, Easing.InOutQuad); + swing.RotateTo(targetAngle, effectiveBeatLength, Easing.InOutQuad); } private void onTickPlayed() @@ -335,7 +336,7 @@ namespace osu.Game.Screens.Edit.Timing // Originally, this flash only occurred when the pendulum correctly passess the centre. // Mappers weren't happy with the metronome tick not playing immediately after starting playback // so now this matches the actual tick sample. - stick.FlashColour(overlayColourProvider.Content1, beatLength, Easing.OutQuint); + stick.FlashColour(overlayColourProvider.Content1, effectiveBeatLength, Easing.OutQuint); } protected override bool OnKeyDown(KeyDownEvent e)