1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-05 04:13:03 +08:00

Merge branch 'master' into fix-accuracy-formatting

This commit is contained in:
Bartłomiej Dach 2021-03-26 21:24:04 +01:00 committed by GitHub
commit e9289853fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 183 additions and 86 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,2 +1,6 @@
[General] [General]
Version: 1.0 Version: 1.0
[Fonts]
HitCircleOverlap: 3
ScoreOverlap: 3

View File

@ -33,12 +33,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public SpinnerSpmCounter SpmCounter { get; private set; } public SpinnerSpmCounter SpmCounter { get; private set; }
private Container<DrawableSpinnerTick> ticks; private Container<DrawableSpinnerTick> ticks;
private SpinnerBonusDisplay bonusDisplay;
private PausableSkinnableSound spinningSample; private PausableSkinnableSound spinningSample;
private Bindable<bool> isSpinning; private Bindable<bool> isSpinning;
private bool spinnerFrequencyModulate; private bool spinnerFrequencyModulate;
/// <summary>
/// The amount of bonus score gained from spinning after the required number of spins, for display purposes.
/// </summary>
public IBindable<double> GainedBonus => gainedBonus;
private readonly Bindable<double> gainedBonus = new Bindable<double>();
private const double fade_out_duration = 160; private const double fade_out_duration = 160;
public DrawableSpinner() public DrawableSpinner()
@ -67,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Children = new Drawable[] Children = new Drawable[]
{ {
new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SpinnerBody), _ => new DefaultSpinnerDisc()), new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SpinnerBody), _ => new DefaultSpinner()),
RotationTracker = new SpinnerRotationTracker(this) RotationTracker = new SpinnerRotationTracker(this)
} }
}, },
@ -78,12 +84,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Y = 120, Y = 120,
Alpha = 0 Alpha = 0
}, },
bonusDisplay = new SpinnerBonusDisplay
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Y = -120,
},
spinningSample = new PausableSkinnableSound spinningSample = new PausableSkinnableSound
{ {
Volume = { Value = 0 }, Volume = { Value = 0 },
@ -298,6 +298,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private void fadeInCounter() => SpmCounter.FadeIn(HitObject.TimeFadeIn); private void fadeInCounter() => SpmCounter.FadeIn(HitObject.TimeFadeIn);
private static readonly int score_per_tick = new SpinnerBonusTick.OsuSpinnerBonusTickJudgement().MaxNumericResult;
private int wholeSpins; private int wholeSpins;
private void updateBonusScore() private void updateBonusScore()
@ -322,8 +324,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (tick != null) if (tick != null)
{ {
tick.TriggerResult(true); tick.TriggerResult(true);
if (tick is DrawableSpinnerBonusTick) if (tick is DrawableSpinnerBonusTick)
bonusDisplay.SetBonusCount(spins - HitObject.SpinsRequired); gainedBonus.Value = score_per_tick * (spins - HitObject.SpinsRequired);
} }
wholeSpins++; wholeSpins++;

View File

@ -18,6 +18,6 @@ namespace osu.Game.Rulesets.Osu
SliderFollowCircle, SliderFollowCircle,
SliderBall, SliderBall,
SliderBody, SliderBody,
SpinnerBody SpinnerBody,
} }
} }

View File

@ -0,0 +1,68 @@
// 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.Globalization;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Skinning.Default
{
public class DefaultSpinner : CompositeDrawable
{
private DrawableSpinner drawableSpinner;
private OsuSpriteText bonusCounter;
public DefaultSpinner()
{
RelativeSizeAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
}
[BackgroundDependencyLoader]
private void load(DrawableHitObject drawableHitObject)
{
drawableSpinner = (DrawableSpinner)drawableHitObject;
AddRangeInternal(new Drawable[]
{
new DefaultSpinnerDisc
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
bonusCounter = new OsuSpriteText
{
Alpha = 0,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.Numeric.With(size: 24),
Y = -120,
}
});
}
private IBindable<double> gainedBonus;
protected override void LoadComplete()
{
base.LoadComplete();
gainedBonus = drawableSpinner.GainedBonus.GetBoundCopy();
gainedBonus.BindValueChanged(bonus =>
{
bonusCounter.Text = bonus.NewValue.ToString(NumberFormatInfo.InvariantInfo);
bonusCounter.FadeOutFromOne(1500);
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
});
}
}
}

View File

@ -40,14 +40,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default
public DefaultSpinnerDisc() public DefaultSpinnerDisc()
{ {
RelativeSizeAxes = Axes.Both;
// we are slightly bigger than our parent, to clip the top and bottom of the circle // we are slightly bigger than our parent, to clip the top and bottom of the circle
// this should probably be revisited when scaled spinners are a thing. // this should probably be revisited when scaled spinners are a thing.
Scale = new Vector2(initial_scale); Scale = new Vector2(initial_scale);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -1,47 +0,0 @@
// 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.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Skinning.Default
{
/// <summary>
/// Shows incremental bonus score achieved for a spinner.
/// </summary>
public class SpinnerBonusDisplay : CompositeDrawable
{
private static readonly int score_per_tick = new SpinnerBonusTick().CreateJudgement().MaxNumericResult;
private readonly OsuSpriteText bonusCounter;
public SpinnerBonusDisplay()
{
AutoSizeAxes = Axes.Both;
InternalChild = bonusCounter = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.Numeric.With(size: 24),
Alpha = 0,
};
}
private int displayedCount;
public void SetBonusCount(int count)
{
if (displayedCount == count)
return;
displayedCount = count;
bonusCounter.Text = $"{score_per_tick * count}";
bonusCounter.FadeOutFromOne(1500);
bonusCounter.ScaleTo(1.5f).Then().ScaleTo(1f, 1000, Easing.OutQuint);
}
}
}

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; using System;
using System.Globalization;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -32,6 +33,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
private Sprite spin; private Sprite spin;
private Sprite clear; private Sprite clear;
private LegacySpriteText bonusCounter;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(DrawableHitObject drawableHitObject, ISkinSource source) private void load(DrawableHitObject drawableHitObject, ISkinSource source)
{ {
@ -45,36 +48,67 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
DrawableSpinner = (DrawableSpinner)drawableHitObject; DrawableSpinner = (DrawableSpinner)drawableHitObject;
AddRangeInternal(new[] Container overlayContainer;
AddInternal(overlayContainer = new Container
{ {
spin = new Sprite Depth = float.MinValue,
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{ {
Anchor = Anchor.TopCentre, spin = new Sprite
Origin = Anchor.Centre, {
Depth = float.MinValue, Anchor = Anchor.TopCentre,
Texture = source.GetTexture("spinner-spin"), Origin = Anchor.Centre,
Scale = new Vector2(SPRITE_SCALE), Texture = source.GetTexture("spinner-spin"),
Y = SPINNER_TOP_OFFSET + 335, Scale = new Vector2(SPRITE_SCALE),
}, Y = SPINNER_TOP_OFFSET + 335,
clear = new Sprite },
{ clear = new Sprite
Alpha = 0, {
Anchor = Anchor.TopCentre, Alpha = 0,
Origin = Anchor.Centre, Anchor = Anchor.TopCentre,
Depth = float.MinValue, Origin = Anchor.Centre,
Texture = source.GetTexture("spinner-clear"), Texture = source.GetTexture("spinner-clear"),
Scale = new Vector2(SPRITE_SCALE), Scale = new Vector2(SPRITE_SCALE),
Y = SPINNER_TOP_OFFSET + 115, Y = SPINNER_TOP_OFFSET + 115,
}, },
}
}); });
bonusCounter = (source.GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreText)) as LegacySpriteText)?.With(c =>
{
c.Alpha = 0f;
c.Anchor = Anchor.TopCentre;
c.Origin = Anchor.Centre;
c.Font = c.Font.With(fixedWidth: false);
c.Scale = new Vector2(SPRITE_SCALE);
c.Y = SPINNER_TOP_OFFSET + 299;
});
if (bonusCounter != null)
overlayContainer.Add(bonusCounter);
} }
private IBindable<double> gainedBonus;
private readonly Bindable<bool> completed = new Bindable<bool>(); private readonly Bindable<bool> completed = new Bindable<bool>();
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
if (bonusCounter != null)
{
gainedBonus = DrawableSpinner.GainedBonus.GetBoundCopy();
gainedBonus.BindValueChanged(bonus =>
{
bonusCounter.Text = bonus.NewValue.ToString(NumberFormatInfo.InvariantInfo);
bonusCounter.FadeOutFromOne(800, Easing.Out);
bonusCounter.ScaleTo(SPRITE_SCALE * 2f).Then().ScaleTo(SPRITE_SCALE * 1.28f, 800, Easing.Out);
});
}
completed.BindValueChanged(onCompletedChanged, true); completed.BindValueChanged(onCompletedChanged, true);
DrawableSpinner.ApplyCustomUpdateState += UpdateStateTransforms; DrawableSpinner.ApplyCustomUpdateState += UpdateStateTransforms;

View File

@ -34,6 +34,7 @@ namespace osu.Game.Tests.Visual.UserInterface
public void SetUp() => Schedule(() => public void SetUp() => Schedule(() =>
{ {
OsuSpriteText query; OsuSpriteText query;
OsuSpriteText general;
OsuSpriteText ruleset; OsuSpriteText ruleset;
OsuSpriteText category; OsuSpriteText category;
OsuSpriteText genre; OsuSpriteText genre;
@ -58,6 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface
Children = new Drawable[] Children = new Drawable[]
{ {
query = new OsuSpriteText(), query = new OsuSpriteText(),
general = new OsuSpriteText(),
ruleset = new OsuSpriteText(), ruleset = new OsuSpriteText(),
category = new OsuSpriteText(), category = new OsuSpriteText(),
genre = new OsuSpriteText(), genre = new OsuSpriteText(),
@ -71,6 +73,7 @@ namespace osu.Game.Tests.Visual.UserInterface
}; };
control.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true); control.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true);
control.General.BindCollectionChanged((u, v) => general.Text = $"General: {(control.General.Any() ? string.Join('.', control.General.Select(i => i.ToString().ToLowerInvariant())) : "")}", true);
control.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true); control.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true);
control.Category.BindValueChanged(c => category.Text = $"Category: {c.NewValue}", true); control.Category.BindValueChanged(c => category.Text = $"Category: {c.NewValue}", true);
control.Genre.BindValueChanged(g => genre.Text = $"Genre: {g.NewValue}", true); control.Genre.BindValueChanged(g => genre.Text = $"Genre: {g.NewValue}", true);

View File

@ -15,6 +15,9 @@ namespace osu.Game.Online.API.Requests
{ {
public class SearchBeatmapSetsRequest : APIRequest<SearchBeatmapSetsResponse> public class SearchBeatmapSetsRequest : APIRequest<SearchBeatmapSetsResponse>
{ {
[CanBeNull]
public IReadOnlyCollection<SearchGeneral> General { get; }
public SearchCategory SearchCategory { get; } public SearchCategory SearchCategory { get; }
public SortCriteria SortCriteria { get; } public SortCriteria SortCriteria { get; }
@ -45,6 +48,7 @@ namespace osu.Game.Online.API.Requests
string query, string query,
RulesetInfo ruleset, RulesetInfo ruleset,
Cursor cursor = null, Cursor cursor = null,
IReadOnlyCollection<SearchGeneral> general = null,
SearchCategory searchCategory = SearchCategory.Any, SearchCategory searchCategory = SearchCategory.Any,
SortCriteria sortCriteria = SortCriteria.Ranked, SortCriteria sortCriteria = SortCriteria.Ranked,
SortDirection sortDirection = SortDirection.Descending, SortDirection sortDirection = SortDirection.Descending,
@ -59,6 +63,7 @@ namespace osu.Game.Online.API.Requests
this.ruleset = ruleset; this.ruleset = ruleset;
this.cursor = cursor; this.cursor = cursor;
General = general;
SearchCategory = searchCategory; SearchCategory = searchCategory;
SortCriteria = sortCriteria; SortCriteria = sortCriteria;
SortDirection = sortDirection; SortDirection = sortDirection;
@ -75,6 +80,9 @@ namespace osu.Game.Online.API.Requests
var req = base.CreateWebRequest(); var req = base.CreateWebRequest();
req.AddParameter("q", query); req.AddParameter("q", query);
if (General != null && General.Any())
req.AddParameter("c", string.Join('.', General.Select(e => e.ToString().ToLowerInvariant())));
if (ruleset.ID.HasValue) if (ruleset.ID.HasValue)
req.AddParameter("m", ruleset.ID.Value.ToString()); req.AddParameter("m", ruleset.ID.Value.ToString());

View File

@ -123,13 +123,13 @@ namespace osu.Game.Online
{ {
if (attachedRequest.Progress == 1) if (attachedRequest.Progress == 1)
{ {
State.Value = DownloadState.Importing;
Progress.Value = 1; Progress.Value = 1;
State.Value = DownloadState.Importing;
} }
else else
{ {
State.Value = DownloadState.Downloading;
Progress.Value = attachedRequest.Progress; Progress.Value = attachedRequest.Progress;
State.Value = DownloadState.Downloading;
attachedRequest.Failure += onRequestFailure; attachedRequest.Failure += onRequestFailure;
attachedRequest.DownloadProgressed += onRequestProgress; attachedRequest.DownloadProgressed += onRequestProgress;

View File

@ -45,6 +45,9 @@ namespace osu.Game.Online.Rooms
Progress.BindValueChanged(_ => Progress.BindValueChanged(_ =>
{ {
if (State.Value != DownloadState.Downloading)
return;
// incoming progress changes are going to be at a very high rate. // incoming progress changes are going to be at a very high rate.
// we don't want to flood the network with this, so rate limit how often we send progress updates. // we don't want to flood the network with this, so rate limit how often we send progress updates.
if (progressUpdate?.Completed != false) if (progressUpdate?.Completed != false)

View File

@ -134,6 +134,7 @@ namespace osu.Game.Overlays.BeatmapListing
queueUpdateSearch(true); queueUpdateSearch(true);
}); });
searchControl.General.CollectionChanged += (_, __) => queueUpdateSearch();
searchControl.Ruleset.BindValueChanged(_ => queueUpdateSearch()); searchControl.Ruleset.BindValueChanged(_ => queueUpdateSearch());
searchControl.Category.BindValueChanged(_ => queueUpdateSearch()); searchControl.Category.BindValueChanged(_ => queueUpdateSearch());
searchControl.Genre.BindValueChanged(_ => queueUpdateSearch()); searchControl.Genre.BindValueChanged(_ => queueUpdateSearch());
@ -187,6 +188,7 @@ namespace osu.Game.Overlays.BeatmapListing
searchControl.Query.Value, searchControl.Query.Value,
searchControl.Ruleset.Value, searchControl.Ruleset.Value,
lastResponse?.Cursor, lastResponse?.Cursor,
searchControl.General,
searchControl.Category.Value, searchControl.Category.Value,
sortControl.Current.Value, sortControl.Current.Value,
sortControl.SortDirection.Value, sortControl.SortDirection.Value,

View File

@ -29,6 +29,8 @@ namespace osu.Game.Overlays.BeatmapListing
public Bindable<string> Query => textBox.Current; public Bindable<string> Query => textBox.Current;
public BindableList<SearchGeneral> General => generalFilter.Current;
public Bindable<RulesetInfo> Ruleset => modeFilter.Current; public Bindable<RulesetInfo> Ruleset => modeFilter.Current;
public Bindable<SearchCategory> Category => categoryFilter.Current; public Bindable<SearchCategory> Category => categoryFilter.Current;
@ -61,6 +63,7 @@ namespace osu.Game.Overlays.BeatmapListing
} }
private readonly BeatmapSearchTextBox textBox; private readonly BeatmapSearchTextBox textBox;
private readonly BeatmapSearchMultipleSelectionFilterRow<SearchGeneral> generalFilter;
private readonly BeatmapSearchRulesetFilterRow modeFilter; private readonly BeatmapSearchRulesetFilterRow modeFilter;
private readonly BeatmapSearchFilterRow<SearchCategory> categoryFilter; private readonly BeatmapSearchFilterRow<SearchCategory> categoryFilter;
private readonly BeatmapSearchFilterRow<SearchGenre> genreFilter; private readonly BeatmapSearchFilterRow<SearchGenre> genreFilter;
@ -123,6 +126,7 @@ namespace osu.Game.Overlays.BeatmapListing
Padding = new MarginPadding { Horizontal = 10 }, Padding = new MarginPadding { Horizontal = 10 },
Children = new Drawable[] Children = new Drawable[]
{ {
generalFilter = new BeatmapSearchMultipleSelectionFilterRow<SearchGeneral>(@"General"),
modeFilter = new BeatmapSearchRulesetFilterRow(), modeFilter = new BeatmapSearchRulesetFilterRow(),
categoryFilter = new BeatmapSearchFilterRow<SearchCategory>(@"Categories"), categoryFilter = new BeatmapSearchFilterRow<SearchCategory>(@"Categories"),
genreFilter = new BeatmapSearchFilterRow<SearchGenre>(@"Genre"), genreFilter = new BeatmapSearchFilterRow<SearchGenre>(@"Genre"),

View File

@ -0,0 +1,19 @@
// 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.ComponentModel;
namespace osu.Game.Overlays.BeatmapListing
{
public enum SearchGeneral
{
[Description("Recommended difficulty")]
Recommended,
[Description("Include converted beatmaps")]
Converts,
[Description("Subscribed mappers")]
Follows
}
}

View File

@ -2,7 +2,6 @@
// 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; using System;
using System.Diagnostics;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -170,7 +169,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
private void joinRequested(Room room) private void joinRequested(Room room)
{ {
Debug.Assert(joiningRoomOperation == null); if (joiningRoomOperation != null)
return;
joiningRoomOperation = ongoingOperationTracker?.BeginOperation(); joiningRoomOperation = ongoingOperationTracker?.BeginOperation();
RoomManager?.JoinRoom(room, r => RoomManager?.JoinRoom(room, r =>