1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 22:33:05 +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,95 +56,71 @@ 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]",
Artist = "This artist has a really long name how is this possible",
Author = new User
{ {
Title = "Very Long Title (TV size) [TATOE]", Username = "author",
Artist = "This artist has a really long name how is this possible", Id = 100
Author = new User
{
Username = "author",
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.Now
},
Ranked = DateTimeOffset.Now
}
}, },
new BeatmapSetInfo new APIBeatmapSet
{ {
Metadata = new BeatmapMetadata Title = "Very Long Title (TV size) [TATOE]",
Artist = "This artist has a really long name how is this possible",
Author = new User
{ {
Title = "Very Long Title (TV size) [TATOE]", Username = "author",
Artist = "This artist has a really long name how is this possible", Id = 100
Author = new User
{
Username = "author",
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.Now
},
Ranked = DateTimeOffset.MinValue
}
} }
}; };
private static readonly List<BeatmapSetInfo> popular_beatmaps = new List<BeatmapSetInfo> private static readonly List<APIBeatmapSet> popular_beatmaps = new List<APIBeatmapSet>
{ {
new BeatmapSetInfo new APIBeatmapSet
{ {
Metadata = new BeatmapMetadata Title = "Very Long Title (TV size) [TATOE]",
Artist = "This artist has a really long name how is this possible",
Author = new User
{ {
Title = "Title", Username = "author",
Artist = "Artist", Id = 100
Author = new User
{
Username = "author",
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/1079428/covers/cover.jpg?1595295586", Ranked = DateTimeOffset.Now
},
FavouriteCount = 100
}
}, },
new BeatmapSetInfo new APIBeatmapSet
{ {
Metadata = new BeatmapMetadata Title = "Very Long Title (TV size) [TATOE]",
Artist = "This artist has a really long name how is this possible",
Author = new User
{ {
Title = "Title 2", Username = "author",
Artist = "Artist 2", Id = 100
Author = new User
{
Username = "someone",
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/1079428/covers/cover.jpg?1595295586", Ranked = DateTimeOffset.Now
},
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,8 +50,11 @@ 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.
apiBeatmap.BeatmapSet = value; if (!(Beatmap is APIBeatmap apiBeatmap))
throw new InvalidOperationException("Beatmap set metadata arrived before beatmap metadata in response");
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);