Merge branch 'master' into fix-skin-layout-editor-crash

This commit is contained in:
Dean Herbert
2021-10-21 20:33:47 +09:00
committed by GitHub
46 changed files with 499 additions and 361 deletions

View File

@ -3,6 +3,7 @@
using NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.BeatmapSet;
namespace osu.Game.Tests.Visual.Online
@ -22,7 +23,7 @@ namespace osu.Game.Tests.Visual.Online
{
AddStep("set undownloadable beatmapset with link", () => container.BeatmapSet = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Availability = new BeatmapSetOnlineAvailability
{
@ -40,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online
{
AddStep("set undownloadable beatmapset without link", () => container.BeatmapSet = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Availability = new BeatmapSetOnlineAvailability
{
@ -57,7 +58,7 @@ namespace osu.Game.Tests.Visual.Online
{
AddStep("set parts-removed beatmapset with link", () => container.BeatmapSet = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Availability = new BeatmapSetOnlineAvailability
{
@ -75,7 +76,7 @@ namespace osu.Game.Tests.Visual.Online
{
AddStep("set normal beatmapset", () => container.BeatmapSet = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Availability = new BeatmapSetOnlineAvailability
{

View File

@ -11,6 +11,7 @@ using osu.Game.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Tests.Visual.Online
{
@ -63,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online
Id = 3,
},
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Preview = @"https://b.ppy.sh/preview/12345.mp3",
PlayCount = 123,
@ -134,7 +135,7 @@ namespace osu.Game.Tests.Visual.Online
Id = 3,
},
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Availability = new BeatmapSetOnlineAvailability
{
@ -224,7 +225,7 @@ namespace osu.Game.Tests.Visual.Online
Id = 3,
}
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers(),
},
@ -309,7 +310,7 @@ namespace osu.Game.Tests.Visual.Online
Id = 3,
},
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Preview = @"https://b.ppy.sh/preview/123.mp3",
HasVideo = true,

View File

@ -8,6 +8,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapSet;
using osu.Game.Screens.Select.Details;
@ -57,7 +58,7 @@ namespace osu.Game.Tests.Visual.Online
},
}
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Status = BeatmapSetOnlineStatus.Ranked
}

View File

@ -7,6 +7,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Online;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Rulesets.Osu;
using osu.Game.Tests.Resources;
@ -74,7 +75,7 @@ namespace osu.Game.Tests.Visual.Online
{
ID = 1,
OnlineBeatmapSetID = 241526,
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Availability = new BeatmapSetOnlineAvailability
{

View File

@ -7,6 +7,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.BeatmapListing.Panels;
using osu.Game.Rulesets;
using osu.Game.Users;
@ -31,7 +32,7 @@ namespace osu.Game.Tests.Visual.Online
Id = 3,
},
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Availability = new BeatmapSetOnlineAvailability
{
@ -86,7 +87,7 @@ namespace osu.Game.Tests.Visual.Online
Id = 3,
}
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
HasVideo = true,
HasStoryboard = true,

View File

@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapListing;
using osuTK;
@ -111,7 +112,7 @@ namespace osu.Game.Tests.Visual.UserInterface
private static readonly BeatmapSetInfo beatmap_set = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers
{
@ -122,7 +123,7 @@ namespace osu.Game.Tests.Visual.UserInterface
private static readonly BeatmapSetInfo no_cover_beatmap_set = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers
{

View File

@ -11,6 +11,7 @@ using osu.Game.Users;
using System;
using osu.Framework.Graphics.Shapes;
using System.Collections.Generic;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Tests.Visual.UserInterface
{
@ -69,7 +70,7 @@ namespace osu.Game.Tests.Visual.UserInterface
Id = 100
}
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers
{
@ -90,7 +91,7 @@ namespace osu.Game.Tests.Visual.UserInterface
Id = 100
}
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers
{
@ -115,7 +116,7 @@ namespace osu.Game.Tests.Visual.UserInterface
Id = 100
}
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers
{
@ -136,7 +137,7 @@ namespace osu.Game.Tests.Visual.UserInterface
Id = 100
}
},
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers
{

View File

@ -1,80 +1,67 @@
// 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 System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.UserInterface
{
public class TestSceneOsuTextBox : OsuTestScene
public class TestSceneOsuTextBox : ThemeComparisonTestScene
{
private readonly OsuNumberBox numberBox;
private IEnumerable<OsuNumberBox> numberBoxes => this.ChildrenOfType<OsuNumberBox>();
public TestSceneOsuTextBox()
protected override Drawable CreateContent() => new FillFlowContainer
{
Child = new Container
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Padding = new MarginPadding(50f),
Spacing = new Vector2(0f, 50f),
Children = new[]
{
Masking = true,
CornerRadius = 10f,
AutoSizeAxes = Axes.Both,
Padding = new MarginPadding(15f),
Children = new Drawable[]
new OsuTextBox
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.DarkSlateGray,
Alpha = 0.75f,
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Padding = new MarginPadding(50f),
Spacing = new Vector2(0f, 50f),
Children = new[]
{
new OsuTextBox
{
Width = 500f,
PlaceholderText = "Normal textbox",
},
new OsuPasswordTextBox
{
Width = 500f,
PlaceholderText = "Password textbox",
},
numberBox = new OsuNumberBox
{
Width = 500f,
PlaceholderText = "Number textbox"
}
}
}
RelativeSizeAxes = Axes.X,
PlaceholderText = "Normal textbox",
},
new OsuPasswordTextBox
{
RelativeSizeAxes = Axes.X,
PlaceholderText = "Password textbox",
},
new OsuNumberBox
{
RelativeSizeAxes = Axes.X,
PlaceholderText = "Number textbox"
}
};
}
}
};
[Test]
public void TestNumberBox()
{
clearTextbox(numberBox);
AddStep("enter numbers", () => numberBox.Text = "987654321");
expectedValue(numberBox, "987654321");
AddStep("create themed content", () => CreateThemedContent(OverlayColourScheme.Red));
clearTextbox(numberBox);
AddStep("enter text + single number", () => numberBox.Text = "1 hello 2 world 3");
expectedValue(numberBox, "123");
clearTextboxes(numberBoxes);
AddStep("enter numbers", () => numberBoxes.ForEach(numberBox => numberBox.Text = "987654321"));
expectedValue(numberBoxes, "987654321");
clearTextbox(numberBox);
clearTextboxes(numberBoxes);
AddStep("enter text + single number", () => numberBoxes.ForEach(numberBox => numberBox.Text = "1 hello 2 world 3"));
expectedValue(numberBoxes, "123");
clearTextboxes(numberBoxes);
}
private void clearTextbox(OsuTextBox textBox) => AddStep("clear textbox", () => textBox.Text = null);
private void expectedValue(OsuTextBox textBox, string value) => AddAssert("expected textbox value", () => textBox.Text == value);
private void clearTextboxes(IEnumerable<OsuTextBox> textBoxes) => AddStep("clear textbox", () => textBoxes.ForEach(textBox => textBox.Text = null));
private void expectedValue(IEnumerable<OsuTextBox> textBoxes, string value) => AddAssert("expected textbox value", () => textBoxes.All(textbox => textbox.Text == value));
}
}

View File

@ -13,6 +13,7 @@ using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests.Responses;
using osuTK;
namespace osu.Game.Tests.Visual.UserInterface
@ -22,21 +23,21 @@ namespace osu.Game.Tests.Visual.UserInterface
[Test]
public void TestLocal([Values] BeatmapSetCoverType coverType)
{
AddStep("setup cover", () => Child = new UpdateableBeatmapSetCover(coverType)
AddStep("setup cover", () => Child = new UpdateableOnlineBeatmapSetCover(coverType)
{
BeatmapSet = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet,
RelativeSizeAxes = Axes.Both,
Masking = true,
});
AddUntilStep("wait for load", () => this.ChildrenOfType<BeatmapSetCover>().SingleOrDefault()?.IsLoaded ?? false);
AddUntilStep("wait for load", () => this.ChildrenOfType<OnlineBeatmapSetCover>().SingleOrDefault()?.IsLoaded ?? false);
}
[Test]
public void TestUnloadAndReload()
{
OsuScrollContainer scroll = null;
List<UpdateableBeatmapSetCover> covers = new List<UpdateableBeatmapSetCover>();
List<UpdateableOnlineBeatmapSetCover> covers = new List<UpdateableOnlineBeatmapSetCover>();
AddStep("setup covers", () =>
{
@ -65,7 +66,7 @@ namespace osu.Game.Tests.Visual.UserInterface
{
var coverType = coverTypes[i % coverTypes.Count];
var cover = new UpdateableBeatmapSetCover(coverType)
var cover = new UpdateableOnlineBeatmapSetCover(coverType)
{
BeatmapSet = setInfo,
Height = 100,
@ -84,7 +85,7 @@ namespace osu.Game.Tests.Visual.UserInterface
}
});
var loadedCovers = covers.Where(c => c.ChildrenOfType<BeatmapSetCover>().SingleOrDefault()?.IsLoaded ?? false);
var loadedCovers = covers.Where(c => c.ChildrenOfType<OnlineBeatmapSetCover>().SingleOrDefault()?.IsLoaded ?? false);
AddUntilStep("some loaded", () => loadedCovers.Any());
AddStep("scroll to end", () => scroll.ScrollToEnd());
@ -94,9 +95,9 @@ namespace osu.Game.Tests.Visual.UserInterface
[Test]
public void TestSetNullBeatmapWhileLoading()
{
TestUpdateableBeatmapSetCover updateableCover = null;
TestUpdateableOnlineBeatmapSetCover updateableCover = null;
AddStep("setup cover", () => Child = updateableCover = new TestUpdateableBeatmapSetCover
AddStep("setup cover", () => Child = updateableCover = new TestUpdateableOnlineBeatmapSetCover
{
BeatmapSet = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet,
RelativeSizeAxes = Axes.Both,
@ -111,10 +112,10 @@ namespace osu.Game.Tests.Visual.UserInterface
[Test]
public void TestCoverChangeOnNewBeatmap()
{
TestUpdateableBeatmapSetCover updateableCover = null;
BeatmapSetCover initialCover = null;
TestUpdateableOnlineBeatmapSetCover updateableCover = null;
OnlineBeatmapSetCover initialCover = null;
AddStep("setup cover", () => Child = updateableCover = new TestUpdateableBeatmapSetCover(0)
AddStep("setup cover", () => Child = updateableCover = new TestUpdateableOnlineBeatmapSetCover(0)
{
BeatmapSet = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg"),
RelativeSizeAxes = Axes.Both,
@ -122,38 +123,38 @@ namespace osu.Game.Tests.Visual.UserInterface
Alpha = 0.4f
});
AddUntilStep("cover loaded", () => updateableCover.ChildrenOfType<BeatmapSetCover>().Any());
AddStep("store initial cover", () => initialCover = updateableCover.ChildrenOfType<BeatmapSetCover>().Single());
AddUntilStep("cover loaded", () => updateableCover.ChildrenOfType<OnlineBeatmapSetCover>().Any());
AddStep("store initial cover", () => initialCover = updateableCover.ChildrenOfType<OnlineBeatmapSetCover>().Single());
AddUntilStep("wait for fade complete", () => initialCover.Alpha == 1);
AddStep("switch beatmap",
() => updateableCover.BeatmapSet = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg"));
AddUntilStep("new cover loaded", () => updateableCover.ChildrenOfType<BeatmapSetCover>().Except(new[] { initialCover }).Any());
AddUntilStep("new cover loaded", () => updateableCover.ChildrenOfType<OnlineBeatmapSetCover>().Except(new[] { initialCover }).Any());
}
private static BeatmapSetInfo createBeatmapWithCover(string coverUrl) => new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
OnlineInfo = new APIBeatmapSet
{
Covers = new BeatmapSetOnlineCovers { Cover = coverUrl }
}
};
private class TestUpdateableBeatmapSetCover : UpdateableBeatmapSetCover
private class TestUpdateableOnlineBeatmapSetCover : UpdateableOnlineBeatmapSetCover
{
private readonly int loadDelay;
public TestUpdateableBeatmapSetCover(int loadDelay = 10000)
public TestUpdateableOnlineBeatmapSetCover(int loadDelay = 10000)
{
this.loadDelay = loadDelay;
}
protected override Drawable CreateDrawable(BeatmapSetInfo model)
protected override Drawable CreateDrawable(IBeatmapSetOnlineInfo model)
{
if (model == null)
return null;
return new TestBeatmapSetCover(model, loadDelay)
return new TestOnlineBeatmapSetCover(model, loadDelay)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@ -163,11 +164,11 @@ namespace osu.Game.Tests.Visual.UserInterface
}
}
private class TestBeatmapSetCover : BeatmapSetCover
private class TestOnlineBeatmapSetCover : OnlineBeatmapSetCover
{
private readonly int loadDelay;
public TestBeatmapSetCover(BeatmapSetInfo set, int loadDelay)
public TestOnlineBeatmapSetCover(IBeatmapSetOnlineInfo set, int loadDelay)
: base(set)
{
this.loadDelay = loadDelay;

View File

@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.UserInterface
});
}
private void createThemedContent(OverlayColourScheme colourScheme)
protected void CreateThemedContent(OverlayColourScheme colourScheme)
{
var colourProvider = new OverlayColourProvider(colourScheme);
@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.UserInterface
public void TestAllColourSchemes()
{
foreach (var scheme in Enum.GetValues(typeof(OverlayColourScheme)).Cast<OverlayColourScheme>())
AddStep($"set {scheme} scheme", () => createThemedContent(scheme));
AddStep($"set {scheme} scheme", () => CreateThemedContent(scheme));
}
}
}

View File

@ -10,7 +10,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Textures;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics;
@ -21,7 +20,8 @@ namespace osu.Game.Tournament.Components
{
public class TournamentBeatmapPanel : CompositeDrawable
{
public readonly BeatmapInfo BeatmapInfo;
public readonly IBeatmapInfo BeatmapInfo;
private readonly string mod;
private const float horizontal_padding = 10;
@ -32,12 +32,13 @@ namespace osu.Game.Tournament.Components
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
private Box flash;
public TournamentBeatmapPanel(BeatmapInfo beatmapInfo, string mod = null)
public TournamentBeatmapPanel(IBeatmapInfo beatmapInfo, string mod = null)
{
if (beatmapInfo == null) throw new ArgumentNullException(nameof(beatmapInfo));
BeatmapInfo = beatmapInfo;
this.mod = mod;
Width = 400;
Height = HEIGHT;
}
@ -57,11 +58,11 @@ namespace osu.Game.Tournament.Components
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
},
new UpdateableBeatmapSetCover
new UpdateableOnlineBeatmapSetCover
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(0.5f),
BeatmapSet = BeatmapInfo.BeatmapSet,
BeatmapSet = BeatmapInfo.BeatmapSet as IBeatmapSetOnlineInfo,
},
new FillFlowContainer
{
@ -74,9 +75,7 @@ namespace osu.Game.Tournament.Components
{
new TournamentSpriteText
{
Text = new RomanisableString(
$"{BeatmapInfo.Metadata.ArtistUnicode ?? BeatmapInfo.Metadata.Artist} - {BeatmapInfo.Metadata.TitleUnicode ?? BeatmapInfo.Metadata.Title}",
$"{BeatmapInfo.Metadata.Artist} - {BeatmapInfo.Metadata.Title}"),
Text = BeatmapInfo.GetDisplayTitleRomanisable(false),
Font = OsuFont.Torus.With(weight: FontWeight.Bold),
},
new FillFlowContainer
@ -93,7 +92,7 @@ namespace osu.Game.Tournament.Components
},
new TournamentSpriteText
{
Text = BeatmapInfo.Metadata.AuthorString,
Text = BeatmapInfo.Metadata?.Author,
Padding = new MarginPadding { Right = 20 },
Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14)
},
@ -105,7 +104,7 @@ namespace osu.Game.Tournament.Components
},
new TournamentSpriteText
{
Text = BeatmapInfo.Version,
Text = BeatmapInfo.DifficultyName,
Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14)
},
}
@ -149,7 +148,7 @@ namespace osu.Game.Tournament.Components
private void updateState()
{
var found = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == BeatmapInfo.OnlineBeatmapID);
var found = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == BeatmapInfo.OnlineID);
bool doFlash = found != choice;
choice = found;

View File

@ -147,11 +147,11 @@ namespace osu.Game.Tournament.Screens.MapPool
if (map != null)
{
if (e.Button == MouseButton.Left && map.BeatmapInfo.OnlineBeatmapID != null)
addForBeatmap(map.BeatmapInfo.OnlineBeatmapID.Value);
if (e.Button == MouseButton.Left && map.BeatmapInfo.OnlineID > 0)
addForBeatmap(map.BeatmapInfo.OnlineID);
else
{
var existing = CurrentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == map.BeatmapInfo.OnlineBeatmapID);
var existing = CurrentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == map.BeatmapInfo.OnlineID);
if (existing != null)
{

View File

@ -16,12 +16,17 @@ 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)
public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapInfo beatmapInfo, bool includeDifficultyName = true)
{
var metadata = getClosestMetadata(beatmapInfo).GetDisplayTitleRomanisable();
var versionString = getVersionString(beatmapInfo);
return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim());
if (includeDifficultyName)
{
var versionString = getVersionString(beatmapInfo);
return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim());
}
return new RomanisableString($"{metadata.GetPreferred(true)}".Trim(), $"{metadata.GetPreferred(false)}".Trim());
}
public static string[] GetSearchableTerms(this IBeatmapInfo beatmapInfo) => new[]

View File

@ -83,9 +83,9 @@ namespace osu.Game.Beatmaps
if (res != null)
{
beatmapInfo.Status = res.Status;
beatmapInfo.BeatmapSet.Status = res.BeatmapSet.Status;
beatmapInfo.BeatmapSet.Status = res.BeatmapSet?.Status ?? BeatmapSetOnlineStatus.None;
beatmapInfo.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID;
beatmapInfo.OnlineBeatmapID = res.OnlineBeatmapID;
beatmapInfo.OnlineBeatmapID = res.OnlineID;
if (beatmapInfo.Metadata != null)
beatmapInfo.Metadata.AuthorID = res.AuthorID;
@ -93,7 +93,7 @@ namespace osu.Game.Beatmaps
if (beatmapInfo.BeatmapSet.Metadata != null)
beatmapInfo.BeatmapSet.Metadata.AuthorID = res.AuthorID;
logForModel(set, $"Online retrieval mapped {beatmapInfo} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.");
logForModel(set, $"Online retrieval mapped {beatmapInfo} to {res.OnlineBeatmapSetID} / {res.OnlineID}.");
}
}
catch (Exception e)

View File

@ -6,13 +6,15 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Beatmaps
{
[ExcludeFromDynamicCompile]
public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles<BeatmapSetFileInfo>, ISoftDelete, IEquatable<BeatmapSetInfo>, IBeatmapSetInfo
public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles<BeatmapSetFileInfo>, ISoftDelete, IEquatable<BeatmapSetInfo>, IBeatmapSetInfo, IBeatmapSetOnlineInfo
{
public int ID { get; set; }
@ -26,8 +28,6 @@ namespace osu.Game.Beatmaps
public DateTimeOffset DateAdded { get; set; }
public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None;
public BeatmapMetadata Metadata { get; set; }
public List<BeatmapInfo> Beatmaps { get; set; }
@ -36,7 +36,7 @@ namespace osu.Game.Beatmaps
public List<BeatmapSetFileInfo> Files { get; set; } = new List<BeatmapSetFileInfo>();
[NotMapped]
public BeatmapSetOnlineInfo OnlineInfo { get; set; }
public APIBeatmapSet OnlineInfo { get; set; }
[NotMapped]
public BeatmapSetMetrics Metrics { get; set; }
@ -102,5 +102,141 @@ namespace osu.Game.Beatmaps
IEnumerable<INamedFileUsage> IBeatmapSetInfo.Files => Files;
#endregion
#region Delegation for IBeatmapSetOnlineInfo
[NotMapped]
[JsonIgnore]
public DateTimeOffset Submitted
{
get => OnlineInfo.Submitted;
set => OnlineInfo.Submitted = value;
}
[NotMapped]
[JsonIgnore]
public DateTimeOffset? Ranked
{
get => OnlineInfo.Ranked;
set => OnlineInfo.Ranked = value;
}
[NotMapped]
[JsonIgnore]
public DateTimeOffset? LastUpdated
{
get => OnlineInfo.LastUpdated;
set => OnlineInfo.LastUpdated = value;
}
[NotMapped]
[JsonIgnore]
public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None;
[NotMapped]
[JsonIgnore]
public bool HasExplicitContent
{
get => OnlineInfo.HasExplicitContent;
set => OnlineInfo.HasExplicitContent = value;
}
[NotMapped]
[JsonIgnore]
public bool HasVideo
{
get => OnlineInfo.HasVideo;
set => OnlineInfo.HasVideo = value;
}
[NotMapped]
[JsonIgnore]
public bool HasStoryboard
{
get => OnlineInfo.HasStoryboard;
set => OnlineInfo.HasStoryboard = value;
}
[NotMapped]
[JsonIgnore]
public BeatmapSetOnlineCovers Covers
{
get => OnlineInfo.Covers;
set => OnlineInfo.Covers = value;
}
[NotMapped]
[JsonIgnore]
public string Preview
{
get => OnlineInfo.Preview;
set => OnlineInfo.Preview = value;
}
[NotMapped]
[JsonIgnore]
public double BPM
{
get => OnlineInfo.BPM;
set => OnlineInfo.BPM = value;
}
[NotMapped]
[JsonIgnore]
public int PlayCount
{
get => OnlineInfo.PlayCount;
set => OnlineInfo.PlayCount = value;
}
[NotMapped]
[JsonIgnore]
public int FavouriteCount
{
get => OnlineInfo.FavouriteCount;
set => OnlineInfo.FavouriteCount = value;
}
[NotMapped]
[JsonIgnore]
public bool HasFavourited
{
get => OnlineInfo.HasFavourited;
set => OnlineInfo.HasFavourited = value;
}
[NotMapped]
[JsonIgnore]
public BeatmapSetOnlineAvailability Availability
{
get => OnlineInfo.Availability;
set => OnlineInfo.Availability = value;
}
[NotMapped]
[JsonIgnore]
public BeatmapSetOnlineGenre Genre
{
get => OnlineInfo.Genre;
set => OnlineInfo.Genre = value;
}
[NotMapped]
[JsonIgnore]
public BeatmapSetOnlineLanguage Language
{
get => OnlineInfo.Language;
set => OnlineInfo.Language = value;
}
[NotMapped]
[JsonIgnore]
public int? TrackId
{
get => OnlineInfo.TrackId;
set => OnlineInfo.TrackId = value;
}
#endregion
}
}

View File

@ -0,0 +1,16 @@
// 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 Newtonsoft.Json;
namespace osu.Game.Beatmaps
{
public struct BeatmapSetOnlineAvailability
{
[JsonProperty(@"download_disabled")]
public bool DownloadDisabled { get; set; }
[JsonProperty(@"more_information")]
public string ExternalLink { get; set; }
}
}

View File

@ -0,0 +1,25 @@
// 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 Newtonsoft.Json;
namespace osu.Game.Beatmaps
{
public struct BeatmapSetOnlineCovers
{
public string CoverLowRes { get; set; }
[JsonProperty(@"cover@2x")]
public string Cover { get; set; }
public string CardLowRes { get; set; }
[JsonProperty(@"card@2x")]
public string Card { get; set; }
public string ListLowRes { get; set; }
[JsonProperty(@"list@2x")]
public string List { get; set; }
}
}

View File

@ -0,0 +1,11 @@
// 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.
namespace osu.Game.Beatmaps
{
public struct BeatmapSetOnlineGenre
{
public int Id { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,11 @@
// 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.
namespace osu.Game.Beatmaps
{
public struct BeatmapSetOnlineLanguage
{
public int Id { get; set; }
public string Name { get; set; }
}
}

View File

@ -9,12 +9,12 @@ using osu.Framework.Graphics.Textures;
namespace osu.Game.Beatmaps.Drawables
{
[LongRunningLoad]
public class BeatmapSetCover : Sprite
public class OnlineBeatmapSetCover : Sprite
{
private readonly BeatmapSetInfo set;
private readonly IBeatmapSetOnlineInfo set;
private readonly BeatmapSetCoverType type;
public BeatmapSetCover(BeatmapSetInfo set, BeatmapSetCoverType type = BeatmapSetCoverType.Cover)
public OnlineBeatmapSetCover(IBeatmapSetOnlineInfo set, BeatmapSetCoverType type = BeatmapSetCoverType.Cover)
{
if (set == null)
throw new ArgumentNullException(nameof(set));
@ -31,15 +31,15 @@ namespace osu.Game.Beatmaps.Drawables
switch (type)
{
case BeatmapSetCoverType.Cover:
resource = set.OnlineInfo.Covers.Cover;
resource = set.Covers.Cover;
break;
case BeatmapSetCoverType.Card:
resource = set.OnlineInfo.Covers.Card;
resource = set.Covers.Card;
break;
case BeatmapSetCoverType.List:
resource = set.OnlineInfo.Covers.List;
resource = set.Covers.List;
break;
}

View File

@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps.Drawables
{
// prefer online cover where available.
if (model?.BeatmapSet?.OnlineInfo != null)
return new BeatmapSetCover(model.BeatmapSet, beatmapSetCoverType);
return new OnlineBeatmapSetCover(model.BeatmapSet, beatmapSetCoverType);
return model?.ID > 0
? new BeatmapBackgroundSprite(beatmaps.GetWorkingBeatmap(model))

View File

@ -9,11 +9,11 @@ using osu.Game.Graphics;
namespace osu.Game.Beatmaps.Drawables
{
public class UpdateableBeatmapSetCover : ModelBackedDrawable<BeatmapSetInfo>
public class UpdateableOnlineBeatmapSetCover : ModelBackedDrawable<IBeatmapSetOnlineInfo>
{
private readonly BeatmapSetCoverType coverType;
public BeatmapSetInfo BeatmapSet
public IBeatmapSetOnlineInfo BeatmapSet
{
get => Model;
set => Model = value;
@ -25,7 +25,7 @@ namespace osu.Game.Beatmaps.Drawables
set => base.Masking = value;
}
public UpdateableBeatmapSetCover(BeatmapSetCoverType coverType = BeatmapSetCoverType.Cover)
public UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType coverType = BeatmapSetCoverType.Cover)
{
this.coverType = coverType;
@ -43,12 +43,12 @@ namespace osu.Game.Beatmaps.Drawables
protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func<Drawable> createContentFunc, double timeBeforeLoad)
=> new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad);
protected override Drawable CreateDrawable(BeatmapSetInfo model)
protected override Drawable CreateDrawable(IBeatmapSetOnlineInfo model)
{
if (model == null)
return null;
return new BeatmapSetCover(model, coverType)
return new OnlineBeatmapSetCover(model, coverType)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,

View File

@ -1,139 +1,101 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// 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 System;
using Newtonsoft.Json;
#nullable enable
namespace osu.Game.Beatmaps
{
/// <summary>
/// Beatmap set info retrieved for previewing locally without having the set downloaded.
/// </summary>
public class BeatmapSetOnlineInfo
public interface IBeatmapSetOnlineInfo
{
/// <summary>
/// The date this beatmap set was submitted to the online listing.
/// </summary>
public DateTimeOffset Submitted { get; set; }
DateTimeOffset Submitted { get; set; }
/// <summary>
/// The date this beatmap set was ranked.
/// </summary>
public DateTimeOffset? Ranked { get; set; }
DateTimeOffset? Ranked { get; set; }
/// <summary>
/// The date this beatmap set was last updated.
/// </summary>
public DateTimeOffset? LastUpdated { get; set; }
DateTimeOffset? LastUpdated { get; set; }
/// <summary>
/// The status of this beatmap set.
/// </summary>
public BeatmapSetOnlineStatus Status { get; set; }
BeatmapSetOnlineStatus Status { get; set; }
/// <summary>
/// Whether or not this beatmap set has explicit content.
/// </summary>
public bool HasExplicitContent { get; set; }
bool HasExplicitContent { get; set; }
/// <summary>
/// Whether or not this beatmap set has a background video.
/// </summary>
public bool HasVideo { get; set; }
bool HasVideo { get; set; }
/// <summary>
/// Whether or not this beatmap set has a storyboard.
/// </summary>
public bool HasStoryboard { get; set; }
bool HasStoryboard { get; set; }
/// <summary>
/// The different sizes of cover art for this beatmap set.
/// </summary>
public BeatmapSetOnlineCovers Covers { get; set; }
BeatmapSetOnlineCovers Covers { get; set; }
/// <summary>
/// A small sample clip of this beatmap set's song.
/// </summary>
public string Preview { get; set; }
string Preview { get; set; }
/// <summary>
/// The beats per minute of this beatmap set's song.
/// </summary>
public double BPM { get; set; }
double BPM { get; set; }
/// <summary>
/// The amount of plays this beatmap set has.
/// </summary>
public int PlayCount { get; set; }
int PlayCount { get; set; }
/// <summary>
/// The amount of people who have favourited this beatmap set.
/// </summary>
public int FavouriteCount { get; set; }
int FavouriteCount { get; set; }
/// <summary>
/// Whether this beatmap set has been favourited by the current user.
/// </summary>
public bool HasFavourited { get; set; }
bool HasFavourited { get; set; }
/// <summary>
/// The availability of this beatmap set.
/// </summary>
public BeatmapSetOnlineAvailability Availability { get; set; }
BeatmapSetOnlineAvailability Availability { get; set; }
/// <summary>
/// The song genre of this beatmap set.
/// </summary>
public BeatmapSetOnlineGenre Genre { get; set; }
BeatmapSetOnlineGenre Genre { get; set; }
/// <summary>
/// The song language of this beatmap set.
/// </summary>
public BeatmapSetOnlineLanguage Language { get; set; }
BeatmapSetOnlineLanguage Language { get; set; }
/// <summary>
/// The track ID of this beatmap set.
/// Non-null only if the track is linked to a featured artist track entry.
/// </summary>
public int? TrackId { get; set; }
}
public class BeatmapSetOnlineGenre
{
public int Id { get; set; }
public string Name { get; set; }
}
public class BeatmapSetOnlineLanguage
{
public int Id { get; set; }
public string Name { get; set; }
}
public class BeatmapSetOnlineCovers
{
public string CoverLowRes { get; set; }
[JsonProperty(@"cover@2x")]
public string Cover { get; set; }
public string CardLowRes { get; set; }
[JsonProperty(@"card@2x")]
public string Card { get; set; }
public string ListLowRes { get; set; }
[JsonProperty(@"list@2x")]
public string List { get; set; }
}
public class BeatmapSetOnlineAvailability
{
[JsonProperty(@"download_disabled")]
public bool DownloadDisabled { get; set; }
[JsonProperty(@"more_information")]
public string ExternalLink { get; set; }
int? TrackId { get; set; }
}
}

View File

@ -1,6 +1,8 @@
// 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.
#nullable enable
using osuTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Input.Events;
@ -8,6 +10,7 @@ using osu.Framework.Platform;
using osu.Game.Input.Bindings;
using osuTK.Input;
using osu.Framework.Input.Bindings;
using osu.Game.Overlays;
namespace osu.Game.Graphics.UserInterface
{
@ -42,13 +45,13 @@ namespace osu.Game.Graphics.UserInterface
}
[Resolved]
private GameHost host { get; set; }
private GameHost? host { get; set; }
[BackgroundDependencyLoader]
private void load()
[BackgroundDependencyLoader(true)]
private void load(OverlayColourProvider? colourProvider)
{
BackgroundUnfocused = new Color4(10, 10, 10, 255);
BackgroundFocused = new Color4(10, 10, 10, 255);
BackgroundUnfocused = colourProvider?.Background5 ?? new Color4(10, 10, 10, 255);
BackgroundFocused = colourProvider?.Background5 ?? new Color4(10, 10, 10, 255);
}
// We may not be focused yet, but we need to handle keyboard input to be able to request focus

View File

@ -1,6 +1,8 @@
// 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.
#nullable enable
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Audio;
@ -17,18 +19,13 @@ using osu.Framework.Input.Events;
using osu.Framework.Utils;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics.Containers;
using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Graphics.UserInterface
{
public class OsuTextBox : BasicTextBox
{
private readonly Sample[] textAddedSamples = new Sample[4];
private Sample capsTextAddedSample;
private Sample textRemovedSample;
private Sample textCommittedSample;
private Sample caretMovedSample;
/// <summary>
/// Whether to allow playing a different samples based on the type of character.
/// If set to false, the same sample will be used for all characters.
@ -42,10 +39,17 @@ namespace osu.Game.Graphics.UserInterface
protected override SpriteText CreatePlaceholder() => new OsuSpriteText
{
Font = OsuFont.GetFont(italics: true),
Colour = new Color4(180, 180, 180, 255),
Margin = new MarginPadding { Left = 2 },
};
private readonly Sample?[] textAddedSamples = new Sample[4];
private Sample? capsTextAddedSample;
private Sample? textRemovedSample;
private Sample? textCommittedSample;
private Sample? caretMovedSample;
private OsuCaret? caret;
public OsuTextBox()
{
Height = 40;
@ -56,12 +60,18 @@ namespace osu.Game.Graphics.UserInterface
Current.DisabledChanged += disabled => { Alpha = disabled ? 0.3f : 1; };
}
[BackgroundDependencyLoader]
private void load(OsuColour colour, AudioManager audio)
[BackgroundDependencyLoader(true)]
private void load(OverlayColourProvider? colourProvider, OsuColour colour, AudioManager audio)
{
BackgroundUnfocused = Color4.Black.Opacity(0.5f);
BackgroundFocused = OsuColour.Gray(0.3f).Opacity(0.8f);
BackgroundCommit = BorderColour = colour.Yellow;
BackgroundUnfocused = colourProvider?.Background5 ?? Color4.Black.Opacity(0.5f);
BackgroundFocused = colourProvider?.Background4 ?? OsuColour.Gray(0.3f).Opacity(0.8f);
BackgroundCommit = BorderColour = colourProvider?.Highlight1 ?? colour.Yellow;
selectionColour = colourProvider?.Background1 ?? new Color4(249, 90, 255, 255);
if (caret != null)
caret.SelectionColour = selectionColour;
Placeholder.Colour = colourProvider?.Foreground1 ?? new Color4(180, 180, 180, 255);
for (int i = 0; i < textAddedSamples.Length; i++)
textAddedSamples[i] = audio.Samples.Get($@"Keyboard/key-press-{1 + i}");
@ -72,7 +82,9 @@ namespace osu.Game.Graphics.UserInterface
caretMovedSample = audio.Samples.Get(@"Keyboard/key-movement");
}
protected override Color4 SelectionColour => new Color4(249, 90, 255, 255);
private Color4 selectionColour;
protected override Color4 SelectionColour => selectionColour;
protected override void OnUserTextAdded(string added)
{
@ -124,7 +136,7 @@ namespace osu.Game.Graphics.UserInterface
Child = new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) },
};
protected override Caret CreateCaret() => new OsuCaret
protected override Caret CreateCaret() => caret = new OsuCaret
{
CaretWidth = CaretWidth,
SelectionColour = SelectionColour,

View File

@ -6,12 +6,14 @@ using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
#nullable enable
namespace osu.Game.Online.API.Requests.Responses
{
public class APIBeatmap : BeatmapMetadata
public class APIBeatmap : BeatmapMetadata, IBeatmapInfo
{
[JsonProperty(@"id")]
public int OnlineBeatmapID { get; set; }
public int OnlineID { get; set; }
[JsonProperty(@"beatmapset_id")]
public int OnlineBeatmapSetID { get; set; }
@ -19,8 +21,11 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty(@"status")]
public BeatmapSetOnlineStatus Status { get; set; }
[JsonProperty("checksum")]
public string Checksum { get; set; } = string.Empty;
[JsonProperty(@"beatmapset")]
public APIBeatmapSet BeatmapSet { get; set; }
public APIBeatmapSet? BeatmapSet { get; set; }
[JsonProperty(@"playcount")]
private int playCount { get; set; }
@ -29,10 +34,10 @@ namespace osu.Game.Online.API.Requests.Responses
private int passCount { get; set; }
[JsonProperty(@"mode_int")]
private int ruleset { get; set; }
public int RulesetID { get; set; }
[JsonProperty(@"difficulty_rating")]
private double starDifficulty { get; set; }
public double StarRating { get; set; }
[JsonProperty(@"drain")]
private float drainRate { get; set; }
@ -47,7 +52,7 @@ namespace osu.Game.Online.API.Requests.Responses
private float overallDifficulty { get; set; }
[JsonProperty(@"total_length")]
private double length { get; set; }
public double Length { get; set; }
[JsonProperty(@"count_circles")]
private int circleCount { get; set; }
@ -56,10 +61,10 @@ namespace osu.Game.Online.API.Requests.Responses
private int sliderCount { get; set; }
[JsonProperty(@"version")]
private string version { get; set; }
public string DifficultyName { get; set; } = string.Empty;
[JsonProperty(@"failtimes")]
private BeatmapMetrics metrics { get; set; }
private BeatmapMetrics? metrics { get; set; }
[JsonProperty(@"max_combo")]
private int? maxCombo { get; set; }
@ -71,13 +76,14 @@ namespace osu.Game.Online.API.Requests.Responses
return new BeatmapInfo
{
Metadata = set?.Metadata ?? this,
Ruleset = rulesets.GetRuleset(ruleset),
StarDifficulty = starDifficulty,
OnlineBeatmapID = OnlineBeatmapID,
Version = version,
Ruleset = rulesets.GetRuleset(RulesetID),
StarDifficulty = StarRating,
OnlineBeatmapID = OnlineID,
Version = DifficultyName,
// this is actually an incorrect mapping (Length is calculated as drain length in lazer's import process, see BeatmapManager.calculateLength).
Length = TimeSpan.FromSeconds(length).TotalMilliseconds,
Length = TimeSpan.FromSeconds(Length).TotalMilliseconds,
Status = Status,
MD5Hash = Checksum,
BeatmapSet = set,
Metrics = metrics,
MaxCombo = maxCombo,
@ -97,5 +103,28 @@ namespace osu.Game.Online.API.Requests.Responses
},
};
}
#region Implementation of IBeatmapInfo
public IBeatmapMetadataInfo Metadata => this;
public IBeatmapDifficultyInfo Difficulty => new BeatmapDifficulty
{
DrainRate = drainRate,
CircleSize = circleSize,
ApproachRate = approachRate,
OverallDifficulty = overallDifficulty,
};
IBeatmapSetInfo? IBeatmapInfo.BeatmapSet => BeatmapSet;
public string MD5Hash => Checksum;
public IRulesetInfo Ruleset => new RulesetInfo { ID = RulesetID };
public double BPM => throw new NotImplementedException();
public string Hash => throw new NotImplementedException();
#endregion
}
}

View File

@ -6,65 +6,62 @@ using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Rulesets;
#nullable enable
namespace osu.Game.Online.API.Requests.Responses
{
public class APIBeatmapSet : BeatmapMetadata // todo: this is a bit wrong...
public class APIBeatmapSet : BeatmapMetadata, IBeatmapSetOnlineInfo, IBeatmapSetInfo
{
[JsonProperty(@"covers")]
private BeatmapSetOnlineCovers covers { get; set; }
private int? onlineBeatmapSetID;
public BeatmapSetOnlineCovers Covers { get; set; }
[JsonProperty(@"id")]
public int? OnlineBeatmapSetID
{
get => onlineBeatmapSetID;
set => onlineBeatmapSetID = value > 0 ? value : null;
}
public int OnlineID { get; set; }
[JsonProperty(@"status")]
public BeatmapSetOnlineStatus Status { get; set; }
[JsonProperty(@"preview_url")]
private string preview { get; set; }
public string Preview { get; set; } = string.Empty;
[JsonProperty(@"has_favourited")]
private bool hasFavourited { get; set; }
public bool HasFavourited { get; set; }
[JsonProperty(@"play_count")]
private int playCount { get; set; }
public int PlayCount { get; set; }
[JsonProperty(@"favourite_count")]
private int favouriteCount { get; set; }
public int FavouriteCount { get; set; }
[JsonProperty(@"bpm")]
private double bpm { get; set; }
public double BPM { get; set; }
[JsonProperty(@"nsfw")]
private bool hasExplicitContent { get; set; }
public bool HasExplicitContent { get; set; }
[JsonProperty(@"video")]
private bool hasVideo { get; set; }
public bool HasVideo { get; set; }
[JsonProperty(@"storyboard")]
private bool hasStoryboard { get; set; }
public bool HasStoryboard { get; set; }
[JsonProperty(@"submitted_date")]
private DateTimeOffset submitted { get; set; }
public DateTimeOffset Submitted { get; set; }
[JsonProperty(@"ranked_date")]
private DateTimeOffset? ranked { get; set; }
public DateTimeOffset? Ranked { get; set; }
[JsonProperty(@"last_updated")]
private DateTimeOffset lastUpdated { get; set; }
public DateTimeOffset? LastUpdated { get; set; }
[JsonProperty(@"ratings")]
private int[] ratings { get; set; }
private int[] ratings { get; set; } = Array.Empty<int>();
[JsonProperty(@"track_id")]
private int? trackId { get; set; }
public int? TrackId { get; set; }
[JsonProperty(@"user_id")]
private int creatorId
@ -73,48 +70,29 @@ namespace osu.Game.Online.API.Requests.Responses
}
[JsonProperty(@"availability")]
private BeatmapSetOnlineAvailability availability { get; set; }
public BeatmapSetOnlineAvailability Availability { get; set; }
[JsonProperty(@"genre")]
private BeatmapSetOnlineGenre genre { get; set; }
public BeatmapSetOnlineGenre Genre { get; set; }
[JsonProperty(@"language")]
private BeatmapSetOnlineLanguage language { get; set; }
public BeatmapSetOnlineLanguage Language { get; set; }
[JsonProperty(@"beatmaps")]
private IEnumerable<APIBeatmap> beatmaps { get; set; }
private IEnumerable<APIBeatmap> beatmaps { get; set; } = Array.Empty<APIBeatmap>();
public virtual BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets)
{
var beatmapSet = new BeatmapSetInfo
{
OnlineBeatmapSetID = OnlineBeatmapSetID,
OnlineBeatmapSetID = OnlineID,
Metadata = this,
Status = Status,
Metrics = ratings == null ? null : new BeatmapSetMetrics { Ratings = ratings },
OnlineInfo = new BeatmapSetOnlineInfo
{
Covers = covers,
Preview = preview,
PlayCount = playCount,
FavouriteCount = favouriteCount,
BPM = bpm,
Status = Status,
HasExplicitContent = hasExplicitContent,
HasVideo = hasVideo,
HasStoryboard = hasStoryboard,
Submitted = submitted,
Ranked = ranked,
LastUpdated = lastUpdated,
Availability = availability,
HasFavourited = hasFavourited,
Genre = genre,
Language = language,
TrackId = trackId
},
Metrics = new BeatmapSetMetrics { Ratings = ratings },
OnlineInfo = this
};
beatmapSet.Beatmaps = beatmaps?.Select(b =>
beatmapSet.Beatmaps = beatmaps.Select(b =>
{
var beatmap = b.ToBeatmapInfo(rulesets);
beatmap.BeatmapSet = beatmapSet;
@ -124,5 +102,19 @@ namespace osu.Game.Online.API.Requests.Responses
return beatmapSet;
}
#region Implementation of IBeatmapSetInfo
IEnumerable<IBeatmapInfo> IBeatmapSetInfo.Beatmaps => beatmaps;
IBeatmapMetadataInfo IBeatmapSetInfo.Metadata => this;
DateTimeOffset IBeatmapSetInfo.DateAdded => throw new NotImplementedException();
IEnumerable<INamedFileUsage> IBeatmapSetInfo.Files => throw new NotImplementedException();
double IBeatmapSetInfo.MaxStarDifficulty => throw new NotImplementedException();
double IBeatmapSetInfo.MaxLength => throw new NotImplementedException();
double IBeatmapSetInfo.MaxBPM => throw new NotImplementedException();
#endregion
}
}

View File

@ -1,23 +0,0 @@
// 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 Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
namespace osu.Game.Online.Rooms
{
public class APIPlaylistBeatmap : APIBeatmap
{
[JsonProperty("checksum")]
public string Checksum { get; set; }
public override BeatmapInfo ToBeatmapInfo(RulesetStore rulesets)
{
var b = base.ToBeatmapInfo(rulesets);
b.MD5Hash = Checksum;
return b;
}
}
}

View File

@ -59,7 +59,7 @@ namespace osu.Game.Online.Rooms
protected override bool VerifyDatabasedModel(BeatmapSetInfo databasedSet)
{
int? beatmapId = SelectedItem.Value?.Beatmap.Value.OnlineBeatmapID;
int beatmapId = SelectedItem.Value?.Beatmap.Value.OnlineID ?? -1;
string checksum = SelectedItem.Value?.Beatmap.Value.MD5Hash;
var matchingBeatmap = databasedSet.Beatmaps.FirstOrDefault(b => b.OnlineBeatmapID == beatmapId && b.MD5Hash == checksum);
@ -75,10 +75,10 @@ namespace osu.Game.Online.Rooms
protected override bool IsModelAvailableLocally()
{
int? beatmapId = SelectedItem.Value.Beatmap.Value.OnlineBeatmapID;
int onlineId = SelectedItem.Value.Beatmap.Value.OnlineID;
string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash;
var beatmap = Manager.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId && b.MD5Hash == checksum);
var beatmap = Manager.QueryBeatmap(b => b.OnlineBeatmapID == onlineId && b.MD5Hash == checksum);
return beatmap?.BeatmapSet.DeletePending == false;
}

View File

@ -7,6 +7,7 @@ using Newtonsoft.Json;
using osu.Framework.Bindables;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
@ -42,7 +43,7 @@ namespace osu.Game.Online.Rooms
public readonly BindableList<Mod> RequiredMods = new BindableList<Mod>();
[JsonProperty("beatmap")]
private APIPlaylistBeatmap apiBeatmap { get; set; }
private APIBeatmap apiBeatmap { get; set; }
private APIMod[] allowedModsBacking;

View File

@ -76,7 +76,7 @@ namespace osu.Game.Overlays.BeatmapListing
private readonly BeatmapSearchFilterRow<SearchExplicit> explicitContentFilter;
private readonly Box background;
private readonly UpdateableBeatmapSetCover beatmapCover;
private readonly UpdateableOnlineBeatmapSetCover beatmapCover;
public BeatmapListingSearchControl()
{
@ -196,7 +196,7 @@ namespace osu.Game.Overlays.BeatmapListing
}
}
private class TopSearchBeatmapSetCover : UpdateableBeatmapSetCover
private class TopSearchBeatmapSetCover : UpdateableOnlineBeatmapSetCover
{
protected override bool TransformImmediately => true;
}

View File

@ -160,7 +160,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
return icons;
}
protected Drawable CreateBackground() => new UpdateableBeatmapSetCover
protected Drawable CreateBackground() => new UpdateableOnlineBeatmapSetCover
{
RelativeSizeAxes = Axes.Both,
BeatmapSet = SetInfo,

View File

@ -92,7 +92,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
break;
default:
if (BeatmapSet.Value?.OnlineInfo?.Availability?.DownloadDisabled ?? false)
if (BeatmapSet.Value?.OnlineInfo?.Availability.DownloadDisabled ?? false)
{
button.Enabled.Value = false;
button.TooltipText = "this beatmap is currently not available for download.";

View File

@ -16,8 +16,8 @@ namespace osu.Game.Overlays.BeatmapSet
{
private BeatmapSetInfo beatmapSet;
private bool downloadDisabled => BeatmapSet?.OnlineInfo.Availability?.DownloadDisabled ?? false;
private bool hasExternalLink => !string.IsNullOrEmpty(BeatmapSet?.OnlineInfo.Availability?.ExternalLink);
private bool downloadDisabled => BeatmapSet?.OnlineInfo.Availability.DownloadDisabled ?? false;
private bool hasExternalLink => !string.IsNullOrEmpty(BeatmapSet?.OnlineInfo.Availability.ExternalLink);
private readonly LinkFlowContainer textContainer;

View File

@ -32,7 +32,7 @@ namespace osu.Game.Overlays.BeatmapSet
public readonly Details Details;
public readonly BeatmapPicker Picker;
private readonly UpdateableBeatmapSetCover cover;
private readonly UpdateableOnlineBeatmapSetCover cover;
private readonly Box coverGradient;
private readonly OsuSpriteText title, artist;
private readonly AuthorInfo author;
@ -68,7 +68,7 @@ namespace osu.Game.Overlays.BeatmapSet
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
cover = new UpdateableBeatmapSetCover
cover = new UpdateableOnlineBeatmapSetCover
{
RelativeSizeAxes = Axes.Both,
Masking = true,
@ -266,7 +266,7 @@ namespace osu.Game.Overlays.BeatmapSet
{
if (BeatmapSet.Value == null) return;
if ((BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) && State.Value != DownloadState.LocallyAvailable)
if (BeatmapSet.Value.OnlineInfo.Availability.DownloadDisabled && State.Value != DownloadState.LocallyAvailable)
{
downloadButtonsContainer.Clear();
return;

View File

@ -117,8 +117,8 @@ namespace osu.Game.Overlays.BeatmapSet
{
source.Text = b.NewValue?.Metadata.Source ?? string.Empty;
tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty;
genre.Text = b.NewValue?.OnlineInfo?.Genre?.Name ?? string.Empty;
language.Text = b.NewValue?.OnlineInfo?.Language?.Name ?? string.Empty;
genre.Text = b.NewValue?.OnlineInfo?.Genre.Name ?? string.Empty;
language.Text = b.NewValue?.OnlineInfo?.Language.Name ?? string.Empty;
var setHasLeaderboard = b.NewValue?.OnlineInfo?.Status > 0;
successRate.Alpha = setHasLeaderboard ? 1 : 0;
notRankedPlaceholder.Alpha = setHasLeaderboard ? 0 : 1;

View File

@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Dashboard.Home
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 6,
Child = new UpdateableBeatmapSetCover
Child = new UpdateableOnlineBeatmapSetCover
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,

View File

@ -60,12 +60,12 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
protected override APIRequest<List<APIBeatmapSet>> CreateRequest() =>
new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
protected override Drawable CreateDrawableItem(APIBeatmapSet model) => !model.OnlineBeatmapSetID.HasValue
? null
: new GridBeatmapPanel(model.ToBeatmapSet(Rulesets))
protected override Drawable CreateDrawableItem(APIBeatmapSet model) => model.OnlineID > 0
? new GridBeatmapPanel(model.ToBeatmapSet(Rulesets))
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
};
}
: null;
}
}

View File

@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
{
AddRangeInternal(new Drawable[]
{
new UpdateableBeatmapSetCover(BeatmapSetCoverType.List)
new UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType.List)
{
RelativeSizeAxes = Axes.Y,
Width = cover_width,

View File

@ -86,7 +86,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
Text = new RomanisableString(beatmap.Value.Metadata.TitleUnicode, beatmap.Value.Metadata.Title),
Font = OsuFont.GetFont(size: TextSize),
}
}, LinkAction.OpenBeatmap, beatmap.Value.OnlineBeatmapID.ToString(), "Open beatmap");
}, LinkAction.OpenBeatmap, beatmap.Value.OnlineID.ToString(), "Open beatmap");
}
}
}

View File

@ -61,7 +61,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
{
var beatmap = playlistItem?.Beatmap.Value;
if (background?.BeatmapInfo?.BeatmapSet?.OnlineInfo?.Covers?.Cover == beatmap?.BeatmapSet?.OnlineInfo?.Covers?.Cover)
if (background?.BeatmapInfo?.BeatmapSet?.OnlineInfo?.Covers.Cover == beatmap?.BeatmapSet?.OnlineInfo?.Covers.Cover)
return;
cancellationSource?.Cancel();

View File

@ -17,7 +17,6 @@ using osu.Framework.Input.Events;
using osu.Framework.Logging;
using osu.Framework.Screens;
using osu.Framework.Threading;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input;
@ -126,7 +125,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
{
RelativeSizeAxes = Axes.X,
Height = Header.HEIGHT,
Child = searchTextBox = new LoungeSearchTextBox
Child = searchTextBox = new SearchTextBox
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
@ -362,15 +361,5 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
protected abstract RoomSubScreen CreateRoomSubScreen(Room room);
protected abstract ListingPollingComponent CreatePollingComponent();
private class LoungeSearchTextBox : SearchTextBox
{
[BackgroundDependencyLoader]
private void load()
{
BackgroundUnfocused = OsuColour.Gray(0.06f);
BackgroundFocused = OsuColour.Gray(0.12f);
}
}
}
}

View File

@ -12,7 +12,6 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
using osu.Game.Online.Rooms;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Match.Components
{
@ -91,31 +90,6 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
{
}
protected class SettingsTextBox : OsuTextBox
{
[BackgroundDependencyLoader]
private void load()
{
BackgroundUnfocused = Color4.Black;
BackgroundFocused = Color4.Black;
}
}
protected class SettingsNumberTextBox : SettingsTextBox
{
protected override bool CanAddCharacter(char character) => char.IsNumber(character);
}
protected class SettingsPasswordTextBox : OsuPasswordTextBox
{
[BackgroundDependencyLoader]
private void load()
{
BackgroundUnfocused = Color4.Black;
BackgroundFocused = Color4.Black;
}
}
protected class SectionContainer : FillFlowContainer<Section>
{
public SectionContainer()

View File

@ -153,7 +153,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
new Section("Room name")
{
Child = NameField = new SettingsTextBox
Child = NameField = new OsuTextBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
@ -202,7 +202,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
new Section("Max participants")
{
Alpha = disabled_alpha,
Child = MaxParticipantsField = new SettingsNumberTextBox
Child = MaxParticipantsField = new OsuNumberBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
@ -211,7 +211,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
},
new Section("Password (optional)")
{
Child = PasswordTextBox = new SettingsPasswordTextBox
Child = PasswordTextBox = new OsuPasswordTextBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,

View File

@ -121,7 +121,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
{
new Section("Room name")
{
Child = NameField = new SettingsTextBox
Child = NameField = new OsuTextBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
@ -150,7 +150,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
},
new Section("Allowed attempts (across all playlist items)")
{
Child = MaxAttemptsField = new SettingsNumberTextBox
Child = MaxAttemptsField = new OsuNumberBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
@ -168,7 +168,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
new Section("Max participants")
{
Alpha = disabled_alpha,
Child = MaxParticipantsField = new SettingsNumberTextBox
Child = MaxParticipantsField = new OsuNumberBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,
@ -178,7 +178,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
new Section("Password (optional)")
{
Alpha = disabled_alpha,
Child = new SettingsPasswordTextBox
Child = new OsuPasswordTextBox
{
RelativeSizeAxes = Axes.X,
TabbableContentContainer = this,

View File

@ -8,6 +8,7 @@ using System.Text;
using osu.Framework.Extensions;
using osu.Game.Beatmaps;
using osu.Game.IO;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
using Decoder = osu.Game.Beatmaps.Formats.Decoder;
@ -32,7 +33,7 @@ namespace osu.Game.Tests.Beatmaps
BeatmapInfo.BeatmapSet.Beatmaps = new List<BeatmapInfo> { BeatmapInfo };
BeatmapInfo.Length = 75000;
BeatmapInfo.OnlineInfo = new BeatmapOnlineInfo();
BeatmapInfo.BeatmapSet.OnlineInfo = new BeatmapSetOnlineInfo
BeatmapInfo.BeatmapSet.OnlineInfo = new APIBeatmapSet
{
Status = BeatmapSetOnlineStatus.Ranked,
Covers = new BeatmapSetOnlineCovers