1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 13:27:23 +08:00

Handle beatmaps with disabled download or missing content (#4986)

Handle beatmaps with disabled download or missing content

Co-authored-by: Dean Herbert <pe@ppy.sh>
Co-authored-by: Dan Balasescu <smoogipoo@smgi.me>
This commit is contained in:
Dean Herbert 2019-06-27 13:59:54 +09:00 committed by GitHub
commit 98ee2d660a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 489 additions and 305 deletions

View File

@ -0,0 +1,95 @@
// 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 NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Overlays.BeatmapSet;
namespace osu.Game.Tests.Visual.Online
{
[TestFixture]
public class TestSceneBeatmapAvailability : OsuTestScene
{
private readonly BeatmapAvailability container;
public TestSceneBeatmapAvailability()
{
Add(container = new BeatmapAvailability());
}
[Test]
public void TestUndownloadableWithLink()
{
AddStep("set undownloadable beatmapset with link", () => container.BeatmapSet = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
{
Availability = new BeatmapSetOnlineAvailability
{
DownloadDisabled = true,
ExternalLink = @"https://osu.ppy.sh",
},
},
});
visiblityAssert(true);
}
[Test]
public void TestUndownloadableNoLink()
{
AddStep("set undownloadable beatmapset without link", () => container.BeatmapSet = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
{
Availability = new BeatmapSetOnlineAvailability
{
DownloadDisabled = true,
},
},
});
visiblityAssert(true);
}
[Test]
public void TestPartsRemovedWithLink()
{
AddStep("set parts-removed beatmapset with link", () => container.BeatmapSet = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
{
Availability = new BeatmapSetOnlineAvailability
{
DownloadDisabled = false,
ExternalLink = @"https://osu.ppy.sh",
},
},
});
visiblityAssert(true);
}
[Test]
public void TestNormal()
{
AddStep("set normal beatmapset", () => container.BeatmapSet = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
{
Availability = new BeatmapSetOnlineAvailability
{
DownloadDisabled = false,
},
},
});
visiblityAssert(false);
}
private void visiblityAssert(bool shown)
{
AddAssert($"is container {(shown ? "visible" : "hidden")}", () => container.Alpha == (shown ? 1 : 0));
}
}
}

View File

@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Online
[TestFixture] [TestFixture]
public class TestSceneBeatmapSetOverlay : OsuTestScene public class TestSceneBeatmapSetOverlay : OsuTestScene
{ {
private readonly BeatmapSetOverlay overlay; private readonly TestBeatmapSetOverlay overlay;
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
@ -39,21 +39,22 @@ namespace osu.Game.Tests.Visual.Online
typeof(Info), typeof(Info),
typeof(PreviewButton), typeof(PreviewButton),
typeof(SuccessRate), typeof(SuccessRate),
typeof(BeatmapAvailability),
}; };
private RulesetInfo maniaRuleset;
private RulesetInfo taikoRuleset; private RulesetInfo taikoRuleset;
private RulesetInfo maniaRuleset;
public TestSceneBeatmapSetOverlay() public TestSceneBeatmapSetOverlay()
{ {
Add(overlay = new BeatmapSetOverlay()); Add(overlay = new TestBeatmapSetOverlay());
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(RulesetStore rulesets) private void load(RulesetStore rulesets)
{ {
maniaRuleset = rulesets.GetRuleset(3);
taikoRuleset = rulesets.GetRuleset(1); taikoRuleset = rulesets.GetRuleset(1);
maniaRuleset = rulesets.GetRuleset(3);
} }
[Test] [Test]
@ -75,159 +76,53 @@ namespace osu.Game.Tests.Visual.Online
{ {
overlay.ShowBeatmapSet(new BeatmapSetInfo overlay.ShowBeatmapSet(new BeatmapSetInfo
{ {
OnlineBeatmapSetID = 1235,
Metadata = new BeatmapMetadata Metadata = new BeatmapMetadata
{ {
Title = @"Lachryma <Re:QueenM>", Title = @"an awesome beatmap",
Artist = @"Kaneko Chiharu", Artist = @"naru narusegawa",
Source = @"SOUND VOLTEX III GRAVITY WARS", Source = @"hinata sou",
Tags = @"sdvx grace the 5th kac original song contest konami bemani", Tags = @"test tag tag more tag",
Author = new User Author = new User
{ {
Username = @"Fresh Chicken", Username = @"BanchoBot",
Id = 3984370, Id = 3,
}, },
}, },
OnlineInfo = new BeatmapSetOnlineInfo OnlineInfo = new BeatmapSetOnlineInfo
{ {
Preview = @"https://b.ppy.sh/preview/415886.mp3", Preview = @"https://b.ppy.sh/preview/12345.mp3",
PlayCount = 681380, PlayCount = 123,
FavouriteCount = 356, FavouriteCount = 456,
Submitted = new DateTime(2016, 2, 10), Submitted = DateTime.Now,
Ranked = new DateTime(2016, 6, 19), Ranked = DateTime.Now,
Status = BeatmapSetOnlineStatus.Ranked, BPM = 111,
BPM = 236,
HasVideo = true, HasVideo = true,
Covers = new BeatmapSetOnlineCovers HasStoryboard = true,
{ Covers = new BeatmapSetOnlineCovers(),
Cover = @"https://assets.ppy.sh/beatmaps/415886/covers/cover.jpg?1465651778",
},
}, },
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
Beatmaps = new List<BeatmapInfo> Beatmaps = new List<BeatmapInfo>
{ {
new BeatmapInfo new BeatmapInfo
{ {
StarDifficulty = 1.36, StarDifficulty = 9.99,
Version = @"BASIC", Version = @"TEST",
Ruleset = maniaRuleset, Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty BaseDifficulty = new BeatmapDifficulty
{ {
CircleSize = 4, CircleSize = 1,
DrainRate = 6.5f, DrainRate = 2.3f,
OverallDifficulty = 6.5f, OverallDifficulty = 4.5f,
ApproachRate = 5, ApproachRate = 6,
}, },
OnlineInfo = new BeatmapOnlineInfo OnlineInfo = new BeatmapOnlineInfo
{ {
Length = 115000, Length = 456000,
CircleCount = 265, CircleCount = 111,
SliderCount = 71, SliderCount = 12,
PlayCount = 47906, PlayCount = 222,
PassCount = 19899, PassCount = 21,
},
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 2.22,
Version = @"NOVICE",
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
DrainRate = 7,
OverallDifficulty = 7,
ApproachRate = 5,
},
OnlineInfo = new BeatmapOnlineInfo
{
Length = 118000,
CircleCount = 592,
SliderCount = 62,
PlayCount = 162021,
PassCount = 72116,
},
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 3.49,
Version = @"ADVANCED",
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
DrainRate = 7.5f,
OverallDifficulty = 7.5f,
ApproachRate = 5,
},
OnlineInfo = new BeatmapOnlineInfo
{
Length = 118000,
CircleCount = 1042,
SliderCount = 79,
PlayCount = 225178,
PassCount = 73001,
},
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 4.24,
Version = @"EXHAUST",
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
DrainRate = 8,
OverallDifficulty = 8,
ApproachRate = 5,
},
OnlineInfo = new BeatmapOnlineInfo
{
Length = 118000,
CircleCount = 1352,
SliderCount = 69,
PlayCount = 131545,
PassCount = 42703,
},
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 5.26,
Version = @"GRAVITY",
Ruleset = maniaRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 4,
DrainRate = 8.5f,
OverallDifficulty = 8.5f,
ApproachRate = 5,
},
OnlineInfo = new BeatmapOnlineInfo
{
Length = 118000,
CircleCount = 1730,
SliderCount = 115,
PlayCount = 117673,
PassCount = 24241,
}, },
Metrics = new BeatmapMetrics Metrics = new BeatmapMetrics
{ {
@ -239,162 +134,68 @@ namespace osu.Game.Tests.Visual.Online
}); });
}); });
AddStep(@"show second", () => downloadAssert(true);
}
[Test]
public void TestAvailability()
{
AddStep(@"show undownloadable", () =>
{ {
overlay.ShowBeatmapSet(new BeatmapSetInfo overlay.ShowBeatmapSet(new BeatmapSetInfo
{ {
OnlineBeatmapSetID = 1234,
Metadata = new BeatmapMetadata Metadata = new BeatmapMetadata
{ {
Title = @"Soumatou Labyrinth", Title = @"undownloadable beatmap",
Artist = @"Yunomi with Momobako&miko", Artist = @"no one",
Tags = @"mmbk.com yuzu__rinrin charlotte", Source = @"some source",
Tags = @"another test tag tag more test tags",
Author = new User Author = new User
{ {
Username = @"komasy", Username = @"BanchoBot",
Id = 1980256, Id = 3,
}, },
}, },
OnlineInfo = new BeatmapSetOnlineInfo OnlineInfo = new BeatmapSetOnlineInfo
{ {
Preview = @"https://b.ppy.sh/preview/625493.mp3", Availability = new BeatmapSetOnlineAvailability
PlayCount = 22996,
FavouriteCount = 58,
Submitted = new DateTime(2016, 6, 11),
Ranked = new DateTime(2016, 7, 12),
Status = BeatmapSetOnlineStatus.Pending,
BPM = 160,
HasVideo = false,
Covers = new BeatmapSetOnlineCovers
{ {
Cover = @"https://assets.ppy.sh/beatmaps/625493/covers/cover.jpg?1499167472", DownloadDisabled = true,
ExternalLink = "https://osu.ppy.sh",
}, },
Preview = @"https://b.ppy.sh/preview/1234.mp3",
PlayCount = 123,
FavouriteCount = 456,
Submitted = DateTime.Now,
Ranked = DateTime.Now,
BPM = 111,
HasVideo = true,
HasStoryboard = true,
Covers = new BeatmapSetOnlineCovers(),
}, },
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
Beatmaps = new List<BeatmapInfo> Beatmaps = new List<BeatmapInfo>
{ {
new BeatmapInfo new BeatmapInfo
{ {
StarDifficulty = 1.40, StarDifficulty = 5.67,
Version = @"yzrin's Kantan", Version = @"ANOTHER TEST",
Ruleset = taikoRuleset, Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty BaseDifficulty = new BeatmapDifficulty
{ {
CircleSize = 2, CircleSize = 9,
DrainRate = 7, DrainRate = 8,
OverallDifficulty = 3, OverallDifficulty = 7,
ApproachRate = 10, ApproachRate = 6,
}, },
OnlineInfo = new BeatmapOnlineInfo OnlineInfo = new BeatmapOnlineInfo
{ {
Length = 193000, Length = 123000,
CircleCount = 262, CircleCount = 123,
SliderCount = 0, SliderCount = 45,
PlayCount = 3952, PlayCount = 567,
PassCount = 1373, PassCount = 89,
},
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 2.23,
Version = @"Futsuu",
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 2,
DrainRate = 6,
OverallDifficulty = 4,
ApproachRate = 10,
},
OnlineInfo = new BeatmapOnlineInfo
{
Length = 193000,
CircleCount = 464,
SliderCount = 0,
PlayCount = 4833,
PassCount = 920,
},
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 3.19,
Version = @"Muzukashii",
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 2,
DrainRate = 6,
OverallDifficulty = 5,
ApproachRate = 10,
},
OnlineInfo = new BeatmapOnlineInfo
{
Length = 193000,
CircleCount = 712,
SliderCount = 0,
PlayCount = 4405,
PassCount = 854,
},
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 3.97,
Version = @"Charlotte's Oni",
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 5,
DrainRate = 6,
OverallDifficulty = 5.5f,
ApproachRate = 10,
},
OnlineInfo = new BeatmapOnlineInfo
{
Length = 193000,
CircleCount = 943,
SliderCount = 0,
PlayCount = 3950,
PassCount = 693,
},
Metrics = new BeatmapMetrics
{
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
},
},
new BeatmapInfo
{
StarDifficulty = 5.08,
Version = @"Labyrinth Oni",
Ruleset = taikoRuleset,
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 5,
DrainRate = 5,
OverallDifficulty = 6,
ApproachRate = 10,
},
OnlineInfo = new BeatmapOnlineInfo
{
Length = 193000,
CircleCount = 1068,
SliderCount = 0,
PlayCount = 5856,
PassCount = 1207,
}, },
Metrics = new BeatmapMetrics Metrics = new BeatmapMetrics
{ {
@ -405,6 +206,8 @@ namespace osu.Game.Tests.Visual.Online
}, },
}); });
}); });
downloadAssert(false);
} }
[Test] [Test]
@ -418,5 +221,15 @@ namespace osu.Game.Tests.Visual.Online
{ {
AddStep(@"show without reload", overlay.Show); AddStep(@"show without reload", overlay.Show);
} }
private void downloadAssert(bool shown)
{
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.DownloadButtonsVisible == shown);
}
private class TestBeatmapSetOverlay : BeatmapSetOverlay
{
public bool DownloadButtonsVisible => Header.DownloadButtonsVisible;
}
} }
} }

View File

@ -0,0 +1,94 @@
// 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 System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Overlays.Direct;
using osu.Game.Rulesets.Osu;
using osuTK;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneDirectDownloadButton : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(DownloadButton)
};
private TestDownloadButton downloadButton;
[Test]
public void TestDownloadableBeatmap()
{
createButton(true);
assertEnabled(true);
}
[Test]
public void TestUndownloadableBeatmap()
{
createButton(false);
assertEnabled(false);
}
private void assertEnabled(bool enabled)
{
AddAssert($"button {(enabled ? "enabled" : "disabled")}", () => downloadButton.DownloadEnabled == enabled);
}
private void createButton(bool downloadable)
{
AddStep("create button", () =>
{
Child = downloadButton = new TestDownloadButton(downloadable ? getDownloadableBeatmapSet() : getUndownloadableBeatmapSet())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(75, 50),
};
});
}
private BeatmapSetInfo getDownloadableBeatmapSet()
{
var normal = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).BeatmapSetInfo;
normal.OnlineInfo.HasVideo = true;
normal.OnlineInfo.HasStoryboard = true;
return normal;
}
private BeatmapSetInfo getUndownloadableBeatmapSet()
{
var beatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).BeatmapSetInfo;
beatmap.Metadata.Artist = "test";
beatmap.Metadata.Title = "undownloadable";
beatmap.Metadata.AuthorString = "test";
beatmap.OnlineInfo.HasVideo = true;
beatmap.OnlineInfo.HasStoryboard = true;
beatmap.OnlineInfo.Availability = new BeatmapSetOnlineAvailability
{
DownloadDisabled = true,
ExternalLink = "http://osu.ppy.sh",
};
return beatmap;
}
private class TestDownloadButton : DownloadButton
{
public new bool DownloadEnabled => base.DownloadEnabled;
public TestDownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false)
: base(beatmapSet, noVideo)
{
}
}
}
}

View File

@ -6,8 +6,11 @@ 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.Overlays.Direct; using osu.Game.Overlays.Direct;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Users;
using osuTK; using osuTK;
namespace osu.Game.Tests.Visual.Online namespace osu.Game.Tests.Visual.Online
@ -21,25 +24,74 @@ namespace osu.Game.Tests.Visual.Online
typeof(IconPill) typeof(IconPill)
}; };
private BeatmapSetInfo getUndownloadableBeatmapSet(RulesetInfo ruleset) => new BeatmapSetInfo
{
OnlineBeatmapSetID = 123,
Metadata = new BeatmapMetadata
{
Title = "undownloadable beatmap",
Artist = "test",
Source = "more tests",
Author = new User
{
Username = "BanchoBot",
Id = 3,
},
},
OnlineInfo = new BeatmapSetOnlineInfo
{
Availability = new BeatmapSetOnlineAvailability
{
DownloadDisabled = true,
},
Preview = @"https://b.ppy.sh/preview/12345.mp3",
PlayCount = 123,
FavouriteCount = 456,
BPM = 111,
HasVideo = true,
HasStoryboard = true,
Covers = new BeatmapSetOnlineCovers(),
},
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
Ruleset = ruleset,
Version = "Test",
StarDifficulty = 6.42,
}
}
};
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
var beatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); var ruleset = new OsuRuleset().RulesetInfo;
beatmap.BeatmapSetInfo.OnlineInfo.HasVideo = true;
beatmap.BeatmapSetInfo.OnlineInfo.HasStoryboard = true;
Child = new FillFlowContainer var normal = CreateWorkingBeatmap(ruleset).BeatmapSetInfo;
normal.OnlineInfo.HasVideo = true;
normal.OnlineInfo.HasStoryboard = true;
var undownloadable = getUndownloadableBeatmapSet(ruleset);
Child = new BasicScrollContainer
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.Both,
AutoSizeAxes = Axes.Y, Child = new FillFlowContainer
Direction = FillDirection.Vertical,
Padding = new MarginPadding(20),
Spacing = new Vector2(0, 20),
Children = new Drawable[]
{ {
new DirectGridPanel(beatmap.BeatmapSetInfo), RelativeSizeAxes = Axes.X,
new DirectListPanel(beatmap.BeatmapSetInfo) AutoSizeAxes = Axes.Y,
} Direction = FillDirection.Vertical,
Padding = new MarginPadding(20),
Spacing = new Vector2(0, 20),
Children = new Drawable[]
{
new DirectGridPanel(normal),
new DirectListPanel(normal),
new DirectGridPanel(undownloadable),
new DirectListPanel(undownloadable),
},
},
}; };
} }
} }

View File

@ -65,6 +65,11 @@ namespace osu.Game.Beatmaps
/// The amount of people who have favourited this beatmap set. /// The amount of people who have favourited this beatmap set.
/// </summary> /// </summary>
public int FavouriteCount { get; set; } public int FavouriteCount { get; set; }
/// <summary>
/// The availability of this beatmap set.
/// </summary>
public BeatmapSetOnlineAvailability Availability { get; set; }
} }
public class BeatmapSetOnlineCovers public class BeatmapSetOnlineCovers
@ -84,4 +89,13 @@ namespace osu.Game.Beatmaps
[JsonProperty(@"list@2x")] [JsonProperty(@"list@2x")]
public string List { get; set; } public string List { get; set; }
} }
public class BeatmapSetOnlineAvailability
{
[JsonProperty(@"download_disabled")]
public bool DownloadDisabled { get; set; }
[JsonProperty(@"more_information")]
public string ExternalLink { get; set; }
}
} }

View File

@ -2,9 +2,10 @@
// 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 osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osuTK.Graphics; using osu.Game.Graphics;
namespace osu.Game.Beatmaps.Drawables namespace osu.Game.Beatmaps.Drawables
{ {
@ -49,7 +50,7 @@ namespace osu.Game.Beatmaps.Drawables
Child = new Box Child = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = Color4.Black, Colour = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.1f)),
}; };
} }

View File

@ -63,6 +63,9 @@ namespace osu.Game.Online.API.Requests.Responses
set => Author.Id = value; set => Author.Id = value;
} }
[JsonProperty(@"availability")]
private BeatmapSetOnlineAvailability availability { get; set; }
[JsonProperty(@"beatmaps")] [JsonProperty(@"beatmaps")]
private IEnumerable<APIBeatmap> beatmaps { get; set; } private IEnumerable<APIBeatmap> beatmaps { get; set; }
@ -87,6 +90,7 @@ namespace osu.Game.Online.API.Requests.Responses
Submitted = submitted, Submitted = submitted,
Ranked = ranked, Ranked = ranked,
LastUpdated = lastUpdated, LastUpdated = lastUpdated,
Availability = availability,
}, },
Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(), Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(),
}; };

View File

@ -0,0 +1,83 @@
// 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.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osuTK.Graphics;
namespace osu.Game.Overlays.BeatmapSet
{
public class BeatmapAvailability : Container
{
private BeatmapSetInfo beatmapSet;
private bool downloadDisabled => BeatmapSet?.OnlineInfo.Availability?.DownloadDisabled ?? false;
private bool hasExternalLink => !string.IsNullOrEmpty(BeatmapSet?.OnlineInfo.Availability?.ExternalLink);
private readonly LinkFlowContainer textContainer;
public BeatmapAvailability()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Padding = new MarginPadding { Top = 10, Right = 20 };
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(0.6f),
},
textContainer = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 14))
{
Direction = FillDirection.Full,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding(10),
},
};
}
public BeatmapSetInfo BeatmapSet
{
get => beatmapSet;
set
{
if (value == beatmapSet)
return;
beatmapSet = value;
if (downloadDisabled || hasExternalLink)
{
Show();
updateText();
}
else
Hide();
}
}
private void updateText()
{
textContainer.Clear();
textContainer.AddParagraph(downloadDisabled
? "This beatmap is currently not available for download."
: "Portions of this beatmap have been removed at the request of the creator or a third-party rights holder.", t => t.Colour = Color4.Orange);
if (hasExternalLink)
{
textContainer.NewParagraph();
textContainer.NewParagraph();
textContainer.AddLink("Check here for more information.", BeatmapSet.OnlineInfo.Availability.ExternalLink, creationParameters: t => t.Font = OsuFont.GetFont(size: 10));
}
}
}
}

View File

@ -1,6 +1,7 @@
// 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. // See the LICENCE file in the repository root for full licence text.
using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -33,9 +34,12 @@ namespace osu.Game.Overlays.BeatmapSet
private readonly OsuSpriteText title, artist; private readonly OsuSpriteText title, artist;
private readonly AuthorInfo author; private readonly AuthorInfo author;
private readonly FillFlowContainer downloadButtonsContainer; private readonly FillFlowContainer downloadButtonsContainer;
private readonly BeatmapAvailability beatmapAvailability;
private readonly BeatmapSetOnlineStatusPill onlineStatusPill; private readonly BeatmapSetOnlineStatusPill onlineStatusPill;
public Details Details; public Details Details;
public bool DownloadButtonsVisible => downloadButtonsContainer.Any();
public readonly BeatmapPicker Picker; public readonly BeatmapPicker Picker;
private readonly FavouriteButton favouriteButton; private readonly FavouriteButton favouriteButton;
@ -100,7 +104,8 @@ namespace osu.Game.Overlays.BeatmapSet
}, },
new Container new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding Padding = new MarginPadding
{ {
Top = 20, Top = 20,
@ -149,6 +154,7 @@ namespace osu.Game.Overlays.BeatmapSet
Margin = new MarginPadding { Top = 20 }, Margin = new MarginPadding { Top = 20 },
Child = author = new AuthorInfo(), Child = author = new AuthorInfo(),
}, },
beatmapAvailability = new BeatmapAvailability(),
new Container new Container
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
@ -167,13 +173,14 @@ namespace osu.Game.Overlays.BeatmapSet
}, },
}, },
}, },
loading = new LoadingAnimation
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
} }
}, },
loading = new LoadingAnimation
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(1.5f),
},
new FillFlowContainer new FillFlowContainer
{ {
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
@ -214,7 +221,7 @@ namespace osu.Game.Overlays.BeatmapSet
BeatmapSet.BindValueChanged(setInfo => BeatmapSet.BindValueChanged(setInfo =>
{ {
Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; Picker.BeatmapSet = author.BeatmapSet = beatmapAvailability.BeatmapSet = Details.BeatmapSet = setInfo.NewValue;
cover.BeatmapSet = setInfo.NewValue; cover.BeatmapSet = setInfo.NewValue;
if (setInfo.NewValue == null) if (setInfo.NewValue == null)
@ -251,11 +258,17 @@ namespace osu.Game.Overlays.BeatmapSet
{ {
if (BeatmapSet.Value == null) return; if (BeatmapSet.Value == null) return;
if (BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false)
{
downloadButtonsContainer.Clear();
return;
}
switch (State.Value) switch (State.Value)
{ {
case DownloadState.LocallyAvailable: case DownloadState.LocallyAvailable:
// temporary for UX until new design is implemented. // temporary for UX until new design is implemented.
downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) downloadButtonsContainer.Child = new Direct.DownloadButton(BeatmapSet.Value)
{ {
Width = 50, Width = 50,
RelativeSizeAxes = Axes.Y RelativeSizeAxes = Axes.Y

View File

@ -27,12 +27,10 @@ namespace osu.Game.Overlays
public const float TOP_PADDING = 25; public const float TOP_PADDING = 25;
public const float RIGHT_WIDTH = 275; public const float RIGHT_WIDTH = 275;
private readonly Header header; protected readonly Header Header;
private RulesetStore rulesets; private RulesetStore rulesets;
private readonly OsuScrollContainer scroll;
private readonly Bindable<BeatmapSetInfo> beatmapSet = new Bindable<BeatmapSetInfo>(); private readonly Bindable<BeatmapSetInfo> beatmapSet = new Bindable<BeatmapSetInfo>();
// receive input outside our bounds so we can trigger a close event on ourselves. // receive input outside our bounds so we can trigger a close event on ourselves.
@ -40,6 +38,7 @@ namespace osu.Game.Overlays
public BeatmapSetOverlay() public BeatmapSetOverlay()
{ {
OsuScrollContainer scroll;
Info info; Info info;
ScoresContainer scores; ScoresContainer scores;
@ -61,7 +60,7 @@ namespace osu.Game.Overlays
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Children = new Drawable[] Children = new Drawable[]
{ {
header = new Header(), Header = new Header(),
info = new Info(), info = new Info(),
scores = new ScoresContainer(), scores = new ScoresContainer(),
}, },
@ -69,13 +68,15 @@ namespace osu.Game.Overlays
}, },
}; };
header.BeatmapSet.BindTo(beatmapSet); Header.BeatmapSet.BindTo(beatmapSet);
info.BeatmapSet.BindTo(beatmapSet); info.BeatmapSet.BindTo(beatmapSet);
header.Picker.Beatmap.ValueChanged += b => Header.Picker.Beatmap.ValueChanged += b =>
{ {
info.Beatmap = b.NewValue; info.Beatmap = b.NewValue;
scores.Beatmap = b.NewValue; scores.Beatmap = b.NewValue;
scroll.ScrollToStart();
}; };
} }
@ -104,7 +105,7 @@ namespace osu.Game.Overlays
req.Success += res => req.Success += res =>
{ {
beatmapSet.Value = res.ToBeatmapSet(rulesets); beatmapSet.Value = res.ToBeatmapSet(rulesets);
header.Picker.Beatmap.Value = header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); Header.Picker.Beatmap.Value = Header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId);
}; };
API.Queue(req); API.Queue(req);
Show(); Show();
@ -119,11 +120,14 @@ namespace osu.Game.Overlays
Show(); Show();
} }
/// <summary>
/// Show an already fully-populated beatmap set.
/// </summary>
/// <param name="set">The set to show.</param>
public void ShowBeatmapSet(BeatmapSetInfo set) public void ShowBeatmapSet(BeatmapSetInfo set)
{ {
beatmapSet.Value = set; beatmapSet.Value = set;
Show(); Show();
scroll.ScrollTo(0);
} }
} }
} }

View File

@ -27,6 +27,7 @@ namespace osu.Game.Overlays.Direct
private const float height = 70; private const float height = 70;
private FillFlowContainer statusContainer; private FillFlowContainer statusContainer;
protected DownloadButton DownloadButton;
private PlayButton playButton; private PlayButton playButton;
private Box progressBar; private Box progressBar;
@ -149,7 +150,7 @@ namespace osu.Game.Overlays.Direct
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Child = new DownloadButton(SetInfo) Child = DownloadButton = new DownloadButton(SetInfo)
{ {
Size = new Vector2(height - vertical_padding * 3), Size = new Vector2(height - vertical_padding * 3),
Margin = new MarginPadding { Left = vertical_padding * 2, Right = vertical_padding }, Margin = new MarginPadding { Left = vertical_padding * 2, Right = vertical_padding },

View File

@ -2,6 +2,7 @@
// 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 System.Diagnostics;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
@ -34,6 +35,7 @@ namespace osu.Game.Overlays.Direct
public PreviewTrack Preview => PlayButton.Preview; public PreviewTrack Preview => PlayButton.Preview;
public Bindable<bool> PreviewPlaying => PlayButton.Playing; public Bindable<bool> PreviewPlaying => PlayButton.Playing;
protected abstract PlayButton PlayButton { get; } protected abstract PlayButton PlayButton { get; }
protected abstract Box PreviewBar { get; } protected abstract Box PreviewBar { get; }
@ -43,6 +45,8 @@ namespace osu.Game.Overlays.Direct
protected DirectPanel(BeatmapSetInfo setInfo) protected DirectPanel(BeatmapSetInfo setInfo)
{ {
Debug.Assert(setInfo.OnlineBeatmapSetID != null);
SetInfo = setInfo; SetInfo = setInfo;
} }
@ -117,12 +121,11 @@ namespace osu.Game.Overlays.Direct
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)
{ {
ShowInformation(); Debug.Assert(SetInfo.OnlineBeatmapSetID != null);
beatmapSetOverlay?.FetchAndShowBeatmapSet(SetInfo.OnlineBeatmapSetID.Value);
return true; return true;
} }
protected void ShowInformation() => beatmapSetOverlay?.ShowBeatmapSet(SetInfo);
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();

View File

@ -16,15 +16,15 @@ namespace osu.Game.Overlays.Direct
{ {
public class DownloadButton : BeatmapDownloadTrackingComposite public class DownloadButton : BeatmapDownloadTrackingComposite
{ {
protected bool DownloadEnabled => button.Enabled.Value;
private readonly bool noVideo; private readonly bool noVideo;
private readonly SpriteIcon icon; private readonly SpriteIcon icon;
private readonly SpriteIcon checkmark; private readonly SpriteIcon checkmark;
private readonly Box background; private readonly Box background;
private OsuColour colours; private OsuColour colours;
private readonly ShakeContainer shakeContainer; private readonly ShakeContainer shakeContainer;
private readonly OsuAnimatedButton button; private readonly OsuAnimatedButton button;
public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false)
@ -73,11 +73,18 @@ namespace osu.Game.Overlays.Direct
FinishTransforms(true); FinishTransforms(true);
} }
[BackgroundDependencyLoader(permitNulls: true)] [BackgroundDependencyLoader(true)]
private void load(OsuColour colours, OsuGame game, BeatmapManager beatmaps) private void load(OsuColour colours, OsuGame game, BeatmapManager beatmaps)
{ {
this.colours = colours; this.colours = colours;
if (BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false)
{
button.Enabled.Value = false;
button.TooltipText = "This beatmap is currently not available for download.";
return;
}
button.Action = () => button.Action = () =>
{ {
switch (State.Value) switch (State.Value)