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

Make SkinProvidingContainer able to perform lookup on multiple skins

Currently `protected` functionality for use in custom `SkinProvidingContainer`s, can be exposed to public constructors if it need to later on, but I'm not sure about doing that opposed to just nesting multiple `SkinProvidingContainer`.
This commit is contained in:
Salman Ahmed 2021-06-09 20:36:34 +03:00
parent cf40282f1f
commit 6538d44708
3 changed files with 64 additions and 38 deletions

View File

@ -167,7 +167,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)

View File

@ -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());
} }
} }
} }

View File

@ -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;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
@ -21,8 +22,10 @@ namespace osu.Game.Skinning
{ {
public event Action SourceChanged; public event Action SourceChanged;
[CanBeNull] /// <summary>
private readonly ISkin skin; /// The list of skins provided by this <see cref="SkinProvidingContainer"/>.
/// </summary>
protected readonly List<ISkin> SkinLayers = new List<ISkin>();
[CanBeNull] [CanBeNull]
private ISkinSource fallbackSource; private ISkinSource fallbackSource;
@ -38,13 +41,19 @@ namespace osu.Game.Skinning
protected virtual bool AllowColourLookup => true; protected virtual bool AllowColourLookup => true;
public SkinProvidingContainer(ISkin skin) public SkinProvidingContainer(ISkin skin)
: this()
{ {
this.skin = skin; SkinLayers.Add(skin);
}
protected SkinProvidingContainer()
{
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
} }
public ISkin FindProvider(Func<ISkin, bool> lookupFunction) public ISkin FindProvider(Func<ISkin, bool> lookupFunction)
{
foreach (var skin in SkinLayers)
{ {
if (skin is ISkinSource source) if (skin is ISkinSource source)
{ {
@ -56,40 +65,57 @@ namespace osu.Game.Skinning
if (lookupFunction(skin)) if (lookupFunction(skin))
return skin; return skin;
} }
}
return fallbackSource?.FindProvider(lookupFunction); return fallbackSource?.FindProvider(lookupFunction);
} }
public Drawable GetDrawableComponent(ISkinComponent component) public Drawable GetDrawableComponent(ISkinComponent component)
{
if (AllowDrawableLookup(component))
{
foreach (var skin in SkinLayers)
{ {
Drawable sourceDrawable; Drawable sourceDrawable;
if (AllowDrawableLookup(component) && (sourceDrawable = skin?.GetDrawableComponent(component)) != null) if ((sourceDrawable = skin?.GetDrawableComponent(component)) != null)
return sourceDrawable; 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)
{
if (AllowTextureLookup(componentName))
{
foreach (var skin in SkinLayers)
{ {
Texture sourceTexture; Texture sourceTexture;
if (AllowTextureLookup(componentName) && (sourceTexture = skin?.GetTexture(componentName, wrapModeS, wrapModeT)) != null) if ((sourceTexture = skin?.GetTexture(componentName, wrapModeS, wrapModeT)) != null)
return sourceTexture; return sourceTexture;
}
}
return fallbackSource?.GetTexture(componentName, wrapModeS, wrapModeT); return fallbackSource?.GetTexture(componentName, wrapModeS, wrapModeT);
} }
public ISample GetSample(ISampleInfo sampleInfo) public ISample GetSample(ISampleInfo sampleInfo)
{ {
ISample sourceChannel; if (AllowSampleLookup(sampleInfo))
if (AllowSampleLookup(sampleInfo) && (sourceChannel = skin?.GetSample(sampleInfo)) != null) {
return sourceChannel; foreach (var skin in SkinLayers)
{
ISample sourceSample;
if ((sourceSample = skin?.GetSample(sampleInfo)) != null)
return sourceSample;
}
}
return fallbackSource?.GetSample(sampleInfo); return fallbackSource?.GetSample(sampleInfo);
} }
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
{
if (skin != null)
{ {
if (lookup is GlobalSkinColours || lookup is SkinCustomColourLookup) if (lookup is GlobalSkinColours || lookup is SkinCustomColourLookup)
return lookupWithFallback<TLookup, TValue>(lookup, AllowColourLookup); return lookupWithFallback<TLookup, TValue>(lookup, AllowColourLookup);
@ -97,22 +123,22 @@ namespace osu.Game.Skinning
return lookupWithFallback<TLookup, TValue>(lookup, AllowConfigurationLookup); return lookupWithFallback<TLookup, TValue>(lookup, AllowConfigurationLookup);
} }
return fallbackSource?.GetConfig<TLookup, TValue>(lookup);
}
private IBindable<TValue> lookupWithFallback<TLookup, TValue>(TLookup lookup, bool canUseSkinLookup) private IBindable<TValue> lookupWithFallback<TLookup, TValue>(TLookup lookup, bool canUseSkinLookup)
{ {
if (canUseSkinLookup) if (canUseSkinLookup)
{ {
var bindable = skin?.GetConfig<TLookup, TValue>(lookup); foreach (var skin in SkinLayers)
if (bindable != null) {
IBindable<TValue> bindable;
if ((bindable = skin?.GetConfig<TLookup, TValue>(lookup)) != null)
return bindable; return bindable;
} }
}
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)
{ {
@ -120,7 +146,7 @@ namespace osu.Game.Skinning
fallbackSource = dependencies.Get<ISkinSource>(); fallbackSource = dependencies.Get<ISkinSource>();
if (fallbackSource != null) if (fallbackSource != null)
fallbackSource.SourceChanged += TriggerSourceChanged; fallbackSource.SourceChanged += OnSourceChanged;
dependencies.CacheAs<ISkinSource>(this); dependencies.CacheAs<ISkinSource>(this);
@ -135,7 +161,7 @@ namespace osu.Game.Skinning
base.Dispose(isDisposing); base.Dispose(isDisposing);
if (fallbackSource != null) if (fallbackSource != null)
fallbackSource.SourceChanged -= TriggerSourceChanged; fallbackSource.SourceChanged -= OnSourceChanged;
} }
} }
} }