From 4bcf15f63257eb741775623ce5605bc5fb31220c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 May 2022 17:56:32 +0900 Subject: [PATCH 1/8] Refactor test to allow waveform testing --- .../Editing/TestSceneTapTimingControl.cs | 76 +++++++++++-------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs index de441995b5..46b45979ea 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs @@ -4,15 +4,15 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Timing; using osuTK; @@ -22,9 +22,9 @@ namespace osu.Game.Tests.Visual.Editing [TestFixture] public class TestSceneTapTimingControl : EditorClockTestScene { - [Cached(typeof(EditorBeatmap))] - [Cached(typeof(IBeatSnapProvider))] - private readonly EditorBeatmap editorBeatmap; + private EditorBeatmap editorBeatmap => editorBeatmapContainer?.EditorBeatmap; + + private TestSceneHitObjectComposer.EditorBeatmapContainer editorBeatmapContainer; [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); @@ -33,38 +33,48 @@ namespace osu.Game.Tests.Visual.Editing private Bindable selectedGroup = new Bindable(); private TapTimingControl control; + private OsuSpriteText timingInfo; - public TestSceneTapTimingControl() + [Resolved] + private AudioManager audio { get; set; } + + [SetUpSteps] + public void SetUpSteps() { - var playableBeatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); + AddStep("create beatmap", () => + { + Beatmap.Value = new WaveformTestBeatmap(audio); + }); - // Ensure time doesn't end while testing - playableBeatmap.BeatmapInfo.Length = 1200000; + AddStep("Create component", () => + { + Child = editorBeatmapContainer = new TestSceneHitObjectComposer.EditorBeatmapContainer(Beatmap.Value) + { + Children = new Drawable[] + { + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Y, + Width = 400, + Scale = new Vector2(1.5f), + Child = control = new TapTimingControl(), + }, + timingInfo = new OsuSpriteText(), + } + }; - editorBeatmap = new EditorBeatmap(playableBeatmap); - - selectedGroup.Value = editorBeatmap.ControlPointInfo.Groups.First(); + selectedGroup.Value = editorBeatmap.ControlPointInfo.Groups.First(); + }); } - protected override void LoadComplete() + protected override void Update() { - base.LoadComplete(); + base.Update(); - Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap); - Beatmap.Disabled = true; - - Children = new Drawable[] - { - new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Y, - Width = 400, - Scale = new Vector2(1.5f), - Child = control = new TapTimingControl(), - } - }; + if (selectedGroup.Value != null) + timingInfo.Text = $"offset: {selectedGroup.Value.Time:N2} bpm: {selectedGroup.Value.ControlPoints.OfType().First().BPM:N2}"; } [Test] @@ -104,7 +114,13 @@ namespace osu.Game.Tests.Visual.Editing .TriggerClick(); }); - AddSliderStep("BPM", 30, 400, 60, bpm => editorBeatmap.ControlPointInfo.TimingPoints.First().BeatLength = 60000f / bpm); + AddSliderStep("BPM", 30, 400, 128, bpm => + { + if (editorBeatmap == null) + return; + + editorBeatmap.ControlPointInfo.TimingPoints.First().BeatLength = 60000f / bpm; + }); } protected override void Dispose(bool isDisposing) From 588c5d158320bf5ad26e85337a46084b92d5bda8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 May 2022 19:52:01 +0900 Subject: [PATCH 2/8] Add initial waveform comparison display --- .../ControlPoints/TimingControlPoint.cs | 2 + .../Screens/Edit/Timing/TapTimingControl.cs | 36 ++++- .../Edit/Timing/WaveformComparisonDisplay.cs | 152 ++++++++++++++++++ 3 files changed, 184 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index 922439fcb8..3a7c8b2ec0 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + using osu.Framework.Bindables; using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Edit/Timing/TapTimingControl.cs b/osu.Game/Screens/Edit/Timing/TapTimingControl.cs index 1b0f0a3f5e..d0ab4d1f98 100644 --- a/osu.Game/Screens/Edit/Timing/TapTimingControl.cs +++ b/osu.Game/Screens/Edit/Timing/TapTimingControl.cs @@ -24,8 +24,8 @@ namespace osu.Game.Screens.Edit.Timing [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider, OsuColour colours) { - Height = 200; RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; CornerRadius = LabelledDrawable.CORNER_RADIUS; Masking = true; @@ -39,20 +39,44 @@ namespace osu.Game.Screens.Edit.Timing }, new GridContainer { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, RowDimensions = new[] { - new Dimension(), + new Dimension(GridSizeMode.Absolute, 200), new Dimension(GridSizeMode.Absolute, 60), }, Content = new[] { new Drawable[] { - new MetronomeDisplay + new Container { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[] + { + new MetronomeDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new WaveformComparisonDisplay(), + } + }, + } + } } }, new Drawable[] diff --git a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs new file mode 100644 index 0000000000..67a1d30ebe --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs @@ -0,0 +1,152 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +using System; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Audio; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class WaveformComparisonDisplay : CompositeDrawable + { + private const int total_waveforms = 8; + + private OsuSpriteText beatIndexText = null!; + + private readonly BindableNumber beatLength = new BindableDouble(); + + [Resolved] + private IBindable beatmap { get; set; } = null!; + + [Resolved] + private Bindable selectedGroup { get; set; } = null!; + + [Resolved] + private EditorClock editorClock { get; set; } = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + private TimingControlPoint timingPoint = TimingControlPoint.DEFAULT; + + private int lastDisplayedBeatIndex; + + public WaveformComparisonDisplay() + { + RelativeSizeAxes = Axes.Both; + + CornerRadius = LabelledDrawable.CORNER_RADIUS; + Masking = true; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + for (int i = 0; i < total_waveforms; i++) + { + AddInternal(new WaveformGraph + { + RelativeSizeAxes = Axes.Both, + BaseColour = colourProvider.Colour0, + LowColour = colourProvider.Colour1, + MidColour = colourProvider.Colour2, + HighColour = colourProvider.Colour4, + Waveform = beatmap.Value.Waveform, + Resolution = 1, + RelativePositionAxes = Axes.Both, + Height = 1f / total_waveforms, + Y = (float)i / total_waveforms, + }); + } + + AddInternal(new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.White, + RelativeSizeAxes = Axes.Y, + Width = 3, + }); + + AddInternal(beatIndexText = new OsuSpriteText + { + Margin = new MarginPadding(5), + }); + + selectedGroup.BindValueChanged(selectedGroupChanged, true); + beatLength.BindValueChanged(_ => showFrom(lastDisplayedBeatIndex), true); + } + + private void selectedGroupChanged(ValueChangedEvent group) + { + timingPoint = selectedGroup.Value?.ControlPoints.OfType().FirstOrDefault() + ?? TimingControlPoint.DEFAULT; + + beatLength.UnbindBindings(); + beatLength.BindTo(timingPoint.BeatLengthBindable); + } + + protected override bool OnHover(HoverEvent e) => true; + + protected override bool OnMouseMove(MouseMoveEvent e) + { + float trackLength = (float)beatmap.Value.Track.Length; + int totalBeatsAvailable = (int)(trackLength / timingPoint.BeatLength); + + Scheduler.AddOnce(showFrom, (int)(e.MousePosition.X / DrawWidth * totalBeatsAvailable)); + + return base.OnMouseMove(e); + } + + protected override void Update() + { + base.Update(); + + if (!IsHovered) + { + int beatOffset = (int)Math.Max(0, ((editorClock.CurrentTime - selectedGroup.Value.Time) / timingPoint.BeatLength)); + + showFrom(beatOffset); + } + } + + private void showFrom(int beatIndex) + { + const float visible_width = 300; + + float trackLength = (float)beatmap.Value.Track.Length; + float scale = trackLength / visible_width; + + beatIndexText.Text = beatIndex.ToString(); + + foreach (var waveform in InternalChildren.OfType()) + { + // offset to the required beat index. + float offset = (float)(selectedGroup.Value.Time + (beatIndex * timingPoint.BeatLength - (visible_width / 2))) / trackLength * scale; + + waveform.X = -offset; + waveform.Scale = new Vector2(scale, 1); + + beatIndex++; + } + + lastDisplayedBeatIndex = beatIndex; + } + } +} From 7040dec013d1c050d7d1d068af770f337f2be5f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 May 2022 20:01:25 +0900 Subject: [PATCH 3/8] Fix disabled bindable woes by not using `TimingControlPoint.DEFAULT` --- .../Screens/Edit/Timing/WaveformComparisonDisplay.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs index 67a1d30ebe..e410d380d6 100644 --- a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Edit.Timing private IBindable beatmap { get; set; } = null!; [Resolved] - private Bindable selectedGroup { get; set; } = null!; + private Bindable selectedGroup { get; set; } = null!; [Resolved] private EditorClock editorClock { get; set; } = null!; @@ -46,6 +46,8 @@ namespace osu.Game.Screens.Edit.Timing private int lastDisplayedBeatIndex; + private double offsetZeroTime => selectedGroup.Value?.Time ?? 0; + public WaveformComparisonDisplay() { RelativeSizeAxes = Axes.Both; @@ -93,10 +95,10 @@ namespace osu.Game.Screens.Edit.Timing beatLength.BindValueChanged(_ => showFrom(lastDisplayedBeatIndex), true); } - private void selectedGroupChanged(ValueChangedEvent group) + private void selectedGroupChanged(ValueChangedEvent group) { timingPoint = selectedGroup.Value?.ControlPoints.OfType().FirstOrDefault() - ?? TimingControlPoint.DEFAULT; + ?? new TimingControlPoint(); beatLength.UnbindBindings(); beatLength.BindTo(timingPoint.BeatLengthBindable); @@ -120,7 +122,7 @@ namespace osu.Game.Screens.Edit.Timing if (!IsHovered) { - int beatOffset = (int)Math.Max(0, ((editorClock.CurrentTime - selectedGroup.Value.Time) / timingPoint.BeatLength)); + int beatOffset = (int)Math.Max(0, ((editorClock.CurrentTime - offsetZeroTime) / timingPoint.BeatLength)); showFrom(beatOffset); } @@ -138,7 +140,7 @@ namespace osu.Game.Screens.Edit.Timing foreach (var waveform in InternalChildren.OfType()) { // offset to the required beat index. - float offset = (float)(selectedGroup.Value.Time + (beatIndex * timingPoint.BeatLength - (visible_width / 2))) / trackLength * scale; + float offset = (float)(offsetZeroTime + (beatIndex * timingPoint.BeatLength - (visible_width / 2))) / trackLength * scale; waveform.X = -offset; waveform.Scale = new Vector2(scale, 1); From c1720c128d1f591281194b4b76744ea7dcefd7cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 May 2022 21:00:21 +0900 Subject: [PATCH 4/8] Dim rows which are not part of the active control point (and offset centre) --- .../Edit/Timing/WaveformComparisonDisplay.cs | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs index e410d380d6..2667ae5396 100644 --- a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs @@ -33,6 +33,9 @@ namespace osu.Game.Screens.Edit.Timing [Resolved] private IBindable beatmap { get; set; } = null!; + [Resolved] + private EditorBeatmap editorBeatmap { get; set; } = null!; + [Resolved] private Bindable selectedGroup { get; set; } = null!; @@ -46,7 +49,10 @@ namespace osu.Game.Screens.Edit.Timing private int lastDisplayedBeatIndex; - private double offsetZeroTime => selectedGroup.Value?.Time ?? 0; + private double selectedGroupStartTime; + private double selectedGroupEndTime; + + private readonly BindableList controlPointGroups = new BindableList(); public WaveformComparisonDisplay() { @@ -88,20 +94,45 @@ namespace osu.Game.Screens.Edit.Timing AddInternal(beatIndexText = new OsuSpriteText { - Margin = new MarginPadding(5), + Anchor = Anchor.CentreLeft, + Margin = new MarginPadding(4), }); - selectedGroup.BindValueChanged(selectedGroupChanged, true); + selectedGroup.BindValueChanged(_ => updateTimingGroup(), true); + + ((IBindableList)controlPointGroups).BindTo(editorBeatmap.ControlPointInfo.Groups); + controlPointGroups.BindCollectionChanged((_, __) => updateTimingGroup()); + beatLength.BindValueChanged(_ => showFrom(lastDisplayedBeatIndex), true); } - private void selectedGroupChanged(ValueChangedEvent group) + private void updateTimingGroup() { - timingPoint = selectedGroup.Value?.ControlPoints.OfType().FirstOrDefault() - ?? new TimingControlPoint(); - beatLength.UnbindBindings(); + + selectedGroupStartTime = 0; + selectedGroupEndTime = beatmap.Value.Track.Length; + + var tcp = selectedGroup.Value?.ControlPoints.OfType().FirstOrDefault(); + + if (tcp == null) + { + timingPoint = new TimingControlPoint(); + return; + } + + timingPoint = tcp; beatLength.BindTo(timingPoint.BeatLengthBindable); + + selectedGroupStartTime = selectedGroup.Value?.Time ?? 0; + + var nextGroup = editorBeatmap.ControlPointInfo.TimingPoints + .SkipWhile(g => g != tcp) + .Skip(1) + .FirstOrDefault(); + + if (nextGroup != null) + selectedGroupEndTime = nextGroup.Time; } protected override bool OnHover(HoverEvent e) => true; @@ -122,7 +153,7 @@ namespace osu.Game.Screens.Edit.Timing if (!IsHovered) { - int beatOffset = (int)Math.Max(0, ((editorClock.CurrentTime - offsetZeroTime) / timingPoint.BeatLength)); + int beatOffset = (int)Math.Floor((editorClock.CurrentTimeAccurate - selectedGroupStartTime) / timingPoint.BeatLength); showFrom(beatOffset); } @@ -137,11 +168,17 @@ namespace osu.Game.Screens.Edit.Timing beatIndexText.Text = beatIndex.ToString(); + // Start displaying from before the current beat + beatIndex -= total_waveforms / 2; + foreach (var waveform in InternalChildren.OfType()) { // offset to the required beat index. - float offset = (float)(offsetZeroTime + (beatIndex * timingPoint.BeatLength - (visible_width / 2))) / trackLength * scale; + double time = selectedGroupStartTime + beatIndex * timingPoint.BeatLength; + float offset = (float)(time - visible_width / 2) / trackLength * scale; + + waveform.Alpha = time < selectedGroupStartTime || time > selectedGroupEndTime ? 0.2f : 1; waveform.X = -offset; waveform.Scale = new Vector2(scale, 1); From 4fcdcef166b5089fd9403011d2f8ae3405308059 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 May 2022 21:32:55 +0900 Subject: [PATCH 5/8] Add indexing on each wavefrom row --- .../Edit/Timing/WaveformComparisonDisplay.cs | 72 ++++++++++++------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs index 2667ae5396..ad4e1e737d 100644 --- a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs @@ -26,8 +26,6 @@ namespace osu.Game.Screens.Edit.Timing { private const int total_waveforms = 8; - private OsuSpriteText beatIndexText = null!; - private readonly BindableNumber beatLength = new BindableDouble(); [Resolved] @@ -42,9 +40,6 @@ namespace osu.Game.Screens.Edit.Timing [Resolved] private EditorClock editorClock { get; set; } = null!; - [Resolved] - private OverlayColourProvider colourProvider { get; set; } = null!; - private TimingControlPoint timingPoint = TimingControlPoint.DEFAULT; private int lastDisplayedBeatIndex; @@ -68,15 +63,9 @@ namespace osu.Game.Screens.Edit.Timing for (int i = 0; i < total_waveforms; i++) { - AddInternal(new WaveformGraph + AddInternal(new WaveformRow { RelativeSizeAxes = Axes.Both, - BaseColour = colourProvider.Colour0, - LowColour = colourProvider.Colour1, - MidColour = colourProvider.Colour2, - HighColour = colourProvider.Colour4, - Waveform = beatmap.Value.Waveform, - Resolution = 1, RelativePositionAxes = Axes.Both, Height = 1f / total_waveforms, Y = (float)i / total_waveforms, @@ -92,12 +81,6 @@ namespace osu.Game.Screens.Edit.Timing Width = 3, }); - AddInternal(beatIndexText = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Margin = new MarginPadding(4), - }); - selectedGroup.BindValueChanged(_ => updateTimingGroup(), true); ((IBindableList)controlPointGroups).BindTo(editorBeatmap.ControlPointInfo.Groups); @@ -166,26 +149,63 @@ namespace osu.Game.Screens.Edit.Timing float trackLength = (float)beatmap.Value.Track.Length; float scale = trackLength / visible_width; - beatIndexText.Text = beatIndex.ToString(); - // Start displaying from before the current beat beatIndex -= total_waveforms / 2; - foreach (var waveform in InternalChildren.OfType()) + foreach (var row in InternalChildren.OfType()) { // offset to the required beat index. double time = selectedGroupStartTime + beatIndex * timingPoint.BeatLength; float offset = (float)(time - visible_width / 2) / trackLength * scale; - waveform.Alpha = time < selectedGroupStartTime || time > selectedGroupEndTime ? 0.2f : 1; - waveform.X = -offset; - waveform.Scale = new Vector2(scale, 1); - - beatIndex++; + row.Alpha = time < selectedGroupStartTime || time > selectedGroupEndTime ? 0.2f : 1; + row.WaveformOffset = -offset; + row.WaveformScale = new Vector2(scale, 1); + row.BeatIndex = beatIndex++; } lastDisplayedBeatIndex = beatIndex; } + + internal class WaveformRow : CompositeDrawable + { + private OsuSpriteText beatIndexText = null!; + private WaveformGraph waveformGraph = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + [BackgroundDependencyLoader] + private void load(IBindable beatmap) + { + InternalChildren = new Drawable[] + { + waveformGraph = new WaveformGraph + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Waveform = beatmap.Value.Waveform, + Resolution = 1, + + BaseColour = colourProvider.Colour0, + LowColour = colourProvider.Colour1, + MidColour = colourProvider.Colour2, + HighColour = colourProvider.Colour4, + }, + beatIndexText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Padding = new MarginPadding(5), + Colour = colourProvider.Content2 + } + }; + } + + public int BeatIndex { set => beatIndexText.Text = value.ToString(); } + public Vector2 WaveformScale { set => waveformGraph.Scale = value; } + public float WaveformOffset { set => waveformGraph.X = value; } + } } } From 49a21736464330baf0333ff5bfec2461885edd50 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 May 2022 14:33:05 +0900 Subject: [PATCH 6/8] Avoid needlessly updating display (and add better documentation on chosen scale) --- .../Screens/Edit/Timing/WaveformComparisonDisplay.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs index ad4e1e737d..0830ba8cf4 100644 --- a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs @@ -136,14 +136,21 @@ namespace osu.Game.Screens.Edit.Timing if (!IsHovered) { - int beatOffset = (int)Math.Floor((editorClock.CurrentTimeAccurate - selectedGroupStartTime) / timingPoint.BeatLength); + int currentBeat = (int)Math.Floor((editorClock.CurrentTimeAccurate - selectedGroupStartTime) / timingPoint.BeatLength); - showFrom(beatOffset); + showFrom(currentBeat); } } private void showFrom(int beatIndex) { + if (lastDisplayedBeatIndex == beatIndex) + return; + + // Chosen as a pretty usable number across all BPMs. + // Optimally we'd want this to scale with the BPM in question, but performing + // scaling of the display is both expensive in resampling, and decreases usability + // (as it is harder to track the waveform when making realtime adjustments). const float visible_width = 300; float trackLength = (float)beatmap.Value.Track.Length; From f1d4902be524cbd65a73c8298739ba36f1990ef4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 May 2022 19:25:23 +0900 Subject: [PATCH 7/8] Remove unnecessary bindable cast --- osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs index 0830ba8cf4..c80d3c4261 100644 --- a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Edit.Timing private double selectedGroupStartTime; private double selectedGroupEndTime; - private readonly BindableList controlPointGroups = new BindableList(); + private readonly IBindableList controlPointGroups = new BindableList(); public WaveformComparisonDisplay() { @@ -83,7 +83,7 @@ namespace osu.Game.Screens.Edit.Timing selectedGroup.BindValueChanged(_ => updateTimingGroup(), true); - ((IBindableList)controlPointGroups).BindTo(editorBeatmap.ControlPointInfo.Groups); + controlPointGroups.BindTo(editorBeatmap.ControlPointInfo.Groups); controlPointGroups.BindCollectionChanged((_, __) => updateTimingGroup()); beatLength.BindValueChanged(_ => showFrom(lastDisplayedBeatIndex), true); From 795c9fcbc9cfa9345d9ed1cbde3a8e9fc4a7606d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 25 May 2022 19:38:50 +0900 Subject: [PATCH 8/8] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index aaea784852..d5a77c6349 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5bc65ca507..32a0adb859 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -35,7 +35,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 3597e7e5c0..112b5b4615 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -61,7 +61,7 @@ - + @@ -84,7 +84,7 @@ - +