1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 18:42:56 +08:00

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 Action<float> DownloadProgressed;
public event Action<float> DownloadProgressed;
private readonly bool noVideo;

View File

@ -7,8 +7,8 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API;
using osu.Game.Overlays.Direct;
@ -18,75 +18,100 @@ using osuTK.Graphics;
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>();
public DownloadButton(BeatmapSetInfo set, bool noVideo = false)
{
Width = 120;
private ShakeContainer shakeContainer;
private HeaderButton button;
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;
AddRange(new Drawable[]
AddRangeInternal(new Drawable[]
{
new Container
shakeContainer = new ShakeContainer
{
Depth = -1,
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Horizontal = 10 },
Masking = true,
CornerRadius = 5,
Children = new Drawable[]
{
downloader = new BeatmapSetDownloader(set, noVideo),
textSprites = new FillFlowContainer
button = new HeaderButton { RelativeSizeAxes = Axes.Both },
new Container
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
AutoSizeAxes = Axes.Both,
AutoSizeDuration = 500,
AutoSizeEasing = Easing.OutQuint,
Direction = FillDirection.Vertical,
// cannot nest inside here due to the structure of button (putting things in its own content).
// requires framework fix.
Padding = new MarginPadding { Horizontal = 10 },
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
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,
Origin = Anchor.CentreRight,
Icon = FontAwesome.fa_download,
Size = new Vector2(16),
Margin = new MarginPadding { Right = 5 },
Depth = -2,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
},
},
},
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()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
shakeContainer.Shake();
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)
{
case BeatmapSetDownloader.DownloadStatus.Downloading:
case DownloadState.Downloading:
textSprites.Children = new Drawable[]
{
new OsuSpriteText
@ -97,10 +122,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
},
};
break;
case BeatmapSetDownloader.DownloadStatus.Downloaded:
case DownloadState.Downloaded:
this.FadeOut(200);
break;
case BeatmapSetDownloader.DownloadStatus.NotDownloaded:
case DownloadState.NotDownloaded:
textSprites.Children = new Drawable[]
{
new OsuSpriteText
@ -111,7 +136,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
},
new OsuSpriteText
{
Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty,
Text = BeatmapSet.Value.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty,
TextSize = 11,
Font = @"Exo2.0-Bold",
},
@ -119,20 +144,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
this.FadeIn(200);
break;
}
};
downloader.DownloadState.TriggerChange();
}, true);
}
[BackgroundDependencyLoader]
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 userChanged(User user) => button.Enabled.Value = user.IsSupporter;
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.UserInterface;
using osu.Game.Overlays.BeatmapSet.Buttons;
using osu.Game.Overlays.Direct;
using osuTK;
using osuTK.Graphics;
using DownloadButton = osu.Game.Overlays.BeatmapSet.Buttons.DownloadButton;
namespace osu.Game.Overlays.BeatmapSet
{
public class Header : Container
public class Header : DownloadTrackingComposite
{
private const float transition_duration = 200;
private const float tabs_height = 50;
@ -35,78 +37,16 @@ namespace osu.Game.Overlays.BeatmapSet
public readonly BeatmapPicker Picker;
private BeatmapSetInfo beatmapSet;
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()
{
ExternalLinkButton externalLink;
RelativeSizeAxes = Axes.X;
Height = 400;
Masking = true;
EdgeEffect = new EdgeEffectParameters
{
Colour = Color4.Black.Opacity(0.25f),
@ -114,7 +54,8 @@ namespace osu.Game.Overlays.BeatmapSet
Radius = 3,
Offset = new Vector2(0f, 1f),
};
Children = new Drawable[]
InternalChildren = new Drawable[]
{
new Container
{
@ -241,14 +182,64 @@ namespace osu.Game.Overlays.BeatmapSet
};
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]
private void load(OsuColour colours)
{
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)
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 =>
{
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);
Show();

View File

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

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
using System;
using Microsoft.EntityFrameworkCore.Internal;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests;
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;
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
@ -29,49 +64,62 @@ namespace osu.Game.Overlays.Direct
#endregion
[BackgroundDependencyLoader(true)]
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 DownloadBeatmapSetRequest attachedRequest;
private void attachDownload(DownloadBeatmapSetRequest request)
{
if (request.BeatmapSet.OnlineBeatmapSetID != setInfo.OnlineBeatmapSetID)
return;
if (attachedRequest != null)
{
attachedRequest.Failure -= onRequestFailure;
attachedRequest.DownloadProgressed -= onRequestProgress;
attachedRequest.Success -= onRequestSuccess;
}
DownloadStarted();
attachedRequest = request;
request.Failure += e => { DownloadFailed(); };
request.DownloadProgressed += progress => Schedule(() => ProgressChanged(progress));
request.Success += data => { DownloadComleted(); };
if (attachedRequest != null)
{
State.Value = DownloadState.Downloading;
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();
protected abstract void BeatmapImported();
protected abstract void DownloadStarted();
private void onRequestFailure(Exception e)
{
Schedule(() => State.Value = DownloadState.Downloading);
}
private void setAdded(BeatmapSetInfo s, bool existing, bool silent)
{
if (s.OnlineBeatmapSetID != setInfo.OnlineBeatmapSetID)
if (s.OnlineBeatmapSetID != BeatmapSet.Value?.OnlineBeatmapSetID)
return;
Schedule(BeatmapImported);
Schedule(() => State.Value = DownloadState.LocallyAvailable);
}
}
}
public enum DownloadState
{
NotDownloaded,
Downloading,
Downloaded,
LocallyAvailable
}
}