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

Make MusicController handle all movement to previous/next tracks

This commit is contained in:
smoogipoo 2018-05-14 17:41:35 +09:00
parent 07fc71e077
commit 6eb7590ab0
3 changed files with 90 additions and 131 deletions

View File

@ -4,7 +4,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input; using osu.Framework.Input;
@ -16,7 +17,8 @@ namespace osu.Game.Overlays.Music
{ {
public class PlaylistList : CompositeDrawable public class PlaylistList : CompositeDrawable
{ {
public Action<BeatmapSetInfo> OnSelect; public Action<BeatmapSetInfo> Selected;
public Action<BeatmapSetInfo, int> OrderChanged;
private readonly ItemsScrollContainer items; private readonly ItemsScrollContainer items;
@ -25,7 +27,8 @@ namespace osu.Game.Overlays.Music
InternalChild = items = new ItemsScrollContainer InternalChild = items = new ItemsScrollContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
OnSelect = set => OnSelect?.Invoke(set) Selected = set => Selected?.Invoke(set),
OrderChanged = (s, i) => OrderChanged?.Invoke(s, i)
}; };
} }
@ -35,34 +38,20 @@ namespace osu.Game.Overlays.Music
set { base.Padding = value; } set { base.Padding = value; }
} }
public IEnumerable<BeatmapSetInfo> BeatmapSets
{
get { return items.Sets; }
set { items.Sets = value; }
}
public BeatmapSetInfo FirstVisibleSet => items.FirstVisibleSet; public BeatmapSetInfo FirstVisibleSet => items.FirstVisibleSet;
public BeatmapSetInfo NextSet => items.NextSet;
public BeatmapSetInfo PreviousSet => items.PreviousSet;
public BeatmapSetInfo SelectedSet
{
get { return items.SelectedSet; }
set { items.SelectedSet = value; }
}
public void AddBeatmapSet(BeatmapSetInfo beatmapSet) => items.AddBeatmapSet(beatmapSet);
public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => items.RemoveBeatmapSet(beatmapSet);
public void Filter(string searchTerm) => items.SearchTerm = searchTerm; public void Filter(string searchTerm) => items.SearchTerm = searchTerm;
private class ItemsScrollContainer : OsuScrollContainer private class ItemsScrollContainer : OsuScrollContainer
{ {
public Action<BeatmapSetInfo> OnSelect; public Action<BeatmapSetInfo> Selected;
public Action<BeatmapSetInfo, int> OrderChanged;
private readonly SearchContainer search; private readonly SearchContainer search;
private readonly FillFlowContainer<PlaylistItem> items; private readonly FillFlowContainer<PlaylistItem> items;
private readonly IBindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>();
public ItemsScrollContainer() public ItemsScrollContainer()
{ {
Children = new Drawable[] Children = new Drawable[]
@ -83,14 +72,36 @@ namespace osu.Game.Overlays.Music
}; };
} }
public IEnumerable<BeatmapSetInfo> Sets [BackgroundDependencyLoader]
private void load(BeatmapManager beatmaps, OsuGameBase osuGame)
{ {
get { return items.Select(x => x.BeatmapSetInfo).ToList(); } beatmaps.GetAllUsableBeatmapSets().ForEach(addBeatmapSet);
set beatmaps.ItemAdded += addBeatmapSet;
{ beatmaps.ItemRemoved += removeBeatmapSet;
items.Clear();
value.ForEach(AddBeatmapSet); beatmapBacking.BindTo(osuGame.Beatmap);
} beatmapBacking.ValueChanged += _ => updateSelectedSet();
}
private void addBeatmapSet(BeatmapSetInfo obj)
{
var newItem = new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) };
items.Add(newItem);
items.SetLayoutPosition(newItem, items.Count - 1);
}
private void removeBeatmapSet(BeatmapSetInfo obj)
{
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;
} }
public string SearchTerm public string SearchTerm
@ -99,34 +110,7 @@ namespace osu.Game.Overlays.Music
set { search.SearchTerm = value; } set { search.SearchTerm = value; }
} }
public void AddBeatmapSet(BeatmapSetInfo beatmapSet)
{
var newItem = new PlaylistItem(beatmapSet) { OnSelect = set => OnSelect?.Invoke(set) };
items.Add(newItem);
items.SetLayoutPosition(newItem, items.Count);
}
public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet)
{
var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == beatmapSet.ID);
if (itemToRemove != null)
items.Remove(itemToRemove);
}
public BeatmapSetInfo SelectedSet
{
get { return items.FirstOrDefault(i => i.Selected)?.BeatmapSetInfo; }
set
{
foreach (PlaylistItem s in items.Children)
s.Selected = s.BeatmapSetInfo.ID == value?.ID;
}
}
public BeatmapSetInfo FirstVisibleSet => items.FirstOrDefault(i => i.MatchingFilter)?.BeatmapSetInfo; public BeatmapSetInfo FirstVisibleSet => items.FirstOrDefault(i => i.MatchingFilter)?.BeatmapSetInfo;
public BeatmapSetInfo NextSet => (items.SkipWhile(i => !i.Selected).Skip(1).FirstOrDefault() ?? items.FirstOrDefault())?.BeatmapSetInfo;
public BeatmapSetInfo PreviousSet => (items.TakeWhile(i => !i.Selected).LastOrDefault() ?? items.LastOrDefault())?.BeatmapSetInfo;
private Vector2 nativeDragPosition; private Vector2 nativeDragPosition;
private PlaylistItem draggedItem; private PlaylistItem draggedItem;
@ -227,6 +211,7 @@ namespace osu.Game.Overlays.Music
} }
items.SetLayoutPosition(draggedItem, dstIndex); items.SetLayoutPosition(draggedItem, dstIndex);
OrderChanged?.Invoke(draggedItem.BeatmapSetInfo, dstIndex);
} }
private class ItemSearchContainer : FillFlowContainer<PlaylistItem>, IHasFilterableChildren private class ItemSearchContainer : FillFlowContainer<PlaylistItem>, IHasFilterableChildren

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2018 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.Collections.Generic; using System;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration; using osu.Framework.Configuration;
@ -19,18 +19,16 @@ namespace osu.Game.Overlays.Music
public class PlaylistOverlay : OverlayContainer public class PlaylistOverlay : OverlayContainer
{ {
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 Action<BeatmapSetInfo, int> OrderChanged;
private BeatmapManager beatmaps;
private FilterControl filter; private FilterControl filter;
private PlaylistList list; private PlaylistList list;
private BeatmapManager beatmaps;
private readonly Bindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>(); private readonly Bindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>();
public IEnumerable<BeatmapSetInfo> BeatmapSets => list.BeatmapSets;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours) private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours)
{ {
@ -60,7 +58,8 @@ namespace osu.Game.Overlays.Music
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = 95, Bottom = 10, Right = 10 }, Padding = new MarginPadding { Top = 95, Bottom = 10, Right = 10 },
OnSelect = itemSelected, Selected = itemSelected,
OrderChanged = (s, i) => OrderChanged?.Invoke(s, i)
}, },
filter = new FilterControl filter = new FilterControl
{ {
@ -74,30 +73,16 @@ namespace osu.Game.Overlays.Music
}, },
}; };
beatmaps.ItemAdded += handleBeatmapAdded;
beatmaps.ItemRemoved += handleBeatmapRemoved;
list.BeatmapSets = beatmaps.GetAllUsableBeatmapSets();
beatmapBacking.BindTo(game.Beatmap); beatmapBacking.BindTo(game.Beatmap);
filter.Search.OnCommit = (sender, newText) => filter.Search.OnCommit = (sender, newText) =>
{ {
var beatmap = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); BeatmapInfo beatmap = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
if (beatmap != null) playSpecified(beatmap); if (beatmap != null)
beatmapBacking.Value = beatmaps.GetWorkingBeatmap(beatmap);
}; };
} }
protected override void LoadComplete()
{
base.LoadComplete();
beatmapBacking.ValueChanged += b => list.SelectedSet = b?.BeatmapSetInfo;
beatmapBacking.TriggerChange();
}
private void handleBeatmapAdded(BeatmapSetInfo setInfo) => Schedule(() => list.AddBeatmapSet(setInfo));
private void handleBeatmapRemoved(BeatmapSetInfo setInfo) => Schedule(() => list.RemoveBeatmapSet(setInfo));
protected override void PopIn() protected override void PopIn()
{ {
filter.Search.HoldFocus = true; filter.Search.HoldFocus = true;
@ -123,49 +108,7 @@ namespace osu.Game.Overlays.Music
return; return;
} }
playSpecified(set.Beatmaps.First()); beatmapBacking.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First());
}
public void PlayPrevious()
{
var playable = list.PreviousSet;
if (playable != null)
{
playSpecified(playable.Beatmaps.First());
list.SelectedSet = playable;
}
}
public void PlayNext()
{
var playable = list.NextSet;
if (playable != null)
{
playSpecified(playable.Beatmaps.First());
list.SelectedSet = playable;
}
}
private void playSpecified(BeatmapInfo info)
{
beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking);
var track = beatmapBacking.Value.Track;
track.Restart();
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (beatmaps != null)
{
beatmaps.ItemAdded -= handleBeatmapAdded;
beatmaps.ItemRemoved -= handleBeatmapRemoved;
}
} }
} }

View File

@ -2,6 +2,7 @@
// 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 System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -50,7 +51,10 @@ namespace osu.Game.Overlays
private LocalisationEngine localisation; private LocalisationEngine localisation;
private BeatmapManager beatmaps;
private readonly Bindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>(); private readonly Bindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>();
private List<BeatmapSetInfo> beatmapSets;
private BeatmapSetInfo currentSet;
private Container dragContainer; private Container dragContainer;
private Container playerContainer; private Container playerContainer;
@ -93,8 +97,9 @@ namespace osu.Game.Overlays
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuGameBase game, OsuColour colours, LocalisationEngine localisation) private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours, LocalisationEngine localisation)
{ {
this.beatmaps = beatmaps;
this.localisation = localisation; this.localisation = localisation;
Children = new Drawable[] Children = new Drawable[]
@ -111,6 +116,7 @@ namespace osu.Game.Overlays
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Y = player_height + 10, Y = player_height + 10,
OrderChanged = playlistOrderChanged
}, },
playerContainer = new Container playerContainer = new Container
{ {
@ -185,7 +191,7 @@ namespace osu.Game.Overlays
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Action = next, Action = () => next(),
Icon = FontAwesome.fa_step_forward, Icon = FontAwesome.fa_step_forward,
}, },
} }
@ -214,11 +220,24 @@ namespace osu.Game.Overlays
} }
}; };
beatmapSets = beatmaps.GetAllUsableBeatmapSets();
beatmaps.ItemAdded += handleBeatmapAdded;
beatmaps.ItemRemoved += handleBeatmapRemoved;
beatmapBacking.BindTo(game.Beatmap); beatmapBacking.BindTo(game.Beatmap);
playlist.StateChanged += s => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); playlist.StateChanged += s => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint);
} }
private void playlistOrderChanged(BeatmapSetInfo beatmapSetInfo, int index)
{
beatmapSets.Remove(beatmapSetInfo);
beatmapSets.Insert(index, beatmapSetInfo);
}
private void handleBeatmapAdded(BeatmapSetInfo obj) => beatmapSets.Add(obj);
private void handleBeatmapRemoved(BeatmapSetInfo obj) => beatmapSets.RemoveAll(s => s.ID == obj.ID);
protected override void LoadComplete() protected override void LoadComplete()
{ {
beatmapBacking.ValueChanged += beatmapChanged; beatmapBacking.ValueChanged += beatmapChanged;
@ -257,7 +276,7 @@ namespace osu.Game.Overlays
playButton.Icon = track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o; playButton.Icon = track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o;
if (track.HasCompleted && !track.Looping && !beatmapBacking.Disabled && playlist.BeatmapSets.Any()) if (track.HasCompleted && !track.Looping && !beatmapBacking.Disabled && beatmapSets.Any())
next(); next();
} }
else else
@ -271,7 +290,7 @@ namespace osu.Game.Overlays
if (track == null) if (track == null)
{ {
if (!beatmapBacking.Disabled) if (!beatmapBacking.Disabled)
playlist.PlayNext(); next(true);
return; return;
} }
@ -284,13 +303,25 @@ namespace osu.Game.Overlays
private void prev() private void prev()
{ {
queuedDirection = TransformDirection.Prev; queuedDirection = TransformDirection.Prev;
playlist.PlayPrevious();
var playable = beatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? beatmapSets.LastOrDefault();
if (playable != null)
playSpecified(playable.Beatmaps.First());
} }
private void next() private void next(bool instant = false)
{ {
queuedDirection = TransformDirection.Next; queuedDirection = TransformDirection.Next;
playlist.PlayNext();
var playable = beatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? beatmapSets.FirstOrDefault();
if (playable != null)
playSpecified(playable.Beatmaps.First());
}
private void playSpecified(BeatmapInfo info)
{
beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking);
beatmapBacking.Value.Track.Restart();
} }
private WorkingBeatmap current; private WorkingBeatmap current;
@ -314,8 +345,8 @@ namespace osu.Game.Overlays
else else
{ {
//figure out the best direction based on order in playlist. //figure out the best direction based on order in playlist.
var last = playlist.BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); var last = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count();
var next = beatmap == null ? -1 : playlist.BeatmapSets.TakeWhile(b => b.ID != beatmap.BeatmapSetInfo?.ID).Count(); var next = beatmap == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.BeatmapSetInfo?.ID).Count();
direction = last > next ? TransformDirection.Prev : TransformDirection.Next; direction = last > next ? TransformDirection.Prev : TransformDirection.Next;
} }