Skip to content

Commit dddab34

Browse files
authored
Merge pull request #349 from winnerspiros/copilot/merge-ppy-commits-prioritize-fork
Merge latest 5 commits from ppy/master while preserving fork behavior on conflicts
2 parents 013c45e + 94deee5 commit dddab34

24 files changed

Lines changed: 593 additions & 131 deletions

osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardEncoderTest.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,23 @@ public void TestBackground()
2929
Assert.That(decodedAfterEncode.Beatmap.BeatmapInfo.Metadata.BackgroundFile, Is.EqualTo("bg.jpg"));
3030
}
3131

32+
[Test]
33+
public void TestBackgroundOffset()
34+
{
35+
var initial = createComponents();
36+
initial.Beatmap.BeatmapInfo.Metadata.BackgroundFile = "bg_offset.jpg";
37+
initial.Storyboard.BackgroundOffset = new Vector2(0, 45);
38+
39+
var encoded = encode(initial);
40+
var decodedAfterEncode = decode(encoded);
41+
42+
Assert.Multiple(() =>
43+
{
44+
Assert.That(decodedAfterEncode.Beatmap.BeatmapInfo.Metadata.BackgroundFile, Is.EqualTo("bg_offset.jpg"));
45+
Assert.That(decodedAfterEncode.Storyboard.BackgroundOffset, Is.EqualTo(new Vector2(0, 45)));
46+
});
47+
}
48+
3249
[Test]
3350
public void TestVideos()
3451
{

osu.Game.Tests/Visual/UserInterface/TestSceneFormControls.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ public TestSceneFormControls()
188188
Caption = "File selector",
189189
PlaceholderText = "Select a file",
190190
},
191+
new FormFileSelector
192+
{
193+
Caption = "File selector with deselection",
194+
PlaceholderText = "Select a file",
195+
AllowClear = true,
196+
},
191197
new FormBeatmapFileSelector(true)
192198
{
193199
Caption = "File selector with intermediate choice dialog",
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 NUnit.Framework;
5+
using osu.Framework.Testing;
6+
using osu.Game.Configuration;
7+
using osu.Game.Overlays;
8+
9+
namespace osu.Game.Tests.Visual.UserInterface
10+
{
11+
public partial class TestSceneMigrateAudioDialog : OsuManualInputManagerTestScene
12+
{
13+
private DialogOverlay overlay = null!;
14+
15+
[SetUpSteps]
16+
public void SetUpSteps()
17+
{
18+
AddStep("create dialog overlay", () => Child = overlay = new DialogOverlay());
19+
}
20+
21+
[Test]
22+
public void TestWasUsing()
23+
{
24+
AddStep("create dialog", () =>
25+
{
26+
overlay.Push(new MigrateNewAudioDialog(true));
27+
});
28+
}
29+
30+
[Test]
31+
public void TestNotUsing()
32+
{
33+
AddStep("create dialog", () =>
34+
{
35+
overlay.Push(new MigrateNewAudioDialog(false));
36+
});
37+
}
38+
}
39+
}

osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,10 @@ private void load(BeatmapSetOverlay? beatmapSetOverlay)
244244
});
245245

246246
if (BeatmapSet.HasVideo)
247-
leftIconArea.Add(new VideoIconPill { IconSize = new Vector2(16) });
247+
leftIconArea.Add(new VideoIconPill());
248248

249249
if (BeatmapSet.HasStoryboard)
250-
leftIconArea.Add(new StoryboardIconPill { IconSize = new Vector2(16) });
250+
leftIconArea.Add(new StoryboardIconPill());
251251

252252
if (BeatmapSet.FeaturedInSpotlight)
253253
{

osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,10 @@ private void load()
226226
});
227227

228228
if (BeatmapSet.HasVideo)
229-
leftIconArea.Add(new VideoIconPill { IconSize = new Vector2(16) });
229+
leftIconArea.Add(new VideoIconPill());
230230

231231
if (BeatmapSet.HasStoryboard)
232-
leftIconArea.Add(new StoryboardIconPill { IconSize = new Vector2(16) });
232+
leftIconArea.Add(new StoryboardIconPill());
233233

234234
if (BeatmapSet.FeaturedInSpotlight)
235235
{

osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,20 @@ private void handleEvents(string line, bool isPrimaryStream)
119119

120120
switch (type)
121121
{
122+
case LegacyEventType.Background:
123+
{
124+
// the actual filename is handled in `LegacyBeatmapDecoder`.
125+
// this only handles the background offset, because it does not logically belong in `Beatmap` or related classes.
126+
if (split.Length > 4)
127+
{
128+
float x = Parsing.ParseFloat(split[3]);
129+
float y = Parsing.ParseFloat(split[4]);
130+
storyboard.BackgroundOffset = new Vector2(x, y);
131+
}
132+
133+
break;
134+
}
135+
122136
case LegacyEventType.Video:
123137
{
124138
int offset = Parsing.ParseInt(split[1]);

osu.Game/Beatmaps/Formats/LegacyStoryboardEncoder.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,9 @@ private void encodeEvents(TextWriter writer, StoryboardElementSource target)
5454
if (target == StoryboardElementSource.Beatmap)
5555
{
5656
// https://github.com/peppy/osu-stable-reference/blob/c34a74fb61c17c5667486a12548485d1f03baa2e/osu!/GameplayElements/HitObjectManager_LoadSave.cs#L1499
57-
// TODO: handle nonzero background offset (https://github.com/ppy/osu/issues/14238)
5857
writer.WriteLine(string.Format(CultureInfo.InvariantCulture,
5958
@"{0},{1},""{2}"",{3},{4}",
60-
(int)LegacyEventType.Background, 0, storyboard.BeatmapInfo.Metadata.BackgroundFile, 0, 0));
59+
(int)LegacyEventType.Background, 0, storyboard.BeatmapInfo.Metadata.BackgroundFile, storyboard.BackgroundOffset.X, storyboard.BackgroundOffset.Y));
6160
}
6261

6362
// https://github.com/peppy/osu-stable-reference/blob/c34a74fb61c17c5667486a12548485d1f03baa2e/osu!/GameplayElements/HitObjectManager_LoadSave.cs#L1496

osu.Game/Beatmaps/FramedBeatmapClock.cs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Diagnostics;
66
using osu.Framework;
77
using osu.Framework.Allocation;
8+
using osu.Framework.Audio;
89
using osu.Framework.Bindables;
910
using osu.Framework.Graphics;
1011
using osu.Framework.Timing;
@@ -49,6 +50,11 @@ public partial class FramedBeatmapClock : Component, IFrameBasedClock, IAdjustab
4950
[Resolved]
5051
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
5152

53+
[Resolved]
54+
private AudioManager audioManager { get; set; } = null!;
55+
56+
private Bindable<bool> experimentalAudio = null!;
57+
5258
public bool IsRewinding { get; private set; }
5359

5460
public FramedBeatmapClock(bool applyOffsets, bool requireDecoupling, IClock? source = null)
@@ -66,9 +72,7 @@ public FramedBeatmapClock(bool applyOffsets, bool requireDecoupling, IClock? sou
6672

6773
if (applyOffsets)
6874
{
69-
// Audio timings in general with newer BASS versions don't match stable.
70-
// This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
71-
platformOffsetClock = new OffsetCorrectionClock(interpolatedTrack) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 15 : 0 };
75+
platformOffsetClock = new OffsetCorrectionClock(interpolatedTrack);
7276

7377
// User global offset (set in settings) should also be applied.
7478
userGlobalOffsetClock = new OffsetCorrectionClock(platformOffsetClock);
@@ -94,6 +98,9 @@ protected override void LoadComplete()
9498
userAudioOffset = config.GetBindable<double>(OsuSetting.AudioOffset);
9599
userAudioOffset.BindValueChanged(offset => userGlobalOffsetClock.Offset = offset.NewValue, true);
96100

101+
experimentalAudio = audioManager.UseExperimentalWasapi.GetBoundCopy();
102+
experimentalAudio.BindValueChanged(_ => updatePlatformOffset());
103+
97104
// TODO: this doesn't update when using ChangeSource() to change beatmap.
98105
beatmapOffsetSubscription = realm.SubscribeToPropertyChanged(
99106
r => r.Find<BeatmapInfo>(beatmap.Value.BeatmapInfo.ID)?.UserSettings,
@@ -105,6 +112,39 @@ protected override void LoadComplete()
105112
}
106113
}
107114

115+
/// <summary>
116+
/// Audio timings in general with newer BASS versions don't match stable.
117+
/// This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
118+
/// </summary>
119+
public const double WINDOWS_BASE_AUDIO_OFFSET = 15;
120+
121+
/// <summary>
122+
/// An additional offset applied to account for experimental mode being much better.
123+
/// </summary>
124+
public const double WINDOWS_EXPERIMENTAL_AUDIO_OFFSET = -25;
125+
126+
private void updatePlatformOffset()
127+
{
128+
if (!applyOffsets)
129+
return;
130+
131+
Debug.Assert(platformOffsetClock != null);
132+
133+
switch (RuntimeInfo.OS)
134+
{
135+
case RuntimeInfo.Platform.Windows:
136+
platformOffsetClock.Offset = WINDOWS_BASE_AUDIO_OFFSET;
137+
138+
if (audioManager.UseExperimentalWasapi.Value)
139+
platformOffsetClock.Offset += WINDOWS_EXPERIMENTAL_AUDIO_OFFSET;
140+
return;
141+
142+
default:
143+
platformOffsetClock.Offset = 0;
144+
break;
145+
}
146+
}
147+
108148
protected override void Update()
109149
{
110150
base.Update();
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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 osu.Framework.Allocation;
5+
using osu.Framework.Graphics;
6+
using osu.Framework.Graphics.Containers;
7+
using osu.Framework.Graphics.Sprites;
8+
using osu.Game.Localisation;
9+
using osu.Game.Overlays;
10+
using osu.Game.Overlays.Dialog;
11+
using osu.Game.Overlays.Settings.Sections.Audio;
12+
13+
namespace osu.Game.Configuration
14+
{
15+
public partial class MigrateNewAudioDialog : PopupDialog
16+
{
17+
[Cached]
18+
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
19+
20+
public MigrateNewAudioDialog(bool wasAlreadyUsing)
21+
{
22+
Icon = FontAwesome.Regular.Bell;
23+
24+
if (wasAlreadyUsing)
25+
{
26+
HeaderText = @"New audio engine is now default!";
27+
BodyText =
28+
$"""
29+
We recently added a new "Experimental Audio" backend for Windows users to reduce hitsound latency. Due to overwhelmingly positive feedback, this is now the default mode.
30+
31+
As you were already using this engine, your audio offset has been adjusted to account for an internal offset change (no intervention required).
32+
33+
If you have any issues, you can switch back to the legacy engine from settings via the "{AudioSettingsStrings.LegacyAudioLabel}" checkbox.
34+
""";
35+
}
36+
else
37+
{
38+
HeaderText = @"New audio engine has been enabled";
39+
BodyText =
40+
$"""
41+
We recently added a new "Experimental Audio" backend for Windows users to reduce hitsound latency. Due to overwhelmingly positive feedback, this is now the default mode.
42+
43+
If you have any issues, you can switch back to the legacy engine below, or at any time in settings via the "{AudioSettingsStrings.LegacyAudioLabel}" checkbox.
44+
""";
45+
46+
MainContent.Add(new Container
47+
{
48+
Margin = new MarginPadding { Top = 20 },
49+
Anchor = Anchor.Centre,
50+
Origin = Anchor.Centre,
51+
Width = 400,
52+
AutoSizeAxes = Axes.Y,
53+
Children = new Drawable[]
54+
{
55+
new LegacyAudioCheckbox(),
56+
}
57+
});
58+
}
59+
60+
Buttons = new PopupDialogButton[]
61+
{
62+
new PopupDialogOkButton
63+
{
64+
Text = BeatmapOverlayStrings.UserContentConfirmButtonText,
65+
},
66+
};
67+
}
68+
}
69+
}

osu.Game/Graphics/UserInterfaceV2/FormFileSelector.cs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
using osu.Framework.Platform;
2222
using osu.Game.Database;
2323
using osu.Game.Graphics.Sprites;
24+
using osu.Game.Graphics.UserInterface;
2425
using osu.Game.Overlays;
26+
using osu.Game.Resources.Localisation.Web;
2527
using System.Numerics;
2628

2729
namespace osu.Game.Graphics.UserInterfaceV2
@@ -66,6 +68,12 @@ public Bindable<FileInfo?> Current
6668
/// </summary>
6769
public LocalisableString PlaceholderText { get; init; }
6870

71+
/// <summary>
72+
/// If set to <see langword="true"/>, the selector will display a button,
73+
/// which when clicked, will change <see cref="Current"/>'s value to <see langword="null"/>.
74+
/// </summary>
75+
public bool AllowClear { get; init; }
76+
6977
public Container PreviewContainer { get; private set; } = null!;
7078

7179
private FormControlBackground background = null!;
@@ -179,7 +187,7 @@ protected override void LoadComplete()
179187

180188
private void onFileSelected()
181189
{
182-
if (Current.Value != null)
190+
if (Current.Value != null || AllowClear)
183191
this.HidePopover();
184192

185193
initialChooserPath = Current.Value?.DirectoryName;
@@ -237,12 +245,12 @@ Task ICanAcceptFiles.Import(params string[] paths)
237245

238246
Task ICanAcceptFiles.Import(ImportTask[] tasks, ImportParameters parameters) => throw new NotImplementedException();
239247

240-
protected virtual FileChooserPopover CreatePopover(string[] handledExtensions, Bindable<FileInfo?> current, string? chooserPath) =>
241-
new FileChooserPopover(handledExtensions, current, chooserPath);
248+
protected virtual FileChooserPopover CreatePopover(string[] handledExtensions, Bindable<FileInfo?> current, string? chooserPath, bool allowClear) =>
249+
new FileChooserPopover(handledExtensions, current, chooserPath, allowClear);
242250

243251
public Popover GetPopover()
244252
{
245-
var popover = CreatePopover(handledExtensions, Current, initialChooserPath);
253+
var popover = CreatePopover(handledExtensions, Current, initialChooserPath, AllowClear);
246254
popoverState.UnbindBindings();
247255
popoverState.BindTo(popover.State);
248256
return popover;
@@ -257,7 +265,7 @@ public partial class FileChooserPopover : OsuPopover
257265

258266
protected OsuFileSelector FileSelector;
259267

260-
public FileChooserPopover(string[] handledExtensions, Bindable<FileInfo?> current, string? chooserPath)
268+
public FileChooserPopover(string[] handledExtensions, Bindable<FileInfo?> current, string? chooserPath, bool allowClear)
261269
: base(false)
262270
{
263271
Child = new Container
@@ -266,9 +274,37 @@ public FileChooserPopover(string[] handledExtensions, Bindable<FileInfo?> curren
266274
// simplest solution to avoid underlying text to bleed through the bottom border
267275
// https://github.com/ppy/osu/pull/30005#issuecomment-2378884430
268276
Padding = new MarginPadding { Bottom = 1 },
269-
Child = FileSelector = new OsuFileSelector(chooserPath, handledExtensions)
277+
Children = new[]
270278
{
271-
RelativeSizeAxes = Axes.Both,
279+
new Container
280+
{
281+
RelativeSizeAxes = Axes.Both,
282+
Padding = new MarginPadding { Bottom = allowClear ? 50 : 0 },
283+
Child = FileSelector = new OsuFileSelector(chooserPath, handledExtensions)
284+
{
285+
RelativeSizeAxes = Axes.Both,
286+
},
287+
},
288+
allowClear
289+
? new Container
290+
{
291+
RelativeSizeAxes = Axes.X,
292+
AutoSizeAxes = Axes.Y,
293+
Anchor = Anchor.BottomCentre,
294+
Origin = Anchor.BottomCentre,
295+
Padding = new MarginPadding(5),
296+
Child = new DangerousRoundedButton
297+
{
298+
Text = CommonStrings.ButtonsClear,
299+
Action = () => OnFileSelected(null),
300+
Enabled = { Value = current.Value != null },
301+
Padding = new MarginPadding(5),
302+
Anchor = Anchor.CentreRight,
303+
Origin = Anchor.CentreRight,
304+
Width = 60,
305+
}
306+
}
307+
: Empty()
272308
},
273309
};
274310

@@ -307,7 +343,7 @@ protected override void LoadComplete()
307343
};
308344
}
309345

310-
protected virtual void OnFileSelected(FileInfo file) => current.Value = file;
346+
protected virtual void OnFileSelected(FileInfo? file) => current.Value = file;
311347
}
312348
}
313349
}

0 commit comments

Comments
 (0)