1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-26 17:53:53 +08:00

Merge branch 'master' into drag-volume-controls

This commit is contained in:
Salman Ahmed 2024-01-17 08:37:34 +03:00 committed by GitHub
commit 23e5167cb5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 164 additions and 70 deletions

View File

@ -51,7 +51,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
public void TestUserAlreadyHasTouchDeviceActive()
{
loadPlayer();
// it is presumed that a previous screen (i.e. song select) will set this up
AddStep("set up touchscreen user", () =>
{
currentPlayer.Score.ScoreInfo.Mods = currentPlayer.Score.ScoreInfo.Mods.Append(new OsuModTouchDevice()).ToArray();
@ -69,6 +68,14 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
AddAssert("touch device mod activated", () => currentPlayer.Score.ScoreInfo.Mods, () => Has.One.InstanceOf<OsuModTouchDevice>());
}
[Test]
public void TestTouchActivePriorToPlayerLoad()
{
AddStep("set touch input active", () => statics.SetValue(Static.TouchInputActive, true));
loadPlayer();
AddUntilStep("touch device mod activated", () => currentPlayer.Score.ScoreInfo.Mods, () => Has.One.InstanceOf<OsuModTouchDevice>());
}
[Test]
public void TestTouchDuringBreak()
{

View File

@ -135,7 +135,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
protected override void Update()
{
base.Update();
spinningMiddle.Rotation = discTop.Rotation = DrawableSpinner.RotationTracker.Rotation;
float turnRatio = spinningMiddle.Texture != null ? 0.5f : 1;
discTop.Rotation = DrawableSpinner.RotationTracker.Rotation * turnRatio;
spinningMiddle.Rotation = DrawableSpinner.RotationTracker.Rotation;
discBottom.Rotation = discTop.Rotation / 3;
glow.Alpha = DrawableSpinner.Progress;

View File

@ -18,10 +18,12 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Scoring.Legacy;
using osu.Game.Tests.Beatmaps;
@ -385,6 +387,42 @@ namespace osu.Game.Tests.Rulesets.Scoring
Assert.That(scoreProcessor.Accuracy.Value, Is.Not.EqualTo(1));
}
[Test]
public void TestNormalGrades()
{
scoreProcessor.ApplyBeatmap(new Beatmap());
Assert.That(scoreProcessor.Rank.Value, Is.EqualTo(ScoreRank.X));
scoreProcessor.Accuracy.Value = 0.99f;
Assert.That(scoreProcessor.Rank.Value, Is.EqualTo(ScoreRank.S));
}
[Test]
public void TestSilverGrades()
{
scoreProcessor.ApplyBeatmap(new Beatmap());
Assert.That(scoreProcessor.Rank.Value, Is.EqualTo(ScoreRank.X));
scoreProcessor.Mods.Value = new[] { new OsuModHidden() };
Assert.That(scoreProcessor.Rank.Value, Is.EqualTo(ScoreRank.XH));
scoreProcessor.Accuracy.Value = 0.99f;
Assert.That(scoreProcessor.Rank.Value, Is.EqualTo(ScoreRank.SH));
}
[Test]
public void TestSilverGradesModsAppliedFirst()
{
scoreProcessor.Mods.Value = new[] { new OsuModHidden() };
scoreProcessor.ApplyBeatmap(new Beatmap());
Assert.That(scoreProcessor.Rank.Value, Is.EqualTo(ScoreRank.XH));
scoreProcessor.Accuracy.Value = 0.99f;
Assert.That(scoreProcessor.Rank.Value, Is.EqualTo(ScoreRank.SH));
}
private class TestJudgement : Judgement
{
public override HitResult MaxResult { get; }

View File

@ -35,6 +35,7 @@ using osu.Game.Screens.OnlinePlay.Lounge;
using osu.Game.Screens.OnlinePlay.Match.Components;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Carousel;
@ -834,6 +835,24 @@ namespace osu.Game.Tests.Visual.Navigation
AddAssert("exit dialog is shown", () => Game.Dependencies.Get<IDialogOverlay>().CurrentDialog is ConfirmExitDialog);
}
[Test]
public void TestQuickSkinEditorDoesntNukeSkin()
{
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
AddStep("open", () => InputManager.Key(Key.Space));
AddStep("skin", () => InputManager.Key(Key.E));
AddStep("editor", () => InputManager.Key(Key.S));
AddStep("and close immediately", () => InputManager.Key(Key.Escape));
AddStep("open again", () => InputManager.Key(Key.S));
Player player = null;
AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null);
AddUntilStep("wait for gameplay still has health bar", () => player.ChildrenOfType<ArgonHealthDisplay>().Any());
}
[Test]
public void TestTouchScreenDetectionAtSongSelect()
{

View File

@ -5,95 +5,90 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Framework.Utils;
using osuTK;
namespace osu.Game.Graphics.Sprites
{
public partial class GlowingSpriteText : Container, IHasText
public partial class GlowingSpriteText : BufferedContainer, IHasText
{
private readonly OsuSpriteText spriteText, blurredText;
private const float blur_sigma = 3f;
// Inflate draw quad to prevent glow from trimming at the edges.
// Padding won't suffice since it will affect text position in cases when it's not centered.
protected override Quad ComputeScreenSpaceDrawQuad() => base.ComputeScreenSpaceDrawQuad().AABBFloat.Inflate(Blur.KernelSize(blur_sigma));
private readonly OsuSpriteText text;
public LocalisableString Text
{
get => spriteText.Text;
set => blurredText.Text = spriteText.Text = value;
get => text.Text;
set => text.Text = value;
}
public FontUsage Font
{
get => spriteText.Font;
set => blurredText.Font = spriteText.Font = value.With(fixedWidth: true);
get => text.Font;
set => text.Font = value.With(fixedWidth: true);
}
public Vector2 TextSize
{
get => spriteText.Size;
set => blurredText.Size = spriteText.Size = value;
get => text.Size;
set => text.Size = value;
}
public ColourInfo TextColour
{
get => spriteText.Colour;
set => spriteText.Colour = value;
get => text.Colour;
set => text.Colour = value;
}
public ColourInfo GlowColour
{
get => blurredText.Colour;
set => blurredText.Colour = value;
get => EffectColour;
set
{
EffectColour = value;
BackgroundColour = value.MultiplyAlpha(0f);
}
}
public Vector2 Spacing
{
get => spriteText.Spacing;
set => spriteText.Spacing = blurredText.Spacing = value;
get => text.Spacing;
set => text.Spacing = value;
}
public bool UseFullGlyphHeight
{
get => spriteText.UseFullGlyphHeight;
set => spriteText.UseFullGlyphHeight = blurredText.UseFullGlyphHeight = value;
get => text.UseFullGlyphHeight;
set => text.UseFullGlyphHeight = value;
}
public Bindable<string> Current
{
get => spriteText.Current;
set => spriteText.Current = value;
get => text.Current;
set => text.Current = value;
}
public GlowingSpriteText()
: base(cachedFrameBuffer: true)
{
AutoSizeAxes = Axes.Both;
Children = new Drawable[]
BlurSigma = new Vector2(blur_sigma);
RedrawOnScale = false;
DrawOriginal = true;
EffectBlending = BlendingParameters.Additive;
EffectPlacement = EffectPlacement.InFront;
Child = text = new OsuSpriteText
{
new BufferedContainer(cachedFrameBuffer: true)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
BlurSigma = new Vector2(4),
RedrawOnScale = false,
RelativeSizeAxes = Axes.Both,
Blending = BlendingParameters.Additive,
Size = new Vector2(3f),
Children = new[]
{
blurredText = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Shadow = false,
},
},
},
spriteText = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Shadow = false,
},
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Shadow = false,
};
}
}

View File

@ -164,7 +164,8 @@ namespace osu.Game.Online.Leaderboards
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
AutoSizeAxes = Axes.Both,
AutoSizeAxes = Axes.X,
Height = 28,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(10f, 0f),
Children = new Drawable[]
@ -357,14 +358,12 @@ namespace osu.Game.Online.Leaderboards
},
},
},
new GlowingSpriteText
new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
TextColour = Color4.White,
GlowColour = Color4Extensions.FromHex(@"83ccfa"),
Text = statistic.Value,
Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold),
Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold, fixedWidth: true)
},
},
};

View File

@ -47,7 +47,7 @@ namespace osu.Game.Overlays.SkinEditor
protected override bool StartHidden => true;
private Drawable targetScreen = null!;
private Drawable? targetScreen;
private OsuTextFlowContainer headerText = null!;
@ -541,8 +541,14 @@ namespace osu.Game.Overlays.SkinEditor
if (!hasBegunMutating)
return;
if (targetScreen?.IsLoaded != true)
return;
SkinComponentsContainer[] targetContainers = availableTargets.ToArray();
if (!targetContainers.All(c => c.ComponentsLoaded))
return;
foreach (var t in targetContainers)
currentSkin.Value.UpdateDrawableTarget(t);

View File

@ -136,10 +136,15 @@ namespace osu.Game.Overlays.SkinEditor
globallyReenableBeatmapSkinSetting();
}
public void PresentGameplay()
public void PresentGameplay() => presentGameplay(false);
private void presentGameplay(bool attemptedBeatmapSwitch)
{
performer?.PerformFromScreen(screen =>
{
if (State.Value != Visibility.Visible)
return;
if (beatmap.Value is DummyWorkingBeatmap)
{
// presume we don't have anything good to play and just bail.
@ -149,8 +154,12 @@ namespace osu.Game.Overlays.SkinEditor
// If we're playing the intro, switch away to another beatmap.
if (beatmap.Value.BeatmapSetInfo.Protected)
{
music.NextTrack();
Schedule(PresentGameplay);
if (!attemptedBeatmapSwitch)
{
music.NextTrack();
Schedule(() => presentGameplay(true));
}
return;
}

View File

@ -94,6 +94,11 @@ namespace osu.Game.Rulesets.Judgements
/// </summary>
public bool IsHit => Type.IsHit();
/// <summary>
/// The increase in health resulting from this judgement result.
/// </summary>
public double HealthIncrease => Judgement.HealthIncreaseFor(this);
/// <summary>
/// Creates a new <see cref="JudgementResult"/>.
/// </summary>

View File

@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Scoring
/// </summary>
/// <param name="result">The <see cref="JudgementResult"/>.</param>
/// <returns>The health increase.</returns>
protected virtual double GetHealthIncreaseFor(JudgementResult result) => result.Judgement.HealthIncreaseFor(result);
protected virtual double GetHealthIncreaseFor(JudgementResult result) => result.HealthIncrease;
/// <summary>
/// The default conditions for failing.

View File

@ -186,16 +186,7 @@ namespace osu.Game.Rulesets.Scoring
Ruleset = ruleset;
Combo.ValueChanged += combo => HighestCombo.Value = Math.Max(HighestCombo.Value, combo.NewValue);
Accuracy.ValueChanged += accuracy =>
{
// Once failed, we shouldn't update the rank anymore.
if (rank.Value == ScoreRank.F)
return;
rank.Value = RankFromAccuracy(accuracy.NewValue);
foreach (var mod in Mods.Value.OfType<IApplicableToScoreProcessor>())
rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue);
};
Accuracy.ValueChanged += _ => updateRank();
Mods.ValueChanged += mods =>
{
@ -205,6 +196,7 @@ namespace osu.Game.Rulesets.Scoring
scoreMultiplier *= m.ScoreMultiplier;
updateScore();
updateRank();
};
}
@ -372,6 +364,17 @@ namespace osu.Game.Rulesets.Scoring
TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboProgress, accuracyProcess, currentBonusPortion) * scoreMultiplier);
}
private void updateRank()
{
// Once failed, we shouldn't update the rank anymore.
if (rank.Value == ScoreRank.F)
return;
rank.Value = RankFromAccuracy(Accuracy.Value);
foreach (var mod in Mods.Value.OfType<IApplicableToScoreProcessor>())
rank.Value = mod.AdjustRank(Rank.Value, Accuracy.Value);
}
protected virtual double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion)
{
return 500000 * Accuracy.Value * comboProgress +
@ -417,8 +420,8 @@ namespace osu.Game.Rulesets.Scoring
TotalScore.Value = 0;
Accuracy.Value = 1;
Combo.Value = 0;
rank.Value = ScoreRank.X;
HighestCombo.Value = 0;
updateRank();
}
/// <summary>

View File

@ -136,7 +136,12 @@ namespace osu.Game.Screens.Play.HUD
BarHeight.BindValueChanged(_ => updateContentSize(), true);
}
private void onNewJudgement(JudgementResult result) => pendingMissAnimation |= !result.IsHit;
private void onNewJudgement(JudgementResult result)
{
// Check the health increase because cases like osu!catch bananas fire `IgnoreMiss`,
// which counts as a miss but doesn't actually subtract any health.
pendingMissAnimation |= !result.IsHit && result.HealthIncrease < 0;
}
protected override void Update()
{

View File

@ -20,12 +20,16 @@ namespace osu.Game.Screens.Play
private GameplayState gameplayState { get; set; } = null!;
private IBindable<bool> touchActive = new BindableBool();
private IBindable<bool> isBreakTime = null!;
[BackgroundDependencyLoader]
private void load(SessionStatics statics)
{
touchActive = statics.GetBindable<bool>(Static.TouchInputActive);
touchActive.BindValueChanged(_ => updateState());
isBreakTime = player.IsBreakTime.GetBoundCopy();
isBreakTime.BindValueChanged(_ => updateState(), true);
}
private void updateState()
@ -39,7 +43,7 @@ namespace osu.Game.Screens.Play
if (gameplayState.Score.ScoreInfo.Mods.OfType<ModTouchDevice>().Any())
return;
if (player.IsBreakTime.Value)
if (isBreakTime.Value)
return;
var touchDeviceMod = gameplayState.Ruleset.GetTouchDeviceMod();