Merge pull request #9769 from frenzibyte/catch-combo-counter
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-0.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-1.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-2.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-3.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-4.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-5.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-6.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-7.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-8.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
osu.Game.Rulesets.Catch.Tests/Resources/old-skin/score-9.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 923 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.4 KiB |
@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
Schedule(() =>
|
Schedule(() =>
|
||||||
{
|
{
|
||||||
area.AttemptCatch(fruit);
|
area.AttemptCatch(fruit);
|
||||||
area.OnResult(drawable, new JudgementResult(fruit, new CatchJudgement()) { Type = miss ? HitResult.Miss : HitResult.Great });
|
area.OnNewResult(drawable, new JudgementResult(fruit, new CatchJudgement()) { Type = miss ? HitResult.Miss : HitResult.Great });
|
||||||
|
|
||||||
drawable.Expire();
|
drawable.Expire();
|
||||||
});
|
});
|
||||||
|
65
osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
|
{
|
||||||
|
public class TestSceneComboCounter : CatchSkinnableTestScene
|
||||||
|
{
|
||||||
|
private ScoreProcessor scoreProcessor;
|
||||||
|
|
||||||
|
private Color4 judgedObjectColour = Color4.White;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => Schedule(() =>
|
||||||
|
{
|
||||||
|
scoreProcessor = new ScoreProcessor();
|
||||||
|
|
||||||
|
SetContents(() => new CatchComboDisplay
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(2.5f),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCatchComboCounter()
|
||||||
|
{
|
||||||
|
AddRepeatStep("perform hit", () => performJudgement(HitResult.Perfect), 20);
|
||||||
|
AddStep("perform miss", () => performJudgement(HitResult.Miss));
|
||||||
|
|
||||||
|
AddStep("randomize judged object colour", () =>
|
||||||
|
{
|
||||||
|
judgedObjectColour = new Color4(
|
||||||
|
RNG.NextSingle(1f),
|
||||||
|
RNG.NextSingle(1f),
|
||||||
|
RNG.NextSingle(1f),
|
||||||
|
1f
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performJudgement(HitResult type, Judgement judgement = null)
|
||||||
|
{
|
||||||
|
var judgedObject = new DrawableFruit(new Fruit()) { AccentColour = { Value = judgedObjectColour } };
|
||||||
|
|
||||||
|
var result = new JudgementResult(judgedObject.HitObject, judgement ?? new Judgement()) { Type = type };
|
||||||
|
scoreProcessor.ApplyResult(result);
|
||||||
|
|
||||||
|
foreach (var counter in CreatedDrawables.Cast<CatchComboDisplay>())
|
||||||
|
counter.OnNewResult(judgedObject, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
Droplet,
|
Droplet,
|
||||||
CatcherIdle,
|
CatcherIdle,
|
||||||
CatcherFail,
|
CatcherFail,
|
||||||
CatcherKiai
|
CatcherKiai,
|
||||||
|
CatchComboCounter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
using static osu.Game.Skinning.LegacySkinConfiguration;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Skinning
|
namespace osu.Game.Rulesets.Catch.Skinning
|
||||||
{
|
{
|
||||||
@ -52,6 +53,15 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
|||||||
case CatchSkinComponents.CatcherKiai:
|
case CatchSkinComponents.CatcherKiai:
|
||||||
return this.GetAnimation("fruit-catcher-kiai", true, true, true) ??
|
return this.GetAnimation("fruit-catcher-kiai", true, true, true) ??
|
||||||
this.GetAnimation("fruit-ryuuta", true, true, true);
|
this.GetAnimation("fruit-ryuuta", true, true, true);
|
||||||
|
|
||||||
|
case CatchSkinComponents.CatchComboCounter:
|
||||||
|
var comboFont = GetConfig<LegacySetting, string>(LegacySetting.ComboPrefix)?.Value ?? "score";
|
||||||
|
|
||||||
|
// For simplicity, let's use legacy combo font texture existence as a way to identify legacy skins from default.
|
||||||
|
if (this.HasFont(comboFont))
|
||||||
|
return new LegacyComboCounter(Source);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
103
osu.Game.Rulesets.Catch/Skinning/LegacyComboCounter.cs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// 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.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
using static osu.Game.Skinning.LegacySkinConfiguration;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A combo counter implementation that visually behaves almost similar to stable's osu!catch combo counter.
|
||||||
|
/// </summary>
|
||||||
|
public class LegacyComboCounter : CompositeDrawable, ICatchComboCounter
|
||||||
|
{
|
||||||
|
private readonly LegacyRollingCounter counter;
|
||||||
|
|
||||||
|
private readonly LegacyRollingCounter explosion;
|
||||||
|
|
||||||
|
public LegacyComboCounter(ISkin skin)
|
||||||
|
{
|
||||||
|
var fontName = skin.GetConfig<LegacySetting, string>(LegacySetting.ComboPrefix)?.Value ?? "score";
|
||||||
|
var fontOverlap = skin.GetConfig<LegacySetting, float>(LegacySetting.ComboOverlap)?.Value ?? -2f;
|
||||||
|
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
Alpha = 0f;
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
Scale = new Vector2(0.8f);
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
explosion = new LegacyRollingCounter(skin, fontName, fontOverlap)
|
||||||
|
{
|
||||||
|
Alpha = 0.65f,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(1.5f),
|
||||||
|
},
|
||||||
|
counter = new LegacyRollingCounter(skin, fontName, fontOverlap)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private int lastDisplayedCombo;
|
||||||
|
|
||||||
|
public void UpdateCombo(int combo, Color4? hitObjectColour = null)
|
||||||
|
{
|
||||||
|
if (combo == lastDisplayedCombo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// There may still be existing transforms to the counter (including value change after 250ms),
|
||||||
|
// finish them immediately before new transforms.
|
||||||
|
counter.SetCountWithoutRolling(lastDisplayedCombo);
|
||||||
|
|
||||||
|
lastDisplayedCombo = combo;
|
||||||
|
|
||||||
|
if (Time.Elapsed < 0)
|
||||||
|
{
|
||||||
|
// needs more work to make rewind somehow look good.
|
||||||
|
// basically we want the previous increment to play... or turning off RemoveCompletedTransforms (not feasible from a performance angle).
|
||||||
|
Hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combo fell to zero, roll down and fade out the counter.
|
||||||
|
if (combo == 0)
|
||||||
|
{
|
||||||
|
counter.Current.Value = 0;
|
||||||
|
explosion.Current.Value = 0;
|
||||||
|
|
||||||
|
this.FadeOut(400, Easing.Out);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.FadeInFromZero().Then().Delay(1000).FadeOut(300);
|
||||||
|
|
||||||
|
counter.ScaleTo(1.5f)
|
||||||
|
.ScaleTo(0.8f, 250, Easing.Out)
|
||||||
|
.OnComplete(c => c.SetCountWithoutRolling(combo));
|
||||||
|
|
||||||
|
counter.Delay(250)
|
||||||
|
.ScaleTo(1f)
|
||||||
|
.ScaleTo(1.1f, 60).Then().ScaleTo(1f, 30);
|
||||||
|
|
||||||
|
explosion.Colour = hitObjectColour ?? Color4.White;
|
||||||
|
|
||||||
|
explosion.SetCountWithoutRolling(combo);
|
||||||
|
explosion.ScaleTo(1.5f)
|
||||||
|
.ScaleTo(1.9f, 400, Easing.Out)
|
||||||
|
.FadeOutFromOne(400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// 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 JetBrains.Annotations;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a component that displays a skinned <see cref="ICatchComboCounter"/> and handles combo judgement results for updating it accordingly.
|
||||||
|
/// </summary>
|
||||||
|
public class CatchComboDisplay : SkinnableDrawable
|
||||||
|
{
|
||||||
|
private int currentCombo;
|
||||||
|
|
||||||
|
[CanBeNull]
|
||||||
|
public ICatchComboCounter ComboCounter => Drawable as ICatchComboCounter;
|
||||||
|
|
||||||
|
public CatchComboDisplay()
|
||||||
|
: base(new CatchSkinComponent(CatchSkinComponents.CatchComboCounter), _ => Empty())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||||
|
{
|
||||||
|
base.SkinChanged(skin, allowFallback);
|
||||||
|
ComboCounter?.UpdateCombo(currentCombo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnNewResult(DrawableCatchHitObject judgedObject, JudgementResult result)
|
||||||
|
{
|
||||||
|
if (!result.Judgement.AffectsCombo || !result.HasResult)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result.Type == HitResult.Miss)
|
||||||
|
{
|
||||||
|
updateCombo(0, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCombo(result.ComboAtJudgement + 1, judgedObject.AccentColour.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRevertResult(DrawableCatchHitObject judgedObject, JudgementResult result)
|
||||||
|
{
|
||||||
|
if (!result.Judgement.AffectsCombo || !result.HasResult)
|
||||||
|
return;
|
||||||
|
|
||||||
|
updateCombo(result.ComboAtJudgement, judgedObject.AccentColour.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCombo(int newCombo, Color4? hitObjectColour)
|
||||||
|
{
|
||||||
|
currentCombo = newCombo;
|
||||||
|
ComboCounter?.UpdateCombo(newCombo, hitObjectColour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
explodingFruitContainer,
|
explodingFruitContainer,
|
||||||
CatcherArea.MovableCatcher.CreateProxiedContent(),
|
CatcherArea.MovableCatcher.CreateProxiedContent(),
|
||||||
HitObjectContainer,
|
HitObjectContainer,
|
||||||
CatcherArea
|
CatcherArea,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +62,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
public override void Add(DrawableHitObject h)
|
public override void Add(DrawableHitObject h)
|
||||||
{
|
{
|
||||||
h.OnNewResult += onNewResult;
|
h.OnNewResult += onNewResult;
|
||||||
|
h.OnRevertResult += onRevertResult;
|
||||||
|
|
||||||
base.Add(h);
|
base.Add(h);
|
||||||
|
|
||||||
@ -70,6 +71,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onNewResult(DrawableHitObject judgedObject, JudgementResult result)
|
private void onNewResult(DrawableHitObject judgedObject, JudgementResult result)
|
||||||
=> CatcherArea.OnResult((DrawableCatchHitObject)judgedObject, result);
|
=> CatcherArea.OnNewResult((DrawableCatchHitObject)judgedObject, result);
|
||||||
|
|
||||||
|
private void onRevertResult(DrawableHitObject judgedObject, JudgementResult result)
|
||||||
|
=> CatcherArea.OnRevertResult((DrawableCatchHitObject)judgedObject, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
public Func<CatchHitObject, DrawableHitObject<CatchHitObject>> CreateDrawableRepresentation;
|
public Func<CatchHitObject, DrawableHitObject<CatchHitObject>> CreateDrawableRepresentation;
|
||||||
|
|
||||||
public readonly Catcher MovableCatcher;
|
public readonly Catcher MovableCatcher;
|
||||||
|
private readonly CatchComboDisplay comboDisplay;
|
||||||
|
|
||||||
public Container ExplodingFruitTarget
|
public Container ExplodingFruitTarget
|
||||||
{
|
{
|
||||||
@ -34,10 +35,22 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
public CatcherArea(BeatmapDifficulty difficulty = null)
|
public CatcherArea(BeatmapDifficulty difficulty = null)
|
||||||
{
|
{
|
||||||
Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE);
|
Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE);
|
||||||
Child = MovableCatcher = new Catcher(this, difficulty) { X = CatchPlayfield.CENTER_X };
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
comboDisplay = new CatchComboDisplay
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.None,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Margin = new MarginPadding { Bottom = 350f },
|
||||||
|
X = CatchPlayfield.CENTER_X
|
||||||
|
},
|
||||||
|
MovableCatcher = new Catcher(this, difficulty) { X = CatchPlayfield.CENTER_X },
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnResult(DrawableCatchHitObject fruit, JudgementResult result)
|
public void OnNewResult(DrawableCatchHitObject fruit, JudgementResult result)
|
||||||
{
|
{
|
||||||
if (result.Judgement is IgnoreJudgement)
|
if (result.Judgement is IgnoreJudgement)
|
||||||
return;
|
return;
|
||||||
@ -86,8 +99,13 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
else
|
else
|
||||||
MovableCatcher.Drop();
|
MovableCatcher.Drop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comboDisplay.OnNewResult(fruit, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnRevertResult(DrawableCatchHitObject fruit, JudgementResult result)
|
||||||
|
=> comboDisplay.OnRevertResult(fruit, result);
|
||||||
|
|
||||||
public void OnReleased(CatchAction action)
|
public void OnReleased(CatchAction action)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -105,6 +123,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
if (state?.CatcherX != null)
|
if (state?.CatcherX != null)
|
||||||
MovableCatcher.X = state.CatcherX.Value;
|
MovableCatcher.X = state.CatcherX.Value;
|
||||||
|
|
||||||
|
comboDisplay.X = MovableCatcher.X;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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.Graphics;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface providing a set of methods to update the combo counter.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICatchComboCounter : IDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the counter to animate a transition from the old combo value it had to the current provided one.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is called regardless of whether the clock is rewinding.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="combo">The new combo value.</param>
|
||||||
|
/// <param name="hitObjectColour">The colour of the object if hit, null on miss.</param>
|
||||||
|
void UpdateCombo(int combo, Color4? hitObjectColour = null);
|
||||||
|
}
|
||||||
|
}
|
@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
var font = GetConfig<OsuSkinConfiguration, string>(OsuSkinConfiguration.HitCirclePrefix)?.Value ?? "default";
|
var font = GetConfig<OsuSkinConfiguration, string>(OsuSkinConfiguration.HitCirclePrefix)?.Value ?? "default";
|
||||||
var overlap = GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? -2;
|
var overlap = GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? -2;
|
||||||
|
|
||||||
return !hasFont(font)
|
return !this.HasFont(font)
|
||||||
? null
|
? null
|
||||||
: new LegacySpriteText(Source, font)
|
: new LegacySpriteText(Source, font)
|
||||||
{
|
{
|
||||||
@ -145,7 +145,5 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
|
|
||||||
return Source.GetConfig<TLookup, TValue>(lookup);
|
return Source.GetConfig<TLookup, TValue>(lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool hasFont(string fontName) => Source.GetTexture($"{fontName}-0") != null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
osu.Game/Skinning/LegacyRollingCounter.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An integer <see cref="RollingCounter{T}"/> that uses number sprites from a legacy skin.
|
||||||
|
/// </summary>
|
||||||
|
public class LegacyRollingCounter : RollingCounter<int>
|
||||||
|
{
|
||||||
|
private readonly ISkin skin;
|
||||||
|
|
||||||
|
private readonly string fontName;
|
||||||
|
private readonly float fontOverlap;
|
||||||
|
|
||||||
|
protected override bool IsRollingProportional => true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="LegacyRollingCounter"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="skin">The <see cref="ISkin"/> from which to get counter number sprites.</param>
|
||||||
|
/// <param name="fontName">The name of the legacy font to use.</param>
|
||||||
|
/// <param name="fontOverlap">
|
||||||
|
/// The numeric overlap of number sprites to use.
|
||||||
|
/// A positive number will bring the number sprites closer together, while a negative number
|
||||||
|
/// will split them apart more.
|
||||||
|
/// </param>
|
||||||
|
public LegacyRollingCounter(ISkin skin, string fontName, float fontOverlap)
|
||||||
|
{
|
||||||
|
this.skin = skin;
|
||||||
|
this.fontName = fontName;
|
||||||
|
this.fontOverlap = fontOverlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override double GetProportionalDuration(int currentValue, int newValue)
|
||||||
|
{
|
||||||
|
return Math.Abs(newValue - currentValue) * 75.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected sealed override OsuSpriteText CreateSpriteText() =>
|
||||||
|
new LegacySpriteText(skin, fontName)
|
||||||
|
{
|
||||||
|
Spacing = new Vector2(-fontOverlap, 0f)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,8 @@ namespace osu.Game.Skinning
|
|||||||
public enum LegacySetting
|
public enum LegacySetting
|
||||||
{
|
{
|
||||||
Version,
|
Version,
|
||||||
|
ComboPrefix,
|
||||||
|
ComboOverlap,
|
||||||
AnimationFramerate,
|
AnimationFramerate,
|
||||||
LayeredHitSounds,
|
LayeredHitSounds,
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,9 @@ namespace osu.Game.Skinning
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool HasFont(this ISkin source, string fontPrefix)
|
||||||
|
=> source.GetTexture($"{fontPrefix}-0") != null;
|
||||||
|
|
||||||
public class SkinnableTextureAnimation : TextureAnimation
|
public class SkinnableTextureAnimation : TextureAnimation
|
||||||
{
|
{
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
|
@ -160,6 +160,11 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
||||||
{
|
{
|
||||||
|
var lookup = base.GetTexture(componentName, wrapModeS, wrapModeT);
|
||||||
|
|
||||||
|
if (lookup != null)
|
||||||
|
return lookup;
|
||||||
|
|
||||||
// extrapolate frames to test longer animations
|
// extrapolate frames to test longer animations
|
||||||
if (extrapolateAnimations)
|
if (extrapolateAnimations)
|
||||||
{
|
{
|
||||||
@ -169,7 +174,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}"), wrapModeS, wrapModeT);
|
return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}"), wrapModeS, wrapModeT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.GetTexture(componentName, wrapModeS, wrapModeT);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|