Merge pull request #25267 from bdach/legacy-font-fixed-width

Fix legacy sprite texts not matching stable with respect to fixed width
This commit is contained in:
Salman Ahmed 2023-10-28 07:32:15 +03:00 committed by GitHub
commit c5ff708c6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 29 additions and 12 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1,3 +1,4 @@
[General] [General]
Version: latest Version: latest
HitCircleOverlayAboveNumber: 0 HitCircleOverlayAboveNumber: 0
HitCirclePrefix: display

View File

@ -34,6 +34,7 @@ namespace osu.Game.Rulesets.Osu.Tests
AddStep("Hit Big Stream", () => SetContents(_ => testStream(2, true))); AddStep("Hit Big Stream", () => SetContents(_ => testStream(2, true)));
AddStep("Hit Medium Stream", () => SetContents(_ => testStream(5, true))); AddStep("Hit Medium Stream", () => SetContents(_ => testStream(5, true)));
AddStep("Hit Small Stream", () => SetContents(_ => testStream(7, true))); AddStep("Hit Small Stream", () => SetContents(_ => testStream(7, true)));
AddStep("High combo index", () => SetContents(_ => testSingle(2, true, comboIndex: 15)));
} }
[Test] [Test]
@ -66,12 +67,12 @@ namespace osu.Game.Rulesets.Osu.Tests
AddStep("Hit Big Single", () => SetContents(_ => testSingle(2, true))); AddStep("Hit Big Single", () => SetContents(_ => testSingle(2, true)));
} }
private Drawable testSingle(float circleSize, bool auto = false, double timeOffset = 0, Vector2? positionOffset = null) private Drawable testSingle(float circleSize, bool auto = false, double timeOffset = 0, Vector2? positionOffset = null, int comboIndex = 0)
{ {
var playfield = new TestOsuPlayfield(); var playfield = new TestOsuPlayfield();
for (double t = timeOffset; t < timeOffset + 60000; t += 2000) for (double t = timeOffset; t < timeOffset + 60000; t += 2000)
playfield.Add(createSingle(circleSize, auto, t, positionOffset)); playfield.Add(createSingle(circleSize, auto, t, positionOffset, comboIndex: comboIndex));
return playfield; return playfield;
} }
@ -84,14 +85,14 @@ namespace osu.Game.Rulesets.Osu.Tests
for (int i = 0; i <= 1000; i += 100) for (int i = 0; i <= 1000; i += 100)
{ {
playfield.Add(createSingle(circleSize, auto, i, pos, hitOffset)); playfield.Add(createSingle(circleSize, auto, i, pos, hitOffset, i / 100 - 1));
pos.X += 50; pos.X += 50;
} }
return playfield; return playfield;
} }
private TestDrawableHitCircle createSingle(float circleSize, bool auto, double timeOffset, Vector2? positionOffset, double hitOffset = 0) private TestDrawableHitCircle createSingle(float circleSize, bool auto, double timeOffset, Vector2? positionOffset, double hitOffset = 0, int comboIndex = 0)
{ {
positionOffset ??= Vector2.Zero; positionOffset ??= Vector2.Zero;
@ -99,6 +100,7 @@ namespace osu.Game.Rulesets.Osu.Tests
{ {
StartTime = Time.Current + 1000 + timeOffset, StartTime = Time.Current + 1000 + timeOffset,
Position = OsuPlayfield.BASE_SIZE / 4 + positionOffset.Value, Position = OsuPlayfield.BASE_SIZE / 4 + positionOffset.Value,
IndexInCurrentCombo = comboIndex,
}; };
circle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize }); circle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });

View File

@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
Origin = Anchor.Centre, Origin = Anchor.Centre,
Scale = new Vector2(SPRITE_SCALE), Scale = new Vector2(SPRITE_SCALE),
Y = SPINNER_TOP_OFFSET + 299, Y = SPINNER_TOP_OFFSET + 299,
}.With(s => s.Font = s.Font.With(fixedWidth: false)), },
spmBackground = new Sprite spmBackground = new Sprite
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
Scale = new Vector2(SPRITE_SCALE * 0.9f), Scale = new Vector2(SPRITE_SCALE * 0.9f),
Position = new Vector2(80, 448 + spm_hide_offset), Position = new Vector2(80, 448 + spm_hide_offset),
}.With(s => s.Font = s.Font.With(fixedWidth: false)), },
} }
}); });
} }

View File

@ -145,10 +145,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
return null; return null;
const float hitcircle_text_scale = 0.8f; const float hitcircle_text_scale = 0.8f;
return new LegacySpriteText(LegacyFont.HitCircle, OsuHitObject.OBJECT_DIMENSIONS * 2 / hitcircle_text_scale) return new LegacySpriteText(LegacyFont.HitCircle)
{ {
// stable applies a blanket 0.8x scale to hitcircle fonts // stable applies a blanket 0.8x scale to hitcircle fonts
Scale = new Vector2(hitcircle_text_scale), Scale = new Vector2(hitcircle_text_scale),
MaxSizePerGlyph = OsuHitObject.OBJECT_DIMENSIONS * 2 / hitcircle_text_scale,
}; };
case OsuSkinComponents.SpinnerBody: case OsuSkinComponents.SpinnerBody:

View File

@ -25,6 +25,7 @@ namespace osu.Game.Skinning
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
FixedWidth = true,
}; };
} }
} }

View File

@ -28,6 +28,7 @@ namespace osu.Game.Skinning
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
FixedWidth = true,
}; };
} }
} }

View File

@ -1,6 +1,7 @@
// 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;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
@ -12,8 +13,10 @@ namespace osu.Game.Skinning
{ {
public sealed partial class LegacySpriteText : OsuSpriteText public sealed partial class LegacySpriteText : OsuSpriteText
{ {
public Vector2? MaxSizePerGlyph { get; init; }
public bool FixedWidth { get; init; }
private readonly LegacyFont font; private readonly LegacyFont font;
private readonly Vector2? maxSizePerGlyph;
private LegacyGlyphStore glyphStore = null!; private LegacyGlyphStore glyphStore = null!;
@ -21,10 +24,18 @@ namespace osu.Game.Skinning
protected override char[] FixedWidthExcludeCharacters => new[] { ',', '.', '%', 'x' }; protected override char[] FixedWidthExcludeCharacters => new[] { ',', '.', '%', 'x' };
public LegacySpriteText(LegacyFont font, Vector2? maxSizePerGlyph = null) // ReSharper disable once UnusedMember.Global
// being unused is the point here
public new FontUsage Font
{
get => base.Font;
set => throw new InvalidOperationException(@"Attempting to use this setter will not work correctly. "
+ $@"Use specific init-only properties exposed by {nameof(LegacySpriteText)} instead.");
}
public LegacySpriteText(LegacyFont font)
{ {
this.font = font; this.font = font;
this.maxSizePerGlyph = maxSizePerGlyph;
Shadow = false; Shadow = false;
UseFullGlyphHeight = false; UseFullGlyphHeight = false;
@ -33,10 +44,10 @@ namespace osu.Game.Skinning
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(ISkinSource skin) private void load(ISkinSource skin)
{ {
Font = new FontUsage(skin.GetFontPrefix(font), 1, fixedWidth: true); base.Font = new FontUsage(skin.GetFontPrefix(font), 1, fixedWidth: FixedWidth);
Spacing = new Vector2(-skin.GetFontOverlap(font), 0); Spacing = new Vector2(-skin.GetFontOverlap(font), 0);
glyphStore = new LegacyGlyphStore(skin, maxSizePerGlyph); glyphStore = new LegacyGlyphStore(skin, MaxSizePerGlyph);
} }
protected override TextBuilder CreateTextBuilder(ITexturedGlyphLookupStore store) => base.CreateTextBuilder(glyphStore); protected override TextBuilder CreateTextBuilder(ITexturedGlyphLookupStore store) => base.CreateTextBuilder(glyphStore);