1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 00:02:54 +08:00

Merge pull request #10510 from peppy/skinnable-accuracy-display

Add legacy skinning support for accuracy display
This commit is contained in:
Dan Balasescu 2020-10-15 21:20:48 +09:00 committed by GitHub
commit 583fdc3a95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 233 additions and 17 deletions

View File

@ -0,0 +1,49 @@
// 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.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Play.HUD;
namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneSkinnableAccuracyCounter : SkinnableTestScene
{
private IEnumerable<SkinnableAccuracyCounter> accuracyCounters => CreatedDrawables.OfType<SkinnableAccuracyCounter>();
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
[SetUpSteps]
public void SetUpSteps()
{
AddStep("Create combo counters", () => SetContents(() =>
{
var accuracyCounter = new SkinnableAccuracyCounter();
accuracyCounter.Current.Value = 1;
return accuracyCounter;
}));
}
[Test]
public void TestChangingAccuracy()
{
AddStep(@"Reset all", delegate
{
foreach (var s in accuracyCounters)
s.Current.Value = 1;
});
AddStep(@"Hit! :D", delegate
{
foreach (var s in accuracyCounters)
s.Current.Value -= 0.023f;
});
}
}
}

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Utils;
@ -28,9 +27,6 @@ namespace osu.Game.Graphics.UserInterface
Current.Value = DisplayedCount = 1.0f;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours) => Colour = colours.BlueLighter;
protected override string FormatCount(double count) => count.FormatAccuracy();
protected override double GetProportionalDuration(double currentValue, double newValue)

View File

@ -0,0 +1,43 @@
// 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.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osuTK;
namespace osu.Game.Screens.Play.HUD
{
public class DefaultAccuracyCounter : PercentageCounter, IAccuracyCounter
{
private readonly Vector2 offset = new Vector2(-20, 5);
public DefaultAccuracyCounter()
{
Origin = Anchor.TopRight;
Anchor = Anchor.TopRight;
}
[Resolved(canBeNull: true)]
private HUDOverlay hud { get; set; }
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Colour = colours.BlueLighter;
}
protected override void Update()
{
base.Update();
if (hud?.ScoreCounter.Drawable is DefaultScoreCounter score)
{
// for now align with the score counter. eventually this will be user customisable.
Anchor = Anchor.TopLeft;
Position = Parent.ToLocalSpace(score.ScreenSpaceDrawQuad.TopLeft) + offset;
}
}
}
}

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 osu.Framework.Bindables;
using osu.Framework.Graphics;
namespace osu.Game.Screens.Play.HUD
{
/// <summary>
/// An interface providing a set of methods to update a accuracy counter.
/// </summary>
public interface IAccuracyCounter : IDrawable
{
/// <summary>
/// The current accuracy to be displayed.
/// </summary>
Bindable<double> Current { get; }
}
}

View File

@ -0,0 +1,29 @@
// 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.Bindables;
using osu.Game.Skinning;
namespace osu.Game.Screens.Play.HUD
{
public class SkinnableAccuracyCounter : SkinnableDrawable, IAccuracyCounter
{
public Bindable<double> Current { get; } = new Bindable<double>();
public SkinnableAccuracyCounter()
: base(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter), _ => new DefaultAccuracyCounter())
{
CentreComponent = false;
}
private IAccuracyCounter skinnedCounter;
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
skinnedCounter = Drawable as IAccuracyCounter;
skinnedCounter?.Current.BindTo(Current);
}
}
}

View File

@ -10,13 +10,13 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Play.HUD;
using osu.Game.Skinning;
using osuTK;
using osuTK.Input;
@ -32,7 +32,7 @@ namespace osu.Game.Screens.Play
public readonly KeyCounterDisplay KeyCounter;
public readonly SkinnableComboCounter ComboCounter;
public readonly SkinnableScoreCounter ScoreCounter;
public readonly RollingCounter<double> AccuracyCounter;
public readonly SkinnableAccuracyCounter AccuracyCounter;
public readonly HealthDisplay HealthDisplay;
public readonly SongProgress Progress;
public readonly ModDisplay ModDisplay;
@ -66,6 +66,8 @@ namespace osu.Game.Screens.Play
private readonly FillFlowContainer bottomRightElements;
private readonly FillFlowContainer topRightElements;
private readonly Container mainUIElements;
private IEnumerable<Drawable> hideTargets => new Drawable[] { visibilityContainer, KeyCounter };
public HUDOverlay(ScoreProcessor scoreProcessor, HealthProcessor healthProcessor, DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods)
@ -90,7 +92,7 @@ namespace osu.Game.Screens.Play
{
new Drawable[]
{
new Container
mainUIElements = new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
@ -206,7 +208,17 @@ namespace osu.Game.Screens.Play
{
base.Update();
topRightElements.Y = ToLocalSpace(ScoreCounter.Drawable.ScreenSpaceDrawQuad.BottomRight).Y;
float topRightOffset = 0;
// fetch the bottom-most position of any main ui element that is anchored to the top of the screen.
// consider this kind of temporary.
foreach (var d in mainUIElements)
{
if (d is SkinnableDrawable sd && (sd.Drawable.Anchor & Anchor.y0) > 0)
topRightOffset = Math.Max(sd.Drawable.ScreenSpaceDrawQuad.BottomRight.Y, topRightOffset);
}
topRightElements.Y = ToLocalSpace(new Vector2(0, topRightOffset)).Y;
bottomRightElements.Y = -Progress.Height;
}
@ -254,13 +266,7 @@ namespace osu.Game.Screens.Play
return base.OnKeyDown(e);
}
protected virtual RollingCounter<double> CreateAccuracyCounter() => new PercentageCounter
{
BypassAutoSizeAxes = Axes.X,
Anchor = Anchor.TopLeft,
Origin = Anchor.TopRight,
Margin = new MarginPadding { Top = 5, Right = 20 },
};
protected virtual SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter();
protected virtual SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter();

View File

@ -6,6 +6,7 @@ namespace osu.Game.Skinning
public enum HUDSkinComponents
{
ComboCounter,
ScoreCounter
ScoreCounter,
AccuracyCounter
}
}

View File

@ -0,0 +1,50 @@
// 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.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD;
using osuTK;
namespace osu.Game.Skinning
{
public class LegacyAccuracyCounter : PercentageCounter, IAccuracyCounter
{
private readonly ISkin skin;
public LegacyAccuracyCounter(ISkin skin)
{
Anchor = Anchor.TopRight;
Origin = Anchor.TopRight;
Scale = new Vector2(0.75f);
Margin = new MarginPadding(10);
this.skin = skin;
}
[Resolved(canBeNull: true)]
private HUDOverlay hud { get; set; }
protected sealed override OsuSpriteText CreateSpriteText() =>
new LegacySpriteText(skin, "score" /*, true*/)
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
};
protected override void Update()
{
base.Update();
if (hud?.ScoreCounter.Drawable is LegacyScoreCounter score)
{
// for now align with the score counter. eventually this will be user customisable.
Y = Parent.ToLocalSpace(score.ScreenSpaceDrawQuad.BottomRight).Y;
}
}
}
}

View File

@ -344,6 +344,9 @@ namespace osu.Game.Skinning
case HUDSkinComponents.ScoreCounter:
return new LegacyScoreCounter(this);
case HUDSkinComponents.AccuracyCounter:
return new LegacyAccuracyCounter(this);
}
return null;

View File

@ -34,7 +34,9 @@ namespace osu.Game.Skinning
public ITexturedCharacterGlyph Get(string fontName, char character)
{
var texture = skin.GetTexture($"{fontName}-{character}");
var lookup = getLookupName(character);
var texture = skin.GetTexture($"{fontName}-{lookup}");
if (texture == null)
return null;
@ -42,6 +44,24 @@ namespace osu.Game.Skinning
return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture.Width, null), texture, 1f / texture.ScaleAdjust);
}
private static string getLookupName(char character)
{
switch (character)
{
case ',':
return "comma";
case '.':
return "dot";
case '%':
return "percent";
default:
return character.ToString();
}
}
public Task<ITexturedCharacterGlyph> GetAsync(string fontName, char character) => Task.Run(() => Get(fontName, character));
}
}