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

Merge branch 'master' into multiplier1x

This commit is contained in:
Salman Ahmed 2023-12-31 16:48:00 +03:00 committed by GitHub
commit 34acb435b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 105 additions and 28 deletions

View File

@ -42,7 +42,7 @@ body:
- type: input - type: input
attributes: attributes:
label: Version label: Version
description: The version you encountered this bug on. This is shown at the bottom of the main menu and also at the end of the settings screen. description: The version you encountered this bug on. This is shown at the end of the settings overlay.
validations: validations:
required: true required: true
- type: markdown - type: markdown

View File

@ -19,6 +19,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
{ {
public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement
{ {
private const float judgement_y_position = 160;
private RingExplosion? ringExplosion; private RingExplosion? ringExplosion;
[Resolved] [Resolved]
@ -30,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Y = 160; Y = judgement_y_position;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -76,7 +78,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
this.ScaleTo(1.6f); this.ScaleTo(1.6f);
this.ScaleTo(1, 100, Easing.In); this.ScaleTo(1, 100, Easing.In);
this.MoveTo(Vector2.Zero); this.MoveToY(judgement_y_position);
this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint);
this.RotateTo(0); this.RotateTo(0);

View File

@ -3,7 +3,7 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Utils; using osu.Framework.Utils;
@ -25,9 +25,15 @@ namespace osu.Game.Tests.Visual.Settings
private Container content = null!; private Container content = null!;
protected override Container Content => content; protected override Container Content => content;
private OsuConfigManager localConfig = null!;
private AudioOffsetAdjustControl adjustControl = null!;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
localConfig = new OsuConfigManager(LocalStorage);
Dependencies.CacheAs(localConfig);
base.Content.AddRange(new Drawable[] base.Content.AddRange(new Drawable[]
{ {
tracker, tracker,
@ -41,17 +47,21 @@ namespace osu.Game.Tests.Visual.Settings
}); });
} }
[Test] [SetUp]
public void TestBehaviour() public void SetUp() => Schedule(() =>
{ {
AddStep("create control", () => Child = new AudioOffsetAdjustControl Child = adjustControl = new AudioOffsetAdjustControl
{ {
Current = new BindableDouble Current = localConfig.GetBindable<double>(OsuSetting.AudioOffset),
{ };
MinValue = -500,
MaxValue = 500 localConfig.SetValue(OsuSetting.AudioOffset, 0.0);
} tracker.ClearHistory();
}); });
[Test]
public void TestDisplay()
{
AddStep("set new score", () => statics.SetValue(Static.LastLocalUserScore, new ScoreInfo AddStep("set new score", () => statics.SetValue(Static.LastLocalUserScore, new ScoreInfo
{ {
HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(RNG.NextDouble(-100, 100)), HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(RNG.NextDouble(-100, 100)),
@ -59,5 +69,63 @@ namespace osu.Game.Tests.Visual.Settings
})); }));
AddStep("clear history", () => tracker.ClearHistory()); AddStep("clear history", () => tracker.ClearHistory());
} }
[Test]
public void TestBehaviour()
{
AddStep("set score with -20ms", () => setScore(-20));
AddAssert("suggested global offset is 20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(20));
AddStep("clear history", () => tracker.ClearHistory());
AddStep("set score with 40ms", () => setScore(40));
AddAssert("suggested global offset is -40ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(-40));
AddStep("clear history", () => tracker.ClearHistory());
}
[Test]
public void TestNonZeroGlobalOffset()
{
AddStep("set global offset to -20ms", () => localConfig.SetValue(OsuSetting.AudioOffset, -20.0));
AddStep("set score with -20ms", () => setScore(-20));
AddAssert("suggested global offset is 0ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(0));
AddStep("clear history", () => tracker.ClearHistory());
AddStep("set global offset to 20ms", () => localConfig.SetValue(OsuSetting.AudioOffset, 20.0));
AddStep("set score with 40ms", () => setScore(40));
AddAssert("suggested global offset is -20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(-20));
AddStep("clear history", () => tracker.ClearHistory());
}
[Test]
public void TestMultiplePlays()
{
AddStep("set score with -20ms", () => setScore(-20));
AddStep("set score with -10ms", () => setScore(-10));
AddAssert("suggested global offset is 15ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(15));
AddStep("clear history", () => tracker.ClearHistory());
AddStep("set score with -20ms", () => setScore(-20));
AddStep("set global offset to 30ms", () => localConfig.SetValue(OsuSetting.AudioOffset, 30.0));
AddStep("set score with 10ms", () => setScore(10));
AddAssert("suggested global offset is 20ms", () => adjustControl.SuggestedOffset.Value, () => Is.EqualTo(20));
AddStep("clear history", () => tracker.ClearHistory());
}
private void setScore(double averageHitError)
{
statics.SetValue(Static.LastLocalUserScore, new ScoreInfo
{
HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(averageHitError),
BeatmapInfo = Beatmap.Value.BeatmapInfo,
});
}
protected override void Dispose(bool isDisposing)
{
if (localConfig.IsNotNull())
localConfig.Dispose();
base.Dispose(isDisposing);
}
} }
} }

View File

@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Profile.Header
bool anyInfoAdded = false; bool anyInfoAdded = false;
anyInfoAdded |= tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); anyInfoAdded |= tryAddInfo(FontAwesome.Solid.MapMarker, user.Location);
anyInfoAdded |= tryAddInfo(OsuIcon.Heart, user.Interests); anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Heart, user.Interests);
anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation); anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation);
if (anyInfoAdded) if (anyInfoAdded)

View File

@ -24,6 +24,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
{ {
public partial class AudioOffsetAdjustControl : SettingsItem<double> public partial class AudioOffsetAdjustControl : SettingsItem<double>
{ {
public IBindable<double?> SuggestedOffset => ((AudioOffsetPreview)Control).SuggestedOffset;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
@ -44,7 +46,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
private readonly IBindableList<SessionAverageHitErrorTracker.DataPoint> averageHitErrorHistory = new BindableList<SessionAverageHitErrorTracker.DataPoint>(); private readonly IBindableList<SessionAverageHitErrorTracker.DataPoint> averageHitErrorHistory = new BindableList<SessionAverageHitErrorTracker.DataPoint>();
private readonly Bindable<double?> suggestedOffset = new Bindable<double?>(); public readonly Bindable<double?> SuggestedOffset = new Bindable<double?>();
private Container<Box> notchContainer = null!; private Container<Box> notchContainer = null!;
private TextFlowContainer hintText = null!; private TextFlowContainer hintText = null!;
@ -90,8 +92,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
Text = "Apply suggested offset", Text = "Apply suggested offset",
Action = () => Action = () =>
{ {
if (suggestedOffset.Value.HasValue) if (SuggestedOffset.Value.HasValue)
current.Value = suggestedOffset.Value.Value; current.Value = SuggestedOffset.Value.Value;
hitErrorTracker.ClearHistory(); hitErrorTracker.ClearHistory();
} }
} }
@ -104,7 +106,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
base.LoadComplete(); base.LoadComplete();
averageHitErrorHistory.BindCollectionChanged(updateDisplay, true); averageHitErrorHistory.BindCollectionChanged(updateDisplay, true);
suggestedOffset.BindValueChanged(_ => updateHintText(), true); SuggestedOffset.BindValueChanged(_ => updateHintText(), true);
} }
private void updateDisplay(object? _, NotifyCollectionChangedEventArgs e) private void updateDisplay(object? _, NotifyCollectionChangedEventArgs e)
@ -143,17 +145,17 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
break; break;
} }
suggestedOffset.Value = averageHitErrorHistory.Any() ? -averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset) : null; SuggestedOffset.Value = averageHitErrorHistory.Any() ? averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset) : null;
} }
private float getXPositionForOffset(double offset) => (float)(Math.Clamp(offset, current.MinValue, current.MaxValue) / (2 * current.MaxValue)); private float getXPositionForOffset(double offset) => (float)(Math.Clamp(offset, current.MinValue, current.MaxValue) / (2 * current.MaxValue));
private void updateHintText() private void updateHintText()
{ {
hintText.Text = suggestedOffset.Value == null hintText.Text = SuggestedOffset.Value == null
? @"Play a few beatmaps to receive a suggested offset!" ? @"Play a few beatmaps to receive a suggested offset!"
: $@"Based on the last {averageHitErrorHistory.Count} play(s), the suggested offset is {suggestedOffset.Value:N0} ms."; : $@"Based on the last {averageHitErrorHistory.Count} play(s), the suggested offset is {SuggestedOffset.Value:N0} ms.";
applySuggestion.Enabled.Value = suggestedOffset.Value != null; applySuggestion.Enabled.Value = SuggestedOffset.Value != null;
} }
} }
} }

View File

@ -31,6 +31,9 @@ namespace osu.Game.Screens.Menu
/// </summary> /// </summary>
public partial class MainMenuButton : BeatSyncedContainer, IStateful<ButtonState> public partial class MainMenuButton : BeatSyncedContainer, IStateful<ButtonState>
{ {
public const float BOUNCE_COMPRESSION = 0.9f;
public const float HOVER_SCALE = 1.2f;
public const float BOUNCE_ROTATION = 8;
public event Action<ButtonState>? StateChanged; public event Action<ButtonState>? StateChanged;
public readonly Key[] TriggerKeys; public readonly Key[] TriggerKeys;
@ -125,8 +128,9 @@ namespace osu.Game.Screens.Menu
Shadow = true, Shadow = true,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Size = new Vector2(30), Size = new Vector2(32),
Position = new Vector2(0, 0), Position = new Vector2(0, 0),
Margin = new MarginPadding { Top = -4 },
Icon = symbol Icon = symbol
}, },
new OsuSpriteText new OsuSpriteText
@ -136,6 +140,7 @@ namespace osu.Game.Screens.Menu
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Position = new Vector2(0, 35), Position = new Vector2(0, 35),
Margin = new MarginPadding { Left = -3 },
Text = text Text = text
} }
} }
@ -153,14 +158,14 @@ namespace osu.Game.Screens.Menu
double duration = timingPoint.BeatLength / 2; double duration = timingPoint.BeatLength / 2;
icon.RotateTo(rightward ? 10 : -10, duration * 2, Easing.InOutSine); icon.RotateTo(rightward ? BOUNCE_ROTATION : -BOUNCE_ROTATION, duration * 2, Easing.InOutSine);
icon.Animate( icon.Animate(
i => i.MoveToY(-10, duration, Easing.Out), i => i.MoveToY(-10, duration, Easing.Out),
i => i.ScaleTo(1, duration, Easing.Out) i => i.ScaleTo(HOVER_SCALE, duration, Easing.Out)
).Then( ).Then(
i => i.MoveToY(0, duration, Easing.In), i => i.MoveToY(0, duration, Easing.In),
i => i.ScaleTo(new Vector2(1, 0.9f), duration, Easing.In) i => i.ScaleTo(new Vector2(HOVER_SCALE, HOVER_SCALE * BOUNCE_COMPRESSION), duration, Easing.In)
); );
rightward = !rightward; rightward = !rightward;
@ -177,8 +182,8 @@ namespace osu.Game.Screens.Menu
double duration = TimeUntilNextBeat; double duration = TimeUntilNextBeat;
icon.ClearTransforms(); icon.ClearTransforms();
icon.RotateTo(rightward ? -10 : 10, duration, Easing.InOutSine); icon.RotateTo(rightward ? -BOUNCE_ROTATION : BOUNCE_ROTATION, duration, Easing.InOutSine);
icon.ScaleTo(new Vector2(1, 0.9f), duration, Easing.Out); icon.ScaleTo(new Vector2(HOVER_SCALE, HOVER_SCALE * BOUNCE_COMPRESSION), duration, Easing.Out);
return true; return true;
} }