mirror of
https://github.com/ppy/osu.git
synced 2025-02-13 15:03:13 +08:00
Merge pull request #13423 from frenzibyte/transformers-per-skin
Refactor ruleset skin transforming logic to be per-`ISkin` rather than one `ISkinSource`
This commit is contained in:
commit
4cb9c6a842
@ -175,7 +175,7 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
||||||
|
|
||||||
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new CatchLegacySkinTransformer(source);
|
public override ISkin CreateLegacySkinProvider(ISkin skin, IBeatmap beatmap) => new CatchLegacySkinTransformer(skin);
|
||||||
|
|
||||||
public override PerformanceCalculator CreatePerformanceCalculator(DifficultyAttributes attributes, ScoreInfo score) => new CatchPerformanceCalculator(this, attributes, score);
|
public override PerformanceCalculator CreatePerformanceCalculator(DifficultyAttributes attributes, ScoreInfo score) => new CatchPerformanceCalculator(this, attributes, score);
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool providesComboCounter => this.HasFont(LegacyFont.Combo);
|
private bool providesComboCounter => this.HasFont(LegacyFont.Combo);
|
||||||
|
|
||||||
public CatchLegacySkinTransformer(ISkinSource source)
|
public CatchLegacySkinTransformer(ISkin skin)
|
||||||
: base(source)
|
: base(skin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
switch (targetComponent.Target)
|
switch (targetComponent.Target)
|
||||||
{
|
{
|
||||||
case SkinnableTarget.MainHUDComponents:
|
case SkinnableTarget.MainHUDComponents:
|
||||||
var components = Source.GetDrawableComponent(component) as SkinnableTargetComponentsContainer;
|
var components = base.GetDrawableComponent(component) as SkinnableTargetComponentsContainer;
|
||||||
|
|
||||||
if (providesComboCounter && components != null)
|
if (providesComboCounter && components != null)
|
||||||
{
|
{
|
||||||
@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
case CatchSkinComponents.Catcher:
|
case CatchSkinComponents.Catcher:
|
||||||
var version = Source.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value ?? 1;
|
var version = GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value ?? 1;
|
||||||
|
|
||||||
if (version < 2.3m)
|
if (version < 2.3m)
|
||||||
{
|
{
|
||||||
@ -83,13 +83,13 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
|
|
||||||
case CatchSkinComponents.CatchComboCounter:
|
case CatchSkinComponents.CatchComboCounter:
|
||||||
if (providesComboCounter)
|
if (providesComboCounter)
|
||||||
return new LegacyCatchComboCounter(Source);
|
return new LegacyCatchComboCounter(Skin);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Source.GetDrawableComponent(component);
|
return base.GetDrawableComponent(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
switch (lookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
case CatchSkinColour colour:
|
case CatchSkinColour colour:
|
||||||
var result = (Bindable<Color4>)Source.GetConfig<SkinCustomColourLookup, TValue>(new SkinCustomColourLookup(colour));
|
var result = (Bindable<Color4>)base.GetConfig<SkinCustomColourLookup, TValue>(new SkinCustomColourLookup(colour));
|
||||||
if (result == null)
|
if (result == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
return (IBindable<TValue>)result;
|
return (IBindable<TValue>)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Source.GetConfig<TLookup, TValue>(lookup);
|
return base.GetConfig<TLookup, TValue>(lookup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
|
|
||||||
public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this);
|
public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this);
|
||||||
|
|
||||||
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new ManiaLegacySkinTransformer(source, beatmap);
|
public override ISkin CreateLegacySkinProvider(ISkin skin, IBeatmap beatmap) => new ManiaLegacySkinTransformer(skin, beatmap);
|
||||||
|
|
||||||
public override IEnumerable<Mod> ConvertFromLegacyMods(LegacyMods mods)
|
public override IEnumerable<Mod> ConvertFromLegacyMods(LegacyMods mods)
|
||||||
{
|
{
|
||||||
|
@ -50,29 +50,25 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
{ HitResult.Miss, "mania-hit0" }
|
{ HitResult.Miss, "mania-hit0" }
|
||||||
};
|
};
|
||||||
|
|
||||||
private Lazy<bool> isLegacySkin;
|
private readonly Lazy<bool> isLegacySkin;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether texture for the keys exists.
|
/// Whether texture for the keys exists.
|
||||||
/// Used to determine if the mania ruleset is skinned.
|
/// Used to determine if the mania ruleset is skinned.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Lazy<bool> hasKeyTexture;
|
private readonly Lazy<bool> hasKeyTexture;
|
||||||
|
|
||||||
public ManiaLegacySkinTransformer(ISkinSource source, IBeatmap beatmap)
|
public ManiaLegacySkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||||
: base(source)
|
: base(skin)
|
||||||
{
|
{
|
||||||
this.beatmap = (ManiaBeatmap)beatmap;
|
this.beatmap = (ManiaBeatmap)beatmap;
|
||||||
|
|
||||||
Source.SourceChanged += sourceChanged;
|
isLegacySkin = new Lazy<bool>(() => GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version) != null);
|
||||||
sourceChanged();
|
hasKeyTexture = new Lazy<bool>(() =>
|
||||||
}
|
{
|
||||||
|
var keyImage = this.GetManiaSkinConfig<string>(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value ?? "mania-key1";
|
||||||
private void sourceChanged()
|
return this.GetAnimation(keyImage, true, true) != null;
|
||||||
{
|
});
|
||||||
isLegacySkin = new Lazy<bool>(() => FindProvider(s => s.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version) != null) != null);
|
|
||||||
hasKeyTexture = new Lazy<bool>(() => FindProvider(s => s.GetAnimation(
|
|
||||||
s.GetManiaSkinConfig<string>(LegacyManiaSkinConfigurationLookups.KeyImage, 0)?.Value
|
|
||||||
?? "mania-key1", true, true) != null) != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Drawable GetDrawableComponent(ISkinComponent component)
|
public override Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
@ -125,7 +121,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Source.GetDrawableComponent(component);
|
return base.GetDrawableComponent(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Drawable getResult(HitResult result)
|
private Drawable getResult(HitResult result)
|
||||||
@ -146,15 +142,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered)
|
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered)
|
||||||
return new SampleVirtual();
|
return new SampleVirtual();
|
||||||
|
|
||||||
return Source.GetSample(sampleInfo);
|
return base.GetSample(sampleInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
{
|
{
|
||||||
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||||
return Source.GetConfig<LegacyManiaSkinConfigurationLookup, TValue>(new LegacyManiaSkinConfigurationLookup(beatmap.TotalColumns, maniaLookup.Lookup, maniaLookup.TargetColumn));
|
return base.GetConfig<LegacyManiaSkinConfigurationLookup, TValue>(new LegacyManiaSkinConfigurationLookup(beatmap.TotalColumns, maniaLookup.Lookup, maniaLookup.TargetColumn));
|
||||||
|
|
||||||
return Source.GetConfig<TLookup, TValue>(lookup);
|
return base.GetConfig<TLookup, TValue>(lookup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
@ -112,7 +113,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => null;
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => null;
|
||||||
|
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => null;
|
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => lookupFunction(this) ? this : null;
|
||||||
|
|
||||||
|
public IEnumerable<ISkin> AllSources => new[] { this };
|
||||||
|
|
||||||
public event Action SourceChanged
|
public event Action SourceChanged
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -164,9 +165,11 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
public ISample GetSample(ISampleInfo sampleInfo) => null;
|
public ISample GetSample(ISampleInfo sampleInfo) => null;
|
||||||
|
|
||||||
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration => default;
|
|
||||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => null;
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => null;
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => null;
|
|
||||||
|
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => lookupFunction(this) ? this : null;
|
||||||
|
|
||||||
|
public IEnumerable<ISkin> AllSources => new[] { this };
|
||||||
|
|
||||||
public event Action SourceChanged;
|
public event Action SourceChanged;
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
|
|
||||||
public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this);
|
public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this);
|
||||||
|
|
||||||
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new OsuLegacySkinTransformer(source);
|
public override ISkin CreateLegacySkinProvider(ISkin skin, IBeatmap beatmap) => new OsuLegacySkinTransformer(skin);
|
||||||
|
|
||||||
public int LegacyID => 0;
|
public int LegacyID => 0;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
{
|
{
|
||||||
public class OsuLegacySkinTransformer : LegacySkinTransformer
|
public class OsuLegacySkinTransformer : LegacySkinTransformer
|
||||||
{
|
{
|
||||||
private Lazy<bool> hasHitCircle;
|
private readonly Lazy<bool> hasHitCircle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc.
|
/// On osu-stable, hitcircles have 5 pixels of transparent padding on each side to allow for shadows etc.
|
||||||
@ -20,16 +20,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const float LEGACY_CIRCLE_RADIUS = 64 - 5;
|
public const float LEGACY_CIRCLE_RADIUS = 64 - 5;
|
||||||
|
|
||||||
public OsuLegacySkinTransformer(ISkinSource source)
|
public OsuLegacySkinTransformer(ISkin skin)
|
||||||
: base(source)
|
: base(skin)
|
||||||
{
|
{
|
||||||
Source.SourceChanged += sourceChanged;
|
hasHitCircle = new Lazy<bool>(() => GetTexture("hitcircle") != null);
|
||||||
sourceChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sourceChanged()
|
|
||||||
{
|
|
||||||
hasHitCircle = new Lazy<bool>(() => FindProvider(s => s.GetTexture("hitcircle") != null) != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Drawable GetDrawableComponent(ISkinComponent component)
|
public override Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
@ -49,16 +43,13 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
return followCircle;
|
return followCircle;
|
||||||
|
|
||||||
case OsuSkinComponents.SliderBall:
|
case OsuSkinComponents.SliderBall:
|
||||||
// specular and nd layers must come from the same source as the ball texure.
|
var sliderBallContent = this.GetAnimation("sliderb", true, true, animationSeparator: "");
|
||||||
var ballProvider = Source.FindProvider(s => s.GetTexture("sliderb") != null || s.GetTexture("sliderb0") != null);
|
|
||||||
|
|
||||||
var sliderBallContent = ballProvider.GetAnimation("sliderb", true, true, animationSeparator: "");
|
|
||||||
|
|
||||||
// todo: slider ball has a custom frame delay based on velocity
|
// todo: slider ball has a custom frame delay based on velocity
|
||||||
// Math.Max((150 / Velocity) * GameBase.SIXTY_FRAME_TIME, GameBase.SIXTY_FRAME_TIME);
|
// Math.Max((150 / Velocity) * GameBase.SIXTY_FRAME_TIME, GameBase.SIXTY_FRAME_TIME);
|
||||||
|
|
||||||
if (sliderBallContent != null)
|
if (sliderBallContent != null)
|
||||||
return new LegacySliderBall(sliderBallContent, ballProvider);
|
return new LegacySliderBall(sliderBallContent, this);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -87,18 +78,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
case OsuSkinComponents.Cursor:
|
case OsuSkinComponents.Cursor:
|
||||||
var cursorProvider = Source.FindProvider(s => s.GetTexture("cursor") != null);
|
if (GetTexture("cursor") != null)
|
||||||
|
return new LegacyCursor(this);
|
||||||
if (cursorProvider != null)
|
|
||||||
return new LegacyCursor(cursorProvider);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
case OsuSkinComponents.CursorTrail:
|
case OsuSkinComponents.CursorTrail:
|
||||||
var trailProvider = Source.FindProvider(s => s.GetTexture("cursortrail") != null);
|
if (GetTexture("cursortrail") != null)
|
||||||
|
return new LegacyCursorTrail(this);
|
||||||
if (trailProvider != null)
|
|
||||||
return new LegacyCursorTrail(trailProvider);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -113,9 +100,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
};
|
};
|
||||||
|
|
||||||
case OsuSkinComponents.SpinnerBody:
|
case OsuSkinComponents.SpinnerBody:
|
||||||
bool hasBackground = Source.GetTexture("spinner-background") != null;
|
bool hasBackground = GetTexture("spinner-background") != null;
|
||||||
|
|
||||||
if (Source.GetTexture("spinner-top") != null && !hasBackground)
|
if (GetTexture("spinner-top") != null && !hasBackground)
|
||||||
return new LegacyNewStyleSpinner();
|
return new LegacyNewStyleSpinner();
|
||||||
else if (hasBackground)
|
else if (hasBackground)
|
||||||
return new LegacyOldStyleSpinner();
|
return new LegacyOldStyleSpinner();
|
||||||
@ -124,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Source.GetDrawableComponent(component);
|
return base.GetDrawableComponent(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
@ -132,7 +119,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
switch (lookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
case OsuSkinColour colour:
|
case OsuSkinColour colour:
|
||||||
return Source.GetConfig<SkinCustomColourLookup, TValue>(new SkinCustomColourLookup(colour));
|
return base.GetConfig<SkinCustomColourLookup, TValue>(new SkinCustomColourLookup(colour));
|
||||||
|
|
||||||
case OsuSkinConfiguration osuLookup:
|
case OsuSkinConfiguration osuLookup:
|
||||||
switch (osuLookup)
|
switch (osuLookup)
|
||||||
@ -146,14 +133,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
case OsuSkinConfiguration.HitCircleOverlayAboveNumber:
|
case OsuSkinConfiguration.HitCircleOverlayAboveNumber:
|
||||||
// See https://osu.ppy.sh/help/wiki/Skinning/skin.ini#%5Bgeneral%5D
|
// See https://osu.ppy.sh/help/wiki/Skinning/skin.ini#%5Bgeneral%5D
|
||||||
// HitCircleOverlayAboveNumer (with typo) should still be supported for now.
|
// HitCircleOverlayAboveNumer (with typo) should still be supported for now.
|
||||||
return Source.GetConfig<OsuSkinConfiguration, TValue>(OsuSkinConfiguration.HitCircleOverlayAboveNumber) ??
|
return base.GetConfig<OsuSkinConfiguration, TValue>(OsuSkinConfiguration.HitCircleOverlayAboveNumber) ??
|
||||||
Source.GetConfig<OsuSkinConfiguration, TValue>(OsuSkinConfiguration.HitCircleOverlayAboveNumer);
|
base.GetConfig<OsuSkinConfiguration, TValue>(OsuSkinConfiguration.HitCircleOverlayAboveNumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Source.GetConfig<TLookup, TValue>(lookup);
|
return base.GetConfig<TLookup, TValue>(lookup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -15,18 +14,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
|||||||
{
|
{
|
||||||
public class TaikoLegacySkinTransformer : LegacySkinTransformer
|
public class TaikoLegacySkinTransformer : LegacySkinTransformer
|
||||||
{
|
{
|
||||||
private Lazy<bool> hasExplosion;
|
private readonly Lazy<bool> hasExplosion;
|
||||||
|
|
||||||
public TaikoLegacySkinTransformer(ISkinSource source)
|
public TaikoLegacySkinTransformer(ISkin skin)
|
||||||
: base(source)
|
: base(skin)
|
||||||
{
|
{
|
||||||
Source.SourceChanged += sourceChanged;
|
hasExplosion = new Lazy<bool>(() => GetTexture(getHitName(TaikoSkinComponents.TaikoExplosionGreat)) != null);
|
||||||
sourceChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sourceChanged()
|
|
||||||
{
|
|
||||||
hasExplosion = new Lazy<bool>(() => Source.GetTexture(getHitName(TaikoSkinComponents.TaikoExplosionGreat)) != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Drawable GetDrawableComponent(ISkinComponent component)
|
public override Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
@ -56,7 +49,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
|||||||
|
|
||||||
case TaikoSkinComponents.CentreHit:
|
case TaikoSkinComponents.CentreHit:
|
||||||
case TaikoSkinComponents.RimHit:
|
case TaikoSkinComponents.RimHit:
|
||||||
|
|
||||||
if (GetTexture("taikohitcircle") != null)
|
if (GetTexture("taikohitcircle") != null)
|
||||||
return new LegacyHit(taikoComponent.Component);
|
return new LegacyHit(taikoComponent.Component);
|
||||||
|
|
||||||
@ -91,7 +83,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
case TaikoSkinComponents.TaikoExplosionMiss:
|
case TaikoSkinComponents.TaikoExplosionMiss:
|
||||||
|
|
||||||
var missSprite = this.GetAnimation(getHitName(taikoComponent.Component), true, false);
|
var missSprite = this.GetAnimation(getHitName(taikoComponent.Component), true, false);
|
||||||
if (missSprite != null)
|
if (missSprite != null)
|
||||||
return new LegacyHitExplosion(missSprite);
|
return new LegacyHitExplosion(missSprite);
|
||||||
@ -100,7 +91,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
|||||||
|
|
||||||
case TaikoSkinComponents.TaikoExplosionOk:
|
case TaikoSkinComponents.TaikoExplosionOk:
|
||||||
case TaikoSkinComponents.TaikoExplosionGreat:
|
case TaikoSkinComponents.TaikoExplosionGreat:
|
||||||
|
|
||||||
var hitName = getHitName(taikoComponent.Component);
|
var hitName = getHitName(taikoComponent.Component);
|
||||||
var hitSprite = this.GetAnimation(hitName, true, false);
|
var hitSprite = this.GetAnimation(hitName, true, false);
|
||||||
|
|
||||||
@ -132,7 +122,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Source.GetDrawableComponent(component);
|
return base.GetDrawableComponent(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getHitName(TaikoSkinComponents component)
|
private string getHitName(TaikoSkinComponents component)
|
||||||
@ -155,13 +145,11 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
|||||||
public override ISample GetSample(ISampleInfo sampleInfo)
|
public override ISample GetSample(ISampleInfo sampleInfo)
|
||||||
{
|
{
|
||||||
if (sampleInfo is HitSampleInfo hitSampleInfo)
|
if (sampleInfo is HitSampleInfo hitSampleInfo)
|
||||||
return Source.GetSample(new LegacyTaikoSampleInfo(hitSampleInfo));
|
return base.GetSample(new LegacyTaikoSampleInfo(hitSampleInfo));
|
||||||
|
|
||||||
return base.GetSample(sampleInfo);
|
return base.GetSample(sampleInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => Source.GetConfig<TLookup, TValue>(lookup);
|
|
||||||
|
|
||||||
private class LegacyTaikoSampleInfo : HitSampleInfo
|
private class LegacyTaikoSampleInfo : HitSampleInfo
|
||||||
{
|
{
|
||||||
public LegacyTaikoSampleInfo(HitSampleInfo sampleInfo)
|
public LegacyTaikoSampleInfo(HitSampleInfo sampleInfo)
|
||||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap, this);
|
||||||
|
|
||||||
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new TaikoLegacySkinTransformer(source);
|
public override ISkin CreateLegacySkinProvider(ISkin skin, IBeatmap beatmap) => new TaikoLegacySkinTransformer(skin);
|
||||||
|
|
||||||
public const string SHORT_NAME = "taiko";
|
public const string SHORT_NAME = "taiko";
|
||||||
|
|
||||||
|
@ -116,12 +116,12 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
private class TestOsuRuleset : OsuRuleset
|
private class TestOsuRuleset : OsuRuleset
|
||||||
{
|
{
|
||||||
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new TestOsuLegacySkinTransformer(source);
|
public override ISkin CreateLegacySkinProvider(ISkin skin, IBeatmap beatmap) => new TestOsuLegacySkinTransformer(skin);
|
||||||
|
|
||||||
private class TestOsuLegacySkinTransformer : OsuLegacySkinTransformer
|
private class TestOsuLegacySkinTransformer : OsuLegacySkinTransformer
|
||||||
{
|
{
|
||||||
public TestOsuLegacySkinTransformer(ISkinSource source)
|
public TestOsuLegacySkinTransformer(ISkin skin)
|
||||||
: base(source)
|
: base(skin)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -167,7 +168,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
public void Disable()
|
public void Disable()
|
||||||
{
|
{
|
||||||
allow = false;
|
allow = false;
|
||||||
TriggerSourceChanged();
|
OnSourceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SwitchableSkinProvidingContainer(ISkin skin)
|
public SwitchableSkinProvidingContainer(ISkin skin)
|
||||||
@ -330,6 +331,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => throw new NotImplementedException();
|
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public IEnumerable<ISkin> AllSources => throw new NotImplementedException();
|
||||||
|
|
||||||
public event Action SourceChanged
|
public event Action SourceChanged
|
||||||
{
|
{
|
||||||
add { }
|
add { }
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -146,7 +147,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => source?.GetTexture(componentName, wrapModeS, wrapModeT);
|
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => source?.GetTexture(componentName, wrapModeS, wrapModeT);
|
||||||
public ISample GetSample(ISampleInfo sampleInfo) => source?.GetSample(sampleInfo);
|
public ISample GetSample(ISampleInfo sampleInfo) => source?.GetSample(sampleInfo);
|
||||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => source?.GetConfig<TLookup, TValue>(lookup);
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => source?.GetConfig<TLookup, TValue>(lookup);
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => source?.FindProvider(lookupFunction);
|
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => lookupFunction(this) ? this : source?.FindProvider(lookupFunction);
|
||||||
|
public IEnumerable<ISkin> AllSources => new[] { this }.Concat(source?.AllSources ?? Enumerable.Empty<ISkin>());
|
||||||
|
|
||||||
public void TriggerSourceChanged()
|
public void TriggerSourceChanged()
|
||||||
{
|
{
|
||||||
|
@ -127,7 +127,7 @@ namespace osu.Game.Rulesets
|
|||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
public ModAutoplay GetAutoplayMod() => GetAllMods().OfType<ModAutoplay>().FirstOrDefault();
|
public ModAutoplay GetAutoplayMod() => GetAllMods().OfType<ModAutoplay>().FirstOrDefault();
|
||||||
|
|
||||||
public virtual ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => null;
|
public virtual ISkin CreateLegacySkinProvider([NotNull] ISkin skin, IBeatmap beatmap) => null;
|
||||||
|
|
||||||
protected Ruleset()
|
protected Ruleset()
|
||||||
{
|
{
|
||||||
|
@ -73,15 +73,7 @@ namespace osu.Game.Screens.Edit.Compose
|
|||||||
{
|
{
|
||||||
Debug.Assert(ruleset != null);
|
Debug.Assert(ruleset != null);
|
||||||
|
|
||||||
var beatmapSkinProvider = new BeatmapSkinProvidingContainer(beatmap.Value.Skin);
|
return new RulesetSkinProvidingContainer(ruleset, EditorBeatmap.PlayableBeatmap, beatmap.Value.Skin).WithChild(content);
|
||||||
|
|
||||||
// the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation
|
|
||||||
// full access to all skin sources.
|
|
||||||
var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, EditorBeatmap.PlayableBeatmap));
|
|
||||||
|
|
||||||
// load the skinning hierarchy first.
|
|
||||||
// this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources.
|
|
||||||
return beatmapSkinProvider.WithChild(rulesetSkinProvider.WithChild(content));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Input Handling
|
#region Input Handling
|
||||||
|
@ -228,29 +228,23 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
dependencies.CacheAs(GameplayBeatmap);
|
dependencies.CacheAs(GameplayBeatmap);
|
||||||
|
|
||||||
var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin);
|
var rulesetSkinProvider = new RulesetSkinProvidingContainer(GameplayRuleset, playableBeatmap, Beatmap.Value.Skin);
|
||||||
|
|
||||||
// the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation
|
|
||||||
// full access to all skin sources.
|
|
||||||
var rulesetSkinProvider = new SkinProvidingContainer(GameplayRuleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap));
|
|
||||||
|
|
||||||
// load the skinning hierarchy first.
|
// load the skinning hierarchy first.
|
||||||
// this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources.
|
// this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources.
|
||||||
GameplayClockContainer.Add(beatmapSkinProvider.WithChild(rulesetSkinProvider));
|
GameplayClockContainer.Add(rulesetSkinProvider);
|
||||||
|
|
||||||
rulesetSkinProvider.AddRange(new[]
|
rulesetSkinProvider.AddRange(new[]
|
||||||
{
|
{
|
||||||
// underlay and gameplay should have access the to skinning sources.
|
// underlay and gameplay should have access to the skinning sources.
|
||||||
createUnderlayComponents(),
|
createUnderlayComponents(),
|
||||||
createGameplayComponents(Beatmap.Value, playableBeatmap)
|
createGameplayComponents(Beatmap.Value, playableBeatmap)
|
||||||
});
|
});
|
||||||
|
|
||||||
// also give the HUD a ruleset container to allow rulesets to potentially override HUD elements (used to disable combo counters etc.)
|
|
||||||
// we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there.
|
|
||||||
var hudRulesetContainer = new SkinProvidingContainer(GameplayRuleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap));
|
|
||||||
|
|
||||||
// add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components.
|
// add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components.
|
||||||
GameplayClockContainer.Add(hudRulesetContainer.WithChild(createOverlayComponents(Beatmap.Value)));
|
// also give the overlays the ruleset skin provider to allow rulesets to potentially override HUD elements (used to disable combo counters etc.)
|
||||||
|
// we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there.
|
||||||
|
rulesetSkinProvider.Add(createOverlayComponents(Beatmap.Value));
|
||||||
|
|
||||||
if (!DrawableRuleset.AllowGameplayOverlays)
|
if (!DrawableRuleset.AllowGameplayOverlays)
|
||||||
{
|
{
|
||||||
|
@ -83,9 +83,9 @@ namespace osu.Game.Skinning
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
beatmapSkins.BindValueChanged(_ => TriggerSourceChanged());
|
beatmapSkins.BindValueChanged(_ => OnSourceChanged());
|
||||||
beatmapColours.BindValueChanged(_ => TriggerSourceChanged());
|
beatmapColours.BindValueChanged(_ => OnSourceChanged());
|
||||||
beatmapHitsounds.BindValueChanged(_ => TriggerSourceChanged());
|
beatmapHitsounds.BindValueChanged(_ => OnSourceChanged());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
@ -20,5 +21,10 @@ namespace osu.Game.Skinning
|
|||||||
/// <returns>The skin to be used for subsequent lookups, or <c>null</c> if none is available.</returns>
|
/// <returns>The skin to be used for subsequent lookups, or <c>null</c> if none is available.</returns>
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
ISkin FindProvider(Func<ISkin, bool> lookupFunction);
|
ISkin FindProvider(Func<ISkin, bool> lookupFunction);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve all sources available for lookup, with highest priority source first.
|
||||||
|
/// </summary>
|
||||||
|
IEnumerable<ISkin> AllSources { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -16,45 +17,38 @@ namespace osu.Game.Skinning
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transformer used to handle support of legacy features for individual rulesets.
|
/// Transformer used to handle support of legacy features for individual rulesets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class LegacySkinTransformer : ISkinSource
|
public abstract class LegacySkinTransformer : ISkin
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Source of the <see cref="ISkin"/> which is being transformed.
|
/// The <see cref="ISkin"/> which is being transformed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ISkinSource Source { get; }
|
[NotNull]
|
||||||
|
protected ISkin Skin { get; }
|
||||||
|
|
||||||
protected LegacySkinTransformer(ISkinSource source)
|
protected LegacySkinTransformer([NotNull] ISkin skin)
|
||||||
{
|
{
|
||||||
Source = source;
|
Skin = skin ?? throw new ArgumentNullException(nameof(skin));
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Drawable GetDrawableComponent(ISkinComponent component);
|
public virtual Drawable GetDrawableComponent(ISkinComponent component) => Skin.GetDrawableComponent(component);
|
||||||
|
|
||||||
public Texture GetTexture(string componentName) => GetTexture(componentName, default, default);
|
public Texture GetTexture(string componentName) => GetTexture(componentName, default, default);
|
||||||
|
|
||||||
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
||||||
=> Source.GetTexture(componentName, wrapModeS, wrapModeT);
|
=> Skin.GetTexture(componentName, wrapModeS, wrapModeT);
|
||||||
|
|
||||||
public virtual ISample GetSample(ISampleInfo sampleInfo)
|
public virtual ISample GetSample(ISampleInfo sampleInfo)
|
||||||
{
|
{
|
||||||
if (!(sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample))
|
if (!(sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample))
|
||||||
return Source.GetSample(sampleInfo);
|
return Skin.GetSample(sampleInfo);
|
||||||
|
|
||||||
var playLayeredHitSounds = GetConfig<LegacySetting, bool>(LegacySetting.LayeredHitSounds);
|
var playLayeredHitSounds = GetConfig<LegacySetting, bool>(LegacySetting.LayeredHitSounds);
|
||||||
if (legacySample.IsLayered && playLayeredHitSounds?.Value == false)
|
if (legacySample.IsLayered && playLayeredHitSounds?.Value == false)
|
||||||
return new SampleVirtual();
|
return new SampleVirtual();
|
||||||
|
|
||||||
return Source.GetSample(sampleInfo);
|
return Skin.GetSample(sampleInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup);
|
public virtual IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => Skin.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => Source.FindProvider(lookupFunction);
|
|
||||||
|
|
||||||
public event Action SourceChanged
|
|
||||||
{
|
|
||||||
add => Source.SourceChanged += value;
|
|
||||||
remove => Source.SourceChanged -= value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
100
osu.Game/Skinning/RulesetSkinProvidingContainer.cs
Normal file
100
osu.Game/Skinning/RulesetSkinProvidingContainer.cs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// 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.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
|
||||||
|
namespace osu.Game.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A type of <see cref="SkinProvidingContainer"/> specialized for <see cref="DrawableRuleset"/> and other gameplay-related components.
|
||||||
|
/// Providing access to parent skin sources and the beatmap skin each surrounded with the ruleset legacy skin transformer.
|
||||||
|
/// </summary>
|
||||||
|
public class RulesetSkinProvidingContainer : SkinProvidingContainer
|
||||||
|
{
|
||||||
|
protected readonly Ruleset Ruleset;
|
||||||
|
protected readonly IBeatmap Beatmap;
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// This container already re-exposes all parent <see cref="ISkinSource"/> sources in a ruleset-usable form.
|
||||||
|
/// Therefore disallow falling back to any parent <see cref="ISkinSource"/> any further.
|
||||||
|
/// </remarks>
|
||||||
|
protected override bool AllowFallingBackToParent => false;
|
||||||
|
|
||||||
|
protected override Container<Drawable> Content { get; }
|
||||||
|
|
||||||
|
public RulesetSkinProvidingContainer(Ruleset ruleset, IBeatmap beatmap, [CanBeNull] ISkin beatmapSkin)
|
||||||
|
{
|
||||||
|
Ruleset = ruleset;
|
||||||
|
Beatmap = beatmap;
|
||||||
|
|
||||||
|
InternalChild = new BeatmapSkinProvidingContainer(beatmapSkin is LegacySkin ? GetLegacyRulesetTransformedSkin(beatmapSkin) : beatmapSkin)
|
||||||
|
{
|
||||||
|
Child = Content = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private ISkinSource skinSource { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
UpdateSkins();
|
||||||
|
skinSource.SourceChanged += OnSourceChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnSourceChanged()
|
||||||
|
{
|
||||||
|
UpdateSkins();
|
||||||
|
base.OnSourceChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateSkins()
|
||||||
|
{
|
||||||
|
SkinSources.Clear();
|
||||||
|
|
||||||
|
foreach (var skin in skinSource.AllSources)
|
||||||
|
{
|
||||||
|
switch (skin)
|
||||||
|
{
|
||||||
|
case LegacySkin legacySkin:
|
||||||
|
SkinSources.Add(GetLegacyRulesetTransformedSkin(legacySkin));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
SkinSources.Add(skin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ISkin GetLegacyRulesetTransformedSkin(ISkin legacySkin)
|
||||||
|
{
|
||||||
|
if (legacySkin == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var rulesetTransformed = Ruleset.CreateLegacySkinProvider(legacySkin, Beatmap);
|
||||||
|
if (rulesetTransformed != null)
|
||||||
|
return rulesetTransformed;
|
||||||
|
|
||||||
|
return legacySkin;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
|
if (skinSource != null)
|
||||||
|
skinSource.SourceChanged -= OnSourceChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,13 @@ using osu.Game.IO.Archives;
|
|||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the storage and retrieval of <see cref="Skin"/>s.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is also exposed and cached as <see cref="ISkinSource"/> to allow for any component to potentially have skinning support.
|
||||||
|
/// For gameplay components, see <see cref="RulesetSkinProvidingContainer"/> which adds extra legacy and toggle logic that may affect the lookup process.
|
||||||
|
/// </remarks>
|
||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
public class SkinManager : ArchiveModelManager<SkinInfo, SkinFileInfo>, ISkinSource, IStorageResourceProvider
|
public class SkinManager : ArchiveModelManager<SkinInfo, SkinFileInfo>, ISkinSource, IStorageResourceProvider
|
||||||
{
|
{
|
||||||
@ -48,9 +55,15 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
protected override string ImportFromStablePath => "Skins";
|
protected override string ImportFromStablePath => "Skins";
|
||||||
|
|
||||||
private readonly Skin defaultLegacySkin;
|
/// <summary>
|
||||||
|
/// The default skin.
|
||||||
|
/// </summary>
|
||||||
|
public Skin DefaultSkin { get; }
|
||||||
|
|
||||||
private readonly Skin defaultSkin;
|
/// <summary>
|
||||||
|
/// The default legacy skin.
|
||||||
|
/// </summary>
|
||||||
|
public Skin DefaultLegacySkin { get; }
|
||||||
|
|
||||||
public SkinManager(Storage storage, DatabaseContextFactory contextFactory, GameHost host, IResourceStore<byte[]> resources, AudioManager audio)
|
public SkinManager(Storage storage, DatabaseContextFactory contextFactory, GameHost host, IResourceStore<byte[]> resources, AudioManager audio)
|
||||||
: base(storage, contextFactory, new SkinStore(contextFactory, storage), host)
|
: base(storage, contextFactory, new SkinStore(contextFactory, storage), host)
|
||||||
@ -59,12 +72,12 @@ namespace osu.Game.Skinning
|
|||||||
this.host = host;
|
this.host = host;
|
||||||
this.resources = resources;
|
this.resources = resources;
|
||||||
|
|
||||||
defaultLegacySkin = new DefaultLegacySkin(this);
|
DefaultLegacySkin = new DefaultLegacySkin(this);
|
||||||
defaultSkin = new DefaultSkin(this);
|
DefaultSkin = new DefaultSkin(this);
|
||||||
|
|
||||||
CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = GetSkin(skin.NewValue);
|
CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = GetSkin(skin.NewValue);
|
||||||
|
|
||||||
CurrentSkin.Value = defaultSkin;
|
CurrentSkin.Value = DefaultSkin;
|
||||||
CurrentSkin.ValueChanged += skin =>
|
CurrentSkin.ValueChanged += skin =>
|
||||||
{
|
{
|
||||||
if (skin.NewValue.SkinInfo != CurrentSkinInfo.Value)
|
if (skin.NewValue.SkinInfo != CurrentSkinInfo.Value)
|
||||||
@ -83,8 +96,8 @@ namespace osu.Game.Skinning
|
|||||||
public List<SkinInfo> GetAllUsableSkins()
|
public List<SkinInfo> GetAllUsableSkins()
|
||||||
{
|
{
|
||||||
var userSkins = GetAllUserSkins();
|
var userSkins = GetAllUserSkins();
|
||||||
userSkins.Insert(0, SkinInfo.Default);
|
userSkins.Insert(0, DefaultSkin.SkinInfo);
|
||||||
userSkins.Insert(1, DefaultLegacySkin.Info);
|
userSkins.Insert(1, DefaultLegacySkin.SkinInfo);
|
||||||
return userSkins;
|
return userSkins;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,32 +236,39 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction)
|
public ISkin FindProvider(Func<ISkin, bool> lookupFunction)
|
||||||
{
|
{
|
||||||
if (lookupFunction(CurrentSkin.Value))
|
foreach (var source in AllSources)
|
||||||
return CurrentSkin.Value;
|
{
|
||||||
|
if (lookupFunction(source))
|
||||||
if (CurrentSkin.Value is LegacySkin && lookupFunction(defaultLegacySkin))
|
return source;
|
||||||
return defaultLegacySkin;
|
}
|
||||||
|
|
||||||
if (lookupFunction(defaultSkin))
|
|
||||||
return defaultSkin;
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ISkin> AllSources
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return CurrentSkin.Value;
|
||||||
|
|
||||||
|
if (CurrentSkin.Value is LegacySkin && CurrentSkin.Value != DefaultLegacySkin)
|
||||||
|
yield return DefaultLegacySkin;
|
||||||
|
|
||||||
|
if (CurrentSkin.Value != DefaultSkin)
|
||||||
|
yield return DefaultSkin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private T lookupWithFallback<T>(Func<ISkin, T> lookupFunction)
|
private T lookupWithFallback<T>(Func<ISkin, T> lookupFunction)
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
if (lookupFunction(CurrentSkin.Value) is T skinSourced)
|
foreach (var source in AllSources)
|
||||||
return skinSourced;
|
{
|
||||||
|
if (lookupFunction(source) is T skinSourced)
|
||||||
|
return skinSourced;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: we also want to return a DefaultLegacySkin here if the current *beatmap* is providing any skinned elements.
|
return null;
|
||||||
// When attempting to address this, we may want to move the full DefaultLegacySkin fallback logic to within Player itself (to better allow
|
|
||||||
// for beatmap skin visibility).
|
|
||||||
if (CurrentSkin.Value is LegacySkin && lookupFunction(defaultLegacySkin) is T legacySourced)
|
|
||||||
return legacySourced;
|
|
||||||
|
|
||||||
// Finally fall back to the (non-legacy) default.
|
|
||||||
return lookupFunction(defaultSkin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IResourceStorageProvider
|
#region IResourceStorageProvider
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
@ -21,13 +24,24 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
public event Action SourceChanged;
|
public event Action SourceChanged;
|
||||||
|
|
||||||
[CanBeNull]
|
/// <summary>
|
||||||
private readonly ISkin skin;
|
/// Skins which should be exposed by this container, in order of lookup precedence.
|
||||||
|
/// </summary>
|
||||||
|
protected readonly BindableList<ISkin> SkinSources = new BindableList<ISkin>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary mapping each <see cref="ISkin"/> from the <see cref="SkinSources"/>
|
||||||
|
/// to one that performs the "allow lookup" checks before proceeding with a lookup.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Dictionary<ISkin, DisableableSkinSource> disableableSkinSources = new Dictionary<ISkin, DisableableSkinSource>();
|
||||||
|
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
private ISkinSource fallbackSource;
|
private ISkinSource fallbackSource;
|
||||||
|
|
||||||
private readonly NoFallbackProxy noFallbackLookupProxy;
|
/// <summary>
|
||||||
|
/// Whether falling back to parent <see cref="ISkinSource"/>s is allowed in this container.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual bool AllowFallingBackToParent => true;
|
||||||
|
|
||||||
protected virtual bool AllowDrawableLookup(ISkinComponent component) => true;
|
protected virtual bool AllowDrawableLookup(ISkinComponent component) => true;
|
||||||
|
|
||||||
@ -39,123 +53,159 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
protected virtual bool AllowColourLookup => true;
|
protected virtual bool AllowColourLookup => true;
|
||||||
|
|
||||||
public SkinProvidingContainer(ISkin skin)
|
/// <summary>
|
||||||
|
/// Constructs a new <see cref="SkinProvidingContainer"/> initialised with a single skin source.
|
||||||
|
/// </summary>
|
||||||
|
public SkinProvidingContainer([CanBeNull] ISkin skin)
|
||||||
|
: this()
|
||||||
{
|
{
|
||||||
this.skin = skin;
|
if (skin != null)
|
||||||
|
SkinSources.Add(skin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new <see cref="SkinProvidingContainer"/> with no sources.
|
||||||
|
/// Implementations can add or change sources through the <see cref="SkinSources"/> list.
|
||||||
|
/// </summary>
|
||||||
|
protected SkinProvidingContainer()
|
||||||
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
noFallbackLookupProxy = new NoFallbackProxy(this);
|
SkinSources.BindCollectionChanged(((_, args) =>
|
||||||
|
{
|
||||||
|
switch (args.Action)
|
||||||
|
{
|
||||||
|
case NotifyCollectionChangedAction.Add:
|
||||||
|
foreach (var skin in args.NewItems.Cast<ISkin>())
|
||||||
|
{
|
||||||
|
disableableSkinSources.Add(skin, new DisableableSkinSource(skin, this));
|
||||||
|
|
||||||
if (skin is ISkinSource source)
|
if (skin is ISkinSource source)
|
||||||
source.SourceChanged += TriggerSourceChanged;
|
source.SourceChanged += OnSourceChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotifyCollectionChangedAction.Reset:
|
||||||
|
case NotifyCollectionChangedAction.Remove:
|
||||||
|
foreach (var skin in args.OldItems.Cast<ISkin>())
|
||||||
|
{
|
||||||
|
disableableSkinSources.Remove(skin);
|
||||||
|
|
||||||
|
if (skin is ISkinSource source)
|
||||||
|
source.SourceChanged -= OnSourceChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotifyCollectionChangedAction.Replace:
|
||||||
|
foreach (var skin in args.OldItems.Cast<ISkin>())
|
||||||
|
{
|
||||||
|
disableableSkinSources.Remove(skin);
|
||||||
|
|
||||||
|
if (skin is ISkinSource source)
|
||||||
|
source.SourceChanged -= OnSourceChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var skin in args.NewItems.Cast<ISkin>())
|
||||||
|
{
|
||||||
|
disableableSkinSources.Add(skin, new DisableableSkinSource(skin, this));
|
||||||
|
|
||||||
|
if (skin is ISkinSource source)
|
||||||
|
source.SourceChanged += OnSourceChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction)
|
public ISkin FindProvider(Func<ISkin, bool> lookupFunction)
|
||||||
{
|
{
|
||||||
if (skin is ISkinSource source)
|
foreach (var skin in SkinSources)
|
||||||
{
|
{
|
||||||
if (source.FindProvider(lookupFunction) is ISkin found)
|
if (lookupFunction(disableableSkinSources[skin]))
|
||||||
return found;
|
|
||||||
}
|
|
||||||
else if (skin != null)
|
|
||||||
{
|
|
||||||
// a proxy must be used here to correctly pass through the "Allow" checks without implicitly falling back to the fallbackSource.
|
|
||||||
if (lookupFunction(noFallbackLookupProxy))
|
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fallbackSource?.FindProvider(lookupFunction);
|
return fallbackSource?.FindProvider(lookupFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Drawable GetDrawableComponent(ISkinComponent component)
|
public IEnumerable<ISkin> AllSources
|
||||||
=> GetDrawableComponent(component, true);
|
|
||||||
|
|
||||||
public Drawable GetDrawableComponent(ISkinComponent component, bool fallback)
|
|
||||||
{
|
{
|
||||||
Drawable sourceDrawable;
|
get
|
||||||
if (AllowDrawableLookup(component) && (sourceDrawable = skin?.GetDrawableComponent(component)) != null)
|
{
|
||||||
return sourceDrawable;
|
foreach (var skin in SkinSources)
|
||||||
|
yield return skin;
|
||||||
|
|
||||||
if (!fallback)
|
if (fallbackSource != null)
|
||||||
return null;
|
{
|
||||||
|
foreach (var skin in fallbackSource.AllSources)
|
||||||
|
yield return skin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
|
{
|
||||||
|
foreach (var skin in SkinSources)
|
||||||
|
{
|
||||||
|
Drawable sourceDrawable;
|
||||||
|
if ((sourceDrawable = disableableSkinSources[skin]?.GetDrawableComponent(component)) != null)
|
||||||
|
return sourceDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
return fallbackSource?.GetDrawableComponent(component);
|
return fallbackSource?.GetDrawableComponent(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
||||||
=> GetTexture(componentName, wrapModeS, wrapModeT, true);
|
|
||||||
|
|
||||||
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT, bool fallback)
|
|
||||||
{
|
{
|
||||||
Texture sourceTexture;
|
foreach (var skin in SkinSources)
|
||||||
if (AllowTextureLookup(componentName) && (sourceTexture = skin?.GetTexture(componentName, wrapModeS, wrapModeT)) != null)
|
{
|
||||||
return sourceTexture;
|
Texture sourceTexture;
|
||||||
|
if ((sourceTexture = disableableSkinSources[skin]?.GetTexture(componentName, wrapModeS, wrapModeT)) != null)
|
||||||
if (!fallback)
|
return sourceTexture;
|
||||||
return null;
|
}
|
||||||
|
|
||||||
return fallbackSource?.GetTexture(componentName, wrapModeS, wrapModeT);
|
return fallbackSource?.GetTexture(componentName, wrapModeS, wrapModeT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISample GetSample(ISampleInfo sampleInfo)
|
public ISample GetSample(ISampleInfo sampleInfo)
|
||||||
=> GetSample(sampleInfo, true);
|
|
||||||
|
|
||||||
public ISample GetSample(ISampleInfo sampleInfo, bool fallback)
|
|
||||||
{
|
{
|
||||||
ISample sourceChannel;
|
foreach (var skin in SkinSources)
|
||||||
if (AllowSampleLookup(sampleInfo) && (sourceChannel = skin?.GetSample(sampleInfo)) != null)
|
{
|
||||||
return sourceChannel;
|
ISample sourceSample;
|
||||||
|
if ((sourceSample = disableableSkinSources[skin]?.GetSample(sampleInfo)) != null)
|
||||||
if (!fallback)
|
return sourceSample;
|
||||||
return null;
|
}
|
||||||
|
|
||||||
return fallbackSource?.GetSample(sampleInfo);
|
return fallbackSource?.GetSample(sampleInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
=> GetConfig<TLookup, TValue>(lookup, true);
|
|
||||||
|
|
||||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup, bool fallback)
|
|
||||||
{
|
{
|
||||||
if (skin != null)
|
foreach (var skin in SkinSources)
|
||||||
{
|
{
|
||||||
if (lookup is GlobalSkinColours || lookup is SkinCustomColourLookup)
|
IBindable<TValue> bindable;
|
||||||
return lookupWithFallback<TLookup, TValue>(lookup, AllowColourLookup, fallback);
|
if ((bindable = disableableSkinSources[skin]?.GetConfig<TLookup, TValue>(lookup)) != null)
|
||||||
|
|
||||||
return lookupWithFallback<TLookup, TValue>(lookup, AllowConfigurationLookup, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fallback)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return fallbackSource?.GetConfig<TLookup, TValue>(lookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IBindable<TValue> lookupWithFallback<TLookup, TValue>(TLookup lookup, bool canUseSkinLookup, bool canUseFallback)
|
|
||||||
{
|
|
||||||
if (canUseSkinLookup)
|
|
||||||
{
|
|
||||||
var bindable = skin?.GetConfig<TLookup, TValue>(lookup);
|
|
||||||
if (bindable != null)
|
|
||||||
return bindable;
|
return bindable;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!canUseFallback)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return fallbackSource?.GetConfig<TLookup, TValue>(lookup);
|
return fallbackSource?.GetConfig<TLookup, TValue>(lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void TriggerSourceChanged() => SourceChanged?.Invoke();
|
protected virtual void OnSourceChanged() => SourceChanged?.Invoke();
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
{
|
{
|
||||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||||
|
|
||||||
fallbackSource = dependencies.Get<ISkinSource>();
|
if (AllowFallingBackToParent)
|
||||||
if (fallbackSource != null)
|
{
|
||||||
fallbackSource.SourceChanged += TriggerSourceChanged;
|
fallbackSource = dependencies.Get<ISkinSource>();
|
||||||
|
if (fallbackSource != null)
|
||||||
|
fallbackSource.SourceChanged += OnSourceChanged;
|
||||||
|
}
|
||||||
|
|
||||||
dependencies.CacheAs<ISkinSource>(this);
|
dependencies.CacheAs<ISkinSource>(this);
|
||||||
|
|
||||||
@ -170,41 +220,67 @@ namespace osu.Game.Skinning
|
|||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
if (fallbackSource != null)
|
if (fallbackSource != null)
|
||||||
fallbackSource.SourceChanged -= TriggerSourceChanged;
|
fallbackSource.SourceChanged -= OnSourceChanged;
|
||||||
|
|
||||||
if (skin is ISkinSource source)
|
foreach (var source in SkinSources.OfType<ISkinSource>())
|
||||||
source.SourceChanged -= TriggerSourceChanged;
|
source.SourceChanged -= OnSourceChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NoFallbackProxy : ISkinSource
|
private class DisableableSkinSource : ISkin
|
||||||
{
|
{
|
||||||
|
private readonly ISkin skin;
|
||||||
private readonly SkinProvidingContainer provider;
|
private readonly SkinProvidingContainer provider;
|
||||||
|
|
||||||
public NoFallbackProxy(SkinProvidingContainer provider)
|
public DisableableSkinSource(ISkin skin, SkinProvidingContainer provider)
|
||||||
{
|
{
|
||||||
|
this.skin = skin;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Drawable GetDrawableComponent(ISkinComponent component)
|
public Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
=> provider.GetDrawableComponent(component, false);
|
|
||||||
|
|
||||||
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
|
||||||
=> provider.GetTexture(componentName, wrapModeS, wrapModeT, false);
|
|
||||||
|
|
||||||
public ISample GetSample(ISampleInfo sampleInfo)
|
|
||||||
=> provider.GetSample(sampleInfo, false);
|
|
||||||
|
|
||||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
|
||||||
=> provider.GetConfig<TLookup, TValue>(lookup, false);
|
|
||||||
|
|
||||||
public event Action SourceChanged
|
|
||||||
{
|
{
|
||||||
add => provider.SourceChanged += value;
|
if (provider.AllowDrawableLookup(component))
|
||||||
remove => provider.SourceChanged -= value;
|
return skin.GetDrawableComponent(component);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) =>
|
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
||||||
provider.FindProvider(lookupFunction);
|
{
|
||||||
|
if (provider.AllowTextureLookup(componentName))
|
||||||
|
return skin.GetTexture(componentName, wrapModeS, wrapModeT);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISample GetSample(ISampleInfo sampleInfo)
|
||||||
|
{
|
||||||
|
if (provider.AllowSampleLookup(sampleInfo))
|
||||||
|
return skin.GetSample(sampleInfo);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
|
{
|
||||||
|
switch (lookup)
|
||||||
|
{
|
||||||
|
case GlobalSkinColours _:
|
||||||
|
case SkinCustomColourLookup _:
|
||||||
|
if (provider.AllowColourLookup)
|
||||||
|
return skin.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (provider.AllowConfigurationLookup)
|
||||||
|
return skin.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,9 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
remove { }
|
remove { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => null;
|
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) => lookupFunction(this) ? this : null;
|
||||||
|
|
||||||
|
public IEnumerable<ISkin> AllSources => new[] { this };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user