1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-16 01:42:58 +08:00

Merge branch 'master' into combo-colour-independence

This commit is contained in:
Dean Herbert 2020-02-20 15:05:15 +09:00
commit 5aea599c5e
22 changed files with 501 additions and 65 deletions

View File

@ -53,7 +53,7 @@
<Reference Include="Java.Interop" /> <Reference Include="Java.Interop" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1230.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.219.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.218.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2020.218.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
typeof(DrawableRoomPlaylistItem) typeof(DrawableRoomPlaylistItem)
}; };
private DrawableRoomPlaylist playlist; private TestPlaylist playlist;
[Test] [Test]
public void TestNonEditableNonSelectable() public void TestNonEditableNonSelectable()
@ -211,30 +211,45 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void assertDeleteButtonVisibility(int index, bool visible) private void assertDeleteButtonVisibility(int index, bool visible)
=> AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType<IconButton>().ElementAt(2 + index * 2).Alpha > 0) == visible); => AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType<IconButton>().ElementAt(2 + index * 2).Alpha > 0) == visible);
private void createPlaylist(bool allowEdit, bool allowSelection) => AddStep("create playlist", () => private void createPlaylist(bool allowEdit, bool allowSelection)
{ {
Child = playlist = new DrawableRoomPlaylist(allowEdit, allowSelection) AddStep("create playlist", () =>
{ {
Anchor = Anchor.Centre, Child = playlist = new TestPlaylist(allowEdit, allowSelection)
Origin = Anchor.Centre,
Size = new Vector2(500, 300)
};
for (int i = 0; i < 20; i++)
{
playlist.Items.Add(new PlaylistItem
{ {
ID = i, Anchor = Anchor.Centre,
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Origin = Anchor.Centre,
Ruleset = { Value = new OsuRuleset().RulesetInfo }, Size = new Vector2(500, 300)
RequiredMods = };
for (int i = 0; i < 20; i++)
{
playlist.Items.Add(new PlaylistItem
{ {
new OsuModHardRock(), ID = i,
new OsuModDoubleTime(), Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
new OsuModAutoplay() Ruleset = { Value = new OsuRuleset().RulesetInfo },
} RequiredMods =
}); {
new OsuModHardRock(),
new OsuModDoubleTime(),
new OsuModAutoplay()
}
});
}
});
AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded));
}
private class TestPlaylist : DrawableRoomPlaylist
{
public new IReadOnlyDictionary<PlaylistItem, RearrangeableListItem<PlaylistItem>> ItemMap => base.ItemMap;
public TestPlaylist(bool allowEdit, bool allowSelection)
: base(allowEdit, allowSelection)
{
} }
}); }
} }
} }

View File

@ -0,0 +1,39 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Game.Overlays;
using NUnit.Framework;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneBeatmapListingOverlay : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(BeatmapListingOverlay),
};
protected override bool UseOnlineAPI => true;
private readonly BeatmapListingOverlay overlay;
public TestSceneBeatmapListingOverlay()
{
Add(overlay = new BeatmapListingOverlay());
}
[Test]
public void TestShow()
{
AddStep("Show", overlay.Show);
}
[Test]
public void TestHide()
{
AddStep("Hide", overlay.Hide);
}
}
}

View File

@ -29,8 +29,8 @@ namespace osu.Game.Tests.Visual.Online
typeof(RankingsOverlayHeader) typeof(RankingsOverlayHeader)
}; };
[Cached] [Cached(typeof(RankingsOverlay))]
private RankingsOverlay rankingsOverlay; private readonly RankingsOverlay rankingsOverlay;
private readonly Bindable<Country> countryBindable = new Bindable<Country>(); private readonly Bindable<Country> countryBindable = new Bindable<Country>();
private readonly Bindable<RankingsScope> scope = new Bindable<RankingsScope>(); private readonly Bindable<RankingsScope> scope = new Bindable<RankingsScope>();

View File

@ -51,6 +51,9 @@ namespace osu.Game.Beatmaps
[NotMapped] [NotMapped]
public BeatmapOnlineInfo OnlineInfo { get; set; } public BeatmapOnlineInfo OnlineInfo { get; set; }
[NotMapped]
public int? MaxCombo { get; set; }
/// <summary> /// <summary>
/// The playable length in milliseconds of this beatmap. /// The playable length in milliseconds of this beatmap.
/// </summary> /// </summary>

View File

@ -61,6 +61,9 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty(@"failtimes")] [JsonProperty(@"failtimes")]
private BeatmapMetrics metrics { get; set; } private BeatmapMetrics metrics { get; set; }
[JsonProperty(@"max_combo")]
private int? maxCombo { get; set; }
public BeatmapInfo ToBeatmap(RulesetStore rulesets) public BeatmapInfo ToBeatmap(RulesetStore rulesets)
{ {
var set = BeatmapSet?.ToBeatmapSet(rulesets); var set = BeatmapSet?.ToBeatmapSet(rulesets);
@ -76,6 +79,7 @@ namespace osu.Game.Online.API.Requests.Responses
Status = Status, Status = Status,
BeatmapSet = set, BeatmapSet = set,
Metrics = metrics, Metrics = metrics,
MaxCombo = maxCombo,
BaseDifficulty = new BeatmapDifficulty BaseDifficulty = new BeatmapDifficulty
{ {
DrainRate = drainRate, DrainRate = drainRate,

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.IO.Network;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Direct; using osu.Game.Overlays.Direct;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -26,8 +27,21 @@ namespace osu.Game.Online.API.Requests
this.direction = direction; this.direction = direction;
} }
// ReSharper disable once ImpureMethodCallOnReadonlyValueField protected override WebRequest CreateWebRequest()
protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={searchCategory.ToString().ToLowerInvariant()}&sort={sortCriteria.ToString().ToLowerInvariant()}_{directionString}"; {
var req = base.CreateWebRequest();
req.AddParameter("q", query);
if (ruleset.ID.HasValue)
req.AddParameter("m", ruleset.ID.Value.ToString());
req.AddParameter("s", searchCategory.ToString().ToLowerInvariant());
req.AddParameter("sort", $"{sortCriteria.ToString().ToLowerInvariant()}_{directionString}");
return req;
}
protected override string Target => @"beatmapsets/search";
} }
public enum BeatmapSearchCategory public enum BeatmapSearchCategory

View File

@ -2,12 +2,17 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests namespace osu.Game.Online.API.Requests
{ {
public class SearchBeatmapSetsResponse : ResponseWithCursor public class SearchBeatmapSetsResponse : ResponseWithCursor
{ {
[JsonProperty("beatmapsets")]
public IEnumerable<APIBeatmapSet> BeatmapSets; public IEnumerable<APIBeatmapSet> BeatmapSets;
[JsonProperty("total")]
public int Total;
} }
} }

View File

@ -0,0 +1,24 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Overlays.BeatmapListing
{
public class BeatmapListingHeader : OverlayHeader
{
protected override ScreenTitle CreateTitle() => new BeatmapListingTitle();
private class BeatmapListingTitle : ScreenTitle
{
public BeatmapListingTitle()
{
Title = @"beatmap";
Section = @"listing";
}
protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/changelog");
}
}
}

View File

@ -104,6 +104,8 @@ namespace osu.Game.Overlays.BeatmapListing
} }
} }
}); });
Category.Value = BeatmapSearchCategory.Leaderboard;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -8,16 +8,17 @@ using osu.Framework.Graphics;
using osuTK.Graphics; using osuTK.Graphics;
using osuTK; using osuTK;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Overlays.Direct;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
public class BeatmapListingSortTabControl : OverlaySortTabControl<BeatmapSortCriteria> public class BeatmapListingSortTabControl : OverlaySortTabControl<DirectSortCriteria>
{ {
public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>(Overlays.SortDirection.Descending); public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>(Overlays.SortDirection.Descending);
public BeatmapListingSortTabControl() public BeatmapListingSortTabControl()
{ {
Current.Value = BeatmapSortCriteria.Ranked; Current.Value = DirectSortCriteria.Ranked;
} }
protected override SortTabControl CreateControl() => new BeatmapSortTabControl protected override SortTabControl CreateControl() => new BeatmapSortTabControl
@ -29,7 +30,7 @@ namespace osu.Game.Overlays.BeatmapListing
{ {
public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>(); public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>();
protected override TabItem<BeatmapSortCriteria> CreateTabItem(BeatmapSortCriteria value) => new BeatmapSortTabItem(value) protected override TabItem<DirectSortCriteria> CreateTabItem(DirectSortCriteria value) => new BeatmapSortTabItem(value)
{ {
SortDirection = { BindTarget = SortDirection } SortDirection = { BindTarget = SortDirection }
}; };
@ -39,12 +40,12 @@ namespace osu.Game.Overlays.BeatmapListing
{ {
public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>(); public readonly Bindable<SortDirection> SortDirection = new Bindable<SortDirection>();
public BeatmapSortTabItem(BeatmapSortCriteria value) public BeatmapSortTabItem(DirectSortCriteria value)
: base(value) : base(value)
{ {
} }
protected override TabButton CreateTabButton(BeatmapSortCriteria value) => new BeatmapTabButton(value) protected override TabButton CreateTabButton(DirectSortCriteria value) => new BeatmapTabButton(value)
{ {
Active = { BindTarget = Active }, Active = { BindTarget = Active },
SortDirection = { BindTarget = SortDirection } SortDirection = { BindTarget = SortDirection }
@ -66,7 +67,7 @@ namespace osu.Game.Overlays.BeatmapListing
private readonly SpriteIcon icon; private readonly SpriteIcon icon;
public BeatmapTabButton(BeatmapSortCriteria value) public BeatmapTabButton(DirectSortCriteria value)
: base(value) : base(value)
{ {
Add(icon = new SpriteIcon Add(icon = new SpriteIcon
@ -104,15 +105,4 @@ namespace osu.Game.Overlays.BeatmapListing
} }
} }
} }
public enum BeatmapSortCriteria
{
Title,
Artist,
Difficulty,
Ranked,
Rating,
Plays,
Favourites,
}
} }

View File

@ -0,0 +1,299 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Threading;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests;
using osu.Game.Overlays.BeatmapListing;
using osu.Game.Overlays.Direct;
using osu.Game.Rulesets;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Overlays
{
public class BeatmapListingOverlay : FullscreenOverlay
{
[Resolved]
private PreviewTrackManager previewTrackManager { get; set; }
[Resolved]
private RulesetStore rulesets { get; set; }
private SearchBeatmapSetsRequest getSetsRequest;
private Container panelsPlaceholder;
private Drawable currentContent;
private BeatmapListingSearchSection searchSection;
private BeatmapListingSortTabControl sortControl;
public BeatmapListingOverlay()
: base(OverlayColourScheme.Blue)
{
}
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider.Background6
},
new BasicScrollContainer
{
RelativeSizeAxes = Axes.Both,
ScrollbarVisible = false,
Child = new ReverseChildIDFillFlowContainer<Drawable>
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Masking = true,
EdgeEffect = new EdgeEffectParameters
{
Colour = Color4.Black.Opacity(0.25f),
Type = EdgeEffectType.Shadow,
Radius = 3,
Offset = new Vector2(0f, 1f),
},
Children = new Drawable[]
{
new BeatmapListingHeader(),
searchSection = new BeatmapListingSearchSection(),
}
},
new Container
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider.Background4,
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.X,
Height = 40,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider.Background5
},
sortControl = new BeatmapListingSortTabControl
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding { Left = 20 }
}
}
},
panelsPlaceholder = new Container
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Padding = new MarginPadding { Horizontal = 20 },
}
}
}
}
}
}
}
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
var sortCriteria = sortControl.Current;
var sortDirection = sortControl.SortDirection;
searchSection.Query.BindValueChanged(query =>
{
sortCriteria.Value = string.IsNullOrEmpty(query.NewValue) ? DirectSortCriteria.Ranked : DirectSortCriteria.Relevance;
sortDirection.Value = SortDirection.Descending;
queueUpdateSearch(true);
});
searchSection.Ruleset.BindValueChanged(_ => queueUpdateSearch());
searchSection.Category.BindValueChanged(_ => queueUpdateSearch());
sortCriteria.BindValueChanged(_ => queueUpdateSearch());
sortDirection.BindValueChanged(_ => queueUpdateSearch());
}
private ScheduledDelegate queryChangedDebounce;
private void queueUpdateSearch(bool queryTextChanged = false)
{
getSetsRequest?.Cancel();
queryChangedDebounce?.Cancel();
queryChangedDebounce = Scheduler.AddDelayed(updateSearch, queryTextChanged ? 500 : 100);
}
private void updateSearch()
{
if (!IsLoaded)
return;
if (State.Value == Visibility.Hidden)
return;
if (API == null)
return;
previewTrackManager.StopAnyPlaying(this);
currentContent?.FadeColour(Color4.DimGray, 400, Easing.OutQuint);
getSetsRequest = new SearchBeatmapSetsRequest(
searchSection.Query.Value,
searchSection.Ruleset.Value,
searchSection.Category.Value,
sortControl.Current.Value,
sortControl.SortDirection.Value);
getSetsRequest.Success += response => Schedule(() => recreatePanels(response));
API.Queue(getSetsRequest);
}
private void recreatePanels(SearchBeatmapSetsResponse response)
{
if (response.Total == 0)
{
searchSection.BeatmapSet = null;
LoadComponentAsync(new NotFoundDrawable(), addContentToPlaceholder);
return;
}
var beatmaps = response.BeatmapSets.Select(r => r.ToBeatmapSet(rulesets)).ToList();
var newPanels = new FillFlowContainer<DirectPanel>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(10),
Alpha = 0,
Margin = new MarginPadding { Vertical = 15 },
ChildrenEnumerable = beatmaps.Select<BeatmapSetInfo, DirectPanel>(b => new DirectGridPanel(b)
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
})
};
LoadComponentAsync(newPanels, loaded =>
{
addContentToPlaceholder(loaded);
searchSection.BeatmapSet = beatmaps.First();
});
}
private void addContentToPlaceholder(Drawable content)
{
Drawable lastContent = currentContent;
if (lastContent != null)
{
lastContent.FadeOut(100, Easing.OutQuint).Expire();
// Consider the case when the new content is smaller than the last content.
// If the auto-size computation is delayed until fade out completes, the background remain high for too long making the resulting transition to the smaller height look weird.
// At the same time, if the last content's height is bypassed immediately, there is a period where the new content is at Alpha = 0 when the auto-sized height will be 0.
// To resolve both of these issues, the bypass is delayed until a point when the content transitions (fade-in and fade-out) overlap and it looks good to do so.
lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y);
}
panelsPlaceholder.Add(currentContent = content);
currentContent.FadeIn(200, Easing.OutQuint);
}
protected override void Dispose(bool isDisposing)
{
getSetsRequest?.Cancel();
queryChangedDebounce?.Cancel();
base.Dispose(isDisposing);
}
private class NotFoundDrawable : CompositeDrawable
{
public NotFoundDrawable()
{
RelativeSizeAxes = Axes.X;
Height = 250;
Alpha = 0;
Margin = new MarginPadding { Top = 15 };
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
AddInternal(new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
AutoSizeAxes = Axes.X,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(10, 0),
Children = new Drawable[]
{
new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
Texture = textures.Get(@"Online/not-found")
},
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = @"... nope, nothing found.",
}
}
});
}
}
}
}

View File

@ -146,7 +146,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
new OsuSpriteText new OsuSpriteText
{ {
Text = $@"{score.MaxCombo:N0}x", Text = $@"{score.MaxCombo:N0}x",
Font = OsuFont.GetFont(size: text_size) Font = OsuFont.GetFont(size: text_size),
Colour = score.MaxCombo == score.Beatmap?.MaxCombo ? highAccuracyColour : Color4.White
} }
}); });

View File

@ -34,14 +34,13 @@ namespace osu.Game.Overlays.Direct
public enum DirectSortCriteria public enum DirectSortCriteria
{ {
Relevance,
Title, Title,
Artist, Artist,
Creator,
Difficulty, Difficulty,
Ranked, Ranked,
Rating, Rating,
Plays, Plays,
Favourites, Favourites,
Relevance,
} }
} }

View File

@ -75,8 +75,6 @@ namespace osu.Game.Overlays.Music
}, },
}; };
list.Items.BindTo(beatmapSets);
filter.Search.OnCommit = (sender, newText) => filter.Search.OnCommit = (sender, newText) =>
{ {
BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
@ -87,7 +85,13 @@ namespace osu.Game.Overlays.Music
beatmap.Value.Track.Restart(); beatmap.Value.Track.Restart();
} }
}; };
}
protected override void LoadComplete()
{
base.LoadComplete();
list.Items.BindTo(beatmapSets);
beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo, true); beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo, true);
} }

View File

@ -25,7 +25,16 @@ namespace osu.Game.Overlays
[Resolved] [Resolved]
private BeatmapManager beatmaps { get; set; } private BeatmapManager beatmaps { get; set; }
public IBindableList<BeatmapSetInfo> BeatmapSets => beatmapSets; public IBindableList<BeatmapSetInfo> BeatmapSets
{
get
{
if (LoadState < LoadState.Ready)
throw new InvalidOperationException($"{nameof(BeatmapSets)} should not be accessed before the music controller is loaded.");
return beatmapSets;
}
}
/// <summary> /// <summary>
/// Point in time after which the current track will be restarted on triggering a "previous track" action. /// Point in time after which the current track will be restarted on triggering a "previous track" action.
@ -54,16 +63,18 @@ namespace osu.Game.Overlays
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next()));
beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemAdded += handleBeatmapAdded;
beatmaps.ItemRemoved += handleBeatmapRemoved; beatmaps.ItemRemoved += handleBeatmapRemoved;
beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next()));
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete();
beatmap.BindValueChanged(beatmapChanged, true); beatmap.BindValueChanged(beatmapChanged, true);
mods.BindValueChanged(_ => ResetTrackAdjustments(), true); mods.BindValueChanged(_ => ResetTrackAdjustments(), true);
base.LoadComplete();
} }
/// <summary> /// <summary>
@ -82,11 +93,16 @@ namespace osu.Game.Overlays
/// </summary> /// </summary>
public bool IsPlaying => current?.Track.IsRunning ?? false; public bool IsPlaying => current?.Track.IsRunning ?? false;
private void handleBeatmapAdded(BeatmapSetInfo set) => private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() =>
Schedule(() => beatmapSets.Add(set)); {
if (!beatmapSets.Contains(set))
beatmapSets.Add(set);
});
private void handleBeatmapRemoved(BeatmapSetInfo set) => private void handleBeatmapRemoved(BeatmapSetInfo set) => Schedule(() =>
Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); {
beatmapSets.RemoveAll(s => s.ID == set.ID);
});
private ScheduledDelegate seekDelegate; private ScheduledDelegate seekDelegate;

View File

@ -58,6 +58,9 @@ namespace osu.Game.Overlays
[Resolved] [Resolved]
private Bindable<WorkingBeatmap> beatmap { get; set; } private Bindable<WorkingBeatmap> beatmap { get; set; }
[Resolved]
private OsuColour colours { get; set; }
public NowPlayingOverlay() public NowPlayingOverlay()
{ {
Width = 400; Width = 400;
@ -65,7 +68,7 @@ namespace osu.Game.Overlays
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load()
{ {
Children = new Drawable[] Children = new Drawable[]
{ {
@ -182,15 +185,15 @@ 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);
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
playlist.BeatmapSets.BindTo(musicController.BeatmapSets);
playlist.State.BindValueChanged(s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint), true);
beatmap.BindDisabledChanged(beatmapDisabledChanged, true); beatmap.BindDisabledChanged(beatmapDisabledChanged, true);
musicController.TrackChanged += trackChanged; musicController.TrackChanged += trackChanged;

View File

@ -9,6 +9,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Graphics.Containers;
namespace osu.Game.Overlays.Rankings.Tables namespace osu.Game.Overlays.Rankings.Tables
{ {
@ -61,18 +62,35 @@ namespace osu.Game.Overlays.Rankings.Tables
} }
}; };
private class CountryName : OsuSpriteText private class CountryName : OsuHoverContainer
{ {
protected override IEnumerable<Drawable> EffectTargets => new[] { text };
[Resolved(canBeNull: true)]
private RankingsOverlay rankings { get; set; }
private readonly OsuSpriteText text;
private readonly Country country;
public CountryName(Country country) public CountryName(Country country)
{ {
Font = OsuFont.GetFont(size: 12); this.country = country;
Text = country.FullName ?? string.Empty;
AutoSizeAxes = Axes.Both;
Add(text = new OsuSpriteText
{
Font = OsuFont.GetFont(size: 12),
Text = country.FullName ?? string.Empty,
});
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider) private void load(OverlayColourProvider colourProvider)
{ {
Colour = colourProvider.Light2; IdleColour = colourProvider.Light2;
HoverColour = colourProvider.Content2;
Action = () => rankings?.ShowCountry(country);
} }
} }
} }

View File

@ -22,7 +22,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1230.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.219.0" />
<PackageReference Include="ppy.osu.Framework" Version="2020.218.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.218.0" />
<PackageReference Include="Sentry" Version="2.0.3" /> <PackageReference Include="Sentry" Version="2.0.3" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />

View File

@ -73,7 +73,7 @@
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1230.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.219.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.218.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2020.218.0" />
</ItemGroup> </ItemGroup>
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. --> <!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->