mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 03:13:21 +08:00
Add skin source fallback chain
This commit is contained in:
parent
fd0391daf7
commit
9ad4e9284a
@ -105,6 +105,7 @@ namespace osu.Game
|
||||
runMigrations();
|
||||
|
||||
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
|
||||
dependencies.CacheAs<ISkinSource>(SkinManager);
|
||||
|
||||
var api = new APIAccess(LocalConfig);
|
||||
|
||||
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Graphics;
|
||||
@ -19,7 +18,7 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableHitObject : CompositeDrawable, IHasAccentColour
|
||||
public abstract class DrawableHitObject : SkinReloadableDrawable, IHasAccentColour
|
||||
{
|
||||
public readonly HitObject HitObject;
|
||||
|
||||
@ -103,6 +102,14 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
|
||||
if (HitObject is IHasComboIndex combo)
|
||||
AccentColour = skin.GetComboColour(combo) ?? Color4.White;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
@ -26,6 +26,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Storyboards.Drawables;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
@ -163,7 +164,11 @@ namespace osu.Game.Screens.Play
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
},
|
||||
RulesetContainer,
|
||||
new LocalSkinOverrideContainer(working.Skin)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = RulesetContainer
|
||||
},
|
||||
new SkipOverlay(firstObjectTime)
|
||||
{
|
||||
Clock = Clock, // skip button doesn't want to use the audio clock directly
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
@ -11,17 +12,20 @@ namespace osu.Game.Skinning
|
||||
public DefaultSkin()
|
||||
: base(SkinInfo.Default)
|
||||
{
|
||||
Configuration = new SkinConfiguration();
|
||||
Configuration = new SkinConfiguration
|
||||
{
|
||||
ComboColours =
|
||||
{
|
||||
new Color4(17, 136, 170, 255),
|
||||
new Color4(102, 136, 0, 255),
|
||||
new Color4(204, 102, 0, 255),
|
||||
new Color4(121, 9, 13, 255)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override Drawable GetDrawableComponent(string componentName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public override Drawable GetDrawableComponent(string componentName) => null;
|
||||
|
||||
public override SampleChannel GetSample(string sampleName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public override SampleChannel GetSample(string sampleName) => null;
|
||||
}
|
||||
}
|
||||
|
25
osu.Game/Skinning/ISkinSource.cs
Normal file
25
osu.Game/Skinning/ISkinSource.cs
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to skinnable elements.
|
||||
/// </summary>
|
||||
public interface ISkinSource
|
||||
{
|
||||
event Action SourceChanged;
|
||||
|
||||
Drawable GetDrawableComponent(string componentName);
|
||||
|
||||
SampleChannel GetSample(string sampleName);
|
||||
|
||||
Color4? GetComboColour(IHasComboIndex comboObject);
|
||||
}
|
||||
}
|
53
osu.Game/Skinning/LocalSkinOverrideContainer.cs
Normal file
53
osu.Game/Skinning/LocalSkinOverrideContainer.cs
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class LocalSkinOverrideContainer : Container, ISkinSource
|
||||
{
|
||||
public event Action SourceChanged;
|
||||
|
||||
public Drawable GetDrawableComponent(string componentName) => source.GetDrawableComponent(componentName) ?? fallbackSource?.GetDrawableComponent(componentName);
|
||||
|
||||
public SampleChannel GetSample(string sampleName) => source.GetSample(sampleName) ?? fallbackSource?.GetSample(sampleName);
|
||||
|
||||
public Color4? GetComboColour(IHasComboIndex comboObject) => source.GetComboColour(comboObject) ?? fallbackSource?.GetComboColour(comboObject);
|
||||
|
||||
private readonly ISkinSource source;
|
||||
private ISkinSource fallbackSource;
|
||||
|
||||
public LocalSkinOverrideContainer(ISkinSource source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent));
|
||||
|
||||
fallbackSource = dependencies.Get<ISkinSource>();
|
||||
if (fallbackSource != null)
|
||||
fallbackSource.SourceChanged += () => SourceChanged?.Invoke();
|
||||
|
||||
dependencies.CacheAs<ISkinSource>(this);
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (fallbackSource != null)
|
||||
fallbackSource.SourceChanged -= SourceChanged;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,19 +4,26 @@
|
||||
using System;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public abstract class Skin : IDisposable
|
||||
public abstract class Skin : IDisposable, ISkinSource
|
||||
{
|
||||
public readonly SkinInfo SkinInfo;
|
||||
|
||||
public virtual SkinConfiguration Configuration { get; protected set; }
|
||||
|
||||
public event Action SourceChanged;
|
||||
|
||||
public abstract Drawable GetDrawableComponent(string componentName);
|
||||
|
||||
public abstract SampleChannel GetSample(string sampleName);
|
||||
|
||||
public virtual Color4? GetComboColour(IHasComboIndex comboObject) =>
|
||||
Configuration.ComboColours.Count == 0 ? (Color4?)null : Configuration.ComboColours[comboObject.ComboIndex % Configuration.ComboColours.Count];
|
||||
|
||||
protected Skin(SkinInfo skin)
|
||||
{
|
||||
SkinInfo = skin;
|
||||
|
@ -7,14 +7,18 @@ using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinManager : ArchiveModelManager<SkinInfo, SkinFileInfo>
|
||||
public class SkinManager : ArchiveModelManager<SkinInfo, SkinFileInfo>, ISkinSource
|
||||
{
|
||||
private readonly AudioManager audio;
|
||||
|
||||
@ -89,6 +93,8 @@ namespace osu.Game.Skinning
|
||||
{
|
||||
if (skin.SkinInfo != CurrentSkinInfo.Value)
|
||||
throw new InvalidOperationException($"Setting {nameof(CurrentSkin)}'s value directly is not supported. Use {nameof(CurrentSkinInfo)} instead.");
|
||||
|
||||
SourceChanged?.Invoke();
|
||||
};
|
||||
|
||||
// migrate older imports which didn't have access to skin.ini
|
||||
@ -108,5 +114,13 @@ namespace osu.Game.Skinning
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>The first result for the provided query, or null if no results were found.</returns>
|
||||
public SkinInfo Query(Expression<Func<SkinInfo, bool>> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query);
|
||||
|
||||
public event Action SourceChanged;
|
||||
|
||||
public Drawable GetDrawableComponent(string componentName) => CurrentSkin.Value.GetDrawableComponent(componentName);
|
||||
|
||||
public SampleChannel GetSample(string sampleName) => CurrentSkin.Value.GetSample(sampleName);
|
||||
|
||||
public Color4? GetComboColour(IHasComboIndex comboObject) => CurrentSkin.Value.GetComboColour(comboObject);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
@ -12,7 +11,7 @@ namespace osu.Game.Skinning
|
||||
/// </summary>
|
||||
public abstract class SkinReloadableDrawable : CompositeDrawable
|
||||
{
|
||||
private Bindable<Skin> skin;
|
||||
private ISkinSource skin;
|
||||
|
||||
/// <summary>
|
||||
/// Whether fallback to default skin should be allowed if the custom skin is missing this resource.
|
||||
@ -29,16 +28,18 @@ namespace osu.Game.Skinning
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(SkinManager skinManager)
|
||||
private void load(ISkinSource source)
|
||||
{
|
||||
skin = skinManager.CurrentSkin.GetBoundCopy();
|
||||
skin.ValueChanged += skin => SkinChanged(skin, allowDefaultFallback || skin.SkinInfo == SkinInfo.Default);
|
||||
skin = source;
|
||||
skin.SourceChanged += onChange;
|
||||
}
|
||||
|
||||
private void onChange() => SkinChanged(skin, allowDefaultFallback);
|
||||
|
||||
protected override void LoadAsyncComplete()
|
||||
{
|
||||
base.LoadAsyncComplete();
|
||||
skin.TriggerChange();
|
||||
onChange();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -46,7 +47,7 @@ namespace osu.Game.Skinning
|
||||
/// </summary>
|
||||
/// <param name="skin">The new skin.</param>
|
||||
/// <param name="allowFallback">Whether fallback to default skin should be allowed if the custom skin is missing this resource.</param>
|
||||
protected virtual void SkinChanged(Skin skin, bool allowFallback)
|
||||
protected virtual void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ namespace osu.Game.Skinning
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
protected override void SkinChanged(Skin skin, bool allowFallback)
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
var drawable = skin.GetDrawableComponent(componentName);
|
||||
if (drawable != null)
|
||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Skinning
|
||||
|
||||
public void Play() => channels?.ForEach(c => c.Play());
|
||||
|
||||
protected override void SkinChanged(Skin skin, bool allowFallback)
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
channels = samples.Select(s =>
|
||||
{
|
||||
|
@ -874,8 +874,10 @@
|
||||
<Compile Include="Screens\Tournament\Teams\StorageBackedTeamList.cs" />
|
||||
<Compile Include="Skinning\BeatmapSkin.cs" />
|
||||
<Compile Include="Skinning\DefaultSkin.cs" />
|
||||
<Compile Include="Skinning\ISkinSource.cs" />
|
||||
<Compile Include="Skinning\LegacySkin.cs" />
|
||||
<Compile Include="Skinning\LegacySkinDecoder.cs" />
|
||||
<Compile Include="Skinning\LocalSkinOverrideContainer.cs" />
|
||||
<Compile Include="Skinning\Skin.cs" />
|
||||
<Compile Include="Skinning\SkinConfiguration.cs" />
|
||||
<Compile Include="Skinning\SkinFileInfo.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user