diff --git a/osu.Android.props b/osu.Android.props
index d893792285..eff0eed278 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs
index d832411104..8b323eefa6 100644
--- a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs
+++ b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs
@@ -1,4 +1,4 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
@@ -26,12 +26,12 @@ namespace osu.Game.Rulesets.Osu.Mods
public BindableFloat Scale { get; } = new BindableFloat(4)
{
Precision = 0.1f,
- MinValue = 2,
+ MinValue = 1.5f,
MaxValue = 10,
};
[SettingSource("Style", "Change the animation style of the approach circles.", 1)]
- public Bindable Style { get; } = new Bindable();
+ public Bindable Style { get; } = new Bindable(AnimationStyle.Gravity);
public void ApplyToDrawableHitObject(DrawableHitObject drawable)
{
@@ -52,9 +52,18 @@ namespace osu.Game.Rulesets.Osu.Mods
{
switch (style)
{
- default:
+ case AnimationStyle.Linear:
return Easing.None;
+ case AnimationStyle.Gravity:
+ return Easing.InBack;
+
+ case AnimationStyle.InOut1:
+ return Easing.InOutCubic;
+
+ case AnimationStyle.InOut2:
+ return Easing.InOutQuint;
+
case AnimationStyle.Accelerate1:
return Easing.In;
@@ -64,9 +73,6 @@ namespace osu.Game.Rulesets.Osu.Mods
case AnimationStyle.Accelerate3:
return Easing.InQuint;
- case AnimationStyle.Gravity:
- return Easing.InBack;
-
case AnimationStyle.Decelerate1:
return Easing.Out;
@@ -76,16 +82,14 @@ namespace osu.Game.Rulesets.Osu.Mods
case AnimationStyle.Decelerate3:
return Easing.OutQuint;
- case AnimationStyle.InOut1:
- return Easing.InOutCubic;
-
- case AnimationStyle.InOut2:
- return Easing.InOutQuint;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(style), style, @"Unsupported animation style");
}
}
public enum AnimationStyle
{
+ Linear,
Gravity,
InOut1,
InOut2,
diff --git a/osu.Game.Tests/Database/BeatmapImporterTests.cs b/osu.Game.Tests/Database/BeatmapImporterTests.cs
index 9ee237cfd9..a6edd6cb5f 100644
--- a/osu.Game.Tests/Database/BeatmapImporterTests.cs
+++ b/osu.Game.Tests/Database/BeatmapImporterTests.cs
@@ -12,6 +12,7 @@ using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Logging;
+using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Extensions;
@@ -474,7 +475,7 @@ namespace osu.Game.Tests.Database
}
[Test]
- public void TestImportThenDeleteThenImport()
+ public void TestImportThenDeleteThenImportOptimisedPath()
{
RunTestWithRealmAsync(async (realmFactory, storage) =>
{
@@ -485,11 +486,39 @@ namespace osu.Game.Tests.Database
deleteBeatmapSet(imported, realmFactory.Context);
+ Assert.IsTrue(imported.DeletePending);
+
var importedSecondTime = await LoadOszIntoStore(importer, realmFactory.Context);
// check the newly "imported" beatmap is actually just the restored previous import. since it matches hash.
Assert.IsTrue(imported.ID == importedSecondTime.ID);
Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Beatmaps.First().ID);
+ Assert.IsFalse(imported.DeletePending);
+ Assert.IsFalse(importedSecondTime.DeletePending);
+ });
+ }
+
+ [Test]
+ public void TestImportThenDeleteThenImportNonOptimisedPath()
+ {
+ RunTestWithRealmAsync(async (realmFactory, storage) =>
+ {
+ using var importer = new NonOptimisedBeatmapImporter(realmFactory, storage);
+ using var store = new RealmRulesetStore(realmFactory, storage);
+
+ var imported = await LoadOszIntoStore(importer, realmFactory.Context);
+
+ deleteBeatmapSet(imported, realmFactory.Context);
+
+ Assert.IsTrue(imported.DeletePending);
+
+ var importedSecondTime = await LoadOszIntoStore(importer, realmFactory.Context);
+
+ // check the newly "imported" beatmap is actually just the restored previous import. since it matches hash.
+ Assert.IsTrue(imported.ID == importedSecondTime.ID);
+ Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Beatmaps.First().ID);
+ Assert.IsFalse(imported.DeletePending);
+ Assert.IsFalse(importedSecondTime.DeletePending);
});
}
@@ -823,7 +852,11 @@ namespace osu.Game.Tests.Database
{
IQueryable? resultSets = null;
- waitForOrAssert(() => (resultSets = realm.All().Where(s => !s.DeletePending && s.OnlineID == 241526)).Any(),
+ waitForOrAssert(() =>
+ {
+ realm.Refresh();
+ return (resultSets = realm.All().Where(s => !s.DeletePending && s.OnlineID == 241526)).Any();
+ },
@"BeatmapSet did not import to the database in allocated time.", timeout);
// ensure we were stored to beatmap database backing...
@@ -836,16 +869,16 @@ namespace osu.Game.Tests.Database
// ReSharper disable once PossibleUnintendedReferenceComparison
IEnumerable queryBeatmaps() => realm.All().Where(s => s.BeatmapSet != null && s.BeatmapSet == set);
- waitForOrAssert(() => queryBeatmaps().Count() == 12, @"Beatmaps did not import to the database in allocated time", timeout);
- waitForOrAssert(() => queryBeatmapSets().Count() == 1, @"BeatmapSet did not import to the database in allocated time", timeout);
+ Assert.AreEqual(12, queryBeatmaps().Count(), @"Beatmap count was not correct");
+ Assert.AreEqual(1, queryBeatmapSets().Count(), @"Beatmapset count was not correct");
- int countBeatmapSetBeatmaps = 0;
- int countBeatmaps = 0;
+ int countBeatmapSetBeatmaps;
+ int countBeatmaps;
- waitForOrAssert(() =>
- (countBeatmapSetBeatmaps = queryBeatmapSets().First().Beatmaps.Count) ==
- (countBeatmaps = queryBeatmaps().Count()),
- $@"Incorrect database beatmap count post-import ({countBeatmaps} but should be {countBeatmapSetBeatmaps}).", timeout);
+ Assert.AreEqual(
+ countBeatmapSetBeatmaps = queryBeatmapSets().First().Beatmaps.Count,
+ countBeatmaps = queryBeatmaps().Count(),
+ $@"Incorrect database beatmap count post-import ({countBeatmaps} but should be {countBeatmapSetBeatmaps}).");
foreach (RealmBeatmap b in set.Beatmaps)
Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineID == b.OnlineID));
@@ -867,5 +900,15 @@ namespace osu.Game.Tests.Database
Assert.Fail(failureMessage);
}
+
+ public class NonOptimisedBeatmapImporter : BeatmapImporter
+ {
+ public NonOptimisedBeatmapImporter(RealmContextFactory realmFactory, Storage storage)
+ : base(realmFactory, storage)
+ {
+ }
+
+ protected override bool HasCustomHashFunction => true;
+ }
}
}
diff --git a/osu.Game.Tests/Database/RealmLiveTests.cs b/osu.Game.Tests/Database/RealmLiveTests.cs
index f86761fdc8..16e2c0fc6a 100644
--- a/osu.Game.Tests/Database/RealmLiveTests.cs
+++ b/osu.Game.Tests/Database/RealmLiveTests.cs
@@ -29,6 +29,22 @@ namespace osu.Game.Tests.Database
});
}
+ [Test]
+ public void TestAccessAfterAttach()
+ {
+ RunTestWithRealm((realmFactory, _) =>
+ {
+ var beatmap = new RealmBeatmap(CreateRuleset(), new RealmBeatmapDifficulty(), new RealmBeatmapMetadata());
+
+ var liveBeatmap = beatmap.ToLive();
+
+ using (var context = realmFactory.CreateContext())
+ context.Write(r => r.Add(beatmap));
+
+ Assert.IsFalse(liveBeatmap.PerformRead(l => l.Hidden));
+ });
+ }
+
[Test]
public void TestAccessNonManaged()
{
@@ -51,7 +67,7 @@ namespace osu.Game.Tests.Database
{
RunTestWithRealm((realmFactory, _) =>
{
- RealmLive? liveBeatmap = null;
+ ILive? liveBeatmap = null;
Task.Factory.StartNew(() =>
{
using (var threadContext = realmFactory.CreateContext())
@@ -88,7 +104,7 @@ namespace osu.Game.Tests.Database
{
RunTestWithRealm((realmFactory, _) =>
{
- RealmLive? liveBeatmap = null;
+ ILive? liveBeatmap = null;
Task.Factory.StartNew(() =>
{
using (var threadContext = realmFactory.CreateContext())
@@ -117,7 +133,7 @@ namespace osu.Game.Tests.Database
{
RunTestWithRealm((realmFactory, _) =>
{
- RealmLive? liveBeatmap = null;
+ ILive? liveBeatmap = null;
Task.Factory.StartNew(() =>
{
using (var threadContext = realmFactory.CreateContext())
@@ -143,7 +159,7 @@ namespace osu.Game.Tests.Database
{
RunTestWithRealm((realmFactory, _) =>
{
- RealmLive? liveBeatmap = null;
+ ILive? liveBeatmap = null;
Task.Factory.StartNew(() =>
{
using (var threadContext = realmFactory.CreateContext())
@@ -176,7 +192,7 @@ namespace osu.Game.Tests.Database
using (var updateThreadContext = realmFactory.CreateContext())
{
updateThreadContext.All().SubscribeForNotifications(gotChange);
- RealmLive? liveBeatmap = null;
+ ILive? liveBeatmap = null;
Task.Factory.StartNew(() =>
{
diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs
new file mode 100644
index 0000000000..aec75884d6
--- /dev/null
+++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs
@@ -0,0 +1,71 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Game.Beatmaps.Drawables.Cards;
+using osu.Game.Graphics;
+using osu.Game.Online.API.Requests.Responses;
+using osu.Game.Overlays;
+
+namespace osu.Game.Tests.Visual.Beatmaps
+{
+ public class TestSceneBeatmapCardDifficultyList : OsuTestScene
+ {
+ [Cached]
+ private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
+
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colours)
+ {
+ var beatmapSet = new APIBeatmapSet
+ {
+ Beatmaps = new[]
+ {
+ new APIBeatmap { RulesetID = 1, StarRating = 5.76, DifficultyName = "Oni" },
+ new APIBeatmap { RulesetID = 1, StarRating = 3.20, DifficultyName = "Muzukashii" },
+ new APIBeatmap { RulesetID = 1, StarRating = 2.45, DifficultyName = "Futsuu" },
+
+ new APIBeatmap { RulesetID = 0, StarRating = 2.04, DifficultyName = "Normal" },
+ new APIBeatmap { RulesetID = 0, StarRating = 3.51, DifficultyName = "Hard" },
+ new APIBeatmap { RulesetID = 0, StarRating = 5.25, DifficultyName = "Insane" },
+
+ new APIBeatmap { RulesetID = 2, StarRating = 2.64, DifficultyName = "Salad" },
+ new APIBeatmap { RulesetID = 2, StarRating = 3.56, DifficultyName = "Platter" },
+ new APIBeatmap { RulesetID = 2, StarRating = 4.65, DifficultyName = "Rain" },
+
+ new APIBeatmap { RulesetID = 3, StarRating = 1.93, DifficultyName = "[7K] Normal" },
+ new APIBeatmap { RulesetID = 3, StarRating = 3.18, DifficultyName = "[7K] Hyper" },
+ new APIBeatmap { RulesetID = 3, StarRating = 4.82, DifficultyName = "[7K] Another" },
+
+ new APIBeatmap { RulesetID = 4, StarRating = 9.99, DifficultyName = "Unknown?!" },
+ }
+ };
+
+ Child = new Container
+ {
+ Width = 300,
+ AutoSizeAxes = Axes.Y,
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = colourProvider.Background2
+ },
+ new Container
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Padding = new MarginPadding(10),
+ Child = new BeatmapCardDifficultyList(beatmapSet)
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
index 13d98145a1..55aa665ff1 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
@@ -17,7 +17,6 @@ using osu.Game.Database;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
-using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
@@ -236,7 +235,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
assertDownloadButtonVisible(false);
void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}",
- () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0));
+ () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0));
}
[Test]
@@ -250,7 +249,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
createPlaylist(byOnlineId, byChecksum);
- AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent));
+ AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent));
}
[Test]
diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs
similarity index 96%
rename from osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs
rename to osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs
index 22a91fa9a3..21bf8d1c5a 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs
@@ -6,15 +6,15 @@ using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.Drawables;
using osu.Game.Online;
using osu.Game.Online.API.Requests.Responses;
-using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Tests.Resources;
using osuTK;
namespace osu.Game.Tests.Visual.Online
{
- public class TestSceneDirectDownloadButton : OsuTestScene
+ public class TestSceneBeatmapDownloadButton : OsuTestScene
{
private TestDownloadButton downloadButton;
@@ -137,7 +137,7 @@ namespace osu.Game.Tests.Visual.Online
return apiBeatmapSet;
}
- private class TestDownloadButton : BeatmapPanelDownloadButton
+ private class TestDownloadButton : BeatmapDownloadButton
{
public new bool DownloadEnabled => base.DownloadEnabled;
diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs
deleted file mode 100644
index 510b9e8483..0000000000
--- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System.Collections.Generic;
-using osu.Framework.Allocation;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Game.Audio;
-using osu.Game.Beatmaps;
-using osu.Game.Online.API.Requests.Responses;
-using osu.Game.Overlays.BeatmapListing.Panels;
-using osu.Game.Rulesets;
-using osuTK;
-using APIUser = osu.Game.Online.API.Requests.Responses.APIUser;
-
-namespace osu.Game.Tests.Visual.Online
-{
- [Cached(typeof(IPreviewTrackOwner))]
- public class TestSceneDirectPanel : OsuTestScene, IPreviewTrackOwner
- {
- [BackgroundDependencyLoader]
- private void load(RulesetStore rulesets)
- {
- var normal = getBeatmapSet();
- normal.HasVideo = true;
- normal.HasStoryboard = true;
-
- var undownloadable = getUndownloadableBeatmapSet();
- var manyDifficulties = getManyDifficultiesBeatmapSet();
-
- var explicitMap = getBeatmapSet();
- explicitMap.HasExplicitContent = true;
-
- var featuredMap = getBeatmapSet();
- featuredMap.TrackId = 1;
-
- var explicitFeaturedMap = getBeatmapSet();
- explicitFeaturedMap.HasExplicitContent = true;
- explicitFeaturedMap.TrackId = 2;
-
- Child = new BasicScrollContainer
- {
- RelativeSizeAxes = Axes.Both,
- Child = new FillFlowContainer
- {
- RelativeSizeAxes = Axes.X,
- AutoSizeAxes = Axes.Y,
- Direction = FillDirection.Full,
- Padding = new MarginPadding(20),
- Spacing = new Vector2(5, 20),
- Children = new Drawable[]
- {
- new GridBeatmapPanel(normal),
- new GridBeatmapPanel(undownloadable),
- new GridBeatmapPanel(manyDifficulties),
- new GridBeatmapPanel(explicitMap),
- new GridBeatmapPanel(featuredMap),
- new GridBeatmapPanel(explicitFeaturedMap),
- new ListBeatmapPanel(normal),
- new ListBeatmapPanel(undownloadable),
- new ListBeatmapPanel(manyDifficulties),
- new ListBeatmapPanel(explicitMap),
- new ListBeatmapPanel(featuredMap),
- new ListBeatmapPanel(explicitFeaturedMap)
- },
- },
- };
-
- APIBeatmapSet getBeatmapSet() => CreateAPIBeatmapSet(Ruleset.Value);
-
- APIBeatmapSet getUndownloadableBeatmapSet() => new APIBeatmapSet
- {
- OnlineID = 123,
- Title = "undownloadable beatmap",
- Artist = "test",
- Source = "more tests",
- Author = new APIUser
- {
- Username = "BanchoBot",
- Id = 3,
- },
- Availability = new BeatmapSetOnlineAvailability
- {
- DownloadDisabled = true,
- },
- Preview = @"https://b.ppy.sh/preview/12345.mp3",
- PlayCount = 123,
- FavouriteCount = 456,
- BPM = 111,
- HasVideo = true,
- HasStoryboard = true,
- Covers = new BeatmapSetOnlineCovers(),
- Beatmaps = new[]
- {
- new APIBeatmap
- {
- RulesetID = Ruleset.Value.OnlineID,
- DifficultyName = "Test",
- StarRating = 6.42,
- }
- }
- };
-
- APIBeatmapSet getManyDifficultiesBeatmapSet()
- {
- var beatmaps = new List();
-
- for (int i = 0; i < 100; i++)
- {
- beatmaps.Add(new APIBeatmap
- {
- RulesetID = i % 4,
- StarRating = 2 + i % 4 * 2,
- OverallDifficulty = 3.5f,
- });
- }
-
- return new APIBeatmapSet
- {
- OnlineID = 1,
- Title = "undownloadable beatmap",
- Artist = "test",
- Source = "more tests",
- Author = new APIUser
- {
- Username = "BanchoBot",
- Id = 3,
- },
- HasVideo = true,
- HasStoryboard = true,
- Covers = new BeatmapSetOnlineCovers(),
- Beatmaps = beatmaps.ToArray(),
- };
- }
- }
- }
-}
diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs
index e7c54efa8c..9ad5242df4 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs
@@ -82,7 +82,7 @@ namespace osu.Game.Tests.Visual.SongSelect
beatmaps.Add(testBeatmap);
- AddStep("set ruleset", () => Ruleset.Value = rulesetInfo);
+ setRuleset(rulesetInfo);
selectBeatmap(testBeatmap);
@@ -167,6 +167,22 @@ namespace osu.Game.Tests.Visual.SongSelect
label => label.Statistic.Name == "BPM" && label.Statistic.Content == target.ToString(CultureInfo.InvariantCulture)));
}
+ private void setRuleset(RulesetInfo rulesetInfo)
+ {
+ Container containerBefore = null;
+
+ AddStep("set ruleset", () =>
+ {
+ // wedge content is only refreshed if the ruleset changes, so only wait for load in that case.
+ if (!rulesetInfo.Equals(Ruleset.Value))
+ containerBefore = infoWedge.DisplayedContent;
+
+ Ruleset.Value = rulesetInfo;
+ });
+
+ AddUntilStep("wait for async load", () => infoWedge.DisplayedContent != containerBefore);
+ }
+
private void selectBeatmap([CanBeNull] IBeatmap b)
{
Container containerBefore = null;
diff --git a/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs b/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs
index 94472a8bc7..d149ec145b 100644
--- a/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs
+++ b/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs
@@ -87,9 +87,9 @@ namespace osu.Game.Tournament.Tests.NonVisual
// Recreate the old setup that uses "tournament" as the base path.
string oldPath = Path.Combine(osuRoot, "tournament");
- string videosPath = Path.Combine(oldPath, "videos");
- string modsPath = Path.Combine(oldPath, "mods");
- string flagsPath = Path.Combine(oldPath, "flags");
+ string videosPath = Path.Combine(oldPath, "Videos");
+ string modsPath = Path.Combine(oldPath, "Mods");
+ string flagsPath = Path.Combine(oldPath, "Flags");
Directory.CreateDirectory(videosPath);
Directory.CreateDirectory(modsPath);
@@ -123,9 +123,9 @@ namespace osu.Game.Tournament.Tests.NonVisual
string migratedPath = Path.Combine(host.Storage.GetFullPath("."), "tournaments", "default");
- videosPath = Path.Combine(migratedPath, "videos");
- modsPath = Path.Combine(migratedPath, "mods");
- flagsPath = Path.Combine(migratedPath, "flags");
+ videosPath = Path.Combine(migratedPath, "Videos");
+ modsPath = Path.Combine(migratedPath, "Mods");
+ flagsPath = Path.Combine(migratedPath, "Flags");
videoFile = Path.Combine(videosPath, "video.mp4");
modFile = Path.Combine(modsPath, "mod.png");
diff --git a/osu.Game.Tournament/Components/TournamentModIcon.cs b/osu.Game.Tournament/Components/TournamentModIcon.cs
index 7c4e9c69a2..0fde263bc8 100644
--- a/osu.Game.Tournament/Components/TournamentModIcon.cs
+++ b/osu.Game.Tournament/Components/TournamentModIcon.cs
@@ -31,7 +31,7 @@ namespace osu.Game.Tournament.Components
[BackgroundDependencyLoader]
private void load(TextureStore textures, LadderInfo ladderInfo)
{
- var customTexture = textures.Get($"mods/{modAcronym}");
+ var customTexture = textures.Get($"Mods/{modAcronym}");
if (customTexture != null)
{
diff --git a/osu.Game.Tournament/IO/TournamentStorage.cs b/osu.Game.Tournament/IO/TournamentStorage.cs
index 044b60bbd5..02cf567837 100644
--- a/osu.Game.Tournament/IO/TournamentStorage.cs
+++ b/osu.Game.Tournament/IO/TournamentStorage.cs
@@ -51,6 +51,23 @@ namespace osu.Game.Tournament.IO
Logger.Log("Changing tournament storage: " + GetFullPath(string.Empty));
}
+ protected override void ChangeTargetStorage(Storage newStorage)
+ {
+ // due to an unfortunate oversight, on OSes that are sensitive to pathname casing
+ // the custom flags directory needed to be named `Flags` (uppercase),
+ // while custom mods and videos directories needed to be named `mods` and `videos` respectively (lowercase).
+ // to unify handling to uppercase, move any non-compliant directories automatically for the user to migrate.
+ // can be removed 20220528
+ if (newStorage.ExistsDirectory("flags"))
+ AttemptOperation(() => Directory.Move(newStorage.GetFullPath("flags"), newStorage.GetFullPath("Flags")));
+ if (newStorage.ExistsDirectory("mods"))
+ AttemptOperation(() => Directory.Move(newStorage.GetFullPath("mods"), newStorage.GetFullPath("Mods")));
+ if (newStorage.ExistsDirectory("videos"))
+ AttemptOperation(() => Directory.Move(newStorage.GetFullPath("videos"), newStorage.GetFullPath("Videos")));
+
+ base.ChangeTargetStorage(newStorage);
+ }
+
public IEnumerable ListTournaments() => AllTournaments.GetDirectories(string.Empty);
public override void Migrate(Storage newStorage)
diff --git a/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs b/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs
index 4b26840b79..964d03220d 100644
--- a/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs
+++ b/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs
@@ -9,7 +9,7 @@ namespace osu.Game.Tournament.IO
public class TournamentVideoResourceStore : NamespacedResourceStore
{
public TournamentVideoResourceStore(Storage storage)
- : base(new StorageBackedResourceStore(storage), "videos")
+ : base(new StorageBackedResourceStore(storage), "Videos")
{
AddExtension("m4v");
AddExtension("avi");
diff --git a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs
index d34a8583b9..cd74a75b10 100644
--- a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs
+++ b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs
@@ -197,7 +197,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
{
row.Add(new Sprite
{
- Texture = textures.Get($"mods/{mods.ToLower()}"),
+ Texture = textures.Get($"Mods/{mods.ToLower()}"),
Scale = new Vector2(0.5f)
});
}
diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs
index fd9d5a97c6..e631d35180 100644
--- a/osu.Game/Audio/PreviewTrackManager.cs
+++ b/osu.Game/Audio/PreviewTrackManager.cs
@@ -105,7 +105,9 @@ namespace osu.Game.Audio
protected override void LoadComplete()
{
base.LoadComplete();
- Logger.Log($"A {nameof(PreviewTrack)} was created without a containing {nameof(IPreviewTrackOwner)}. An owner should be added for correct behaviour.");
+
+ if (Owner == null)
+ Logger.Log($"A {nameof(PreviewTrack)} was created without a containing {nameof(IPreviewTrackOwner)}. An owner should be added for correct behaviour.");
}
protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo.OnlineID}.mp3");
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index d920b194b5..8502b91096 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -288,9 +288,9 @@ namespace osu.Game.Beatmaps
#region Implementation of IModelFileManager
- public void ReplaceFile(BeatmapSetInfo model, BeatmapSetFileInfo file, Stream contents, string filename = null)
+ public void ReplaceFile(BeatmapSetInfo model, BeatmapSetFileInfo file, Stream contents)
{
- beatmapModelManager.ReplaceFile(model, file, contents, filename);
+ beatmapModelManager.ReplaceFile(model, file, contents);
}
public void DeleteFile(BeatmapSetInfo model, BeatmapSetFileInfo file)
diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs b/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs
similarity index 95%
rename from osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs
rename to osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs
index 0a66c3ccb7..e2485e7a77 100644
--- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs
+++ b/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs
@@ -6,7 +6,6 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
-using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Extensions;
using osu.Game.Graphics.Containers;
@@ -14,9 +13,9 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Online.API.Requests.Responses;
-namespace osu.Game.Overlays.BeatmapListing.Panels
+namespace osu.Game.Beatmaps.Drawables
{
- public class BeatmapPanelDownloadButton : CompositeDrawable
+ public class BeatmapDownloadButton : CompositeDrawable
{
protected bool DownloadEnabled => button.Enabled.Value;
@@ -35,7 +34,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
private readonly IBeatmapSetInfo beatmapSet;
- public BeatmapPanelDownloadButton(IBeatmapSetInfo beatmapSet)
+ public BeatmapDownloadButton(IBeatmapSetInfo beatmapSet)
{
this.beatmapSet = beatmapSet;
diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs
index 76b1166626..37c1bacda4 100644
--- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs
+++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs
@@ -23,7 +23,6 @@ using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapSet;
using osuTK;
-using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Resources.Localisation.Web;
using DownloadButton = osu.Game.Beatmaps.Drawables.Cards.Buttons.DownloadButton;
diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs
new file mode 100644
index 0000000000..7753d8480a
--- /dev/null
+++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs
@@ -0,0 +1,103 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Linq;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Sprites;
+using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
+using osu.Game.Online.Chat;
+using osu.Game.Rulesets;
+using osuTK;
+
+namespace osu.Game.Beatmaps.Drawables.Cards
+{
+ public class BeatmapCardDifficultyList : CompositeDrawable
+ {
+ public BeatmapCardDifficultyList(IBeatmapSetInfo beatmapSetInfo)
+ {
+ RelativeSizeAxes = Axes.X;
+ AutoSizeAxes = Axes.Y;
+
+ FillFlowContainer flow;
+
+ InternalChild = flow = new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Direction = FillDirection.Vertical,
+ Spacing = new Vector2(0, 3)
+ };
+
+ bool firstGroup = true;
+
+ foreach (var group in beatmapSetInfo.Beatmaps.GroupBy(beatmap => beatmap.Ruleset.OnlineID).OrderBy(group => group.Key))
+ {
+ if (!firstGroup)
+ {
+ flow.Add(Empty().With(s =>
+ {
+ s.RelativeSizeAxes = Axes.X;
+ s.Height = 4;
+ }));
+ }
+
+ foreach (var difficulty in group.OrderBy(b => b.StarRating))
+ flow.Add(new BeatmapCardDifficultyRow(difficulty));
+
+ firstGroup = false;
+ }
+ }
+
+ private class BeatmapCardDifficultyRow : CompositeDrawable
+ {
+ private readonly IBeatmapInfo beatmapInfo;
+
+ public BeatmapCardDifficultyRow(IBeatmapInfo beatmapInfo)
+ {
+ this.beatmapInfo = beatmapInfo;
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(RulesetStore rulesets)
+ {
+ RelativeSizeAxes = Axes.X;
+ AutoSizeAxes = Axes.Y;
+
+ InternalChild = new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Direction = FillDirection.Horizontal,
+ Spacing = new Vector2(4, 0),
+ Children = new[]
+ {
+ (rulesets.GetRuleset(beatmapInfo.Ruleset.OnlineID)?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle }).With(icon =>
+ {
+ icon.Anchor = icon.Origin = Anchor.CentreLeft;
+ icon.Size = new Vector2(16);
+ }),
+ new StarRatingDisplay(new StarDifficulty(beatmapInfo.StarRating, 0), StarRatingDisplaySize.Small)
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft
+ },
+ new LinkFlowContainer(s =>
+ {
+ s.Font = OsuFont.Default.With(size: 14, weight: FontWeight.SemiBold);
+ }).With(d =>
+ {
+ d.AutoSizeAxes = Axes.Both;
+ d.Anchor = Anchor.CentreLeft;
+ d.Origin = Anchor.CentreLeft;
+ d.Padding = new MarginPadding { Bottom = 2 };
+ d.AddLink(beatmapInfo.DifficultyName, LinkAction.OpenBeatmap, beatmapInfo.OnlineID.ToString());
+ })
+ }
+ };
+ }
+ }
+ }
+}
diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs
index 4574d37da0..f7bab26666 100644
--- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs
+++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs
@@ -97,6 +97,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
if (previewTrack == null)
{
toggleLoading(true);
+
LoadComponentAsync(previewTrack = previewTrackManager.Get(beatmapSetInfo), onPreviewLoaded);
}
else
@@ -112,18 +113,23 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
private void onPreviewLoaded(PreviewTrack loadedPreview)
{
- // another async load might have completed before this one.
- // if so, do not make any changes.
- if (loadedPreview != previewTrack)
- return;
+ // Make sure that we schedule to after the next audio frame to fix crashes in single-threaded execution.
+ // See: https://github.com/ppy/osu-framework/issues/4692
+ Schedule(() =>
+ {
+ // another async load might have completed before this one.
+ // if so, do not make any changes.
+ if (loadedPreview != previewTrack)
+ return;
- AddInternal(loadedPreview);
- toggleLoading(false);
+ AddInternal(loadedPreview);
+ toggleLoading(false);
- loadedPreview.Stopped += () => Schedule(() => Playing.Value = false);
+ loadedPreview.Stopped += () => Schedule(() => Playing.Value = false);
- if (Playing.Value)
- tryStartPreview();
+ if (Playing.Value)
+ tryStartPreview();
+ });
}
private void tryStartPreview()
diff --git a/osu.Game/Overlays/BeatmapListing/Panels/IconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs
similarity index 96%
rename from osu.Game/Overlays/BeatmapListing/Panels/IconPill.cs
rename to osu.Game/Beatmaps/Drawables/Cards/IconPill.cs
index 1cb6c84f13..c55e9c0a28 100644
--- a/osu.Game/Overlays/BeatmapListing/Panels/IconPill.cs
+++ b/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs
@@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites;
using osuTK;
using osuTK.Graphics;
-namespace osu.Game.Overlays.BeatmapListing.Panels
+namespace osu.Game.Beatmaps.Drawables.Cards
{
public class IconPill : CircularContainer
{
diff --git a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs
index f4501f0633..5b211084ab 100644
--- a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs
+++ b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs
@@ -62,7 +62,7 @@ namespace osu.Game.Beatmaps.Drawables
// matching web: https://github.com/ppy/osu-web/blob/d06d8c5e735eb1f48799b1654b528e9a7afb0a35/resources/assets/lib/beatmapset-panel.tsx#L127
bool collapsed = beatmapSet.Beatmaps.Count() > 12;
- foreach (var rulesetGrouping in beatmapSet.Beatmaps.GroupBy(beatmap => beatmap.Ruleset.OnlineID))
+ foreach (var rulesetGrouping in beatmapSet.Beatmaps.GroupBy(beatmap => beatmap.Ruleset.OnlineID).OrderBy(group => group.Key))
{
flow.Add(new RulesetDifficultyGroup(rulesetGrouping.Key, rulesetGrouping, collapsed));
}
diff --git a/osu.Game/Overlays/BeatmapListing/Panels/DownloadProgressBar.cs b/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs
similarity index 97%
rename from osu.Game/Overlays/BeatmapListing/Panels/DownloadProgressBar.cs
rename to osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs
index 93eaf775e0..54dcdc55e3 100644
--- a/osu.Game/Overlays/BeatmapListing/Panels/DownloadProgressBar.cs
+++ b/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs
@@ -5,13 +5,12 @@ using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
-using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osuTK.Graphics;
-namespace osu.Game.Overlays.BeatmapListing.Panels
+namespace osu.Game.Beatmaps.Drawables
{
public class DownloadProgressBar : CompositeDrawable
{
diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs
index e73f4a7f6e..8cabb55cc3 100644
--- a/osu.Game/Database/ArchiveModelManager.cs
+++ b/osu.Game/Database/ArchiveModelManager.cs
@@ -453,13 +453,12 @@ namespace osu.Game.Database
/// The item to operate on.
/// The existing file to be replaced.
/// The new file contents.
- /// An optional filename for the new file. Will use the previous filename if not specified.
- public void ReplaceFile(TModel model, TFileModel file, Stream contents, string filename = null)
+ public void ReplaceFile(TModel model, TFileModel file, Stream contents)
{
using (ContextFactory.GetForWrite())
{
DeleteFile(model, file);
- AddFile(model, contents, filename ?? file.Filename);
+ AddFile(model, contents, file.Filename);
}
}
diff --git a/osu.Game/Database/IModelFileManager.cs b/osu.Game/Database/IModelFileManager.cs
index c74b945eb7..4bc1e2d29b 100644
--- a/osu.Game/Database/IModelFileManager.cs
+++ b/osu.Game/Database/IModelFileManager.cs
@@ -15,8 +15,7 @@ namespace osu.Game.Database
/// The item to operate on.
/// The existing file to be replaced.
/// The new file contents.
- /// An optional filename for the new file. Will use the previous filename if not specified.
- void ReplaceFile(TModel model, TFileModel file, Stream contents, string filename = null);
+ void ReplaceFile(TModel model, TFileModel file, Stream contents);
///
/// Delete an existing file.
diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs
index 3c5dfeafe8..2bc77934a8 100644
--- a/osu.Game/Database/RealmContextFactory.cs
+++ b/osu.Game/Database/RealmContextFactory.cs
@@ -307,6 +307,9 @@ namespace osu.Game.Database
case 10:
string rulesetSettingClassName = getMappedOrOriginalName(typeof(RealmRulesetSetting));
+ if (!migration.OldRealm.Schema.TryFindObjectSchema(rulesetSettingClassName, out _))
+ return;
+
var oldSettings = migration.OldRealm.DynamicApi.All(rulesetSettingClassName);
var newSettings = migration.NewRealm.All().ToList();
@@ -329,6 +332,9 @@ namespace osu.Game.Database
case 11:
string keyBindingClassName = getMappedOrOriginalName(typeof(RealmKeyBinding));
+ if (!migration.OldRealm.Schema.TryFindObjectSchema(keyBindingClassName, out _))
+ return;
+
var oldKeyBindings = migration.OldRealm.DynamicApi.All(keyBindingClassName);
var newKeyBindings = migration.NewRealm.All().ToList();
diff --git a/osu.Game/Database/RealmLive.cs b/osu.Game/Database/RealmLive.cs
index 73e6715aaa..5ee40f5b4d 100644
--- a/osu.Game/Database/RealmLive.cs
+++ b/osu.Game/Database/RealmLive.cs
@@ -17,7 +17,7 @@ namespace osu.Game.Database
{
public Guid ID { get; }
- public bool IsManaged { get; }
+ public bool IsManaged => data.IsManaged;
private readonly SynchronizationContext? fetchedContext;
private readonly int fetchedThreadId;
@@ -37,8 +37,6 @@ namespace osu.Game.Database
if (data.IsManaged)
{
- IsManaged = true;
-
fetchedContext = SynchronizationContext.Current;
fetchedThreadId = Thread.CurrentThread.ManagedThreadId;
}
diff --git a/osu.Game/Database/RealmObjectExtensions.cs b/osu.Game/Database/RealmObjectExtensions.cs
index 18a926fa8c..ac4ca436ad 100644
--- a/osu.Game/Database/RealmObjectExtensions.cs
+++ b/osu.Game/Database/RealmObjectExtensions.cs
@@ -49,13 +49,13 @@ namespace osu.Game.Database
return mapper.Map(item);
}
- public static List> ToLive(this IEnumerable realmList)
+ public static List> ToLive(this IEnumerable realmList)
where T : RealmObject, IHasGuidPrimaryKey
{
- return realmList.Select(l => new RealmLive(l)).ToList();
+ return realmList.Select(l => new RealmLive(l)).Cast>().ToList();
}
- public static RealmLive ToLive(this T realmObject)
+ public static ILive ToLive(this T realmObject)
where T : RealmObject, IHasGuidPrimaryKey
{
return new RealmLive(realmObject);
diff --git a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs
index 68ffc6bf4e..b7e25ae4e7 100644
--- a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs
+++ b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs
@@ -66,7 +66,7 @@ namespace osu.Game.Graphics.UserInterface
Origin = Anchor.TopRight;
BackgroundColour = Color4.Black.Opacity(0.7f);
- MaxHeight = 400;
+ MaxHeight = 200;
}
protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableOsuTabDropdownMenuItem(item);
diff --git a/osu.Game/Models/RealmNamedFileUsage.cs b/osu.Game/Models/RealmNamedFileUsage.cs
index ba12d51d0b..17e32510a8 100644
--- a/osu.Game/Models/RealmNamedFileUsage.cs
+++ b/osu.Game/Models/RealmNamedFileUsage.cs
@@ -16,6 +16,7 @@ namespace osu.Game.Models
{
public RealmFile File { get; set; } = null!;
+ // [Indexed] cannot be used on `EmbeddedObject`s as it only applies to top-level queries. May need to reconsider this if performance becomes a concern.
public string Filename { get; set; } = null!;
public RealmNamedFileUsage(RealmFile file, string filename)
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 88c9ab370c..6eb67b34e8 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -377,6 +377,13 @@ namespace osu.Game
FrameStatistics.ValueChanged += e => fpsDisplayVisible.Value = e.NewValue != FrameStatisticsMode.None;
}
+ protected override void Update()
+ {
+ base.Update();
+
+ realmFactory.Refresh();
+ }
+
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) =>
dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
@@ -442,10 +449,6 @@ namespace osu.Game
protected override Storage CreateStorage(GameHost host, Storage defaultStorage) => new OsuStorage(host, defaultStorage);
- private void migrateDataToRealm()
- {
- }
-
private void onRulesetChanged(ValueChangedEvent r)
{
if (r.NewValue?.Available != true)
diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs
deleted file mode 100644
index 34086c214f..0000000000
--- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using osu.Framework.Allocation;
-using osu.Framework.Bindables;
-using osu.Framework.Extensions.Color4Extensions;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Cursor;
-using osu.Framework.Graphics.Effects;
-using osu.Framework.Graphics.Shapes;
-using osu.Framework.Graphics.Sprites;
-using osu.Framework.Graphics.UserInterface;
-using osu.Framework.Input.Events;
-using osu.Game.Audio;
-using osu.Game.Beatmaps;
-using osu.Game.Beatmaps.Drawables;
-using osu.Game.Graphics;
-using osu.Game.Graphics.Containers;
-using osu.Game.Graphics.Sprites;
-using osu.Game.Graphics.UserInterface;
-using osu.Game.Online.API.Requests.Responses;
-using osuTK;
-using osuTK.Graphics;
-
-namespace osu.Game.Overlays.BeatmapListing.Panels
-{
- public abstract class BeatmapPanel : OsuClickableContainer, IHasContextMenu
- {
- public readonly APIBeatmapSet SetInfo;
-
- private const double hover_transition_time = 400;
- private const int maximum_difficulty_icons = 10;
-
- private Container content;
-
- public PreviewTrack Preview => PlayButton.Preview;
- public IBindable PreviewPlaying => PlayButton?.Playing;
-
- protected abstract PlayButton PlayButton { get; }
- protected abstract Box PreviewBar { get; }
-
- protected virtual bool FadePlayButton => true;
-
- protected override Container Content => content;
-
- protected Action ViewBeatmap;
-
- protected BeatmapPanel(APIBeatmapSet setInfo)
- : base(HoverSampleSet.Submit)
- {
- Debug.Assert(setInfo.OnlineID > 0);
-
- SetInfo = setInfo;
- }
-
- private readonly EdgeEffectParameters edgeEffectNormal = new EdgeEffectParameters
- {
- Type = EdgeEffectType.Shadow,
- Offset = new Vector2(0f, 1f),
- Radius = 2f,
- Colour = Color4.Black.Opacity(0.25f),
- };
-
- private readonly EdgeEffectParameters edgeEffectHovered = new EdgeEffectParameters
- {
- Type = EdgeEffectType.Shadow,
- Offset = new Vector2(0f, 5f),
- Radius = 10f,
- Colour = Color4.Black.Opacity(0.3f),
- };
-
- [BackgroundDependencyLoader(permitNulls: true)]
- private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay)
- {
- AddInternal(content = new Container
- {
- RelativeSizeAxes = Axes.Both,
- Masking = true,
- EdgeEffect = edgeEffectNormal,
- Children = new[]
- {
- CreateBackground(),
- new DownloadProgressBar(SetInfo)
- {
- Anchor = Anchor.BottomLeft,
- Origin = Anchor.BottomLeft,
- Depth = -1,
- },
- }
- });
-
- Action = ViewBeatmap = () =>
- {
- Debug.Assert(SetInfo.OnlineID > 0);
- beatmapSetOverlay?.FetchAndShowBeatmapSet(SetInfo.OnlineID);
- };
- }
-
- protected override void Update()
- {
- base.Update();
-
- if (PreviewPlaying.Value && Preview != null && Preview.TrackLoaded)
- {
- PreviewBar.Width = (float)(Preview.CurrentTime / Preview.Length);
- }
- }
-
- protected override bool OnHover(HoverEvent e)
- {
- content.TweenEdgeEffectTo(edgeEffectHovered, hover_transition_time, Easing.OutQuint);
- content.MoveToY(-4, hover_transition_time, Easing.OutQuint);
- if (FadePlayButton)
- PlayButton.FadeIn(120, Easing.InOutQuint);
-
- return base.OnHover(e);
- }
-
- protected override void OnHoverLost(HoverLostEvent e)
- {
- content.TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint);
- content.MoveToY(0, hover_transition_time, Easing.OutQuint);
- if (FadePlayButton && !PreviewPlaying.Value)
- PlayButton.FadeOut(120, Easing.InOutQuint);
-
- base.OnHoverLost(e);
- }
-
- protected override void LoadComplete()
- {
- base.LoadComplete();
- this.FadeInFromZero(200, Easing.Out);
-
- PreviewPlaying.ValueChanged += playing =>
- {
- PlayButton.FadeTo(playing.NewValue || IsHovered || !FadePlayButton ? 1 : 0, 120, Easing.InOutQuint);
- PreviewBar.FadeTo(playing.NewValue ? 1 : 0, 120, Easing.InOutQuint);
- };
- }
-
- protected List GetDifficultyIcons(OsuColour colours)
- {
- var icons = new List();
-
- if (SetInfo.Beatmaps.Length > maximum_difficulty_icons)
- {
- foreach (var ruleset in SetInfo.Beatmaps.Select(b => b.Ruleset).Distinct())
- icons.Add(new GroupedDifficultyIcon(SetInfo.Beatmaps.Where(b => b.RulesetID == ruleset.OnlineID).ToList(), ruleset, this is ListBeatmapPanel ? Color4.White : colours.Gray5));
- }
- else
- {
- foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.RulesetID).ThenBy(beatmap => beatmap.StarRating))
- icons.Add(new DifficultyIcon(b));
- }
-
- return icons;
- }
-
- protected Drawable CreateBackground() => new UpdateableOnlineBeatmapSetCover
- {
- RelativeSizeAxes = Axes.Both,
- OnlineInfo = SetInfo,
- };
-
- public class Statistic : FillFlowContainer
- {
- private readonly SpriteText text;
-
- private int value;
-
- public int Value
- {
- get => value;
- set
- {
- this.value = value;
- text.Text = Value.ToString(@"N0");
- }
- }
-
- public Statistic(IconUsage icon, int value = 0)
- {
- Anchor = Anchor.TopRight;
- Origin = Anchor.TopRight;
- AutoSizeAxes = Axes.Both;
- Direction = FillDirection.Horizontal;
- Spacing = new Vector2(5f, 0f);
-
- Children = new Drawable[]
- {
- text = new OsuSpriteText { Font = OsuFont.GetFont(weight: FontWeight.SemiBold, italics: true) },
- new SpriteIcon
- {
- Anchor = Anchor.CentreLeft,
- Origin = Anchor.CentreLeft,
- Icon = icon,
- Shadow = true,
- Size = new Vector2(14),
- },
- };
-
- Value = value;
- }
- }
-
- public MenuItem[] ContextMenuItems => new MenuItem[]
- {
- new OsuMenuItem("View Beatmap", MenuItemType.Highlighted, ViewBeatmap),
- };
- }
-}
diff --git a/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs
deleted file mode 100644
index 770e5af7bd..0000000000
--- a/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using osu.Framework.Allocation;
-using osu.Framework.Extensions.Color4Extensions;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Shapes;
-using osu.Framework.Graphics.Sprites;
-using osu.Framework.Input.Events;
-using osu.Framework.Localisation;
-using osu.Game.Beatmaps.Drawables;
-using osu.Game.Graphics;
-using osu.Game.Graphics.Containers;
-using osu.Game.Graphics.Sprites;
-using osu.Game.Online.API.Requests.Responses;
-using osu.Game.Overlays.BeatmapSet;
-using osuTK;
-using osuTK.Graphics;
-
-namespace osu.Game.Overlays.BeatmapListing.Panels
-{
- public class GridBeatmapPanel : BeatmapPanel
- {
- private const float horizontal_padding = 10;
- private const float vertical_padding = 5;
-
- private FillFlowContainer bottomPanel, statusContainer, titleContainer, artistContainer;
- private PlayButton playButton;
- private Box progressBar;
-
- protected override PlayButton PlayButton => playButton;
- protected override Box PreviewBar => progressBar;
-
- public GridBeatmapPanel(APIBeatmapSet beatmap)
- : base(beatmap)
- {
- Width = 380;
- Height = 140 + vertical_padding; // full height of all the elements plus vertical padding (autosize uses the image)
- }
-
- protected override void LoadComplete()
- {
- base.LoadComplete();
- bottomPanel.LayoutDuration = 200;
- bottomPanel.LayoutEasing = Easing.Out;
- bottomPanel.Origin = Anchor.BottomLeft;
- }
-
- [BackgroundDependencyLoader]
- private void load(OsuColour colours)
- {
- Content.CornerRadius = 4;
-
- AddRange(new Drawable[]
- {
- new Box
- {
- RelativeSizeAxes = Axes.Both,
- Colour = Color4.Black.Opacity(0.5f),
- },
- bottomPanel = new FillFlowContainer
- {
- Anchor = Anchor.BottomLeft,
- Origin = Anchor.TopLeft,
- Direction = FillDirection.Vertical,
- RelativeSizeAxes = Axes.X,
- AutoSizeAxes = Axes.Y,
- Spacing = new Vector2(0f, vertical_padding),
- Children = new Drawable[]
- {
- new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Padding = new MarginPadding { Left = horizontal_padding, Right = horizontal_padding },
- Direction = FillDirection.Vertical,
- Children = new Drawable[]
- {
- titleContainer = new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- Children = new Drawable[]
- {
- new OsuSpriteText
- {
- Text = new RomanisableString(SetInfo.TitleUnicode, SetInfo.Title),
- Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true)
- },
- }
- },
- artistContainer = new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- Children = new Drawable[]
- {
- new OsuSpriteText
- {
- Text = new RomanisableString(SetInfo.ArtistUnicode, SetInfo.Artist),
- Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true)
- }
- }
- }
- },
- },
- new Container
- {
- RelativeSizeAxes = Axes.X,
- AutoSizeAxes = Axes.Y,
- Children = new Drawable[]
- {
- new Box
- {
- RelativeSizeAxes = Axes.Both,
- },
- progressBar = new Box
- {
- Origin = Anchor.BottomLeft,
- RelativeSizeAxes = Axes.X,
- BypassAutoSizeAxes = Axes.Both,
- Size = new Vector2(0, 3),
- Alpha = 0,
- Colour = colours.Yellow,
- },
- new FillFlowContainer
- {
- RelativeSizeAxes = Axes.X,
- AutoSizeAxes = Axes.Y,
- Direction = FillDirection.Vertical,
- Padding = new MarginPadding
- {
- Top = vertical_padding,
- Bottom = vertical_padding,
- Left = horizontal_padding,
- Right = horizontal_padding,
- },
- Children = new Drawable[]
- {
- new LinkFlowContainer(s =>
- {
- s.Shadow = false;
- s.Font = OsuFont.GetFont(size: 14);
- }).With(d =>
- {
- d.AutoSizeAxes = Axes.Both;
- d.AddText("mapped by ", t => t.Colour = colours.Gray5);
- d.AddUserLink(SetInfo.Author);
- }),
- new Container
- {
- AutoSizeAxes = Axes.X,
- Height = 14,
- Children = new[]
- {
- new OsuSpriteText
- {
- Text = SetInfo.Source,
- Font = OsuFont.GetFont(size: 14),
- Shadow = false,
- Colour = colours.Gray5,
- Alpha = string.IsNullOrEmpty(SetInfo.Source) ? 0f : 1f,
- },
- },
- },
- new FillFlowContainer
- {
- AutoSizeAxes = Axes.X,
- Height = 20,
- Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding },
- Spacing = new Vector2(3),
- Children = GetDifficultyIcons(colours),
- },
- },
- },
- new BeatmapPanelDownloadButton(SetInfo)
- {
- Size = new Vector2(50, 30),
- Margin = new MarginPadding(horizontal_padding),
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- },
- },
- },
- },
- },
- new FillFlowContainer
- {
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Vertical,
- Margin = new MarginPadding { Top = vertical_padding, Right = vertical_padding },
- Children = new[]
- {
- new Statistic(FontAwesome.Solid.PlayCircle, SetInfo.PlayCount),
- new Statistic(FontAwesome.Solid.Heart, SetInfo.FavouriteCount),
- },
- },
- statusContainer = new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Margin = new MarginPadding { Top = 5, Left = 5 },
- Spacing = new Vector2(5),
- },
- playButton = new PlayButton(SetInfo)
- {
- Margin = new MarginPadding { Top = 5, Left = 10 },
- Size = new Vector2(30),
- Alpha = 0,
- },
- });
-
- if (SetInfo.HasExplicitContent)
- {
- titleContainer.Add(new ExplicitContentBeatmapPill
- {
- Anchor = Anchor.CentreLeft,
- Origin = Anchor.CentreLeft,
- Margin = new MarginPadding { Left = 10f, Top = 2f },
- });
- }
-
- if (SetInfo.TrackId != null)
- {
- artistContainer.Add(new FeaturedArtistBeatmapPill
- {
- Anchor = Anchor.CentreLeft,
- Origin = Anchor.CentreLeft,
- Margin = new MarginPadding { Left = 10f, Top = 2f },
- });
- }
-
- if (SetInfo.HasVideo)
- {
- statusContainer.Add(new IconPill(FontAwesome.Solid.Film));
- }
-
- if (SetInfo.HasStoryboard)
- {
- statusContainer.Add(new IconPill(FontAwesome.Solid.Image));
- }
-
- statusContainer.Add(new BeatmapSetOnlineStatusPill
- {
- AutoSizeAxes = Axes.Both,
- TextSize = 12,
- TextPadding = new MarginPadding { Horizontal = 10, Vertical = 5 },
- Status = SetInfo.Status,
- });
-
- PreviewPlaying.ValueChanged += _ => updateStatusContainer();
- }
-
- protected override bool OnHover(HoverEvent e)
- {
- updateStatusContainer();
- return base.OnHover(e);
- }
-
- protected override void OnHoverLost(HoverLostEvent e)
- {
- base.OnHoverLost(e);
- updateStatusContainer();
- }
-
- private void updateStatusContainer() => statusContainer.FadeTo(IsHovered || PreviewPlaying.Value ? 0 : 1, 120, Easing.InOutQuint);
- }
-}
diff --git a/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs
deleted file mode 100644
index dcd676724a..0000000000
--- a/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using osu.Framework.Allocation;
-using osu.Framework.Extensions.Color4Extensions;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Colour;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Shapes;
-using osu.Framework.Graphics.Sprites;
-using osu.Framework.Localisation;
-using osu.Game.Beatmaps.Drawables;
-using osu.Game.Graphics;
-using osu.Game.Graphics.Containers;
-using osu.Game.Graphics.Sprites;
-using osu.Game.Online.API.Requests.Responses;
-using osu.Game.Overlays.BeatmapSet;
-using osuTK;
-using osuTK.Graphics;
-
-namespace osu.Game.Overlays.BeatmapListing.Panels
-{
- public class ListBeatmapPanel : BeatmapPanel
- {
- private const float transition_duration = 120;
- private const float horizontal_padding = 10;
- private const float vertical_padding = 5;
- private const float height = 70;
-
- private FillFlowContainer statusContainer, titleContainer, artistContainer;
- protected BeatmapPanelDownloadButton DownloadButton;
- private PlayButton playButton;
- private Box progressBar;
-
- protected override bool FadePlayButton => false;
-
- protected override PlayButton PlayButton => playButton;
- protected override Box PreviewBar => progressBar;
-
- public ListBeatmapPanel(APIBeatmapSet beatmap)
- : base(beatmap)
- {
- RelativeSizeAxes = Axes.X;
- Height = height;
- }
-
- [BackgroundDependencyLoader]
- private void load(OsuColour colours)
- {
- Content.CornerRadius = 5;
-
- AddRange(new Drawable[]
- {
- new Box
- {
- RelativeSizeAxes = Axes.Both,
- Colour = ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.25f), Color4.Black.Opacity(0.75f)),
- },
- new Container
- {
- RelativeSizeAxes = Axes.Both,
- Padding = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding, Left = horizontal_padding, Right = vertical_padding },
- Children = new Drawable[]
- {
- new FillFlowContainer
- {
- Origin = Anchor.CentreLeft,
- Anchor = Anchor.CentreLeft,
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- LayoutEasing = Easing.OutQuint,
- LayoutDuration = transition_duration,
- Spacing = new Vector2(10, 0),
- Children = new Drawable[]
- {
- new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Vertical,
- Children = new Drawable[]
- {
- new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- Children = new Drawable[]
- {
- playButton = new PlayButton(SetInfo)
- {
- Origin = Anchor.CentreLeft,
- Anchor = Anchor.CentreLeft,
- Size = new Vector2(height / 3),
- FillMode = FillMode.Fit,
- Margin = new MarginPadding { Right = 10 },
- },
- new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Vertical,
- Children = new Drawable[]
- {
- titleContainer = new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- Children = new[]
- {
- new OsuSpriteText
- {
- Text = new RomanisableString(SetInfo.TitleUnicode, SetInfo.Title),
- Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true)
- },
- }
- },
- artistContainer = new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- Children = new[]
- {
- new OsuSpriteText
- {
- Text = new RomanisableString(SetInfo.ArtistUnicode, SetInfo.Artist),
- Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true)
- },
- },
- },
- }
- },
- }
- },
- new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- Children = new Drawable[]
- {
- statusContainer = new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Margin = new MarginPadding { Vertical = vertical_padding, Horizontal = 5 },
- Spacing = new Vector2(5),
- },
- new FillFlowContainer
- {
- AutoSizeAxes = Axes.X,
- Height = 20,
- Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding },
- Spacing = new Vector2(3),
- Children = GetDifficultyIcons(colours),
- },
- },
- },
- },
- },
- }
- },
- new FillFlowContainer
- {
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- Children = new Drawable[]
- {
- new Container
- {
- Anchor = Anchor.CentreRight,
- Origin = Anchor.CentreRight,
- AutoSizeAxes = Axes.Both,
- Child = DownloadButton = new BeatmapPanelDownloadButton(SetInfo)
- {
- Size = new Vector2(height - vertical_padding * 3),
- Margin = new MarginPadding { Left = vertical_padding * 2, Right = vertical_padding },
- },
- },
- new FillFlowContainer
- {
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Vertical,
- Children = new Drawable[]
- {
- new Statistic(FontAwesome.Solid.PlayCircle, SetInfo.PlayCount),
- new Statistic(FontAwesome.Solid.Heart, SetInfo.FavouriteCount),
- new LinkFlowContainer(s =>
- {
- s.Shadow = false;
- s.Font = OsuFont.GetFont(size: 14);
- })
- {
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- AutoSizeAxes = Axes.Both,
- }.With(d =>
- {
- d.AutoSizeAxes = Axes.Both;
- d.AddText("mapped by ");
- d.AddUserLink(SetInfo.Author);
- }),
- new OsuSpriteText
- {
- Text = SetInfo.Source,
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- Font = OsuFont.GetFont(size: 14),
- Alpha = string.IsNullOrEmpty(SetInfo.Source) ? 0f : 1f,
- },
- },
- },
- },
- },
- },
- },
- progressBar = new Box
- {
- Anchor = Anchor.BottomLeft,
- Origin = Anchor.BottomLeft,
- RelativeSizeAxes = Axes.X,
- BypassAutoSizeAxes = Axes.Y,
- Size = new Vector2(0, 3),
- Alpha = 0,
- Colour = colours.Yellow,
- },
- });
-
- if (SetInfo.HasExplicitContent)
- {
- titleContainer.Add(new ExplicitContentBeatmapPill
- {
- Anchor = Anchor.CentreLeft,
- Origin = Anchor.CentreLeft,
- Margin = new MarginPadding { Left = 10f, Top = 2f },
- });
- }
-
- if (SetInfo.TrackId != null)
- {
- artistContainer.Add(new FeaturedArtistBeatmapPill
- {
- Anchor = Anchor.CentreLeft,
- Origin = Anchor.CentreLeft,
- Margin = new MarginPadding { Left = 10f, Top = 2f },
- });
- }
-
- if (SetInfo.HasVideo)
- {
- statusContainer.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) });
- }
-
- if (SetInfo.HasStoryboard)
- {
- statusContainer.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) });
- }
-
- statusContainer.Add(new BeatmapSetOnlineStatusPill
- {
- AutoSizeAxes = Axes.Both,
- TextSize = 12,
- TextPadding = new MarginPadding { Horizontal = 10, Vertical = 4 },
- Status = SetInfo.Status,
- });
- }
- }
-}
diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs
index 547b8a6ec3..8f4089c707 100644
--- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs
+++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs
@@ -17,7 +17,6 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
-using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Overlays.BeatmapSet.Buttons;
using osuTK;
@@ -286,7 +285,7 @@ namespace osu.Game.Overlays.BeatmapSet
{
case DownloadState.LocallyAvailable:
// temporary for UX until new design is implemented.
- downloadButtonsContainer.Child = new BeatmapPanelDownloadButton(BeatmapSet.Value)
+ downloadButtonsContainer.Child = new BeatmapDownloadButton(BeatmapSet.Value)
{
Width = 50,
RelativeSizeAxes = Axes.Y,
diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs
index 4eed8f28f2..74417b0ac6 100644
--- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs
+++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs
@@ -9,13 +9,13 @@ using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
-using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Resources.Localisation.Web;
using osuTK;
using osuTK.Graphics;
diff --git a/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs
similarity index 99%
rename from osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs
rename to osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs
index c352fe0223..63b7a0a062 100644
--- a/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs
+++ b/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs
@@ -14,7 +14,7 @@ using osu.Game.Online.API.Requests.Responses;
using osuTK;
using osuTK.Graphics;
-namespace osu.Game.Overlays.BeatmapListing.Panels
+namespace osu.Game.Overlays.BeatmapSet.Buttons
{
public class PlayButton : Container
{
diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs
index 6bcdb7bdc5..751299161d 100644
--- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs
+++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs
@@ -11,7 +11,6 @@ using osu.Game.Audio;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests.Responses;
-using osu.Game.Overlays.BeatmapListing.Panels;
using osuTK;
namespace osu.Game.Overlays.BeatmapSet.Buttons
diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs
index f37e6bedf7..4dd23c0008 100644
--- a/osu.Game/Overlays/NowPlayingOverlay.cs
+++ b/osu.Game/Overlays/NowPlayingOverlay.cs
@@ -214,7 +214,8 @@ namespace osu.Game.Overlays
{
base.LoadComplete();
- beatmap.BindDisabledChanged(beatmapDisabledChanged, true);
+ beatmap.BindDisabledChanged(_ => Scheduler.AddOnce(beatmapDisabledChanged));
+ beatmapDisabledChanged();
musicController.TrackChanged += trackChanged;
trackChanged(beatmap.Value);
@@ -318,8 +319,10 @@ namespace osu.Game.Overlays
};
}
- private void beatmapDisabledChanged(bool disabled)
+ private void beatmapDisabledChanged()
{
+ bool disabled = beatmap.Disabled;
+
if (disabled)
playlist?.Hide();
diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
index 5bc89ec77c..acdf9cdea6 100644
--- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
+++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
@@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Text = MaintenanceSettingsStrings.DeleteAllBeatmaps,
Action = () =>
{
- dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
+ dialogOverlay?.Push(new MassDeleteConfirmationDialog(() =>
{
deleteBeatmapsButton.Enabled.Value = false;
Task.Run(() => beatmaps.Delete(beatmaps.GetAllUsableBeatmapSets())).ContinueWith(t => Schedule(() => deleteBeatmapsButton.Enabled.Value = true));
@@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Text = MaintenanceSettingsStrings.DeleteAllScores,
Action = () =>
{
- dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
+ dialogOverlay?.Push(new MassDeleteConfirmationDialog(() =>
{
deleteScoresButton.Enabled.Value = false;
Task.Run(() => scores.Delete(scores.GetAllUsableScores())).ContinueWith(t => Schedule(() => deleteScoresButton.Enabled.Value = true));
@@ -103,7 +103,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Text = MaintenanceSettingsStrings.DeleteAllSkins,
Action = () =>
{
- dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
+ dialogOverlay?.Push(new MassDeleteConfirmationDialog(() =>
{
deleteSkinsButton.Enabled.Value = false;
Task.Run(() => skins.Delete(skins.GetAllUserSkins())).ContinueWith(t => Schedule(() => deleteSkinsButton.Enabled.Value = true));
@@ -131,7 +131,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Text = MaintenanceSettingsStrings.DeleteAllCollections,
Action = () =>
{
- dialogOverlay?.Push(new DeleteAllBeatmapsDialog(collectionManager.DeleteAll));
+ dialogOverlay?.Push(new MassDeleteConfirmationDialog(collectionManager.DeleteAll));
}
});
}
diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs
similarity index 87%
rename from osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs
rename to osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs
index a124501454..6380232bbb 100644
--- a/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs
+++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs
@@ -7,9 +7,9 @@ using osu.Game.Overlays.Dialog;
namespace osu.Game.Overlays.Settings.Sections.Maintenance
{
- public class DeleteAllBeatmapsDialog : PopupDialog
+ public class MassDeleteConfirmationDialog : PopupDialog
{
- public DeleteAllBeatmapsDialog(Action deleteAction)
+ public MassDeleteConfirmationDialog(Action deleteAction)
{
BodyText = "Everything?";
diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
index 9ca105ee7f..6e5fbf6efb 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
@@ -68,13 +68,19 @@ namespace osu.Game.Overlays.Toolbar
{
base.LoadComplete();
- Current.BindDisabledChanged(disabled => this.FadeColour(disabled ? Color4.Gray : Color4.White, 300), true);
- Current.BindValueChanged(_ => moveLineToCurrent());
+ Current.BindDisabledChanged(_ => Scheduler.AddOnce(currentDisabledChanged));
+ currentDisabledChanged();
+ Current.BindValueChanged(_ => moveLineToCurrent());
// Scheduled to allow the button flow layout to be computed before the line position is updated
ScheduleAfterChildren(moveLineToCurrent);
}
+ private void currentDisabledChanged()
+ {
+ this.FadeColour(Current.Disabled ? Color4.Gray : Color4.White, 300);
+ }
+
private bool hasInitialPosition;
private void moveLineToCurrent()
diff --git a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs
index 8e739a786f..1e97218074 100644
--- a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs
+++ b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs
@@ -78,9 +78,9 @@ namespace osu.Game.Screens.Edit.Setup
using (var stream = info.OpenRead())
{
if (oldFile != null)
- beatmaps.ReplaceFile(set, oldFile, stream, info.Name);
- else
- beatmaps.AddFile(set, stream, info.Name);
+ beatmaps.DeleteFile(set, oldFile);
+
+ beatmaps.AddFile(set, stream, info.Name);
}
working.Value.Metadata.BackgroundFile = info.Name;
@@ -105,9 +105,8 @@ namespace osu.Game.Screens.Edit.Setup
using (var stream = info.OpenRead())
{
if (oldFile != null)
- beatmaps.ReplaceFile(set, oldFile, stream, info.Name);
- else
- beatmaps.AddFile(set, stream, info.Name);
+ beatmaps.DeleteFile(set, oldFile);
+ beatmaps.AddFile(set, stream, info.Name);
}
working.Value.Metadata.AudioFile = info.Name;
diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
index 6cbdc80d60..2dbe2df82c 100644
--- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
+++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
@@ -25,7 +25,6 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Online.Chat;
using osu.Game.Online.Rooms;
-using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Overlays.BeatmapSet;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
@@ -147,7 +146,8 @@ namespace osu.Game.Screens.OnlinePlay
if (showItemOwner)
{
ownerAvatar.Show();
- userLookupCache.GetUserAsync(Item.OwnerID).ContinueWith(u => Schedule(() => ownerAvatar.User = u.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
+ userLookupCache.GetUserAsync(Item.OwnerID)
+ .ContinueWith(u => Schedule(() => ownerAvatar.User = u.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
}
difficultyIconContainer.Child = new DifficultyIcon(Item.Beatmap.Value, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(ICON_HEIGHT) };
@@ -338,7 +338,7 @@ namespace osu.Game.Screens.OnlinePlay
return true;
}
- private sealed class PlaylistDownloadButton : BeatmapPanelDownloadButton
+ private sealed class PlaylistDownloadButton : BeatmapDownloadButton
{
private readonly PlaylistItem playlistItem;
@@ -458,7 +458,7 @@ namespace osu.Game.Screens.OnlinePlay
});
}
- public LocalisableString TooltipText => User == null ? "loading user..." : $"queued by {User.Username}";
+ public LocalisableString TooltipText => User == null ? string.Empty : $"queued by {User.Username}";
private class TooltipArea : Component, IHasTooltip
{
diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs
index 8d07dd046a..26ff4457af 100644
--- a/osu.Game/Skinning/SkinManager.cs
+++ b/osu.Game/Skinning/SkinManager.cs
@@ -171,7 +171,7 @@ namespace osu.Game.Skinning
var oldFile = skin.SkinInfo.Files.FirstOrDefault(f => f.Filename == filename);
if (oldFile != null)
- skinModelManager.ReplaceFile(skin.SkinInfo, oldFile, streamContent, oldFile.Filename);
+ skinModelManager.ReplaceFile(skin.SkinInfo, oldFile, streamContent);
else
skinModelManager.AddFile(skin.SkinInfo, streamContent, filename);
}
diff --git a/osu.Game/Stores/RealmArchiveModelImporter.cs b/osu.Game/Stores/RealmArchiveModelImporter.cs
index b74670e722..1681dad750 100644
--- a/osu.Game/Stores/RealmArchiveModelImporter.cs
+++ b/osu.Game/Stores/RealmArchiveModelImporter.cs
@@ -294,12 +294,8 @@ namespace osu.Game.Stores
///
/// In the case of no matching files, a hash will be generated from the passed archive's .
///
- protected virtual string ComputeHash(TModel item, ArchiveReader? reader = null)
+ protected virtual string ComputeHash(TModel item)
{
- if (reader != null)
- // fast hashing for cases where the item's files may not be populated.
- return computeHashFast(reader);
-
// for now, concatenate all hashable files in the set to create a unique hash.
MemoryStream hashable = new MemoryStream();
@@ -374,7 +370,7 @@ namespace osu.Game.Stores
// TODO: look into rollback of file additions (or delayed commit).
item.Files.AddRange(createFileInfos(archive, Files, realm));
- item.Hash = ComputeHash(item, archive);
+ item.Hash = ComputeHash(item);
// TODO: we may want to run this outside of the transaction.
await Populate(item, archive, realm, cancellationToken).ConfigureAwait(false);
@@ -387,7 +383,9 @@ namespace osu.Game.Stores
if (CanReuseExisting(existing, item))
{
LogForModel(item, @$"Found existing {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import.");
+
existing.DeletePending = false;
+ transaction.Commit();
return existing.ToLive();
}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index f9c8d9743d..7cc8893d8d 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -36,7 +36,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 47f8fbb43a..9c21f76617 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -60,7 +60,7 @@
-
+
@@ -83,7 +83,7 @@
-
+