diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs
index c06d9f520f..a73b34c9b6 100644
--- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs
+++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs
@@ -13,6 +13,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
{
public class CatchLegacySkinTransformer : LegacySkinTransformer
{
+ public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasPear;
+
+ private bool hasPear => GetTexture("fruit-pear") != null;
+
///
/// For simplicity, let's use legacy combo font texture existence as a way to identify legacy skins from default.
///
@@ -49,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
switch (catchSkinComponent.Component)
{
case CatchSkinComponents.Fruit:
- if (GetTexture("fruit-pear") != null)
+ if (hasPear)
return new LegacyFruitPiece();
return null;
diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs
index 1d39721a2b..a07dbea368 100644
--- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs
+++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs
@@ -19,6 +19,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
{
public class ManiaLegacySkinTransformer : LegacySkinTransformer
{
+ public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasKeyTexture.Value;
+
///
/// Mapping of to their corresponding
/// value.
diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
index b778bc21d1..856ccb5044 100644
--- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
+++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs
@@ -13,6 +13,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
{
public class OsuLegacySkinTransformer : LegacySkinTransformer
{
+ public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasHitCircle.Value;
+
private readonly Lazy hasHitCircle;
///
diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs
index 992316ca53..020cdab4dc 100644
--- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs
+++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs
@@ -14,8 +14,13 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
{
public class TaikoLegacySkinTransformer : LegacySkinTransformer
{
+ public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasHitCircle || hasBarLeft;
+
private readonly Lazy hasExplosion;
+ private bool hasHitCircle => GetTexture("taikohitcircle") != null;
+ private bool hasBarLeft => GetTexture("taiko-bar-left") != null;
+
public TaikoLegacySkinTransformer(ISkin skin)
: base(skin)
{
@@ -42,14 +47,14 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
return null;
case TaikoSkinComponents.InputDrum:
- if (GetTexture("taiko-bar-left") != null)
+ if (hasBarLeft)
return new LegacyInputDrum();
return null;
case TaikoSkinComponents.CentreHit:
case TaikoSkinComponents.RimHit:
- if (GetTexture("taikohitcircle") != null)
+ if (hasHitCircle)
return new LegacyHit(taikoComponent.Component);
return null;
diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs
index abc7b61036..f0caef9fa1 100644
--- a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs
+++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs
@@ -67,9 +67,12 @@ namespace osu.Game.Skinning
return sampleInfo is StoryboardSampleInfo || beatmapHitsounds.Value;
}
+ private readonly ISkin skin;
+
public BeatmapSkinProvidingContainer(ISkin skin)
: base(skin)
{
+ this.skin = skin;
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@@ -84,11 +87,21 @@ namespace osu.Game.Skinning
}
[BackgroundDependencyLoader]
- private void load()
+ private void load(SkinManager skins)
{
beatmapSkins.BindValueChanged(_ => TriggerSourceChanged());
beatmapColours.BindValueChanged(_ => TriggerSourceChanged());
beatmapHitsounds.BindValueChanged(_ => TriggerSourceChanged());
+
+ // If the beatmap skin looks to have skinnable resources, add the default classic skin as a fallback opportunity.
+ if (skin is LegacySkinTransformer legacySkin && legacySkin.IsProvidingLegacyResources)
+ {
+ SetSources(new[]
+ {
+ skin,
+ skins.DefaultClassicSkin
+ });
+ }
}
}
}
diff --git a/osu.Game/Skinning/LegacySkinTransformer.cs b/osu.Game/Skinning/LegacySkinTransformer.cs
index 2de1564a5c..367e5bae01 100644
--- a/osu.Game/Skinning/LegacySkinTransformer.cs
+++ b/osu.Game/Skinning/LegacySkinTransformer.cs
@@ -13,6 +13,11 @@ namespace osu.Game.Skinning
///
public abstract class LegacySkinTransformer : SkinTransformer
{
+ ///
+ /// Whether the skin being transformed is able to provide legacy resources for the ruleset.
+ ///
+ public virtual bool IsProvidingLegacyResources => this.HasFont(LegacyFont.Combo);
+
protected LegacySkinTransformer(ISkin skin)
: base(skin)
{