Change PlaylistOverlay to use ILive

This commit is contained in:
Dean Herbert
2022-01-26 12:19:05 +09:00
parent 64914c45a4
commit dda513dd08
6 changed files with 76 additions and 64 deletions

View File

@ -8,6 +8,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Overlays.Music; using osu.Game.Overlays.Music;
using osu.Game.Tests.Resources; using osu.Game.Tests.Resources;
@ -18,11 +19,11 @@ namespace osu.Game.Tests.Visual.UserInterface
{ {
public class TestScenePlaylistOverlay : OsuManualInputManagerTestScene public class TestScenePlaylistOverlay : OsuManualInputManagerTestScene
{ {
private readonly BindableList<BeatmapSetInfo> beatmapSets = new BindableList<BeatmapSetInfo>(); private readonly BindableList<ILive<BeatmapSetInfo>> beatmapSets = new BindableList<ILive<BeatmapSetInfo>>();
private PlaylistOverlay playlistOverlay; private PlaylistOverlay playlistOverlay;
private BeatmapSetInfo first; private ILive<BeatmapSetInfo> first;
[SetUp] [SetUp]
public void Setup() => Schedule(() => public void Setup() => Schedule(() =>
@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual.UserInterface
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
beatmapSets.Add(TestResources.CreateTestBeatmapSetInfo()); beatmapSets.Add(TestResources.CreateTestBeatmapSetInfo().ToLiveUnmanaged());
} }
first = beatmapSets.First(); first = beatmapSets.First();
@ -60,7 +61,7 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("hold 1st item handle", () => AddStep("hold 1st item handle", () =>
{ {
var handle = this.ChildrenOfType<OsuRearrangeableListItem<BeatmapSetInfo>.PlaylistItemHandle>().First(); var handle = this.ChildrenOfType<OsuRearrangeableListItem<ILive<BeatmapSetInfo>>.PlaylistItemHandle>().First();
InputManager.MoveMouseTo(handle.ScreenSpaceDrawQuad.Centre); InputManager.MoveMouseTo(handle.ScreenSpaceDrawQuad.Centre);
InputManager.PressButton(MouseButton.Left); InputManager.PressButton(MouseButton.Left);
}); });

View File

@ -25,7 +25,7 @@ namespace osu.Game.Collections
/// <summary> /// <summary>
/// The beatmaps contained by the collection. /// The beatmaps contained by the collection.
/// </summary> /// </summary>
public readonly BindableList<IBeatmapInfo> Beatmaps = new BindableList<IBeatmapInfo>(); public readonly BindableList<BeatmapInfo> Beatmaps = new BindableList<BeatmapInfo>();
/// <summary> /// <summary>
/// The date when this collection was last modified. /// The date when this collection was last modified.

View File

@ -38,7 +38,7 @@ namespace osu.Game.Collections
} }
private readonly IBindableList<BeatmapCollection> collections = new BindableList<BeatmapCollection>(); private readonly IBindableList<BeatmapCollection> collections = new BindableList<BeatmapCollection>();
private readonly IBindableList<IBeatmapInfo> beatmaps = new BindableList<IBeatmapInfo>(); private readonly IBindableList<BeatmapInfo> beatmaps = new BindableList<BeatmapInfo>();
private readonly BindableList<CollectionFilterMenuItem> filters = new BindableList<CollectionFilterMenuItem>(); private readonly BindableList<CollectionFilterMenuItem> filters = new BindableList<CollectionFilterMenuItem>();
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
@ -196,7 +196,7 @@ namespace osu.Game.Collections
private IBindable<WorkingBeatmap> beatmap { get; set; } private IBindable<WorkingBeatmap> beatmap { get; set; }
[CanBeNull] [CanBeNull]
private readonly BindableList<IBeatmapInfo> collectionBeatmaps; private readonly BindableList<BeatmapInfo> collectionBeatmaps;
[NotNull] [NotNull]
private readonly Bindable<string> collectionName; private readonly Bindable<string> collectionName;

View File

@ -7,16 +7,17 @@ using osu.Framework.Bindables;
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;
using osu.Game.Database;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osuTK; using osuTK;
namespace osu.Game.Overlays.Music namespace osu.Game.Overlays.Music
{ {
public class Playlist : OsuRearrangeableListContainer<BeatmapSetInfo> public class Playlist : OsuRearrangeableListContainer<ILive<BeatmapSetInfo>>
{ {
public Action<BeatmapSetInfo> RequestSelection; public Action<ILive<BeatmapSetInfo>> RequestSelection;
public readonly Bindable<BeatmapSetInfo> SelectedSet = new Bindable<BeatmapSetInfo>(); public readonly Bindable<ILive<BeatmapSetInfo>> SelectedSet = new Bindable<ILive<BeatmapSetInfo>>();
public new MarginPadding Padding public new MarginPadding Padding
{ {
@ -26,23 +27,23 @@ namespace osu.Game.Overlays.Music
public void Filter(FilterCriteria criteria) public void Filter(FilterCriteria criteria)
{ {
var items = (SearchContainer<RearrangeableListItem<BeatmapSetInfo>>)ListContainer; var items = (SearchContainer<RearrangeableListItem<ILive<BeatmapSetInfo>>>)ListContainer;
foreach (var item in items.OfType<PlaylistItem>()) foreach (var item in items.OfType<PlaylistItem>())
item.InSelectedCollection = criteria.Collection?.Beatmaps.Any(b => item.Model.Equals(b.BeatmapSet)) ?? true; item.InSelectedCollection = criteria.Collection?.Beatmaps.Any(b => item.Model.ID == b.BeatmapSet?.ID) ?? true;
items.SearchTerm = criteria.SearchText; items.SearchTerm = criteria.SearchText;
} }
public BeatmapSetInfo FirstVisibleSet => Items.FirstOrDefault(i => ((PlaylistItem)ItemMap[i]).MatchingFilter); public ILive<BeatmapSetInfo> FirstVisibleSet => Items.FirstOrDefault(i => ((PlaylistItem)ItemMap[i]).MatchingFilter);
protected override OsuRearrangeableListItem<BeatmapSetInfo> CreateOsuDrawable(BeatmapSetInfo item) => new PlaylistItem(item) protected override OsuRearrangeableListItem<ILive<BeatmapSetInfo>> CreateOsuDrawable(ILive<BeatmapSetInfo> item) => new PlaylistItem(item)
{ {
SelectedSet = { BindTarget = SelectedSet }, SelectedSet = { BindTarget = SelectedSet },
RequestSelection = set => RequestSelection?.Invoke(set) RequestSelection = set => RequestSelection?.Invoke(set)
}; };
protected override FillFlowContainer<RearrangeableListItem<BeatmapSetInfo>> CreateListFillFlowContainer() => new SearchContainer<RearrangeableListItem<BeatmapSetInfo>> protected override FillFlowContainer<RearrangeableListItem<ILive<BeatmapSetInfo>>> CreateListFillFlowContainer() => new SearchContainer<RearrangeableListItem<ILive<BeatmapSetInfo>>>
{ {
Spacing = new Vector2(0, 3), Spacing = new Vector2(0, 3),
LayoutDuration = 200, LayoutDuration = 200,

View File

@ -10,17 +10,18 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Overlays.Music namespace osu.Game.Overlays.Music
{ {
public class PlaylistItem : OsuRearrangeableListItem<BeatmapSetInfo>, IFilterable public class PlaylistItem : OsuRearrangeableListItem<ILive<BeatmapSetInfo>>, IFilterable
{ {
public readonly Bindable<BeatmapSetInfo> SelectedSet = new Bindable<BeatmapSetInfo>(); public readonly Bindable<ILive<BeatmapSetInfo>> SelectedSet = new Bindable<ILive<BeatmapSetInfo>>();
public Action<BeatmapSetInfo> RequestSelection; public Action<ILive<BeatmapSetInfo>> RequestSelection;
private TextFlowContainer text; private TextFlowContainer text;
private ITextPart titlePart; private ITextPart titlePart;
@ -28,7 +29,7 @@ namespace osu.Game.Overlays.Music
[Resolved] [Resolved]
private OsuColour colours { get; set; } private OsuColour colours { get; set; }
public PlaylistItem(BeatmapSetInfo item) public PlaylistItem(ILive<BeatmapSetInfo> item)
: base(item) : base(item)
{ {
Padding = new MarginPadding { Left = 5 }; Padding = new MarginPadding { Left = 5 };
@ -44,34 +45,37 @@ namespace osu.Game.Overlays.Music
{ {
base.LoadComplete(); base.LoadComplete();
var metadata = Model.Metadata; Model.PerformRead(m =>
var title = new RomanisableString(metadata.TitleUnicode, metadata.Title);
var artist = new RomanisableString(metadata.ArtistUnicode, metadata.Artist);
titlePart = text.AddText(title, sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular));
titlePart.DrawablePartsRecreated += _ => updateSelectionState(true);
text.AddText(@" "); // to separate the title from the artist.
text.AddText(artist, sprite =>
{ {
sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); var metadata = m.Metadata;
sprite.Colour = colours.Gray9;
sprite.Padding = new MarginPadding { Top = 1 }; var title = new RomanisableString(metadata.TitleUnicode, metadata.Title);
var artist = new RomanisableString(metadata.ArtistUnicode, metadata.Artist);
titlePart = text.AddText(title, sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular));
titlePart.DrawablePartsRecreated += _ => updateSelectionState(true);
text.AddText(@" "); // to separate the title from the artist.
text.AddText(artist, sprite =>
{
sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold);
sprite.Colour = colours.Gray9;
sprite.Padding = new MarginPadding { Top = 1 };
});
SelectedSet.BindValueChanged(set =>
{
bool newSelected = set.NewValue?.Equals(Model) == true;
if (newSelected == selected)
return;
selected = newSelected;
updateSelectionState(false);
});
updateSelectionState(true);
}); });
SelectedSet.BindValueChanged(set =>
{
bool newSelected = set.NewValue?.Equals(Model) == true;
if (newSelected == selected)
return;
selected = newSelected;
updateSelectionState(false);
});
updateSelectionState(true);
} }
private bool selected; private bool selected;
@ -109,7 +113,7 @@ namespace osu.Game.Overlays.Music
} }
} }
public IEnumerable<string> FilterTerms => Model.Metadata.GetSearchableTerms(); public IEnumerable<string> FilterTerms => Model.PerformRead(m => m.Metadata.GetSearchableTerms());
private bool matchingFilter = true; private bool matchingFilter = true;

View File

@ -24,9 +24,9 @@ namespace osu.Game.Overlays.Music
private const float transition_duration = 600; private const float transition_duration = 600;
private const float playlist_height = 510; private const float playlist_height = 510;
public IBindableList<BeatmapSetInfo> BeatmapSets => beatmapSets; public IBindableList<ILive<BeatmapSetInfo>> BeatmapSets => beatmapSets;
private readonly BindableList<BeatmapSetInfo> beatmapSets = new BindableList<BeatmapSetInfo>(); private readonly BindableList<ILive<BeatmapSetInfo>> beatmapSets = new BindableList<ILive<BeatmapSetInfo>>();
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>(); private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
@ -85,13 +85,16 @@ namespace osu.Game.Overlays.Music
filter.Search.OnCommit += (sender, newText) => filter.Search.OnCommit += (sender, newText) =>
{ {
BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps.FirstOrDefault(); list.FirstVisibleSet.PerformRead(set =>
if (toSelect != null)
{ {
beatmap.Value = beatmaps.GetWorkingBeatmap(toSelect); BeatmapInfo toSelect = set.Beatmaps.FirstOrDefault();
beatmap.Value.Track.Restart();
} if (toSelect != null)
{
beatmap.Value = beatmaps.GetWorkingBeatmap(toSelect);
beatmap.Value.Track.Restart();
}
});
}; };
} }
@ -104,7 +107,7 @@ namespace osu.Game.Overlays.Music
beatmapSubscription = realm.RegisterForNotifications(r => r.All<BeatmapSetInfo>().Where(s => !s.DeletePending), beatmapsChanged); beatmapSubscription = realm.RegisterForNotifications(r => r.All<BeatmapSetInfo>().Where(s => !s.DeletePending), beatmapsChanged);
list.Items.BindTo(beatmapSets); list.Items.BindTo(beatmapSets);
beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo, true); beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo.ToLive(realm), true);
} }
private void beatmapsChanged(IRealmCollection<BeatmapSetInfo> sender, ChangeSet changes, Exception error) private void beatmapsChanged(IRealmCollection<BeatmapSetInfo> sender, ChangeSet changes, Exception error)
@ -113,12 +116,12 @@ namespace osu.Game.Overlays.Music
{ {
beatmapSets.Clear(); beatmapSets.Clear();
// must use AddRange to avoid RearrangeableList sort overhead per add op. // must use AddRange to avoid RearrangeableList sort overhead per add op.
beatmapSets.AddRange(sender); beatmapSets.AddRange(sender.ToLive(realm));
return; return;
} }
foreach (int i in changes.InsertedIndices) foreach (int i in changes.InsertedIndices)
beatmapSets.Insert(i, sender[i]); beatmapSets.Insert(i, sender[i].ToLive(realm));
foreach (int i in changes.DeletedIndices.OrderByDescending(i => i)) foreach (int i in changes.DeletedIndices.OrderByDescending(i => i))
beatmapSets.RemoveAt(i); beatmapSets.RemoveAt(i);
@ -141,16 +144,19 @@ namespace osu.Game.Overlays.Music
this.FadeOut(transition_duration); this.FadeOut(transition_duration);
} }
private void itemSelected(BeatmapSetInfo set) private void itemSelected(ILive<BeatmapSetInfo> beatmapSet)
{ {
if (set.Equals((beatmap.Value?.BeatmapSetInfo))) beatmapSet.PerformRead(set =>
{ {
beatmap.Value?.Track.Seek(0); if (set.Equals((beatmap.Value?.BeatmapSetInfo)))
return; {
} beatmap.Value?.Track.Seek(0);
return;
}
beatmap.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First()); beatmap.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First());
beatmap.Value.Track.Restart(); beatmap.Value.Track.Restart();
});
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)