1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 19:27:24 +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);
});
[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]
public Task TestSingleImportMatchingFilename() => runSkinTest(async osu =>
{
@ -190,11 +199,11 @@ namespace osu.Game.Tests.Skins.IO
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();
using var zip = ZipArchive.Create();
zip.AddEntry("skin.ini", generateSkinIni(name, author, makeUnique));
zip.AddEntry(iniFilename, generateSkinIni(name, author, makeUnique));
zip.SaveTo(zipStream);
return zipStream;
}

View File

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

View File

@ -56,95 +56,71 @@ namespace osu.Game.Tests.Visual.UserInterface
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]",
Artist = "This artist has a really long name how is this possible",
Author = new User
{
Username = "author",
Id = 100
}
Username = "author",
Id = 100
},
OnlineInfo = new APIBeatmapSet
Covers = new BeatmapSetOnlineCovers
{
Covers = new BeatmapSetOnlineCovers
{
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
},
Ranked = DateTimeOffset.Now
}
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
},
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]",
Artist = "This artist has a really long name how is this possible",
Author = new User
{
Username = "author",
Id = 100
}
Username = "author",
Id = 100
},
OnlineInfo = new APIBeatmapSet
Covers = new BeatmapSetOnlineCovers
{
Covers = new BeatmapSetOnlineCovers
{
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
},
Ranked = DateTimeOffset.MinValue
}
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
},
Ranked = DateTimeOffset.Now
}
};
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",
Artist = "Artist",
Author = new User
{
Username = "author",
Id = 100
}
Username = "author",
Id = 100
},
OnlineInfo = new APIBeatmapSet
Covers = new BeatmapSetOnlineCovers
{
Covers = new BeatmapSetOnlineCovers
{
Cover = "https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg?1595295586",
},
FavouriteCount = 100
}
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
},
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 = "Title 2",
Artist = "Artist 2",
Author = new User
{
Username = "someone",
Id = 100
}
Username = "author",
Id = 100
},
OnlineInfo = new APIBeatmapSet
Covers = new BeatmapSetOnlineCovers
{
Covers = new BeatmapSetOnlineCovers
{
Cover = "https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg?1595295586",
},
FavouriteCount = 10
}
Cover = "https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg?1595456608",
},
Ranked = DateTimeOffset.Now
}
};
}

View File

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

View File

@ -16,9 +16,9 @@ namespace osu.Game.Beatmaps
/// <summary>
/// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields.
/// </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)
{

View File

@ -34,9 +34,9 @@ namespace osu.Game.Beatmaps
/// <summary>
/// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields.
/// </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 titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode;

View File

@ -8,7 +8,7 @@ namespace osu.Game.Database
public interface IHasOnlineID<out T>
{
/// <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>
/// <remarks>
/// 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>
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}";
}
}

View File

@ -26,13 +26,11 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty(@"user")]
public User User { get; set; }
public bool HasReplay { get; set; }
[JsonProperty(@"id")]
public long OnlineID { get; set; }
[JsonProperty(@"replay")]
public bool Replay { get; set; }
public bool HasReplay { get; set; }
[JsonProperty(@"created_at")]
public DateTimeOffset Date { get; set; }
@ -52,8 +50,11 @@ namespace osu.Game.Online.API.Requests.Responses
set
{
// in the deserialisation case we need to ferry this data across.
if (Beatmap is APIBeatmap apiBeatmap)
apiBeatmap.BeatmapSet = value;
// 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;
}
}
@ -91,13 +92,14 @@ namespace osu.Game.Online.API.Requests.Responses
{
TotalScore = TotalScore,
MaxCombo = MaxCombo,
BeatmapInfo = Beatmap.ToBeatmapInfo(rulesets),
User = User,
Accuracy = Accuracy,
OnlineScoreID = OnlineID,
Date = Date,
PP = PP,
RulesetID = OnlineRulesetID,
Hash = Replay ? "online" : string.Empty, // todo: temporary?
Hash = HasReplay ? "online" : string.Empty, // todo: temporary?
Rank = Rank,
Ruleset = ruleset,
Mods = mods,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,19 +3,19 @@
using System;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Dashboard.Home
{
public class DashboardNewBeatmapPanel : DashboardBeatmapPanel
{
public DashboardNewBeatmapPanel(BeatmapSetInfo setInfo)
: base(setInfo)
public DashboardNewBeatmapPanel(APIBeatmapSet beatmapSet)
: 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
};

View File

@ -4,17 +4,17 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osuTK;
namespace osu.Game.Overlays.Dashboard.Home
{
public class DashboardPopularBeatmapPanel : DashboardBeatmapPanel
{
public DashboardPopularBeatmapPanel(BeatmapSetInfo setInfo)
: base(setInfo)
public DashboardPopularBeatmapPanel(APIBeatmapSet beatmapSet)
: base(beatmapSet)
{
}
@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Dashboard.Home
new OsuSpriteText
{
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.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osuTK;
namespace osu.Game.Overlays.Dashboard.Home
{
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]
@ -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 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.
using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Dashboard.Home
{
public class DrawableNewBeatmapList : DrawableBeatmapList
{
public DrawableNewBeatmapList(List<BeatmapSetInfo> beatmaps)
: base(beatmaps)
public DrawableNewBeatmapList(List<APIBeatmapSet> beatmapSets)
: 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";
}

View File

@ -2,18 +2,18 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.Dashboard.Home
{
public class DrawablePopularBeatmapList : DrawableBeatmapList
{
public DrawablePopularBeatmapList(List<BeatmapSetInfo> beatmaps)
: base(beatmaps)
public DrawablePopularBeatmapList(List<APIBeatmapSet> beatmapSets)
: 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";
}

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 RendererSettings(),
new VideoSettings(),
new ScreenshotSettings(),
};
}

View File

@ -29,7 +29,7 @@ namespace osu.Game.Scoring
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`,
// 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);
}
#region Implementation of IHasOnlineID
public long OnlineID => OnlineScoreID ?? -1;
#endregion
#region Implementation of IScoreInfo
IBeatmapInfo IScoreInfo.Beatmap => BeatmapInfo;
IRulesetInfo IScoreInfo.Ruleset => Ruleset;
bool IScoreInfo.HasReplay => Files.Any();
#endregion
}
}

View File

@ -248,10 +248,7 @@ namespace osu.Game.Screens.OnlinePlay
protected virtual IEnumerable<Drawable> CreateButtons() =>
new Drawable[]
{
new PlaylistDownloadButton(Item)
{
Size = new Vector2(50, 30)
},
new PlaylistDownloadButton(Item),
new PlaylistRemoveButton
{
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.
public override bool IsPresent => true;
private const float width = 50;
public PlaylistDownloadButton(PlaylistItem playlistItem)
: base(playlistItem.Beatmap.Value.BeatmapSet)
{
this.playlistItem = playlistItem;
Size = new Vector2(width, 30);
Alpha = 0;
}
@ -316,12 +317,16 @@ namespace osu.Game.Screens.OnlinePlay
if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.Beatmap.Value.MD5Hash) == null)
State.Value = DownloadState.NotDownloaded;
else
this.FadeTo(0, 500);
{
this.FadeTo(0, 500)
.ResizeWidthTo(0, 500, Easing.OutQuint);
}
break;
default:
this.FadeTo(1, 500);
this.ResizeWidthTo(width, 500, Easing.OutQuint)
.FadeTo(1, 500);
break;
}
}

View File

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

View File

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

View File

@ -93,7 +93,7 @@ namespace osu.Game.Skinning
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))
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>
/// 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);
}
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;
@ -164,7 +164,7 @@ namespace osu.Game.Skinning
// `Skin` will parse the skin.ini and populate `Skin.Configuration` during construction above.
string skinIniSourcedName = instance.Configuration.SkinInfo.Name;
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;
@ -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 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)
item.Name = $"{item.Name} [{archiveName}]";
item.Name = @$"{item.Name} [{archiveName}]";
}
// By this point, the metadata in SkinInfo will be correct.
@ -191,10 +191,10 @@ namespace osu.Game.Skinning
private void updateSkinIniMetadata(SkinInfo item)
{
string nameLine = $"Name: {item.Name}";
string authorLine = $"Author: {item.Creator}";
string nameLine = @$"Name: {item.Name}";
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)
{
@ -210,12 +210,12 @@ namespace osu.Game.Skinning
while ((line = sr.ReadLine()) != null)
{
if (line.StartsWith("Name:", StringComparison.Ordinal))
if (line.StartsWith(@"Name:", StringComparison.Ordinal))
{
outputLines.Add(nameLine);
addedName = true;
}
else if (line.StartsWith("Author:", StringComparison.Ordinal))
else if (line.StartsWith(@"Author:", StringComparison.Ordinal))
{
outputLines.Add(authorLine);
addedAuthor = true;
@ -229,7 +229,7 @@ namespace osu.Game.Skinning
{
outputLines.AddRange(new[]
{
"[General]",
@"[General]",
nameLine,
authorLine,
});
@ -252,13 +252,13 @@ namespace osu.Game.Skinning
{
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
{
sw.WriteLine("[General]");
sw.WriteLine(@"[General]");
sw.WriteLine(nameLine);
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.
CurrentSkinInfo.Value = Import(new SkinInfo
{
Name = skin.SkinInfo.Name + " (modified)",
Name = skin.SkinInfo.Name + @" (modified)",
Creator = skin.SkinInfo.Creator,
InstantiationInfo = skin.SkinInfo.InstantiationInfo,
}).Result.Value;
@ -312,7 +312,7 @@ namespace osu.Game.Skinning
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);