1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-26 19:32:55 +08:00

Merge branch 'beatmap-refactor/get-and-present' into beatmap-refactor/beatmap-overlays

This commit is contained in:
Dean Herbert 2021-11-01 18:07:51 +09:00
commit b21e0e7efb
28 changed files with 201 additions and 148 deletions

View File

@ -29,6 +29,15 @@ namespace osu.Game.Tests.Skins.IO
assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu); assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu);
}); });
[Test]
public Task TestSingleImportWeirdIniFileCase() => runSkinTest(async osu =>
{
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner", iniFilename: "Skin.InI"), "skin.osk"));
// When the import filename doesn't match, it should be appended (and update the skin.ini).
assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu);
});
[Test] [Test]
public Task TestSingleImportMatchingFilename() => runSkinTest(async osu => public Task TestSingleImportMatchingFilename() => runSkinTest(async osu =>
{ {
@ -190,11 +199,11 @@ namespace osu.Game.Tests.Skins.IO
return zipStream; return zipStream;
} }
private MemoryStream createOskWithIni(string name, string author, bool makeUnique = false) private MemoryStream createOskWithIni(string name, string author, bool makeUnique = false, string iniFilename = @"skin.ini")
{ {
var zipStream = new MemoryStream(); var zipStream = new MemoryStream();
using var zip = ZipArchive.Create(); using var zip = ZipArchive.Create();
zip.AddEntry("skin.ini", generateSkinIni(name, author, makeUnique)); zip.AddEntry(iniFilename, generateSkinIni(name, author, makeUnique));
zip.SaveTo(zipStream); zip.SaveTo(zipStream);
return zipStream; return zipStream;
} }

View File

@ -13,6 +13,7 @@ using osu.Framework.Bindables;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
using osuTK.Input; using osuTK.Input;
@ -136,7 +137,8 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
OnlineID = 2553163309, OnlineID = 2553163309,
OnlineRulesetID = 0, OnlineRulesetID = 0,
Replay = replayAvailable, Beatmap = CreateAPIBeatmapSet(new OsuRuleset().RulesetInfo).Beatmaps.First(),
HasReplay = replayAvailable,
User = new User User = new User
{ {
Id = 39828, Id = 39828,

View File

@ -56,11 +56,9 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("Set width to 300", () => content.ResizeWidthTo(300, 500)); AddStep("Set width to 300", () => content.ResizeWidthTo(300, 500));
} }
private static readonly List<BeatmapSetInfo> new_beatmaps = new List<BeatmapSetInfo> private static readonly List<APIBeatmapSet> new_beatmaps = new List<APIBeatmapSet>
{ {
new BeatmapSetInfo new APIBeatmapSet
{
Metadata = new BeatmapMetadata
{ {
Title = "Very Long Title (TV size) [TATOE]", Title = "Very Long Title (TV size) [TATOE]",
Artist = "This artist has a really long name how is this possible", Artist = "This artist has a really long name how is this possible",
@ -68,20 +66,33 @@ namespace osu.Game.Tests.Visual.UserInterface
{ {
Username = "author", Username = "author",
Id = 100 Id = 100
}
}, },
OnlineInfo = new APIBeatmapSet Covers = new BeatmapSetOnlineCovers
{ {
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
},
Ranked = DateTimeOffset.Now
},
new APIBeatmapSet
{
Title = "Very Long Title (TV size) [TATOE]",
Artist = "This artist has a really long name how is this possible",
Author = new User
{
Username = "author",
Id = 100
},
Covers = new BeatmapSetOnlineCovers Covers = new BeatmapSetOnlineCovers
{ {
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608", Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
}, },
Ranked = DateTimeOffset.Now Ranked = DateTimeOffset.Now
} }
}, };
new BeatmapSetInfo
private static readonly List<APIBeatmapSet> popular_beatmaps = new List<APIBeatmapSet>
{ {
Metadata = new BeatmapMetadata new APIBeatmapSet
{ {
Title = "Very Long Title (TV size) [TATOE]", Title = "Very Long Title (TV size) [TATOE]",
Artist = "This artist has a really long name how is this possible", Artist = "This artist has a really long name how is this possible",
@ -89,62 +100,27 @@ namespace osu.Game.Tests.Visual.UserInterface
{ {
Username = "author", Username = "author",
Id = 100 Id = 100
}
}, },
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers Covers = new BeatmapSetOnlineCovers
{ {
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608", Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
}, },
Ranked = DateTimeOffset.MinValue Ranked = DateTimeOffset.Now
} },
} new APIBeatmapSet
};
private static readonly List<BeatmapSetInfo> popular_beatmaps = new List<BeatmapSetInfo>
{ {
new BeatmapSetInfo Title = "Very Long Title (TV size) [TATOE]",
{ Artist = "This artist has a really long name how is this possible",
Metadata = new BeatmapMetadata
{
Title = "Title",
Artist = "Artist",
Author = new User Author = new User
{ {
Username = "author", Username = "author",
Id = 100 Id = 100
}
}, },
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers Covers = new BeatmapSetOnlineCovers
{ {
Cover = "https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg?1595295586", Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
}, },
FavouriteCount = 100 Ranked = DateTimeOffset.Now
}
},
new BeatmapSetInfo
{
Metadata = new BeatmapMetadata
{
Title = "Title 2",
Artist = "Artist 2",
Author = new User
{
Username = "someone",
Id = 100
}
},
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers
{
Cover = "https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg?1595295586",
},
FavouriteCount = 10
}
} }
}; };
} }

View File

@ -76,7 +76,7 @@ namespace osu.Game.Tournament.Components
{ {
new TournamentSpriteText new TournamentSpriteText
{ {
Text = Beatmap.GetDisplayTitleRomanisable(false), Text = Beatmap.GetDisplayTitleRomanisable(false, false),
Font = OsuFont.Torus.With(weight: FontWeight.Bold), Font = OsuFont.Torus.With(weight: FontWeight.Bold),
}, },
new FillFlowContainer new FillFlowContainer

View File

@ -16,9 +16,9 @@ namespace osu.Game.Beatmaps
/// <summary> /// <summary>
/// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields. /// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields.
/// </summary> /// </summary>
public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapInfo beatmapInfo, bool includeDifficultyName = true) public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapInfo beatmapInfo, bool includeDifficultyName = true, bool includeCreator = true)
{ {
var metadata = getClosestMetadata(beatmapInfo).GetDisplayTitleRomanisable(); var metadata = getClosestMetadata(beatmapInfo).GetDisplayTitleRomanisable(includeCreator);
if (includeDifficultyName) if (includeDifficultyName)
{ {

View File

@ -34,9 +34,9 @@ namespace osu.Game.Beatmaps
/// <summary> /// <summary>
/// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields. /// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields.
/// </summary> /// </summary>
public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapMetadataInfo metadataInfo) public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapMetadataInfo metadataInfo, bool includeCreator = true)
{ {
string author = string.IsNullOrEmpty(metadataInfo.Author) ? string.Empty : $"({metadataInfo.Author})"; string author = !includeCreator || string.IsNullOrEmpty(metadataInfo.Author) ? string.Empty : $"({metadataInfo.Author})";
string artistUnicode = string.IsNullOrEmpty(metadataInfo.ArtistUnicode) ? metadataInfo.Artist : metadataInfo.ArtistUnicode; string artistUnicode = string.IsNullOrEmpty(metadataInfo.ArtistUnicode) ? metadataInfo.Artist : metadataInfo.ArtistUnicode;
string titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode; string titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode;

View File

@ -8,7 +8,7 @@ namespace osu.Game.Database
public interface IHasOnlineID<out T> public interface IHasOnlineID<out T>
{ {
/// <summary> /// <summary>
/// The server-side ID representing this instance, if one exists. Any value 0 or less denotes a missing ID. /// The server-side ID representing this instance, if one exists. Any value 0 or less denotes a missing ID (except in special cases where autoincrement is not used, like rulesets).
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Generally we use -1 when specifying "missing" in code, but values of 0 are also considered missing as the online source /// Generally we use -1 when specifying "missing" in code, but values of 0 are also considered missing as the online source

View File

@ -119,6 +119,16 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@"show_cursor_in_screenshots"), @"Show menu cursor in screenshots"); public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@"show_cursor_in_screenshots"), @"Show menu cursor in screenshots");
/// <summary>
/// "Video"
/// </summary>
public static LocalisableString VideoHeader => new TranslatableString(getKey(@"video_header"), @"Video");
/// <summary>
/// "Use hardware acceleration"
/// </summary>
public static LocalisableString UseHardwareAcceleration => new TranslatableString(getKey(@"use_hardware_acceleration"), @"Use hardware acceleration");
private static string getKey(string key) => $"{prefix}:{key}"; private static string getKey(string key) => $"{prefix}:{key}";
} }
} }

View File

@ -26,13 +26,11 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty(@"user")] [JsonProperty(@"user")]
public User User { get; set; } public User User { get; set; }
public bool HasReplay { get; set; }
[JsonProperty(@"id")] [JsonProperty(@"id")]
public long OnlineID { get; set; } public long OnlineID { get; set; }
[JsonProperty(@"replay")] [JsonProperty(@"replay")]
public bool Replay { get; set; } public bool HasReplay { get; set; }
[JsonProperty(@"created_at")] [JsonProperty(@"created_at")]
public DateTimeOffset Date { get; set; } public DateTimeOffset Date { get; set; }
@ -52,7 +50,10 @@ namespace osu.Game.Online.API.Requests.Responses
set set
{ {
// in the deserialisation case we need to ferry this data across. // in the deserialisation case we need to ferry this data across.
if (Beatmap is APIBeatmap apiBeatmap) // the order of properties returned by the API guarantees that the beatmap is populated by this point.
if (!(Beatmap is APIBeatmap apiBeatmap))
throw new InvalidOperationException("Beatmap set metadata arrived before beatmap metadata in response");
apiBeatmap.BeatmapSet = value; apiBeatmap.BeatmapSet = value;
} }
} }
@ -91,13 +92,14 @@ namespace osu.Game.Online.API.Requests.Responses
{ {
TotalScore = TotalScore, TotalScore = TotalScore,
MaxCombo = MaxCombo, MaxCombo = MaxCombo,
BeatmapInfo = Beatmap.ToBeatmapInfo(rulesets),
User = User, User = User,
Accuracy = Accuracy, Accuracy = Accuracy,
OnlineScoreID = OnlineID, OnlineScoreID = OnlineID,
Date = Date, Date = Date,
PP = PP, PP = PP,
RulesetID = OnlineRulesetID, RulesetID = OnlineRulesetID,
Hash = Replay ? "online" : string.Empty, // todo: temporary? Hash = HasReplay ? "online" : string.Empty, // todo: temporary?
Rank = Rank, Rank = Rank,
Ruleset = ruleset, Ruleset = ruleset,
Mods = mods, Mods = mods,

View File

@ -17,7 +17,6 @@ namespace osu.Game.Online.API.Requests.Responses
public APIScoreInfo Score; public APIScoreInfo Score;
public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null) public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null)
{ {
var score = Score.CreateScoreInfo(rulesets, beatmap); var score = Score.CreateScoreInfo(rulesets, beatmap);
score.Position = Position; score.Position = Position;

View File

@ -109,8 +109,7 @@ namespace osu.Game.Online.Rooms
int onlineId = SelectedItem.Value.Beatmap.Value.OnlineID; int onlineId = SelectedItem.Value.Beatmap.Value.OnlineID;
string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash; string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash;
var beatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == onlineId && b.MD5Hash == checksum); return beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == onlineId && b.MD5Hash == checksum && !b.BeatmapSet.DeletePending) != null;
return beatmap?.BeatmapSet.DeletePending == false;
} }
} }
} }

View File

@ -249,6 +249,7 @@ namespace osu.Game.Overlays.BeatmapSet
{ {
downloadTracker = new BeatmapDownloadTracker(setInfo.NewValue); downloadTracker = new BeatmapDownloadTracker(setInfo.NewValue);
downloadTracker.State.BindValueChanged(_ => updateDownloadButtons()); downloadTracker.State.BindValueChanged(_ => updateDownloadButtons());
AddInternal(downloadTracker);
fadeContent.FadeIn(500, Easing.OutQuint); fadeContent.FadeIn(500, Easing.OutQuint);

View File

@ -5,17 +5,17 @@ using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses;
using osuTK; using osuTK;
namespace osu.Game.Overlays.Dashboard.Home namespace osu.Game.Overlays.Dashboard.Home
{ {
public class DashboardBeatmapListing : CompositeDrawable public class DashboardBeatmapListing : CompositeDrawable
{ {
private readonly List<BeatmapSetInfo> newBeatmaps; private readonly List<APIBeatmapSet> newBeatmaps;
private readonly List<BeatmapSetInfo> popularBeatmaps; private readonly List<APIBeatmapSet> popularBeatmaps;
public DashboardBeatmapListing(List<BeatmapSetInfo> newBeatmaps, List<BeatmapSetInfo> popularBeatmaps) public DashboardBeatmapListing(List<APIBeatmapSet> newBeatmaps, List<APIBeatmapSet> popularBeatmaps)
{ {
this.newBeatmaps = newBeatmaps; this.newBeatmaps = newBeatmaps;
this.popularBeatmaps = popularBeatmaps; this.popularBeatmaps = popularBeatmaps;

View File

@ -7,11 +7,11 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables; using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osuTK; using osuTK;
namespace osu.Game.Overlays.Dashboard.Home namespace osu.Game.Overlays.Dashboard.Home
@ -24,14 +24,14 @@ namespace osu.Game.Overlays.Dashboard.Home
[Resolved(canBeNull: true)] [Resolved(canBeNull: true)]
private BeatmapSetOverlay beatmapOverlay { get; set; } private BeatmapSetOverlay beatmapOverlay { get; set; }
protected readonly BeatmapSetInfo SetInfo; protected readonly APIBeatmapSet BeatmapSet;
private Box hoverBackground; private Box hoverBackground;
private SpriteIcon chevron; private SpriteIcon chevron;
protected DashboardBeatmapPanel(BeatmapSetInfo setInfo) protected DashboardBeatmapPanel(APIBeatmapSet beatmapSet)
{ {
SetInfo = setInfo; BeatmapSet = beatmapSet;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -82,7 +82,7 @@ namespace osu.Game.Overlays.Dashboard.Home
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
OnlineInfo = SetInfo.OnlineInfo OnlineInfo = BeatmapSet
} }
}, },
new Container new Container
@ -103,14 +103,14 @@ namespace osu.Game.Overlays.Dashboard.Home
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Truncate = true, Truncate = true,
Font = OsuFont.GetFont(weight: FontWeight.Regular), Font = OsuFont.GetFont(weight: FontWeight.Regular),
Text = SetInfo.Metadata.Title Text = BeatmapSet.Title
}, },
new OsuSpriteText new OsuSpriteText
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Truncate = true, Truncate = true,
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular),
Text = SetInfo.Metadata.Artist Text = BeatmapSet.Artist
}, },
new LinkFlowContainer(f => f.Font = OsuFont.GetFont(size: 10, weight: FontWeight.Regular)) new LinkFlowContainer(f => f.Font = OsuFont.GetFont(size: 10, weight: FontWeight.Regular))
{ {
@ -121,7 +121,7 @@ namespace osu.Game.Overlays.Dashboard.Home
}.With(c => }.With(c =>
{ {
c.AddText("by"); c.AddText("by");
c.AddUserLink(SetInfo.Metadata.Author); c.AddUserLink(BeatmapSet.Author);
c.AddArbitraryDrawable(CreateInfo()); c.AddArbitraryDrawable(CreateInfo());
}) })
} }
@ -143,8 +143,8 @@ namespace osu.Game.Overlays.Dashboard.Home
Action = () => Action = () =>
{ {
if (SetInfo.OnlineBeatmapSetID.HasValue) if (BeatmapSet.OnlineID > 0)
beatmapOverlay?.FetchAndShowBeatmapSet(SetInfo.OnlineBeatmapSetID.Value); beatmapOverlay?.FetchAndShowBeatmapSet(BeatmapSet.OnlineID);
}; };
} }

View File

@ -3,19 +3,19 @@
using System; using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Dashboard.Home namespace osu.Game.Overlays.Dashboard.Home
{ {
public class DashboardNewBeatmapPanel : DashboardBeatmapPanel public class DashboardNewBeatmapPanel : DashboardBeatmapPanel
{ {
public DashboardNewBeatmapPanel(BeatmapSetInfo setInfo) public DashboardNewBeatmapPanel(APIBeatmapSet beatmapSet)
: base(setInfo) : base(beatmapSet)
{ {
} }
protected override Drawable CreateInfo() => new DrawableDate(SetInfo.OnlineInfo.Ranked ?? DateTimeOffset.Now, 10, false) protected override Drawable CreateInfo() => new DrawableDate(BeatmapSet.Ranked ?? DateTimeOffset.Now, 10, false)
{ {
Colour = ColourProvider.Foreground1 Colour = ColourProvider.Foreground1
}; };

View File

@ -4,17 +4,17 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osuTK; using osuTK;
namespace osu.Game.Overlays.Dashboard.Home namespace osu.Game.Overlays.Dashboard.Home
{ {
public class DashboardPopularBeatmapPanel : DashboardBeatmapPanel public class DashboardPopularBeatmapPanel : DashboardBeatmapPanel
{ {
public DashboardPopularBeatmapPanel(BeatmapSetInfo setInfo) public DashboardPopularBeatmapPanel(APIBeatmapSet beatmapSet)
: base(setInfo) : base(beatmapSet)
{ {
} }
@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Dashboard.Home
new OsuSpriteText new OsuSpriteText
{ {
Font = OsuFont.GetFont(size: 10, weight: FontWeight.Regular), Font = OsuFont.GetFont(size: 10, weight: FontWeight.Regular),
Text = SetInfo.OnlineInfo.FavouriteCount.ToString() Text = BeatmapSet.FavouriteCount.ToString()
} }
} }
}; };

View File

@ -6,20 +6,20 @@ using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osuTK; using osuTK;
namespace osu.Game.Overlays.Dashboard.Home namespace osu.Game.Overlays.Dashboard.Home
{ {
public abstract class DrawableBeatmapList : CompositeDrawable public abstract class DrawableBeatmapList : CompositeDrawable
{ {
private readonly List<BeatmapSetInfo> beatmaps; private readonly List<APIBeatmapSet> beatmapSets;
protected DrawableBeatmapList(List<BeatmapSetInfo> beatmaps) protected DrawableBeatmapList(List<APIBeatmapSet> beatmapSets)
{ {
this.beatmaps = beatmaps; this.beatmapSets = beatmapSets;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -46,11 +46,11 @@ namespace osu.Game.Overlays.Dashboard.Home
} }
}; };
flow.AddRange(beatmaps.Select(CreateBeatmapPanel)); flow.AddRange(beatmapSets.Select(CreateBeatmapPanel));
} }
protected abstract string Title { get; } protected abstract string Title { get; }
protected abstract DashboardBeatmapPanel CreateBeatmapPanel(BeatmapSetInfo setInfo); protected abstract DashboardBeatmapPanel CreateBeatmapPanel(APIBeatmapSet beatmapSet);
} }
} }

View File

@ -2,18 +2,18 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Dashboard.Home namespace osu.Game.Overlays.Dashboard.Home
{ {
public class DrawableNewBeatmapList : DrawableBeatmapList public class DrawableNewBeatmapList : DrawableBeatmapList
{ {
public DrawableNewBeatmapList(List<BeatmapSetInfo> beatmaps) public DrawableNewBeatmapList(List<APIBeatmapSet> beatmapSets)
: base(beatmaps) : base(beatmapSets)
{ {
} }
protected override DashboardBeatmapPanel CreateBeatmapPanel(BeatmapSetInfo setInfo) => new DashboardNewBeatmapPanel(setInfo); protected override DashboardBeatmapPanel CreateBeatmapPanel(APIBeatmapSet beatmapSet) => new DashboardNewBeatmapPanel(beatmapSet);
protected override string Title => "New Ranked Beatmaps"; protected override string Title => "New Ranked Beatmaps";
} }

View File

@ -2,18 +2,18 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Dashboard.Home namespace osu.Game.Overlays.Dashboard.Home
{ {
public class DrawablePopularBeatmapList : DrawableBeatmapList public class DrawablePopularBeatmapList : DrawableBeatmapList
{ {
public DrawablePopularBeatmapList(List<BeatmapSetInfo> beatmaps) public DrawablePopularBeatmapList(List<APIBeatmapSet> beatmapSets)
: base(beatmaps) : base(beatmapSets)
{ {
} }
protected override DashboardBeatmapPanel CreateBeatmapPanel(BeatmapSetInfo setInfo) => new DashboardPopularBeatmapPanel(setInfo); protected override DashboardBeatmapPanel CreateBeatmapPanel(APIBeatmapSet beatmapSet) => new DashboardPopularBeatmapPanel(beatmapSet);
protected override string Title => "Popular Beatmaps"; protected override string Title => "Popular Beatmaps";
} }

View File

@ -0,0 +1,43 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Video;
using osu.Framework.Localisation;
using osu.Game.Localisation;
namespace osu.Game.Overlays.Settings.Sections.Graphics
{
public class VideoSettings : SettingsSubsection
{
protected override LocalisableString Header => GraphicsSettingsStrings.VideoHeader;
private Bindable<HardwareVideoDecoder> hardwareVideoDecoder;
private SettingsCheckbox hwAccelCheckbox;
[BackgroundDependencyLoader]
private void load(FrameworkConfigManager config)
{
hardwareVideoDecoder = config.GetBindable<HardwareVideoDecoder>(FrameworkSetting.HardwareVideoDecoder);
Children = new Drawable[]
{
hwAccelCheckbox = new SettingsCheckbox
{
LabelText = GraphicsSettingsStrings.UseHardwareAcceleration,
},
};
hwAccelCheckbox.Current.Default = hardwareVideoDecoder.Default != HardwareVideoDecoder.None;
hwAccelCheckbox.Current.Value = hardwareVideoDecoder.Value != HardwareVideoDecoder.None;
hwAccelCheckbox.Current.BindValueChanged(val =>
{
hardwareVideoDecoder.Value = val.NewValue ? HardwareVideoDecoder.Any : HardwareVideoDecoder.None;
});
}
}
}

View File

@ -24,6 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections
{ {
new LayoutSettings(), new LayoutSettings(),
new RendererSettings(), new RendererSettings(),
new VideoSettings(),
new ScreenshotSettings(), new ScreenshotSettings(),
}; };
} }

View File

@ -29,7 +29,7 @@ namespace osu.Game.Scoring
IRulesetInfo Ruleset { get; } IRulesetInfo Ruleset { get; }
public ScoreRank Rank { get; } ScoreRank Rank { get; }
// Mods is currently missing from this interface as the `IMod` class has properties which can't be fulfilled by `APIMod`, // Mods is currently missing from this interface as the `IMod` class has properties which can't be fulfilled by `APIMod`,
// but also doesn't expose `Settings`. We can consider how to implement this in the future if required. // but also doesn't expose `Settings`. We can consider how to implement this in the future if required.

View File

@ -244,10 +244,18 @@ namespace osu.Game.Scoring
return ReferenceEquals(this, other); return ReferenceEquals(this, other);
} }
#region Implementation of IHasOnlineID
public long OnlineID => OnlineScoreID ?? -1; public long OnlineID => OnlineScoreID ?? -1;
#endregion
#region Implementation of IScoreInfo
IBeatmapInfo IScoreInfo.Beatmap => BeatmapInfo; IBeatmapInfo IScoreInfo.Beatmap => BeatmapInfo;
IRulesetInfo IScoreInfo.Ruleset => Ruleset; IRulesetInfo IScoreInfo.Ruleset => Ruleset;
bool IScoreInfo.HasReplay => Files.Any(); bool IScoreInfo.HasReplay => Files.Any();
#endregion
} }
} }

View File

@ -248,10 +248,7 @@ namespace osu.Game.Screens.OnlinePlay
protected virtual IEnumerable<Drawable> CreateButtons() => protected virtual IEnumerable<Drawable> CreateButtons() =>
new Drawable[] new Drawable[]
{ {
new PlaylistDownloadButton(Item) new PlaylistDownloadButton(Item),
{
Size = new Vector2(50, 30)
},
new PlaylistRemoveButton new PlaylistRemoveButton
{ {
Size = new Vector2(30, 30), Size = new Vector2(30, 30),
@ -292,10 +289,14 @@ namespace osu.Game.Screens.OnlinePlay
// required for download tracking, as this button hides itself. can probably be removed with a bit of consideration. // required for download tracking, as this button hides itself. can probably be removed with a bit of consideration.
public override bool IsPresent => true; public override bool IsPresent => true;
private const float width = 50;
public PlaylistDownloadButton(PlaylistItem playlistItem) public PlaylistDownloadButton(PlaylistItem playlistItem)
: base(playlistItem.Beatmap.Value.BeatmapSet) : base(playlistItem.Beatmap.Value.BeatmapSet)
{ {
this.playlistItem = playlistItem; this.playlistItem = playlistItem;
Size = new Vector2(width, 30);
Alpha = 0; Alpha = 0;
} }
@ -316,12 +317,16 @@ namespace osu.Game.Screens.OnlinePlay
if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.Beatmap.Value.MD5Hash) == null) if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.Beatmap.Value.MD5Hash) == null)
State.Value = DownloadState.NotDownloaded; State.Value = DownloadState.NotDownloaded;
else else
this.FadeTo(0, 500); {
this.FadeTo(0, 500)
.ResizeWidthTo(0, 500, Easing.OutQuint);
}
break; break;
default: default:
this.FadeTo(1, 500); this.ResizeWidthTo(width, 500, Easing.OutQuint)
.FadeTo(1, 500);
break; break;
} }
} }

View File

@ -10,6 +10,7 @@ using ManagedBass.Fx;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -83,7 +84,7 @@ namespace osu.Game.Screens.Play
Content, Content,
redFlashLayer = new Box redFlashLayer = new Box
{ {
Colour = Color4.Red, Colour = Color4.Red.Opacity(0.6f),
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Blending = BlendingParameters.Additive, Blending = BlendingParameters.Additive,
Depth = float.MinValue, Depth = float.MinValue,

View File

@ -94,9 +94,6 @@ namespace osu.Game.Screens.Select.Details
modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue); modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue);
modSettingChangeTracker.SettingChanged += m => modSettingChangeTracker.SettingChanged += m =>
{ {
if (!(m is IApplicableToDifficulty))
return;
debouncedStatisticsUpdate?.Cancel(); debouncedStatisticsUpdate?.Cancel();
debouncedStatisticsUpdate = Scheduler.AddDelayed(updateStatistics, 100); debouncedStatisticsUpdate = Scheduler.AddDelayed(updateStatistics, 100);
}; };

View File

@ -93,7 +93,7 @@ namespace osu.Game.Skinning
private Stream getConfigurationStream() private Stream getConfigurationStream()
{ {
string path = SkinInfo.Files.SingleOrDefault(f => f.Filename == "skin.ini")?.FileInfo.StoragePath; string path = SkinInfo.Files.SingleOrDefault(f => f.Filename.Equals(@"skin.ini", StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
return null; return null;

View File

@ -108,7 +108,7 @@ namespace osu.Game.Skinning
} }
} }
protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk"; protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == @".osk";
/// <summary> /// <summary>
/// Returns a list of all usable <see cref="SkinInfo"/>s. Includes the special default skin plus all skins from <see cref="GetAllUserSkins"/>. /// Returns a list of all usable <see cref="SkinInfo"/>s. Includes the special default skin plus all skins from <see cref="GetAllUserSkins"/>.
@ -149,9 +149,9 @@ namespace osu.Game.Skinning
CurrentSkinInfo.Value = ModelStore.ConsumableItems.Single(i => i.ID == chosen.ID); CurrentSkinInfo.Value = ModelStore.ConsumableItems.Single(i => i.ID == chosen.ID);
} }
protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name ?? "No name" }; protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name ?? @"No name" };
private const string unknown_creator_string = "Unknown"; private const string unknown_creator_string = @"Unknown";
protected override bool HasCustomHashFunction => true; protected override bool HasCustomHashFunction => true;
@ -164,7 +164,7 @@ namespace osu.Game.Skinning
// `Skin` will parse the skin.ini and populate `Skin.Configuration` during construction above. // `Skin` will parse the skin.ini and populate `Skin.Configuration` during construction above.
string skinIniSourcedName = instance.Configuration.SkinInfo.Name; string skinIniSourcedName = instance.Configuration.SkinInfo.Name;
string skinIniSourcedCreator = instance.Configuration.SkinInfo.Creator; string skinIniSourcedCreator = instance.Configuration.SkinInfo.Creator;
string archiveName = item.Name.Replace(".osk", "", StringComparison.OrdinalIgnoreCase); string archiveName = item.Name.Replace(@".osk", string.Empty, StringComparison.OrdinalIgnoreCase);
bool isImport = item.ID == 0; bool isImport = item.ID == 0;
@ -177,7 +177,7 @@ namespace osu.Game.Skinning
// In an ideal world, skin.ini would be the only source of metadata, but a lot of skin creators and users don't update it when making modifications. // In an ideal world, skin.ini would be the only source of metadata, but a lot of skin creators and users don't update it when making modifications.
// In both of these cases, the expectation from the user is that the filename or folder name is displayed somewhere to identify the skin. // In both of these cases, the expectation from the user is that the filename or folder name is displayed somewhere to identify the skin.
if (archiveName != item.Name) if (archiveName != item.Name)
item.Name = $"{item.Name} [{archiveName}]"; item.Name = @$"{item.Name} [{archiveName}]";
} }
// By this point, the metadata in SkinInfo will be correct. // By this point, the metadata in SkinInfo will be correct.
@ -191,10 +191,10 @@ namespace osu.Game.Skinning
private void updateSkinIniMetadata(SkinInfo item) private void updateSkinIniMetadata(SkinInfo item)
{ {
string nameLine = $"Name: {item.Name}"; string nameLine = @$"Name: {item.Name}";
string authorLine = $"Author: {item.Creator}"; string authorLine = @$"Author: {item.Creator}";
var existingFile = item.Files.SingleOrDefault(f => f.Filename == "skin.ini"); var existingFile = item.Files.SingleOrDefault(f => f.Filename.Equals(@"skin.ini", StringComparison.OrdinalIgnoreCase));
if (existingFile != null) if (existingFile != null)
{ {
@ -210,12 +210,12 @@ namespace osu.Game.Skinning
while ((line = sr.ReadLine()) != null) while ((line = sr.ReadLine()) != null)
{ {
if (line.StartsWith("Name:", StringComparison.Ordinal)) if (line.StartsWith(@"Name:", StringComparison.Ordinal))
{ {
outputLines.Add(nameLine); outputLines.Add(nameLine);
addedName = true; addedName = true;
} }
else if (line.StartsWith("Author:", StringComparison.Ordinal)) else if (line.StartsWith(@"Author:", StringComparison.Ordinal))
{ {
outputLines.Add(authorLine); outputLines.Add(authorLine);
addedAuthor = true; addedAuthor = true;
@ -229,7 +229,7 @@ namespace osu.Game.Skinning
{ {
outputLines.AddRange(new[] outputLines.AddRange(new[]
{ {
"[General]", @"[General]",
nameLine, nameLine,
authorLine, authorLine,
}); });
@ -252,13 +252,13 @@ namespace osu.Game.Skinning
{ {
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
{ {
sw.WriteLine("[General]"); sw.WriteLine(@"[General]");
sw.WriteLine(nameLine); sw.WriteLine(nameLine);
sw.WriteLine(authorLine); sw.WriteLine(authorLine);
sw.WriteLine("Version: latest"); sw.WriteLine(@"Version: latest");
} }
AddFile(item, stream, "skin.ini"); AddFile(item, stream, @"skin.ini");
} }
} }
} }
@ -295,7 +295,7 @@ namespace osu.Game.Skinning
// if the user is attempting to save one of the default skin implementations, create a copy first. // if the user is attempting to save one of the default skin implementations, create a copy first.
CurrentSkinInfo.Value = Import(new SkinInfo CurrentSkinInfo.Value = Import(new SkinInfo
{ {
Name = skin.SkinInfo.Name + " (modified)", Name = skin.SkinInfo.Name + @" (modified)",
Creator = skin.SkinInfo.Creator, Creator = skin.SkinInfo.Creator,
InstantiationInfo = skin.SkinInfo.InstantiationInfo, InstantiationInfo = skin.SkinInfo.InstantiationInfo,
}).Result.Value; }).Result.Value;
@ -312,7 +312,7 @@ namespace osu.Game.Skinning
using (var streamContent = new MemoryStream(Encoding.UTF8.GetBytes(json))) using (var streamContent = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{ {
string filename = $"{drawableInfo.Key}.json"; string filename = @$"{drawableInfo.Key}.json";
var oldFile = skin.SkinInfo.Files.FirstOrDefault(f => f.Filename == filename); var oldFile = skin.SkinInfo.Files.FirstOrDefault(f => f.Filename == filename);