1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-28 01:47:33 +08:00

Merge branch 'master' into hold-note-fade

This commit is contained in:
Dean Herbert 2020-11-14 10:17:55 +09:00 committed by GitHub
commit 97ed9db998
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 12 deletions

View File

@ -45,12 +45,12 @@ namespace osu.Game.Rulesets.Osu.Edit
public override bool HandleReverse() public override bool HandleReverse()
{ {
var hitObjects = selectedMovableObjects; var hitObjects = EditorBeatmap.SelectedHitObjects;
double endTime = hitObjects.Max(h => h.GetEndTime()); double endTime = hitObjects.Max(h => h.GetEndTime());
double startTime = hitObjects.Min(h => h.StartTime); double startTime = hitObjects.Min(h => h.StartTime);
bool moreThanOneObject = hitObjects.Length > 1; bool moreThanOneObject = hitObjects.Count > 1;
foreach (var h in hitObjects) foreach (var h in hitObjects)
{ {

View File

@ -6,6 +6,7 @@ using System.Linq;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
@ -21,8 +22,14 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override void AddCheckSteps() protected override void AddCheckSteps()
{ {
AddUntilStep("wait for fail", () => Player.HasFailed); AddUntilStep("wait for fail", () => Player.HasFailed);
AddUntilStep("wait for multiple judged objects", () => ((FailPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.Count(h => h.AllJudged) > 1); AddUntilStep("wait for multiple judgements", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits > 1);
AddAssert("total judgements == 1", () => ((FailPlayer)Player).HealthProcessor.JudgedHits >= 1); AddAssert("total number of results == 1", () =>
{
var score = new ScoreInfo();
((FailPlayer)Player).ScoreProcessor.PopulateScore(score);
return score.Statistics.Values.Sum() == 1;
});
} }
private class FailPlayer : TestPlayer private class FailPlayer : TestPlayer

View File

@ -1,9 +1,12 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Screens; using osu.Game.Screens;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
@ -73,6 +76,22 @@ namespace osu.Game.Tests.Visual.Navigation
AddAssert("did perform", () => actionPerformed); AddAssert("did perform", () => actionPerformed);
} }
[Test]
public void TestOverlaysAlwaysClosed()
{
ChatOverlay chat = null;
AddUntilStep("is at menu", () => Game.ScreenStack.CurrentScreen is MainMenu);
AddUntilStep("wait for chat load", () => (chat = Game.ChildrenOfType<ChatOverlay>().SingleOrDefault()) != null);
AddStep("show chat", () => InputManager.Key(Key.F8));
AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true));
AddUntilStep("still at menu", () => Game.ScreenStack.CurrentScreen is MainMenu);
AddAssert("did perform", () => actionPerformed);
AddAssert("chat closed", () => chat.State.Value == Visibility.Hidden);
}
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void TestPerformBlockedByDialog(bool confirmed) public void TestPerformBlockedByDialog(bool confirmed)

View File

@ -68,6 +68,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
LabelText = "Positional hitsounds", LabelText = "Positional hitsounds",
Current = config.GetBindable<bool>(OsuSetting.PositionalHitSounds) Current = config.GetBindable<bool>(OsuSetting.PositionalHitSounds)
}, },
new SettingsCheckbox
{
LabelText = "Always play first combo break sound",
Current = config.GetBindable<bool>(OsuSetting.AlwaysPlayFirstComboBreak)
},
new SettingsEnumDropdown<ScoreMeterType> new SettingsEnumDropdown<ScoreMeterType>
{ {
LabelText = "Score meter type", LabelText = "Score meter type",

View File

@ -76,6 +76,8 @@ namespace osu.Game
// a dialog may be blocking the execution for now. // a dialog may be blocking the execution for now.
if (checkForDialog(current)) return; if (checkForDialog(current)) return;
game.CloseAllOverlays(false);
// we may already be at the target screen type. // we may already be at the target screen type.
if (validScreens.Contains(getCurrentScreen().GetType()) && !beatmap.Disabled) if (validScreens.Contains(getCurrentScreen().GetType()) && !beatmap.Disabled)
{ {
@ -83,8 +85,6 @@ namespace osu.Game
return; return;
} }
game.CloseAllOverlays(false);
while (current != null) while (current != null)
{ {
if (validScreens.Contains(current.GetType())) if (validScreens.Contains(current.GetType()))

View File

@ -17,8 +17,9 @@ namespace osu.Game.Screens.Play
private SkinnableSound comboBreakSample; private SkinnableSound comboBreakSample;
private Bindable<bool> alwaysPlay; private Bindable<bool> alwaysPlayFirst;
private bool firstTime = true;
private double? firstBreakTime;
public ComboEffects(ScoreProcessor processor) public ComboEffects(ScoreProcessor processor)
{ {
@ -29,7 +30,7 @@ namespace osu.Game.Screens.Play
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
{ {
InternalChild = comboBreakSample = new SkinnableSound(new SampleInfo("Gameplay/combobreak")); InternalChild = comboBreakSample = new SkinnableSound(new SampleInfo("Gameplay/combobreak"));
alwaysPlay = config.GetBindable<bool>(OsuSetting.AlwaysPlayFirstComboBreak); alwaysPlayFirst = config.GetBindable<bool>(OsuSetting.AlwaysPlayFirstComboBreak);
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -38,12 +39,31 @@ namespace osu.Game.Screens.Play
processor.Combo.BindValueChanged(onComboChange); processor.Combo.BindValueChanged(onComboChange);
} }
[Resolved(canBeNull: true)]
private ISamplePlaybackDisabler samplePlaybackDisabler { get; set; }
[Resolved]
private GameplayClock gameplayClock { get; set; }
private void onComboChange(ValueChangedEvent<int> combo) private void onComboChange(ValueChangedEvent<int> combo)
{ {
if (combo.NewValue == 0 && (combo.OldValue > 20 || (alwaysPlay.Value && firstTime))) // handle the case of rewinding before the first combo break time.
if (gameplayClock.CurrentTime < firstBreakTime)
firstBreakTime = null;
if (gameplayClock.ElapsedFrameTime < 0)
return;
if (combo.NewValue == 0 && (combo.OldValue > 20 || (alwaysPlayFirst.Value && firstBreakTime == null)))
{ {
firstBreakTime = gameplayClock.CurrentTime;
// combo break isn't a pausable sound itself as we want to let it play out.
// we still need to disable during seeks, though.
if (samplePlaybackDisabler?.SamplePlaybackDisabled.Value == true)
return;
comboBreakSample?.Play(); comboBreakSample?.Play();
firstTime = false;
} }
} }
} }

View File

@ -302,12 +302,12 @@ namespace osu.Game.Screens.Play
{ {
ScoreProcessor, ScoreProcessor,
HealthProcessor, HealthProcessor,
new ComboEffects(ScoreProcessor),
breakTracker = new BreakTracker(DrawableRuleset.GameplayStartTime, ScoreProcessor) breakTracker = new BreakTracker(DrawableRuleset.GameplayStartTime, ScoreProcessor)
{ {
Breaks = working.Beatmap.Breaks Breaks = working.Beatmap.Breaks
} }
}), }),
new ComboEffects(ScoreProcessor)
} }
}; };