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

Merge branch 'master' into fix-async-playlist-enumeration

This commit is contained in:
Dean Herbert 2020-02-19 23:38:39 +09:00 committed by GitHub
commit 3457d341b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 264 additions and 44 deletions

View File

@ -0,0 +1,90 @@
// 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 NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Sprites;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapListing;
using osuTK;
namespace osu.Game.Tests.Visual.UserInterface
{
public class TestSceneBeatmapListingSearchSection : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(BeatmapListingSearchSection),
};
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
private readonly BeatmapListingSearchSection section;
public TestSceneBeatmapListingSearchSection()
{
OsuSpriteText query;
OsuSpriteText ruleset;
OsuSpriteText category;
Add(section = new BeatmapListingSearchSection
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
});
Add(new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
Children = new Drawable[]
{
query = new OsuSpriteText(),
ruleset = new OsuSpriteText(),
category = new OsuSpriteText(),
}
});
section.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true);
section.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true);
section.Category.BindValueChanged(c => category.Text = $"Category: {c.NewValue}", true);
}
[Test]
public void TestCovers()
{
AddStep("Set beatmap", () => section.BeatmapSet = beatmap_set);
AddStep("Set beatmap (no cover)", () => section.BeatmapSet = no_cover_beatmap_set);
AddStep("Set null beatmap", () => section.BeatmapSet = null);
}
private static readonly BeatmapSetInfo beatmap_set = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
{
Covers = new BeatmapSetOnlineCovers
{
Cover = "https://assets.ppy.sh/beatmaps/1094296/covers/cover@2x.jpg?1581416305"
}
}
};
private static readonly BeatmapSetInfo no_cover_beatmap_set = new BeatmapSetInfo
{
OnlineInfo = new BeatmapSetOnlineInfo
{
Covers = new BeatmapSetOnlineCovers
{
Cover = string.Empty
}
}
};
}
}

View File

@ -17,18 +17,16 @@ namespace osu.Game.Graphics.UserInterface
public SearchTextBox() public SearchTextBox()
{ {
Height = 35; Height = 35;
AddRange(new Drawable[] Add(new SpriteIcon
{ {
new SpriteIcon Icon = FontAwesome.Solid.Search,
{ Origin = Anchor.CentreRight,
Icon = FontAwesome.Solid.Search, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Margin = new MarginPadding { Right = 10 },
Anchor = Anchor.CentreRight, Size = new Vector2(20),
Margin = new MarginPadding { Right = 10 },
Size = new Vector2(20),
}
}); });
TextFlow.Padding = new MarginPadding { Right = 35 };
PlaceholderText = "type to search"; PlaceholderText = "type to search";
} }

View File

@ -0,0 +1,125 @@
// 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.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Online.API.Requests;
using osu.Game.Rulesets;
using osuTK;
using osu.Framework.Bindables;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osuTK.Graphics;
namespace osu.Game.Overlays.BeatmapListing
{
public class BeatmapListingSearchSection : CompositeDrawable
{
public Bindable<string> Query => textBox.Current;
public Bindable<RulesetInfo> Ruleset => modeFilter.Current;
public Bindable<BeatmapSearchCategory> Category => categoryFilter.Current;
public BeatmapSetInfo BeatmapSet
{
set
{
if (value == null || string.IsNullOrEmpty(value.OnlineInfo.Covers.Cover))
{
beatmapCover.FadeOut(600, Easing.OutQuint);
return;
}
beatmapCover.BeatmapSet = value;
beatmapCover.FadeTo(0.1f, 200, Easing.OutQuint);
}
}
private readonly BeatmapSearchTextBox textBox;
private readonly BeatmapSearchRulesetFilterRow modeFilter;
private readonly BeatmapSearchFilterRow<BeatmapSearchCategory> categoryFilter;
private readonly Box background;
private readonly UpdateableBeatmapSetCover beatmapCover;
public BeatmapListingSearchSection()
{
AutoSizeAxes = Axes.Y;
RelativeSizeAxes = Axes.X;
AddRangeInternal(new Drawable[]
{
background = new Box
{
RelativeSizeAxes = Axes.Both
},
new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
Child = beatmapCover = new UpdateableBeatmapSetCover
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
}
},
new Container
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Padding = new MarginPadding
{
Vertical = 20,
Horizontal = 40,
},
Child = new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 20),
Children = new Drawable[]
{
textBox = new BeatmapSearchTextBox
{
RelativeSizeAxes = Axes.X,
},
new ReverseChildIDFillFlowContainer<Drawable>
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Padding = new MarginPadding { Horizontal = 10 },
Children = new Drawable[]
{
modeFilter = new BeatmapSearchRulesetFilterRow(),
categoryFilter = new BeatmapSearchFilterRow<BeatmapSearchCategory>(@"Categories"),
}
}
}
}
}
});
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
background.Colour = colourProvider.Dark6;
}
private class BeatmapSearchTextBox : SearchTextBox
{
protected override Color4 SelectionColour => Color4.Gray;
public BeatmapSearchTextBox()
{
PlaceholderText = @"type in keywords...";
}
}
}
}

View File

@ -26,8 +26,9 @@ namespace osu.Game.Overlays.Music
private TextFlowContainer text; private TextFlowContainer text;
private IEnumerable<Drawable> titleSprites; private IEnumerable<Drawable> titleSprites;
private ILocalisedBindableString titleBind;
private ILocalisedBindableString artistBind; private ILocalisedBindableString title;
private ILocalisedBindableString artist;
private Color4 selectedColour; private Color4 selectedColour;
private Color4 artistColour; private Color4 artistColour;
@ -47,24 +48,24 @@ namespace osu.Game.Overlays.Music
artistColour = colours.Gray9; artistColour = colours.Gray9;
HandleColour = colours.Gray5; HandleColour = colours.Gray5;
titleBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.TitleUnicode, Model.Metadata.Title))); title = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.TitleUnicode, Model.Metadata.Title)));
artistBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.ArtistUnicode, Model.Metadata.Artist))); artist = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.ArtistUnicode, Model.Metadata.Artist)));
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
artist.BindValueChanged(_ => recreateText(), true);
SelectedSet.BindValueChanged(set => SelectedSet.BindValueChanged(set =>
{ {
if (set.OldValue != Model && set.NewValue != Model) if (set.OldValue?.Equals(Model) != true && set.NewValue?.Equals(Model) != true)
return; return;
foreach (Drawable s in titleSprites) foreach (Drawable s in titleSprites)
s.FadeColour(set.NewValue == Model ? selectedColour : Color4.White, FADE_DURATION); s.FadeColour(set.NewValue.Equals(Model) ? selectedColour : Color4.White, FADE_DURATION);
}, true); }, true);
artistBind.BindValueChanged(_ => recreateText(), true);
} }
protected override Drawable CreateContent() => text = new OsuTextFlowContainer protected override Drawable CreateContent() => text = new OsuTextFlowContainer
@ -78,9 +79,9 @@ namespace osu.Game.Overlays.Music
text.Clear(); text.Clear();
//space after the title to put a space between the title and artist //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<SpriteText>(); titleSprites = text.AddText(title.Value + @" ", sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)).OfType<SpriteText>();
text.AddText(artistBind.Value, sprite => text.AddText(artist.Value, sprite =>
{ {
sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold);
sprite.Colour = artistColour; sprite.Colour = artistColour;

View File

@ -11,23 +11,21 @@ namespace osu.Game.Overlays.Rankings
{ {
public class RankingsOverlayHeader : TabControlOverlayHeader<RankingsScope> public class RankingsOverlayHeader : TabControlOverlayHeader<RankingsScope>
{ {
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>(); public Bindable<RulesetInfo> Ruleset => rulesetSelector.Current;
public readonly Bindable<Country> Country = new Bindable<Country>();
public Bindable<Country> Country => countryFilter.Current;
private OverlayRulesetSelector rulesetSelector;
private CountryFilter countryFilter;
protected override ScreenTitle CreateTitle() => new RankingsTitle protected override ScreenTitle CreateTitle() => new RankingsTitle
{ {
Scope = { BindTarget = Current } Scope = { BindTarget = Current }
}; };
protected override Drawable CreateTitleContent() => new OverlayRulesetSelector protected override Drawable CreateTitleContent() => rulesetSelector = new OverlayRulesetSelector();
{
Current = Ruleset
};
protected override Drawable CreateContent() => new CountryFilter protected override Drawable CreateContent() => countryFilter = new CountryFilter();
{
Current = Country
};
private class RankingsTitle : ScreenTitle private class RankingsTitle : ScreenTitle
{ {

View File

@ -19,14 +19,17 @@ namespace osu.Game.Overlays
{ {
public class RankingsOverlay : FullscreenOverlay public class RankingsOverlay : FullscreenOverlay
{ {
protected readonly Bindable<Country> Country = new Bindable<Country>(); protected Bindable<Country> Country => header.Country;
protected readonly Bindable<RankingsScope> Scope = new Bindable<RankingsScope>();
private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>(); protected Bindable<RankingsScope> Scope => header.Current;
private Bindable<RulesetInfo> ruleset => header.Ruleset;
private readonly BasicScrollContainer scrollFlow; private readonly BasicScrollContainer scrollFlow;
private readonly Container contentContainer; private readonly Container contentContainer;
private readonly DimmedLoadingLayer loading; private readonly DimmedLoadingLayer loading;
private readonly Box background; private readonly Box background;
private readonly RankingsOverlayHeader header;
private APIRequest lastRequest; private APIRequest lastRequest;
private CancellationTokenSource cancellationToken; private CancellationTokenSource cancellationToken;
@ -54,14 +57,11 @@ namespace osu.Game.Overlays
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Children = new Drawable[] Children = new Drawable[]
{ {
new RankingsOverlayHeader header = new RankingsOverlayHeader
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Depth = -float.MaxValue, Depth = -float.MaxValue
Country = { BindTarget = Country },
Current = { BindTarget = Scope },
Ruleset = { BindTarget = ruleset }
}, },
new Container new Container
{ {
@ -94,6 +94,8 @@ namespace osu.Game.Overlays
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete();
Country.BindValueChanged(_ => Country.BindValueChanged(_ =>
{ {
// if a country is requested, force performance scope. // if a country is requested, force performance scope.
@ -101,7 +103,7 @@ namespace osu.Game.Overlays
Scope.Value = RankingsScope.Performance; Scope.Value = RankingsScope.Performance;
Scheduler.AddOnce(loadNewContent); Scheduler.AddOnce(loadNewContent);
}, true); });
Scope.BindValueChanged(_ => Scope.BindValueChanged(_ =>
{ {
@ -110,7 +112,7 @@ namespace osu.Game.Overlays
Country.Value = null; Country.Value = null;
Scheduler.AddOnce(loadNewContent); Scheduler.AddOnce(loadNewContent);
}, true); });
ruleset.BindValueChanged(_ => ruleset.BindValueChanged(_ =>
{ {
@ -118,9 +120,7 @@ namespace osu.Game.Overlays
return; return;
Scheduler.AddOnce(loadNewContent); Scheduler.AddOnce(loadNewContent);
}, true); });
base.LoadComplete();
} }
public void ShowCountry(Country requested) public void ShowCountry(Country requested)
@ -158,8 +158,8 @@ namespace osu.Game.Overlays
return; return;
} }
request.Success += () => loadContent(createTableFromResponse(request)); request.Success += () => Schedule(() => loadContent(createTableFromResponse(request)));
request.Failure += _ => loadContent(null); request.Failure += _ => Schedule(() => loadContent(null));
api.Queue(request); api.Queue(request);
} }
@ -221,5 +221,13 @@ namespace osu.Game.Overlays
contentContainer.Child = loaded; contentContainer.Child = loaded;
}, (cancellationToken = new CancellationTokenSource()).Token); }, (cancellationToken = new CancellationTokenSource()).Token);
} }
protected override void Dispose(bool isDisposing)
{
lastRequest?.Cancel();
cancellationToken?.Cancel();
base.Dispose(isDisposing);
}
} }
} }