1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 17:32:54 +08:00

Merge pull request #2735 from DrabWeb/beatmap-set-downloader

Centralise downloaded beatmap set logic
This commit is contained in:
Dean Herbert 2018-06-08 21:03:21 +09:00 committed by GitHub
commit 4e1b801dd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 221 additions and 130 deletions

View File

@ -0,0 +1,84 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
namespace osu.Game.Beatmaps.Drawables
{
/// <summary>
/// A component to allow downloading of a beatmap set. Automatically handles state syncing between other instances.
/// </summary>
public class BeatmapSetDownloader : Component
{
private readonly BeatmapSetInfo set;
private readonly bool noVideo;
private BeatmapManager beatmaps;
/// <summary>
/// Whether the associated beatmap set has been downloading (by this instance or any other instance).
/// </summary>
public readonly BindableBool Downloaded = new BindableBool();
public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false)
{
this.set = set;
this.noVideo = noVideo;
}
[BackgroundDependencyLoader]
private void load(BeatmapManager beatmaps)
{
this.beatmaps = beatmaps;
beatmaps.ItemAdded += setAdded;
beatmaps.ItemRemoved += setRemoved;
// initial value
if (set.OnlineBeatmapSetID != null)
Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any();
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (beatmaps != null)
{
beatmaps.ItemAdded -= setAdded;
beatmaps.ItemRemoved -= setRemoved;
}
}
/// <summary>
/// Begin downloading the associated beatmap set.
/// </summary>
/// <returns>True if downloading began. False if an existing download is active or completed.</returns>
public bool Download()
{
if (Downloaded.Value)
return false;
if (beatmaps.GetExistingDownload(set) != null)
return false;
beatmaps.Download(set, noVideo);
return true;
}
private void setAdded(BeatmapSetInfo s)
{
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
Downloaded.Value = true;
}
private void setRemoved(BeatmapSetInfo s)
{
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
Downloaded.Value = false;
}
}
}

View File

@ -3,6 +3,8 @@
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.Beatmaps.Drawables;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using OpenTK; using OpenTK;
@ -11,10 +13,11 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
{ {
public class DownloadButton : HeaderButton public class DownloadButton : HeaderButton
{ {
public DownloadButton(string title, string subtitle) public DownloadButton(BeatmapSetInfo set, bool noVideo = false)
{ {
Width = 120; Width = 120;
BeatmapSetDownloader downloader;
Add(new Container Add(new Container
{ {
Depth = -1, Depth = -1,
@ -22,6 +25,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
Padding = new MarginPadding { Horizontal = 10 }, Padding = new MarginPadding { Horizontal = 10 },
Children = new Drawable[] Children = new Drawable[]
{ {
downloader = new BeatmapSetDownloader(set, noVideo),
new FillFlowContainer new FillFlowContainer
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
@ -32,13 +36,13 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
{ {
new OsuSpriteText new OsuSpriteText
{ {
Text = title, Text = "Download",
TextSize = 13, TextSize = 13,
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
}, },
new OsuSpriteText new OsuSpriteText
{ {
Text = subtitle, Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty,
TextSize = 11, TextSize = 11,
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
}, },
@ -54,6 +58,25 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
}, },
}, },
}); });
Action = () =>
{
if (!downloader.Download())
{
Content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
}
};
downloader.Downloaded.ValueChanged += d =>
{
if (d)
this.FadeOut(200);
else
this.FadeIn(200);
};
} }
} }
} }

View File

@ -35,8 +35,6 @@ namespace osu.Game.Overlays.BeatmapSet
private readonly BeatmapSetOnlineStatusPill onlineStatusPill; private readonly BeatmapSetOnlineStatusPill onlineStatusPill;
public Details Details; public Details Details;
private BeatmapManager beatmaps;
public readonly BeatmapPicker Picker; public readonly BeatmapPicker Picker;
private BeatmapSetInfo beatmapSet; private BeatmapSetInfo beatmapSet;
@ -68,8 +66,24 @@ namespace osu.Game.Overlays.BeatmapSet
downloadButtonsContainer.FadeIn(transition_duration); downloadButtonsContainer.FadeIn(transition_duration);
favouriteButton.FadeIn(transition_duration); favouriteButton.FadeIn(transition_duration);
noVideoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 0 : 1, transition_duration); if (BeatmapSet.OnlineInfo.HasVideo)
videoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 1 : 0, transition_duration); {
videoButtons.Children = new[]
{
new DownloadButton(BeatmapSet),
new DownloadButton(BeatmapSet, true),
};
videoButtons.FadeIn(transition_duration);
noVideoButtons.FadeOut(transition_duration);
}
else
{
noVideoButtons.Child = new DownloadButton(BeatmapSet);
noVideoButtons.FadeIn(transition_duration);
videoButtons.FadeOut(transition_duration);
}
} }
else else
{ {
@ -192,27 +206,12 @@ namespace osu.Game.Overlays.BeatmapSet
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Alpha = 0f, Alpha = 0f,
Child = new DownloadButton("Download", @"")
{
Action = () => download(false),
},
}, },
videoButtons = new FillFlowContainer videoButtons = new FillFlowContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Spacing = new Vector2(buttons_spacing), Spacing = new Vector2(buttons_spacing),
Alpha = 0f, Alpha = 0f,
Children = new[]
{
new DownloadButton("Download", "with Video")
{
Action = () => download(false),
},
new DownloadButton("Download", "without Video")
{
Action = () => download(true),
},
},
}, },
}, },
}, },
@ -248,41 +247,10 @@ namespace osu.Game.Overlays.BeatmapSet
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours, BeatmapManager beatmaps) private void load(OsuColour colours)
{ {
tabsBg.Colour = colours.Gray3; tabsBg.Colour = colours.Gray3;
this.beatmaps = beatmaps;
beatmaps.ItemAdded += handleBeatmapAdd;
updateDisplay(); updateDisplay();
} }
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (beatmaps != null) beatmaps.ItemAdded -= handleBeatmapAdd;
}
private void handleBeatmapAdd(BeatmapSetInfo beatmap) => Schedule(() =>
{
if (beatmap.OnlineBeatmapSetID == BeatmapSet?.OnlineBeatmapSetID)
downloadButtonsContainer.FadeOut(transition_duration);
});
private void download(bool noVideo)
{
if (beatmaps.GetExistingDownload(BeatmapSet) != null)
{
downloadButtonsContainer.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine).Then();
return;
}
beatmaps.Download(BeatmapSet, noVideo);
}
} }
} }

View File

@ -166,14 +166,13 @@ namespace osu.Game.Overlays.Direct
}, },
}, },
}, },
new DownloadButton new DownloadButton(SetInfo)
{ {
Size = new Vector2(30), Size = new Vector2(30),
Margin = new MarginPadding(horizontal_padding), Margin = new MarginPadding(horizontal_padding),
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
Colour = colours.Gray5, Colour = colours.Gray5,
Action = StartDownload
}, },
}, },
}, },

View File

@ -12,28 +12,31 @@ using osu.Game.Graphics.Sprites;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
namespace osu.Game.Overlays.Direct namespace osu.Game.Overlays.Direct
{ {
public class DirectListPanel : DirectPanel public class DirectListPanel : DirectPanel
{ {
private const float transition_duration = 120;
private const float horizontal_padding = 10; private const float horizontal_padding = 10;
private const float vertical_padding = 5; private const float vertical_padding = 5;
private const float height = 70; private const float height = 70;
private PlayButton playButton;
private Box progressBar;
private Container downloadContainer;
protected override PlayButton PlayButton => playButton;
protected override Box PreviewBar => progressBar;
public DirectListPanel(BeatmapSetInfo beatmap) : base(beatmap) public DirectListPanel(BeatmapSetInfo beatmap) : base(beatmap)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = height; Height = height;
} }
private PlayButton playButton;
private Box progressBar;
protected override PlayButton PlayButton => playButton;
protected override Box PreviewBar => progressBar;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(LocalisationEngine localisation, OsuColour colours) private void load(LocalisationEngine localisation, OsuColour colours)
{ {
@ -59,7 +62,7 @@ namespace osu.Game.Overlays.Direct
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
LayoutEasing = Easing.OutQuint, LayoutEasing = Easing.OutQuint,
LayoutDuration = 120, LayoutDuration = transition_duration,
Spacing = new Vector2(10, 0), Spacing = new Vector2(10, 0),
Children = new Drawable[] Children = new Drawable[]
{ {
@ -104,53 +107,69 @@ namespace osu.Game.Overlays.Direct
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical, Direction = FillDirection.Horizontal,
Margin = new MarginPadding { Right = height - vertical_padding * 2 + vertical_padding }, LayoutEasing = Easing.OutQuint,
LayoutDuration = transition_duration,
Children = new Drawable[] Children = new Drawable[]
{ {
new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0) downloadContainer = new Container
{ {
Margin = new MarginPadding { Right = 1 }, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Alpha = 0,
Child = new DownloadButton(SetInfo)
{
Size = new Vector2(height - vertical_padding * 2),
Margin = new MarginPadding { Left = vertical_padding },
},
}, },
new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0),
new FillFlowContainer new FillFlowContainer
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal, Direction = FillDirection.Vertical,
Children = new[] Children = new Drawable[]
{ {
new OsuSpriteText new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0)
{ {
Text = "mapped by ", Margin = new MarginPadding { Right = 1 },
TextSize = 14, },
new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0),
new FillFlowContainer
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Children = new[]
{
new OsuSpriteText
{
Text = "mapped by ",
TextSize = 14,
},
new OsuSpriteText
{
Text = SetInfo.Metadata.Author.Username,
TextSize = 14,
Font = @"Exo2.0-SemiBoldItalic",
},
},
}, },
new OsuSpriteText new OsuSpriteText
{ {
Text = SetInfo.Metadata.Author.Username, Text = $"from {SetInfo.Metadata.Source}",
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
TextSize = 14, TextSize = 14,
Font = @"Exo2.0-SemiBoldItalic", Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f,
}, },
}, },
}, },
new OsuSpriteText
{
Text = $"from {SetInfo.Metadata.Source}",
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
TextSize = 14,
Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f,
},
}, },
}, },
new DownloadButton
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Size = new Vector2(height - vertical_padding * 2),
Action = StartDownload
},
}, },
}, },
progressBar = new Box progressBar = new Box
@ -165,5 +184,17 @@ namespace osu.Game.Overlays.Direct
}, },
}); });
} }
protected override bool OnHover(InputState state)
{
downloadContainer.FadeIn(transition_duration, Easing.InOutQuint);
return base.OnHover(state);
}
protected override void OnHoverLost(InputState state)
{
downloadContainer.FadeOut(transition_duration, Easing.InOutQuint);
base.OnHoverLost(state);
}
} }
} }

View File

@ -147,22 +147,6 @@ namespace osu.Game.Overlays.Direct
protected void ShowInformation() => beatmapSetOverlay?.ShowBeatmapSet(SetInfo); protected void ShowInformation() => beatmapSetOverlay?.ShowBeatmapSet(SetInfo);
protected void StartDownload()
{
if (beatmaps.GetExistingDownload(SetInfo) != null)
{
// we already have an active download running.
content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine).Then();
return;
}
beatmaps.Download(SetInfo);
}
private void attachDownload(DownloadBeatmapSetRequest request) private void attachDownload(DownloadBeatmapSetRequest request)
{ {
if (request.BeatmapSet.OnlineBeatmapSetID != SetInfo.OnlineBeatmapSetID) if (request.BeatmapSet.OnlineBeatmapSetID != SetInfo.OnlineBeatmapSetID)

View File

@ -3,6 +3,8 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using OpenTK; using OpenTK;
@ -13,10 +15,12 @@ namespace osu.Game.Overlays.Direct
{ {
private readonly SpriteIcon icon; private readonly SpriteIcon icon;
public DownloadButton() public DownloadButton(BeatmapSetInfo set, bool noVideo = false)
{ {
BeatmapSetDownloader downloader;
Children = new Drawable[] Children = new Drawable[]
{ {
downloader = new BeatmapSetDownloader(set, noVideo),
icon = new SpriteIcon icon = new SpriteIcon
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
@ -25,6 +29,25 @@ namespace osu.Game.Overlays.Direct
Icon = FontAwesome.fa_osu_chevron_down_o, Icon = FontAwesome.fa_osu_chevron_down_o,
}, },
}; };
Action = () =>
{
if (!downloader.Download())
{
Content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
}
};
downloader.Downloaded.ValueChanged += d =>
{
if (d)
this.FadeOut(200);
else
this.FadeIn(200);
};
} }
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)

View File

@ -28,7 +28,6 @@ namespace osu.Game.Overlays
private APIAccess api; private APIAccess api;
private RulesetStore rulesets; private RulesetStore rulesets;
private BeatmapManager beatmaps;
private readonly FillFlowContainer resultCountsContainer; private readonly FillFlowContainer resultCountsContainer;
private readonly OsuSpriteText resultCountsText; private readonly OsuSpriteText resultCountsText;
@ -177,24 +176,14 @@ namespace osu.Game.Overlays
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours, APIAccess api, RulesetStore rulesets, BeatmapManager beatmaps) private void load(OsuColour colours, APIAccess api, RulesetStore rulesets)
{ {
this.api = api; this.api = api;
this.rulesets = rulesets; this.rulesets = rulesets;
this.beatmaps = beatmaps;
resultCountsContainer.Colour = colours.Yellow; resultCountsContainer.Colour = colours.Yellow;
beatmaps.ItemAdded += setAdded;
} }
private void setAdded(BeatmapSetInfo set) => Schedule(() =>
{
// if a new map was imported, we should remove it from search results (download completed etc.)
panels?.FirstOrDefault(p => p.SetInfo.OnlineBeatmapSetID == set.OnlineBeatmapSetID)?.FadeOut(400).Expire();
BeatmapSets = BeatmapSets?.Where(b => b.OnlineBeatmapSetID != set.OnlineBeatmapSetID);
});
private void updateResultCounts() private void updateResultCounts()
{ {
resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, Easing.OutQuint); resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, Easing.OutQuint);
@ -297,9 +286,7 @@ namespace osu.Game.Overlays
{ {
Task.Run(() => Task.Run(() =>
{ {
var onlineIds = response.Select(r => r.OnlineBeatmapSetID).ToList(); var sets = response.Select(r => r.ToBeatmapSet(rulesets)).ToList();
var presentOnlineIds = beatmaps.QueryBeatmapSets(s => onlineIds.Contains(s.OnlineBeatmapSetID) && !s.DeletePending).Select(r => r.OnlineBeatmapSetID).ToList();
var sets = response.Select(r => r.ToBeatmapSet(rulesets)).Where(b => !presentOnlineIds.Contains(b.OnlineBeatmapSetID)).ToList();
// may not need scheduling; loads async internally. // may not need scheduling; loads async internally.
Schedule(() => Schedule(() =>
@ -323,14 +310,6 @@ namespace osu.Game.Overlays
private int distinctCount(List<string> list) => list.Distinct().ToArray().Length; private int distinctCount(List<string> list) => list.Distinct().ToArray().Length;
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (beatmaps != null)
beatmaps.ItemAdded -= setAdded;
}
public class ResultCounts public class ResultCounts
{ {
public readonly int Artists; public readonly int Artists;