Remove necessity of BeatmapSetDownloader

This commit is contained in:
Dean Herbert
2019-01-18 14:28:06 +09:00
parent 8848fa8b1b
commit 21e79f51b1
8 changed files with 295 additions and 351 deletions

View File

@ -1,112 +0,0 @@
// 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;
using osu.Game.Online.API.Requests;
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>
/// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded.
/// </summary>
public readonly Bindable<DownloadStatus> DownloadState = new Bindable<DownloadStatus>();
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;
beatmaps.BeatmapDownloadBegan += downloadBegan;
beatmaps.BeatmapDownloadFailed += downloadFailed;
// initial value
if (set.OnlineBeatmapSetID != null && beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any())
DownloadState.Value = DownloadStatus.Downloaded;
else if (beatmaps.GetExistingDownload(set) != null)
DownloadState.Value = DownloadStatus.Downloading;
else
DownloadState.Value = DownloadStatus.NotDownloaded;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (beatmaps != null)
{
beatmaps.ItemAdded -= setAdded;
beatmaps.ItemRemoved -= setRemoved;
beatmaps.BeatmapDownloadBegan -= downloadBegan;
beatmaps.BeatmapDownloadFailed -= downloadFailed;
}
}
/// <summary>
/// Begin downloading the associated beatmap set.
/// </summary>
/// <returns>True if downloading began. False if an existing download is active or completed.</returns>
public void Download()
{
if (DownloadState.Value > DownloadStatus.NotDownloaded)
return;
if (beatmaps.Download(set, noVideo))
{
// Only change state if download can happen
DownloadState.Value = DownloadStatus.Downloading;
}
}
private void setAdded(BeatmapSetInfo s, bool existing, bool silent) => Schedule(() =>
{
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
DownloadState.Value = DownloadStatus.Downloaded;
});
private void setRemoved(BeatmapSetInfo s) => Schedule(() =>
{
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
DownloadState.Value = DownloadStatus.NotDownloaded;
});
private void downloadBegan(DownloadBeatmapSetRequest d)
{
if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
DownloadState.Value = DownloadStatus.Downloading;
}
private void downloadFailed(DownloadBeatmapSetRequest d)
{
if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
DownloadState.Value = DownloadStatus.NotDownloaded;
}
public enum DownloadStatus
{
NotDownloaded,
Downloading,
Downloaded,
}
}
}

View File

@ -10,7 +10,7 @@ namespace osu.Game.Online.API.Requests
{ {
public readonly BeatmapSetInfo BeatmapSet; public readonly BeatmapSetInfo BeatmapSet;
public Action<float> DownloadProgressed; public event Action<float> DownloadProgressed;
private readonly bool noVideo; private readonly bool noVideo;

View File

@ -7,8 +7,8 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Game.Beatmaps; 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.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Overlays.Direct; using osu.Game.Overlays.Direct;
@ -18,75 +18,100 @@ using osuTK.Graphics;
namespace osu.Game.Overlays.BeatmapSet.Buttons namespace osu.Game.Overlays.BeatmapSet.Buttons
{ {
public class DownloadButton : HeaderButton, IHasTooltip public class DownloadButton : DownloadTrackingComposite, IHasTooltip
{ {
public string TooltipText => Enabled ? null : "You gotta be an osu!supporter to download for now 'yo"; private readonly bool noVideo;
public string TooltipText => button.Enabled ? null : "You gotta be an osu!supporter to download for now 'yo";
private readonly IBindable<User> localUser = new Bindable<User>(); private readonly IBindable<User> localUser = new Bindable<User>();
public DownloadButton(BeatmapSetInfo set, bool noVideo = false) private ShakeContainer shakeContainer;
{ private HeaderButton button;
Width = 120;
BeatmapSetDownloader downloader; public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false)
: base(beatmapSet)
{
this.noVideo = noVideo;
Width = 120;
RelativeSizeAxes = Axes.Y;
}
[BackgroundDependencyLoader]
private void load(APIAccess api, BeatmapManager beatmaps)
{
FillFlowContainer textSprites; FillFlowContainer textSprites;
AddRange(new Drawable[] AddRangeInternal(new Drawable[]
{ {
new Container shakeContainer = new ShakeContainer
{ {
Depth = -1, Depth = -1,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Horizontal = 10 }, Masking = true,
CornerRadius = 5,
Children = new Drawable[] Children = new Drawable[]
{ {
downloader = new BeatmapSetDownloader(set, noVideo), button = new HeaderButton { RelativeSizeAxes = Axes.Both },
textSprites = new FillFlowContainer new Container
{ {
Anchor = Anchor.CentreLeft, // cannot nest inside here due to the structure of button (putting things in its own content).
Origin = Anchor.CentreLeft, // requires framework fix.
AutoSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = 10 },
AutoSizeDuration = 500, RelativeSizeAxes = Axes.Both,
AutoSizeEasing = Easing.OutQuint, Children = new Drawable[]
Direction = FillDirection.Vertical, {
textSprites = new FillFlowContainer
{
Depth = -1,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
AutoSizeAxes = Axes.Both,
AutoSizeDuration = 500,
AutoSizeEasing = Easing.OutQuint,
Direction = FillDirection.Vertical,
},
new SpriteIcon
{
Depth = -1,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Icon = FontAwesome.fa_download,
Size = new Vector2(16),
Margin = new MarginPadding { Right = 5 },
},
}
}, },
new SpriteIcon new DownloadProgressBar(BeatmapSet)
{ {
Anchor = Anchor.CentreRight, Depth = -2,
Origin = Anchor.CentreRight, Anchor = Anchor.BottomLeft,
Icon = FontAwesome.fa_download, Origin = Anchor.BottomLeft,
Size = new Vector2(16),
Margin = new MarginPadding { Right = 5 },
}, },
}, },
}, },
new DownloadProgressBar(set)
{
Depth = -2,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
},
}); });
Action = () => button.Action = () =>
{ {
if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloading) if (State.Value == DownloadState.Downloading)
{ {
Content.MoveToX(-5, 50, Easing.OutSine).Then() shakeContainer.Shake();
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
return; return;
} }
downloader.Download(); beatmaps.Download(BeatmapSet, noVideo);
}; };
downloader.DownloadState.ValueChanged += state => localUser.BindTo(api.LocalUser);
localUser.BindValueChanged(userChanged, true);
button.Enabled.BindValueChanged(enabledChanged, true);
State.BindValueChanged(state =>
{ {
switch (state) switch (state)
{ {
case BeatmapSetDownloader.DownloadStatus.Downloading: case DownloadState.Downloading:
textSprites.Children = new Drawable[] textSprites.Children = new Drawable[]
{ {
new OsuSpriteText new OsuSpriteText
@ -97,10 +122,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
}, },
}; };
break; break;
case BeatmapSetDownloader.DownloadStatus.Downloaded: case DownloadState.Downloaded:
this.FadeOut(200); this.FadeOut(200);
break; break;
case BeatmapSetDownloader.DownloadStatus.NotDownloaded: case DownloadState.NotDownloaded:
textSprites.Children = new Drawable[] textSprites.Children = new Drawable[]
{ {
new OsuSpriteText new OsuSpriteText
@ -111,7 +136,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
}, },
new OsuSpriteText new OsuSpriteText
{ {
Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, Text = BeatmapSet.Value.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty,
TextSize = 11, TextSize = 11,
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
}, },
@ -119,20 +144,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
this.FadeIn(200); this.FadeIn(200);
break; break;
} }
}; }, true);
downloader.DownloadState.TriggerChange();
} }
[BackgroundDependencyLoader] private void userChanged(User user) => button.Enabled.Value = user.IsSupporter;
private void load(APIAccess api)
{
localUser.BindTo(api.LocalUser);
localUser.BindValueChanged(userChanged, true);
Enabled.BindValueChanged(enabledChanged, true);
}
private void userChanged(User user) => Enabled.Value = user.IsSupporter;
private void enabledChanged(bool enabled) => this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); private void enabledChanged(bool enabled) => this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint);
} }

View File

@ -13,12 +13,14 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Overlays.BeatmapSet.Buttons;
using osu.Game.Overlays.Direct;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using DownloadButton = osu.Game.Overlays.BeatmapSet.Buttons.DownloadButton;
namespace osu.Game.Overlays.BeatmapSet namespace osu.Game.Overlays.BeatmapSet
{ {
public class Header : Container public class Header : DownloadTrackingComposite
{ {
private const float transition_duration = 200; private const float transition_duration = 200;
private const float tabs_height = 50; private const float tabs_height = 50;
@ -35,78 +37,16 @@ namespace osu.Game.Overlays.BeatmapSet
public readonly BeatmapPicker Picker; public readonly BeatmapPicker Picker;
private BeatmapSetInfo beatmapSet;
private readonly FavouriteButton favouriteButton; private readonly FavouriteButton favouriteButton;
public BeatmapSetInfo BeatmapSet
{
get { return beatmapSet; }
set
{
if (value == beatmapSet) return;
beatmapSet = value;
Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = BeatmapSet;
updateDisplay();
}
}
private BeatmapSetDownloader downloader;
private void updateDisplay()
{
downloader?.Expire();
title.Text = BeatmapSet?.Metadata.Title ?? string.Empty;
artist.Text = BeatmapSet?.Metadata.Artist ?? string.Empty;
onlineStatusPill.Status = BeatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None;
cover.BeatmapSet = BeatmapSet;
if (BeatmapSet != null)
{
downloadButtonsContainer.FadeIn(transition_duration);
favouriteButton.FadeIn(transition_duration);
Add(downloader = new BeatmapSetDownloader(BeatmapSet));
downloader.DownloadState.BindValueChanged(state =>
{
switch (state)
{
case BeatmapSetDownloader.DownloadStatus.Downloaded:
// temporary for UX until new design is implemented.
downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet)
{
Width = 50,
RelativeSizeAxes = Axes.Y
};
break;
case BeatmapSetDownloader.DownloadStatus.Downloading:
// temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design.
downloadButtonsContainer.Child = new DownloadButton(BeatmapSet);
break;
default:
downloadButtonsContainer.Child = new DownloadButton(BeatmapSet);
if (BeatmapSet.OnlineInfo.HasVideo)
downloadButtonsContainer.Add(new DownloadButton(BeatmapSet, true));
break;
}
}, true);
}
else
{
downloadButtonsContainer.FadeOut(transition_duration);
favouriteButton.FadeOut(transition_duration);
}
}
public Header() public Header()
{ {
ExternalLinkButton externalLink; ExternalLinkButton externalLink;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = 400; Height = 400;
Masking = true; Masking = true;
EdgeEffect = new EdgeEffectParameters EdgeEffect = new EdgeEffectParameters
{ {
Colour = Color4.Black.Opacity(0.25f), Colour = Color4.Black.Opacity(0.25f),
@ -114,7 +54,8 @@ namespace osu.Game.Overlays.BeatmapSet
Radius = 3, Radius = 3,
Offset = new Vector2(0f, 1f), Offset = new Vector2(0f, 1f),
}; };
Children = new Drawable[]
InternalChildren = new Drawable[]
{ {
new Container new Container
{ {
@ -241,14 +182,64 @@ namespace osu.Game.Overlays.BeatmapSet
}; };
Picker.Beatmap.ValueChanged += b => Details.Beatmap = b; Picker.Beatmap.ValueChanged += b => Details.Beatmap = b;
Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet?.OnlineBeatmapSetID}#{b?.Ruleset.ShortName}/{b?.OnlineBeatmapID}"; Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet.Value?.OnlineBeatmapSetID}#{b?.Ruleset.ShortName}/{b?.OnlineBeatmapID}";
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
tabsBg.Colour = colours.Gray3; tabsBg.Colour = colours.Gray3;
updateDisplay();
BeatmapSet.BindValueChanged(beatmapSet =>
{
Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = beatmapSet;
title.Text = beatmapSet?.Metadata.Title ?? string.Empty;
artist.Text = beatmapSet?.Metadata.Artist ?? string.Empty;
onlineStatusPill.Status = beatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None;
cover.BeatmapSet = beatmapSet;
if (beatmapSet != null)
{
downloadButtonsContainer.FadeIn(transition_duration);
favouriteButton.FadeIn(transition_duration);
}
else
{
downloadButtonsContainer.FadeOut(transition_duration);
favouriteButton.FadeOut(transition_duration);
}
updateDownloadButtons();
});
State.BindValueChanged(_ => updateDownloadButtons(), true);
}
private void updateDownloadButtons()
{
if (BeatmapSet.Value == null) return;
switch (State.Value)
{
case DownloadState.LocallyAvailable:
// temporary for UX until new design is implemented.
downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet)
{
Width = 50,
RelativeSizeAxes = Axes.Y
};
break;
case DownloadState.Downloading:
case DownloadState.Downloaded:
// temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design.
downloadButtonsContainer.Child = new DownloadButton(BeatmapSet);
break;
default:
downloadButtonsContainer.Child = new DownloadButton(BeatmapSet);
if (BeatmapSet.Value.OnlineInfo.HasVideo)
downloadButtonsContainer.Add(new DownloadButton(BeatmapSet, true));
break;
}
} }
} }
} }

View File

@ -46,7 +46,7 @@ namespace osu.Game.Overlays
if (value == beatmapSet) if (value == beatmapSet)
return; return;
header.BeatmapSet = info.BeatmapSet = beatmapSet = value; header.BeatmapSet.Value = info.BeatmapSet = beatmapSet = value;
} }
} }
@ -140,7 +140,7 @@ namespace osu.Game.Overlays
req.Success += res => req.Success += res =>
{ {
BeatmapSet = res.ToBeatmapSet(rulesets); BeatmapSet = res.ToBeatmapSet(rulesets);
header.Picker.Beatmap.Value = header.BeatmapSet.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();

View File

@ -5,103 +5,114 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps; 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.UserInterface; using osu.Game.Graphics.UserInterface;
using osuTK; using osuTK;
namespace osu.Game.Overlays.Direct namespace osu.Game.Overlays.Direct
{ {
public class DownloadButton : OsuAnimatedButton public class DownloadButton : DownloadTrackingComposite
{ {
private readonly BeatmapSetInfo beatmapSet; private readonly bool noVideo;
private readonly SpriteIcon icon; private readonly SpriteIcon icon;
private readonly SpriteIcon checkmark; private readonly SpriteIcon checkmark;
private readonly BeatmapSetDownloader downloader;
private readonly Box background; private readonly Box background;
private OsuColour colours; private OsuColour colours;
public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) private readonly ShakeContainer shakeContainer;
{
this.beatmapSet = beatmapSet;
AddRange(new Drawable[] private readonly OsuAnimatedButton button;
public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false)
: base(beatmapSet)
{
this.noVideo = noVideo;
InternalChild = shakeContainer = new ShakeContainer
{ {
downloader = new BeatmapSetDownloader(beatmapSet, noVideo), RelativeSizeAxes = Axes.Both,
background = new Box Child = button = new OsuAnimatedButton
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Depth = float.MaxValue Children = new Drawable[]
}, {
icon = new SpriteIcon background = new Box
{ {
Anchor = Anchor.Centre, RelativeSizeAxes = Axes.Both,
Origin = Anchor.Centre, Depth = float.MaxValue
Size = new Vector2(13), },
Icon = FontAwesome.fa_download, icon = new SpriteIcon
}, {
checkmark = new SpriteIcon Anchor = Anchor.Centre,
{ Origin = Anchor.Centre,
Anchor = Anchor.Centre, Size = new Vector2(13),
Origin = Anchor.Centre, Icon = FontAwesome.fa_download,
X = 8, },
Size = Vector2.Zero, checkmark = new SpriteIcon
Icon = FontAwesome.fa_check, {
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
X = 8,
Size = Vector2.Zero,
Icon = FontAwesome.fa_check,
}
}
} }
}); };
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
downloader.DownloadState.BindValueChanged(updateState, true);
State.BindValueChanged(updateState, true);
FinishTransforms(true); FinishTransforms(true);
} }
[BackgroundDependencyLoader(permitNulls: true)] [BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuColour colours, OsuGame game) private void load(OsuColour colours, OsuGame game, BeatmapManager beatmaps)
{ {
this.colours = colours; this.colours = colours;
Action = () => button.Action = () =>
{ {
switch (downloader.DownloadState.Value) switch (State.Value)
{ {
case BeatmapSetDownloader.DownloadStatus.Downloading: case DownloadState.Downloading:
// todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged. case DownloadState.Downloaded:
Content.MoveToX(-5, 50, Easing.OutSine).Then() shakeContainer.Shake();
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
break; break;
case BeatmapSetDownloader.DownloadStatus.Downloaded: case DownloadState.LocallyAvailable:
game.PresentBeatmap(beatmapSet); game.PresentBeatmap(BeatmapSet);
break; break;
default: default:
downloader.Download(); beatmaps.Download(BeatmapSet, noVideo);
break; break;
} }
}; };
} }
private void updateState(BeatmapSetDownloader.DownloadStatus state) private void updateState(DownloadState state)
{ {
switch (state) switch (state)
{ {
case BeatmapSetDownloader.DownloadStatus.NotDownloaded: case DownloadState.NotDownloaded:
background.FadeColour(colours.Gray4, 500, Easing.InOutExpo); background.FadeColour(colours.Gray4, 500, Easing.InOutExpo);
icon.MoveToX(0, 500, Easing.InOutExpo); icon.MoveToX(0, 500, Easing.InOutExpo);
checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo);
break; break;
case BeatmapSetDownloader.DownloadStatus.Downloading: case DownloadState.Downloading:
background.FadeColour(colours.Blue, 500, Easing.InOutExpo); background.FadeColour(colours.Blue, 500, Easing.InOutExpo);
icon.MoveToX(0, 500, Easing.InOutExpo); icon.MoveToX(0, 500, Easing.InOutExpo);
checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo);
break; break;
case DownloadState.Downloaded:
case BeatmapSetDownloader.DownloadStatus.Downloaded: background.FadeColour(colours.Yellow, 500, Easing.InOutExpo);
break;
case DownloadState.LocallyAvailable:
background.FadeColour(colours.Green, 500, Easing.InOutExpo); background.FadeColour(colours.Green, 500, Easing.InOutExpo);
icon.MoveToX(-8, 500, Easing.InOutExpo); icon.MoveToX(-8, 500, Easing.InOutExpo);
checkmark.ScaleTo(new Vector2(13), 500, Easing.InOutExpo); checkmark.ScaleTo(new Vector2(13), 500, Easing.InOutExpo);

View File

@ -11,14 +11,12 @@ using osuTK.Graphics;
namespace osu.Game.Overlays.Direct namespace osu.Game.Overlays.Direct
{ {
public class DownloadProgressBar : DownloadTrackingComponent public class DownloadProgressBar : DownloadTrackingComposite
{ {
private readonly ProgressBar progressBar; private readonly ProgressBar progressBar;
private OsuColour colours; public DownloadProgressBar(BeatmapSetInfo beatmapSet)
: base(beatmapSet)
public DownloadProgressBar(BeatmapSetInfo setInfo)
: base(setInfo)
{ {
AddInternal(progressBar = new ProgressBar AddInternal(progressBar = new ProgressBar
{ {
@ -33,38 +31,31 @@ namespace osu.Game.Overlays.Direct
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
this.colours = colours;
progressBar.FillColour = colours.Blue; progressBar.FillColour = colours.Blue;
progressBar.BackgroundColour = Color4.Black.Opacity(0.7f); progressBar.BackgroundColour = Color4.Black.Opacity(0.7f);
} progressBar.Current = Progress;
protected override void DownloadFailed() State.BindValueChanged(state =>
{ {
progressBar.Current.Value = 0; switch (state)
progressBar.FadeOut(500); {
} case DownloadState.NotDownloaded:
progressBar.Current.Value = 0;
protected override void DownloadComleted() progressBar.FadeOut(500);
{ break;
progressBar.Current.Value = 1; case DownloadState.Downloading:
progressBar.FillColour = colours.Yellow; progressBar.FadeIn(400, Easing.OutQuint);
} progressBar.ResizeHeightTo(4, 400, Easing.OutQuint);
break;
protected override void DownloadStarted() case DownloadState.Downloaded:
{ progressBar.Current.Value = 1;
progressBar.FadeIn(400, Easing.OutQuint); progressBar.FillColour = colours.Yellow;
progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); break;
} case DownloadState.LocallyAvailable:
progressBar.FadeOut(500);
protected override void BeatmapImported() break;
{ }
progressBar.FadeOut(500); }, true);
}
protected override void ProgressChanged(float progress)
{
progressBar.Current.Value = progress;
} }
} }
} }

View File

@ -1,21 +1,56 @@
// Copyright (c) 2007-2019 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using Microsoft.EntityFrameworkCore.Internal;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
namespace osu.Game.Overlays.Direct namespace osu.Game.Overlays.Direct
{ {
public abstract class DownloadTrackingComponent : CompositeDrawable public abstract class DownloadTrackingComposite : CompositeDrawable
{ {
private readonly BeatmapSetInfo setInfo; public readonly Bindable<BeatmapSetInfo> BeatmapSet = new Bindable<BeatmapSetInfo>();
private BeatmapManager beatmaps; private BeatmapManager beatmaps;
protected DownloadTrackingComponent(BeatmapSetInfo beatmapSetInfo) /// <summary>
/// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded.
/// </summary>
protected readonly Bindable<DownloadState> State = new Bindable<DownloadState>();
protected readonly Bindable<double> Progress = new Bindable<double>();
protected DownloadTrackingComposite(BeatmapSetInfo beatmapSet = null)
{ {
setInfo = beatmapSetInfo; BeatmapSet.Value = beatmapSet;
}
[BackgroundDependencyLoader(true)]
private void load(BeatmapManager beatmaps)
{
this.beatmaps = beatmaps;
BeatmapSet.BindValueChanged(set =>
{
if (set == null)
attachDownload(null);
else if (beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID).Any())
State.Value = DownloadState.LocallyAvailable;
else
attachDownload(beatmaps.GetExistingDownload(set));
}, true);
beatmaps.BeatmapDownloadBegan += download =>
{
if (download.BeatmapSet.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID)
attachDownload(download);
};
beatmaps.ItemAdded += setAdded;
} }
#region Disposal #region Disposal
@ -29,49 +64,62 @@ namespace osu.Game.Overlays.Direct
#endregion #endregion
[BackgroundDependencyLoader(true)] private DownloadBeatmapSetRequest attachedRequest;
private void load(BeatmapManager beatmaps)
{
this.beatmaps = beatmaps;
var downloadRequest = beatmaps.GetExistingDownload(setInfo);
if (downloadRequest != null)
attachDownload(downloadRequest);
beatmaps.BeatmapDownloadBegan += attachDownload;
beatmaps.ItemAdded += setAdded;
}
private void attachDownload(DownloadBeatmapSetRequest request) private void attachDownload(DownloadBeatmapSetRequest request)
{ {
if (request.BeatmapSet.OnlineBeatmapSetID != setInfo.OnlineBeatmapSetID) if (attachedRequest != null)
return; {
attachedRequest.Failure -= onRequestFailure;
attachedRequest.DownloadProgressed -= onRequestProgress;
attachedRequest.Success -= onRequestSuccess;
}
DownloadStarted(); attachedRequest = request;
request.Failure += e => { DownloadFailed(); }; if (attachedRequest != null)
{
request.DownloadProgressed += progress => Schedule(() => ProgressChanged(progress)); State.Value = DownloadState.Downloading;
request.Success += data => { DownloadComleted(); }; attachedRequest.Failure += onRequestFailure;
attachedRequest.DownloadProgressed += onRequestProgress;
attachedRequest.Success += onRequestSuccess;
}
else
{
State.Value = DownloadState.NotDownloaded;
}
} }
protected abstract void ProgressChanged(float progress); private void onRequestSuccess(byte[] data)
{
Schedule(() => State.Value = DownloadState.Downloaded);
attachDownload(null);
}
protected abstract void DownloadFailed(); private void onRequestProgress(float progress)
{
Schedule(() => Progress.Value = progress);
}
protected abstract void DownloadComleted(); private void onRequestFailure(Exception e)
{
protected abstract void BeatmapImported(); Schedule(() => State.Value = DownloadState.Downloading);
}
protected abstract void DownloadStarted();
private void setAdded(BeatmapSetInfo s, bool existing, bool silent) private void setAdded(BeatmapSetInfo s, bool existing, bool silent)
{ {
if (s.OnlineBeatmapSetID != setInfo.OnlineBeatmapSetID) if (s.OnlineBeatmapSetID != BeatmapSet.Value?.OnlineBeatmapSetID)
return; return;
Schedule(BeatmapImported); Schedule(() => State.Value = DownloadState.LocallyAvailable);
} }
} }
}
public enum DownloadState
{
NotDownloaded,
Downloading,
Downloaded,
LocallyAvailable
}
}