From 2b2cfd91a6a48b7804870f4dfb19753372b54e9a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 28 Jan 2020 17:59:14 +0900 Subject: [PATCH 1/8] Initial re-implementation using rearrangeable list --- .../UserInterface/TestScenePlaylistOverlay.cs | 59 ++++ osu.Game/Overlays/Music/PlaylistList.cs | 301 ++++-------------- osu.Game/Overlays/Music/PlaylistOverlay.cs | 12 +- 3 files changed, 135 insertions(+), 237 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs new file mode 100644 index 0000000000..a470244f53 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Overlays.Music; +using osuTK; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestScenePlaylistOverlay : OsuTestScene + { + private readonly BindableList beatmapSets = new BindableList(); + + [SetUp] + public void Setup() => Schedule(() => + { + PlaylistOverlay overlay; + + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(300, 500), + Child = overlay = new PlaylistOverlay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + State = { Value = Visibility.Visible } + } + }; + + beatmapSets.Clear(); + + for (int i = 0; i < 100; i++) + { + beatmapSets.Add(new BeatmapSetInfo + { + Metadata = new BeatmapMetadata + { + // Create random metadata, then we can check if sorting works based on these + Artist = "Some Artist " + RNG.Next(0, 9), + Title = $"Some Song {i + 1}", + AuthorString = "Some Guy " + RNG.Next(0, 9), + }, + DateAdded = DateTimeOffset.UtcNow, + }); + } + + overlay.BeatmapSets.BindTo(beatmapSets); + }); + } +} diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 7bdcab6dff..5c091a21db 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -6,30 +6,16 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; +using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; -using osu.Game.Graphics.Containers; -using osuTK; namespace osu.Game.Overlays.Music { - public class PlaylistList : CompositeDrawable + public class PlaylistList2 : BasicRearrangeableListContainer { - public Action Selected; - - private readonly ItemsScrollContainer items; - - public PlaylistList() - { - InternalChild = items = new ItemsScrollContainer - { - RelativeSizeAxes = Axes.Both, - Selected = set => Selected?.Invoke(set), - }; - } + public readonly BindableList BeatmapSets = new BindableList(); public new MarginPadding Padding { @@ -37,232 +23,81 @@ namespace osu.Game.Overlays.Music set => base.Padding = value; } - public BeatmapSetInfo FirstVisibleSet => items.FirstVisibleSet; - - public void Filter(string searchTerm) => items.SearchTerm = searchTerm; - - private class ItemsScrollContainer : OsuScrollContainer + [BackgroundDependencyLoader] + private void load() { - public Action Selected; + BeatmapSets.ItemsAdded += addBeatmapSets; + BeatmapSets.ItemsRemoved += removeBeatmapSets; + } - private readonly SearchContainer search; - private readonly FillFlowContainer items; + public void Filter(string searchTerm) => ((PlaylistListFlowContainer)ListContainer).SearchTerm = searchTerm; - private readonly IBindable beatmapBacking = new Bindable(); + public BeatmapSetInfo FirstVisibleSet => ListContainer.FlowingChildren.Cast().FirstOrDefault(i => i.MatchingFilter)?.Model.BeatmapSetInfo; - private IBindableList beatmaps; + private void addBeatmapSets(IEnumerable sets) => Schedule(() => + { + foreach (var item in sets) + AddItem(new PlaylistListItem(item)); + }); - [Resolved] - private MusicController musicController { get; set; } + private void removeBeatmapSets(IEnumerable sets) => Schedule(() => + { + foreach (var item in sets) + RemoveItem(ListContainer.Children.Select(d => d.Model).FirstOrDefault(m => m.BeatmapSetInfo == item)); + }); - public ItemsScrollContainer() + protected override BasicDrawableRearrangeableListItem CreateBasicItem(PlaylistListItem item) => new DrawablePlaylistListItem(item); + + protected override FillFlowContainer CreateListFillFlowContainer() => new PlaylistListFlowContainer + { + LayoutDuration = 200, + LayoutEasing = Easing.OutQuint + }; + } + + public class PlaylistListFlowContainer : SearchContainer.DrawableRearrangeableListItem> + { + } + + public class PlaylistListItem : IEquatable + { + public readonly BeatmapSetInfo BeatmapSetInfo; + + public PlaylistListItem(BeatmapSetInfo beatmapSetInfo) + { + BeatmapSetInfo = beatmapSetInfo; + } + + public override string ToString() => BeatmapSetInfo.ToString(); + + public bool Equals(PlaylistListItem other) => BeatmapSetInfo.Equals(other?.BeatmapSetInfo); + } + + public class DrawablePlaylistListItem : BasicRearrangeableListContainer.BasicDrawableRearrangeableListItem, IFilterable + { + public DrawablePlaylistListItem(PlaylistListItem item) + : base(item) + { + FilterTerms = item.BeatmapSetInfo.Metadata.SearchableTerms; + } + + public IEnumerable FilterTerms { get; } + + private bool matching = true; + + public bool MatchingFilter + { + get => matching; + set { - Children = new Drawable[] - { - search = new SearchContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - items = new ItemSearchContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - } - } - }; - } + if (matching == value) return; - [BackgroundDependencyLoader] - private void load(IBindable beatmap) - { - beatmaps = musicController.BeatmapSets.GetBoundCopy(); - beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); - beatmaps.ItemsRemoved += i => i.ForEach(removeBeatmapSet); - beatmaps.ForEach(addBeatmapSet); + matching = value; - beatmapBacking.BindTo(beatmap); - beatmapBacking.ValueChanged += _ => Scheduler.AddOnce(updateSelectedSet); - } - - private void addBeatmapSet(BeatmapSetInfo obj) - { - if (obj == draggedItem?.BeatmapSetInfo) return; - - Schedule(() => items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) })); - } - - private void removeBeatmapSet(BeatmapSetInfo obj) - { - if (obj == draggedItem?.BeatmapSetInfo) return; - - Schedule(() => - { - var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == obj.ID); - if (itemToRemove != null) - items.Remove(itemToRemove); - }); - } - - private void updateSelectedSet() - { - foreach (PlaylistItem s in items.Children) - { - s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo?.ID; - if (s.Selected) - ScrollIntoView(s); - } - } - - public string SearchTerm - { - get => search.SearchTerm; - set => search.SearchTerm = value; - } - - public BeatmapSetInfo FirstVisibleSet => items.FirstOrDefault(i => i.MatchingFilter)?.BeatmapSetInfo; - - private Vector2 nativeDragPosition; - private PlaylistItem draggedItem; - - private int? dragDestination; - - protected override bool OnDragStart(DragStartEvent e) - { - nativeDragPosition = e.ScreenSpaceMousePosition; - draggedItem = items.FirstOrDefault(d => d.IsDraggable); - return draggedItem != null || base.OnDragStart(e); - } - - protected override void OnDrag(DragEvent e) - { - nativeDragPosition = e.ScreenSpaceMousePosition; - - if (draggedItem == null) - base.OnDrag(e); - } - - protected override void OnDragEnd(DragEndEvent e) - { - nativeDragPosition = e.ScreenSpaceMousePosition; - - if (draggedItem == null) - { - base.OnDragEnd(e); - return; - } - - if (dragDestination != null) - musicController.ChangeBeatmapSetPosition(draggedItem.BeatmapSetInfo, dragDestination.Value); - - draggedItem = null; - dragDestination = null; - } - - protected override void Update() - { - base.Update(); - - if (draggedItem == null) - return; - - updateScrollPosition(); - updateDragPosition(); - } - - private void updateScrollPosition() - { - const float start_offset = 10; - const double max_power = 50; - const double exp_base = 1.05; - - var localPos = ToLocalSpace(nativeDragPosition); - - if (localPos.Y < start_offset) - { - if (Current <= 0) - return; - - var power = Math.Min(max_power, Math.Abs(start_offset - localPos.Y)); - ScrollBy(-(float)Math.Pow(exp_base, power)); - } - else if (localPos.Y > DrawHeight - start_offset) - { - if (IsScrolledToEnd()) - return; - - var power = Math.Min(max_power, Math.Abs(DrawHeight - start_offset - localPos.Y)); - ScrollBy((float)Math.Pow(exp_base, power)); - } - } - - private void updateDragPosition() - { - var itemsPos = items.ToLocalSpace(nativeDragPosition); - - int srcIndex = (int)items.GetLayoutPosition(draggedItem); - - // Find the last item with position < mouse position. Note we can't directly use - // the item positions as they are being transformed - float heightAccumulator = 0; - int dstIndex = 0; - - for (; dstIndex < items.Count; dstIndex++) - { - // Using BoundingBox here takes care of scale, paddings, etc... - heightAccumulator += items[dstIndex].BoundingBox.Height; - if (heightAccumulator > itemsPos.Y) - break; - } - - dstIndex = Math.Clamp(dstIndex, 0, items.Count - 1); - - if (srcIndex == dstIndex) - return; - - if (srcIndex < dstIndex) - { - for (int i = srcIndex + 1; i <= dstIndex; i++) - items.SetLayoutPosition(items[i], i - 1); - } - else - { - for (int i = dstIndex; i < srcIndex; i++) - items.SetLayoutPosition(items[i], i + 1); - } - - items.SetLayoutPosition(draggedItem, dstIndex); - dragDestination = dstIndex; - } - - private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren - { - public IEnumerable FilterTerms => Array.Empty(); - - public bool MatchingFilter - { - set - { - if (value) - InvalidateLayout(); - } - } - - public bool FilteringActive - { - set { } - } - - public IEnumerable FilterableChildren => Children; - - public ItemSearchContainer() - { - LayoutDuration = 200; - LayoutEasing = Easing.OutQuint; - } + this.FadeTo(matching ? 1 : 0, 200); } } + + public bool FilteringActive { get; set; } } } diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index b89a577282..ff1b26e335 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -21,12 +21,14 @@ namespace osu.Game.Overlays.Music private const float transition_duration = 600; private const float playlist_height = 510; + public readonly BindableList BeatmapSets = new BindableList(); + private readonly Bindable beatmap = new Bindable(); private BeatmapManager beatmaps; private FilterControl filter; - private PlaylistList list; - + private PlaylistList2 list; + [BackgroundDependencyLoader] private void load(OsuColour colours, Bindable beatmap, BeatmapManager beatmaps) { @@ -53,11 +55,11 @@ namespace osu.Game.Overlays.Music Colour = colours.Gray3, RelativeSizeAxes = Axes.Both, }, - list = new PlaylistList + list = new PlaylistList2 { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = 95, Bottom = 10, Right = 10 }, - Selected = itemSelected, + // Selected = itemSelected, }, filter = new FilterControl { @@ -70,6 +72,8 @@ namespace osu.Game.Overlays.Music }, }; + list.BeatmapSets.BindTo(BeatmapSets); + filter.Search.OnCommit = (sender, newText) => { BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); From ebf15c6a1ceacb45aae17b8c384eb7daf2236581 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 29 Jan 2020 12:17:03 +0900 Subject: [PATCH 2/8] General work towards completion + framework updates --- .../UserInterface/TestScenePlaylistOverlay.cs | 7 + osu.Game/Overlays/Music/PlaylistList.cs | 197 ++++++++++++++++-- osu.Game/Overlays/Music/PlaylistOverlay.cs | 12 +- osu.Game/Overlays/NowPlayingOverlay.cs | 1 + 4 files changed, 200 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs index a470244f53..986cf458ab 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -15,6 +16,12 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestScenePlaylistOverlay : OsuTestScene { + public override IReadOnlyList RequiredTypes => new Type[] + { + typeof(PlaylistOverlay), + typeof(PlaylistList) + }; + private readonly BindableList beatmapSets = new BindableList(); [SetUp] diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 5c091a21db..f7be69e1f2 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -8,14 +8,23 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.Music { - public class PlaylistList2 : BasicRearrangeableListContainer + public class PlaylistList : RearrangeableListContainer { - public readonly BindableList BeatmapSets = new BindableList(); + public Action RequestSelection; + + public readonly Bindable SelectedSet = new Bindable(); + public readonly IBindableList BeatmapSets = new BindableList(); public new MarginPadding Padding { @@ -23,21 +32,35 @@ namespace osu.Game.Overlays.Music set => base.Padding = value; } + private readonly HashSet existingItems = new HashSet(); + [BackgroundDependencyLoader] private void load() { BeatmapSets.ItemsAdded += addBeatmapSets; BeatmapSets.ItemsRemoved += removeBeatmapSets; + + foreach (var item in BeatmapSets) + addBeatmapSet(item); } public void Filter(string searchTerm) => ((PlaylistListFlowContainer)ListContainer).SearchTerm = searchTerm; public BeatmapSetInfo FirstVisibleSet => ListContainer.FlowingChildren.Cast().FirstOrDefault(i => i.MatchingFilter)?.Model.BeatmapSetInfo; - private void addBeatmapSets(IEnumerable sets) => Schedule(() => + private void addBeatmapSets(IEnumerable sets) { - foreach (var item in sets) - AddItem(new PlaylistListItem(item)); + foreach (var set in sets) + addBeatmapSet(set); + } + + private void addBeatmapSet(BeatmapSetInfo set) => Schedule(() => + { + if (existingItems.Contains(set)) + return; + + AddItem(new PlaylistListItem(set)); + existingItems.Add(set); }); private void removeBeatmapSets(IEnumerable sets) => Schedule(() => @@ -46,16 +69,23 @@ namespace osu.Game.Overlays.Music RemoveItem(ListContainer.Children.Select(d => d.Model).FirstOrDefault(m => m.BeatmapSetInfo == item)); }); - protected override BasicDrawableRearrangeableListItem CreateBasicItem(PlaylistListItem item) => new DrawablePlaylistListItem(item); - - protected override FillFlowContainer CreateListFillFlowContainer() => new PlaylistListFlowContainer + protected override DrawableRearrangeableListItem CreateDrawable(PlaylistListItem item) => new DrawablePlaylistListItem(item) { + SelectedSet = { BindTarget = SelectedSet }, + RequestSelection = set => RequestSelection?.Invoke(set) + }; + + protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer(); + + protected override FillFlowContainer> CreateListFillFlowContainer() => new PlaylistListFlowContainer + { + Spacing = new Vector2(0, 3), LayoutDuration = 200, - LayoutEasing = Easing.OutQuint + LayoutEasing = Easing.OutQuint, }; } - public class PlaylistListFlowContainer : SearchContainer.DrawableRearrangeableListItem> + public class PlaylistListFlowContainer : SearchContainer> { } @@ -73,14 +103,118 @@ namespace osu.Game.Overlays.Music public bool Equals(PlaylistListItem other) => BeatmapSetInfo.Equals(other?.BeatmapSetInfo); } - public class DrawablePlaylistListItem : BasicRearrangeableListContainer.BasicDrawableRearrangeableListItem, IFilterable + public class DrawablePlaylistListItem : DrawableRearrangeableListItem, IFilterable { + private const float fade_duration = 100; + + public readonly Bindable SelectedSet = new Bindable(); + public Action RequestSelection; + + private PlaylistItemHandle handle; + private TextFlowContainer text; + private IEnumerable titleSprites; + private ILocalisedBindableString titleBind; + private ILocalisedBindableString artistBind; + + private Color4 hoverColour; + private Color4 artistColour; + public DrawablePlaylistListItem(PlaylistListItem item) : base(item) { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Padding = new MarginPadding { Left = 5 }; + FilterTerms = item.BeatmapSetInfo.Metadata.SearchableTerms; } + [BackgroundDependencyLoader] + private void load(OsuColour colours, LocalisationManager localisation) + { + hoverColour = colours.Yellow; + artistColour = colours.Gray9; + + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Content = new[] + { + new Drawable[] + { + handle = new PlaylistItemHandle + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(12), + Colour = colours.Gray5, + Alpha = 0 + }, + text = new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = 5 }, + }, + } + }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } + }; + + titleBind = localisation.GetLocalisedString(new LocalisedString((Model.BeatmapSetInfo.Metadata.TitleUnicode, Model.BeatmapSetInfo.Metadata.Title))); + artistBind = localisation.GetLocalisedString(new LocalisedString((Model.BeatmapSetInfo.Metadata.ArtistUnicode, Model.BeatmapSetInfo.Metadata.Artist))); + + artistBind.BindValueChanged(_ => recreateText(), true); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + SelectedSet.BindValueChanged(set => + { + if (set.OldValue != Model.BeatmapSetInfo && set.NewValue != Model.BeatmapSetInfo) + return; + + foreach (Drawable s in titleSprites) + s.FadeColour(set.NewValue == Model.BeatmapSetInfo ? hoverColour : Color4.White, fade_duration); + }, true); + } + + private void recreateText() + { + text.Clear(); + + //space after the title to put a space between the title and artist + titleSprites = text.AddText(titleBind.Value + @" ", sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)).OfType(); + + text.AddText(artistBind.Value, sprite => + { + sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); + sprite.Colour = artistColour; + sprite.Padding = new MarginPadding { Top = 1 }; + }); + } + + protected override bool OnClick(ClickEvent e) + { + RequestSelection?.Invoke(Model.BeatmapSetInfo); + return true; + } + + protected override bool IsDraggableAt(Vector2 screenSpacePos) => handle.HandlingDrag; + + protected override bool OnHover(HoverEvent e) + { + handle.UpdateHoverState(true); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) => handle.UpdateHoverState(false); + public IEnumerable FilterTerms { get; } private bool matching = true; @@ -99,5 +233,44 @@ namespace osu.Game.Overlays.Music } public bool FilteringActive { get; set; } + + private class PlaylistItemHandle : SpriteIcon + { + public bool HandlingDrag { get; private set; } + private bool isHovering; + + public PlaylistItemHandle() + { + Icon = FontAwesome.Solid.Bars; + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + base.OnMouseDown(e); + + HandlingDrag = true; + UpdateHoverState(isHovering); + + return false; + } + + protected override void OnMouseUp(MouseUpEvent e) + { + base.OnMouseUp(e); + + HandlingDrag = false; + UpdateHoverState(isHovering); + } + + public void UpdateHoverState(bool hovering) + { + isHovering = hovering; + + if (isHovering || HandlingDrag) + this.FadeIn(fade_duration); + else + this.FadeOut(fade_duration); + } + } } } diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index ff1b26e335..87abbd142c 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -21,14 +21,14 @@ namespace osu.Game.Overlays.Music private const float transition_duration = 600; private const float playlist_height = 510; - public readonly BindableList BeatmapSets = new BindableList(); + public readonly IBindableList BeatmapSets = new BindableList(); private readonly Bindable beatmap = new Bindable(); private BeatmapManager beatmaps; private FilterControl filter; - private PlaylistList2 list; - + private PlaylistList list; + [BackgroundDependencyLoader] private void load(OsuColour colours, Bindable beatmap, BeatmapManager beatmaps) { @@ -55,11 +55,11 @@ namespace osu.Game.Overlays.Music Colour = colours.Gray3, RelativeSizeAxes = Axes.Both, }, - list = new PlaylistList2 + list = new PlaylistList { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = 95, Bottom = 10, Right = 10 }, - // Selected = itemSelected, + RequestSelection = itemSelected }, filter = new FilterControl { @@ -84,6 +84,8 @@ namespace osu.Game.Overlays.Music beatmap.Value.Track.Restart(); } }; + + beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo, true); } protected override void PopIn() diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 042e95c6d7..dfcf99d30c 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -183,6 +183,7 @@ namespace osu.Game.Overlays } }; + playlist.BeatmapSets.BindTo(musicController.BeatmapSets); playlist.State.ValueChanged += s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); } From f6ba98eec0f1087d9d7214681f41b8a35c1c47bd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Jan 2020 19:00:59 +0900 Subject: [PATCH 3/8] Apply refactorings for framework-side changes --- osu.Game/Overlays/Music/PlaylistList.cs | 70 +++++----------------- osu.Game/Overlays/Music/PlaylistOverlay.cs | 6 +- 2 files changed, 18 insertions(+), 58 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index f7be69e1f2..e183c14f10 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -19,12 +19,11 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Music { - public class PlaylistList : RearrangeableListContainer + public class PlaylistList : RearrangeableListContainer { public Action RequestSelection; public readonly Bindable SelectedSet = new Bindable(); - public readonly IBindableList BeatmapSets = new BindableList(); public new MarginPadding Padding { @@ -32,44 +31,17 @@ namespace osu.Game.Overlays.Music set => base.Padding = value; } - private readonly HashSet existingItems = new HashSet(); - - [BackgroundDependencyLoader] - private void load() - { - BeatmapSets.ItemsAdded += addBeatmapSets; - BeatmapSets.ItemsRemoved += removeBeatmapSets; - - foreach (var item in BeatmapSets) - addBeatmapSet(item); - } - public void Filter(string searchTerm) => ((PlaylistListFlowContainer)ListContainer).SearchTerm = searchTerm; - public BeatmapSetInfo FirstVisibleSet => ListContainer.FlowingChildren.Cast().FirstOrDefault(i => i.MatchingFilter)?.Model.BeatmapSetInfo; - - private void addBeatmapSets(IEnumerable sets) - { - foreach (var set in sets) - addBeatmapSet(set); - } - - private void addBeatmapSet(BeatmapSetInfo set) => Schedule(() => - { - if (existingItems.Contains(set)) - return; - - AddItem(new PlaylistListItem(set)); - existingItems.Add(set); - }); + public BeatmapSetInfo FirstVisibleSet => ListContainer.FlowingChildren.Cast().FirstOrDefault(i => i.MatchingFilter)?.Model; private void removeBeatmapSets(IEnumerable sets) => Schedule(() => { foreach (var item in sets) - RemoveItem(ListContainer.Children.Select(d => d.Model).FirstOrDefault(m => m.BeatmapSetInfo == item)); + Items.Remove(ListContainer.Children.Select(d => d.Model).FirstOrDefault(m => m == item)); }); - protected override DrawableRearrangeableListItem CreateDrawable(PlaylistListItem item) => new DrawablePlaylistListItem(item) + protected override DrawableRearrangeableListItem CreateDrawable(BeatmapSetInfo item) => new DrawablePlaylistListItem(item) { SelectedSet = { BindTarget = SelectedSet }, RequestSelection = set => RequestSelection?.Invoke(set) @@ -77,7 +49,7 @@ namespace osu.Game.Overlays.Music protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer(); - protected override FillFlowContainer> CreateListFillFlowContainer() => new PlaylistListFlowContainer + protected override FillFlowContainer> CreateListFillFlowContainer() => new PlaylistListFlowContainer { Spacing = new Vector2(0, 3), LayoutDuration = 200, @@ -85,25 +57,11 @@ namespace osu.Game.Overlays.Music }; } - public class PlaylistListFlowContainer : SearchContainer> + public class PlaylistListFlowContainer : SearchContainer> { } - public class PlaylistListItem : IEquatable - { - public readonly BeatmapSetInfo BeatmapSetInfo; - - public PlaylistListItem(BeatmapSetInfo beatmapSetInfo) - { - BeatmapSetInfo = beatmapSetInfo; - } - - public override string ToString() => BeatmapSetInfo.ToString(); - - public bool Equals(PlaylistListItem other) => BeatmapSetInfo.Equals(other?.BeatmapSetInfo); - } - - public class DrawablePlaylistListItem : DrawableRearrangeableListItem, IFilterable + public class DrawablePlaylistListItem : DrawableRearrangeableListItem, IFilterable { private const float fade_duration = 100; @@ -119,7 +77,7 @@ namespace osu.Game.Overlays.Music private Color4 hoverColour; private Color4 artistColour; - public DrawablePlaylistListItem(PlaylistListItem item) + public DrawablePlaylistListItem(BeatmapSetInfo item) : base(item) { RelativeSizeAxes = Axes.X; @@ -127,7 +85,7 @@ namespace osu.Game.Overlays.Music Padding = new MarginPadding { Left = 5 }; - FilterTerms = item.BeatmapSetInfo.Metadata.SearchableTerms; + FilterTerms = item.Metadata.SearchableTerms; } [BackgroundDependencyLoader] @@ -164,8 +122,8 @@ namespace osu.Game.Overlays.Music RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } }; - titleBind = localisation.GetLocalisedString(new LocalisedString((Model.BeatmapSetInfo.Metadata.TitleUnicode, Model.BeatmapSetInfo.Metadata.Title))); - artistBind = localisation.GetLocalisedString(new LocalisedString((Model.BeatmapSetInfo.Metadata.ArtistUnicode, Model.BeatmapSetInfo.Metadata.Artist))); + titleBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.TitleUnicode, Model.Metadata.Title))); + artistBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.ArtistUnicode, Model.Metadata.Artist))); artistBind.BindValueChanged(_ => recreateText(), true); } @@ -176,11 +134,11 @@ namespace osu.Game.Overlays.Music SelectedSet.BindValueChanged(set => { - if (set.OldValue != Model.BeatmapSetInfo && set.NewValue != Model.BeatmapSetInfo) + if (set.OldValue != Model && set.NewValue != Model) return; foreach (Drawable s in titleSprites) - s.FadeColour(set.NewValue == Model.BeatmapSetInfo ? hoverColour : Color4.White, fade_duration); + s.FadeColour(set.NewValue == Model ? hoverColour : Color4.White, fade_duration); }, true); } @@ -201,7 +159,7 @@ namespace osu.Game.Overlays.Music protected override bool OnClick(ClickEvent e) { - RequestSelection?.Invoke(Model.BeatmapSetInfo); + RequestSelection?.Invoke(Model); return true; } diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 87abbd142c..a814712907 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -21,7 +21,9 @@ namespace osu.Game.Overlays.Music private const float transition_duration = 600; private const float playlist_height = 510; - public readonly IBindableList BeatmapSets = new BindableList(); + public IBindableList BeatmapSets => beatmapSets; + + private readonly BindableList beatmapSets = new BindableList(); private readonly Bindable beatmap = new Bindable(); private BeatmapManager beatmaps; @@ -72,7 +74,7 @@ namespace osu.Game.Overlays.Music }, }; - list.BeatmapSets.BindTo(BeatmapSets); + list.Items.BindTo(beatmapSets); filter.Search.OnCommit = (sender, newText) => { From 00a7adcdca53ccc475372b5f9d5221944d17a696 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Jan 2020 19:21:24 +0900 Subject: [PATCH 4/8] Further refactorings --- .../UserInterface/TestScenePlaylistOverlay.cs | 4 +- ...laylistList.cs => DrawablePlaylistItem.cs} | 48 +---- osu.Game/Overlays/Music/Playlist.cs | 46 +++++ osu.Game/Overlays/Music/PlaylistItem.cs | 183 ------------------ osu.Game/Overlays/Music/PlaylistOverlay.cs | 4 +- 5 files changed, 53 insertions(+), 232 deletions(-) rename osu.Game/Overlays/Music/{PlaylistList.cs => DrawablePlaylistItem.cs} (75%) create mode 100644 osu.Game/Overlays/Music/Playlist.cs delete mode 100644 osu.Game/Overlays/Music/PlaylistItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs index 986cf458ab..7476b52b49 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs @@ -16,10 +16,10 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestScenePlaylistOverlay : OsuTestScene { - public override IReadOnlyList RequiredTypes => new Type[] + public override IReadOnlyList RequiredTypes => new[] { typeof(PlaylistOverlay), - typeof(PlaylistList) + typeof(Playlist) }; private readonly BindableList beatmapSets = new BindableList(); diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/DrawablePlaylistItem.cs similarity index 75% rename from osu.Game/Overlays/Music/PlaylistList.cs rename to osu.Game/Overlays/Music/DrawablePlaylistItem.cs index e183c14f10..e3dd72ae8b 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/DrawablePlaylistItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -19,49 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Music { - public class PlaylistList : RearrangeableListContainer - { - public Action RequestSelection; - - public readonly Bindable SelectedSet = new Bindable(); - - public new MarginPadding Padding - { - get => base.Padding; - set => base.Padding = value; - } - - public void Filter(string searchTerm) => ((PlaylistListFlowContainer)ListContainer).SearchTerm = searchTerm; - - public BeatmapSetInfo FirstVisibleSet => ListContainer.FlowingChildren.Cast().FirstOrDefault(i => i.MatchingFilter)?.Model; - - private void removeBeatmapSets(IEnumerable sets) => Schedule(() => - { - foreach (var item in sets) - Items.Remove(ListContainer.Children.Select(d => d.Model).FirstOrDefault(m => m == item)); - }); - - protected override DrawableRearrangeableListItem CreateDrawable(BeatmapSetInfo item) => new DrawablePlaylistListItem(item) - { - SelectedSet = { BindTarget = SelectedSet }, - RequestSelection = set => RequestSelection?.Invoke(set) - }; - - protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer(); - - protected override FillFlowContainer> CreateListFillFlowContainer() => new PlaylistListFlowContainer - { - Spacing = new Vector2(0, 3), - LayoutDuration = 200, - LayoutEasing = Easing.OutQuint, - }; - } - - public class PlaylistListFlowContainer : SearchContainer> - { - } - - public class DrawablePlaylistListItem : DrawableRearrangeableListItem, IFilterable + public class DrawablePlaylistItem : RearrangeableListItem, IFilterable { private const float fade_duration = 100; @@ -77,7 +35,7 @@ namespace osu.Game.Overlays.Music private Color4 hoverColour; private Color4 artistColour; - public DrawablePlaylistListItem(BeatmapSetInfo item) + public DrawablePlaylistItem(BeatmapSetInfo item) : base(item) { RelativeSizeAxes = Axes.X; diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs new file mode 100644 index 0000000000..ba9aaf03d4 --- /dev/null +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -0,0 +1,46 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osuTK; + +namespace osu.Game.Overlays.Music +{ + public class Playlist : RearrangeableListContainer + { + public Action RequestSelection; + + public readonly Bindable SelectedSet = new Bindable(); + + public new MarginPadding Padding + { + get => base.Padding; + set => base.Padding = value; + } + + public void Filter(string searchTerm) => ((SearchContainer>)ListContainer).SearchTerm = searchTerm; + + public BeatmapSetInfo FirstVisibleSet => Items.FirstOrDefault(i => ((DrawablePlaylistItem)ItemMap[i]).MatchingFilter); + + protected override RearrangeableListItem CreateDrawable(BeatmapSetInfo item) => new DrawablePlaylistItem(item) + { + SelectedSet = { BindTarget = SelectedSet }, + RequestSelection = set => RequestSelection?.Invoke(set) + }; + + protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer(); + + protected override FillFlowContainer> CreateListFillFlowContainer() => new SearchContainer> + { + Spacing = new Vector2(0, 3), + LayoutDuration = 200, + LayoutEasing = Easing.OutQuint, + }; + } +} diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs deleted file mode 100644 index d40f391982..0000000000 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using System.Linq; -using osuTK.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; -using osu.Framework.Localisation; -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osuTK; - -namespace osu.Game.Overlays.Music -{ - public class PlaylistItem : Container, IFilterable, IDraggable - { - private const float fade_duration = 100; - - private Color4 hoverColour; - private Color4 artistColour; - - private SpriteIcon handle; - private TextFlowContainer text; - private IEnumerable titleSprites; - private ILocalisedBindableString titleBind; - private ILocalisedBindableString artistBind; - - public readonly BeatmapSetInfo BeatmapSetInfo; - - public Action OnSelect; - - public bool IsDraggable { get; private set; } - - protected override bool OnMouseDown(MouseDownEvent e) - { - IsDraggable = handle.IsHovered; - return base.OnMouseDown(e); - } - - protected override void OnMouseUp(MouseUpEvent e) - { - IsDraggable = false; - base.OnMouseUp(e); - } - - private bool selected; - - public bool Selected - { - get => selected; - set - { - if (value == selected) return; - - selected = value; - - FinishTransforms(true); - foreach (Drawable s in titleSprites) - s.FadeColour(Selected ? hoverColour : Color4.White, fade_duration); - } - } - - public PlaylistItem(BeatmapSetInfo setInfo) - { - BeatmapSetInfo = setInfo; - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Top = 3, Bottom = 3 }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours, LocalisationManager localisation) - { - hoverColour = colours.Yellow; - artistColour = colours.Gray9; - - var metadata = BeatmapSetInfo.Metadata; - FilterTerms = metadata.SearchableTerms; - - Children = new Drawable[] - { - handle = new PlaylistItemHandle - { - Colour = colours.Gray5 - }, - text = new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 20 }, - ContentIndent = 10f, - }, - }; - - titleBind = localisation.GetLocalisedString(new LocalisedString((metadata.TitleUnicode, metadata.Title))); - artistBind = localisation.GetLocalisedString(new LocalisedString((metadata.ArtistUnicode, metadata.Artist))); - - artistBind.BindValueChanged(_ => recreateText(), true); - } - - private void recreateText() - { - text.Clear(); - - //space after the title to put a space between the title and artist - titleSprites = text.AddText(titleBind.Value + @" ", sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)).OfType(); - - text.AddText(artistBind.Value, sprite => - { - sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); - sprite.Colour = artistColour; - sprite.Padding = new MarginPadding { Top = 1 }; - }); - } - - protected override bool OnHover(HoverEvent e) - { - handle.FadeIn(fade_duration); - - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - handle.FadeOut(fade_duration); - } - - protected override bool OnClick(ClickEvent e) - { - OnSelect?.Invoke(BeatmapSetInfo); - return true; - } - - public IEnumerable FilterTerms { get; private set; } - - private bool matching = true; - - public bool MatchingFilter - { - get => matching; - set - { - if (matching == value) return; - - matching = value; - - this.FadeTo(matching ? 1 : 0, 200); - } - } - - public bool FilteringActive { get; set; } - - private class PlaylistItemHandle : SpriteIcon - { - public PlaylistItemHandle() - { - Anchor = Anchor.CentreLeft; - Origin = Anchor.CentreLeft; - Size = new Vector2(12); - Icon = FontAwesome.Solid.Bars; - Alpha = 0f; - Margin = new MarginPadding { Left = 5 }; - } - - public override bool HandlePositionalInput => IsPresent; - } - } - - public interface IDraggable : IDrawable - { - /// - /// Whether this can be dragged in its current state. - /// - bool IsDraggable { get; } - } -} diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index a814712907..7c391e27f9 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Music private BeatmapManager beatmaps; private FilterControl filter; - private PlaylistList list; + private Playlist list; [BackgroundDependencyLoader] private void load(OsuColour colours, Bindable beatmap, BeatmapManager beatmaps) @@ -57,7 +57,7 @@ namespace osu.Game.Overlays.Music Colour = colours.Gray3, RelativeSizeAxes = Axes.Both, }, - list = new PlaylistList + list = new Playlist { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = 95, Bottom = 10, Right = 10 }, From 0c4540b551138d3ca0676469071c0f0d18315ce5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Jan 2020 19:23:53 +0900 Subject: [PATCH 5/8] Rename PlaylistItem --- osu.Game/Overlays/Music/Playlist.cs | 4 ++-- .../Music/{DrawablePlaylistItem.cs => PlaylistItem.cs} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Overlays/Music/{DrawablePlaylistItem.cs => PlaylistItem.cs} (97%) diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index ba9aaf03d4..8744a6db8b 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -26,9 +26,9 @@ namespace osu.Game.Overlays.Music public void Filter(string searchTerm) => ((SearchContainer>)ListContainer).SearchTerm = searchTerm; - public BeatmapSetInfo FirstVisibleSet => Items.FirstOrDefault(i => ((DrawablePlaylistItem)ItemMap[i]).MatchingFilter); + public BeatmapSetInfo FirstVisibleSet => Items.FirstOrDefault(i => ((PlaylistItem)ItemMap[i]).MatchingFilter); - protected override RearrangeableListItem CreateDrawable(BeatmapSetInfo item) => new DrawablePlaylistItem(item) + protected override RearrangeableListItem CreateDrawable(BeatmapSetInfo item) => new PlaylistItem(item) { SelectedSet = { BindTarget = SelectedSet }, RequestSelection = set => RequestSelection?.Invoke(set) diff --git a/osu.Game/Overlays/Music/DrawablePlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs similarity index 97% rename from osu.Game/Overlays/Music/DrawablePlaylistItem.cs rename to osu.Game/Overlays/Music/PlaylistItem.cs index e3dd72ae8b..4ce67c2d66 100644 --- a/osu.Game/Overlays/Music/DrawablePlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -19,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Music { - public class DrawablePlaylistItem : RearrangeableListItem, IFilterable + public class PlaylistItem : RearrangeableListItem, IFilterable { private const float fade_duration = 100; @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Music private Color4 hoverColour; private Color4 artistColour; - public DrawablePlaylistItem(BeatmapSetInfo item) + public PlaylistItem(BeatmapSetInfo item) : base(item) { RelativeSizeAxes = Axes.X; From b6cfb987f327304cfee25efbf4134866794e6925 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Feb 2020 17:00:36 +0900 Subject: [PATCH 6/8] Make drag handles not pop into existence --- osu.Game/Overlays/Music/PlaylistItem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 4ce67c2d66..0f68df737e 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -66,6 +66,7 @@ namespace osu.Game.Overlays.Music Origin = Anchor.CentreLeft, Size = new Vector2(12), Colour = colours.Gray5, + AlwaysPresent = true, Alpha = 0 }, text = new OsuTextFlowContainer From 6b67b601e9033f6d48d813561fd602be25863bef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Feb 2020 17:35:13 +0900 Subject: [PATCH 7/8] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index e5a1ec2f4e..702591231b 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -54,6 +54,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ce58be52ee..81f59a4993 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 6ab3c0f2d2..8e359970a1 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 48350638a247faea83506b24b2eb5bd4b5a48803 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Feb 2020 18:38:00 +0900 Subject: [PATCH 8/8] Hide drag handles of all playlist items not currently being dragged --- osu.Game/Overlays/Music/Playlist.cs | 6 ++++++ osu.Game/Overlays/Music/PlaylistItem.cs | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index 8744a6db8b..1ba568443d 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -18,6 +18,11 @@ namespace osu.Game.Overlays.Music public readonly Bindable SelectedSet = new Bindable(); + /// + /// Whether any item is currently being dragged. Used to hide other items' drag handles. + /// + private readonly BindableBool playlistDragActive = new BindableBool(); + public new MarginPadding Padding { get => base.Padding; @@ -31,6 +36,7 @@ namespace osu.Game.Overlays.Music protected override RearrangeableListItem CreateDrawable(BeatmapSetInfo item) => new PlaylistItem(item) { SelectedSet = { BindTarget = SelectedSet }, + PlaylistDragActive = { BindTarget = playlistDragActive }, RequestSelection = set => RequestSelection?.Invoke(set) }; diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 0f68df737e..0569261867 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -23,7 +23,10 @@ namespace osu.Game.Overlays.Music { private const float fade_duration = 100; + public BindableBool PlaylistDragActive = new BindableBool(); + public readonly Bindable SelectedSet = new Bindable(); + public Action RequestSelection; private PlaylistItemHandle handle; @@ -122,11 +125,26 @@ namespace osu.Game.Overlays.Music return true; } + protected override bool OnDragStart(DragStartEvent e) + { + if (!base.OnDragStart(e)) + return false; + + PlaylistDragActive.Value = true; + return true; + } + + protected override void OnDragEnd(DragEndEvent e) + { + PlaylistDragActive.Value = false; + base.OnDragEnd(e); + } + protected override bool IsDraggableAt(Vector2 screenSpacePos) => handle.HandlingDrag; protected override bool OnHover(HoverEvent e) { - handle.UpdateHoverState(true); + handle.UpdateHoverState(IsDragged || !PlaylistDragActive.Value); return base.OnHover(e); }