mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 13:22:55 +08:00
Merge branch 'master' into multiplier1x
This commit is contained in:
commit
34acb435b8
2
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
2
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user