mirror of
https://github.com/osukey/osukey.git
synced 2025-07-01 16:29:58 +09:00
Add skin source fallback chain
This commit is contained in:
@ -105,6 +105,7 @@ namespace osu.Game
|
|||||||
runMigrations();
|
runMigrations();
|
||||||
|
|
||||||
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
|
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
|
||||||
|
dependencies.CacheAs<ISkinSource>(SkinManager);
|
||||||
|
|
||||||
var api = new APIAccess(LocalConfig);
|
var api = new APIAccess(LocalConfig);
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Primitives;
|
using osu.Framework.Graphics.Primitives;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
@ -19,7 +18,7 @@ using OpenTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Objects.Drawables
|
namespace osu.Game.Rulesets.Objects.Drawables
|
||||||
{
|
{
|
||||||
public abstract class DrawableHitObject : CompositeDrawable, IHasAccentColour
|
public abstract class DrawableHitObject : SkinReloadableDrawable, IHasAccentColour
|
||||||
{
|
{
|
||||||
public readonly HitObject HitObject;
|
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()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
@ -26,6 +26,7 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Storyboards.Drawables;
|
using osu.Game.Storyboards.Drawables;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play
|
namespace osu.Game.Screens.Play
|
||||||
@ -163,7 +164,11 @@ namespace osu.Game.Screens.Play
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
},
|
},
|
||||||
RulesetContainer,
|
new LocalSkinOverrideContainer(working.Skin)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Child = RulesetContainer
|
||||||
|
},
|
||||||
new SkipOverlay(firstObjectTime)
|
new SkipOverlay(firstObjectTime)
|
||||||
{
|
{
|
||||||
Clock = Clock, // skip button doesn't want to use the audio clock directly
|
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.Audio.Sample;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
@ -11,17 +12,20 @@ namespace osu.Game.Skinning
|
|||||||
public DefaultSkin()
|
public DefaultSkin()
|
||||||
: base(SkinInfo.Default)
|
: 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)
|
public override Drawable GetDrawableComponent(string componentName) => null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override SampleChannel GetSample(string sampleName)
|
public override SampleChannel GetSample(string sampleName) => null;
|
||||||
{
|
|
||||||
return 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 System;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
public abstract class Skin : IDisposable
|
public abstract class Skin : IDisposable, ISkinSource
|
||||||
{
|
{
|
||||||
public readonly SkinInfo SkinInfo;
|
public readonly SkinInfo SkinInfo;
|
||||||
|
|
||||||
public virtual SkinConfiguration Configuration { get; protected set; }
|
public virtual SkinConfiguration Configuration { get; protected set; }
|
||||||
|
|
||||||
|
public event Action SourceChanged;
|
||||||
|
|
||||||
public abstract Drawable GetDrawableComponent(string componentName);
|
public abstract Drawable GetDrawableComponent(string componentName);
|
||||||
|
|
||||||
public abstract SampleChannel GetSample(string sampleName);
|
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)
|
protected Skin(SkinInfo skin)
|
||||||
{
|
{
|
||||||
SkinInfo = skin;
|
SkinInfo = skin;
|
||||||
|
@ -7,14 +7,18 @@ using System.Linq;
|
|||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.IO.Archives;
|
using osu.Game.IO.Archives;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
public class SkinManager : ArchiveModelManager<SkinInfo, SkinFileInfo>
|
public class SkinManager : ArchiveModelManager<SkinInfo, SkinFileInfo>, ISkinSource
|
||||||
{
|
{
|
||||||
private readonly AudioManager audio;
|
private readonly AudioManager audio;
|
||||||
|
|
||||||
@ -89,6 +93,8 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
if (skin.SkinInfo != CurrentSkinInfo.Value)
|
if (skin.SkinInfo != CurrentSkinInfo.Value)
|
||||||
throw new InvalidOperationException($"Setting {nameof(CurrentSkin)}'s value directly is not supported. Use {nameof(CurrentSkinInfo)} instead.");
|
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
|
// 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>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>The first result for the provided query, or null if no results were found.</returns>
|
/// <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 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
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Configuration;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
@ -12,7 +11,7 @@ namespace osu.Game.Skinning
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class SkinReloadableDrawable : CompositeDrawable
|
public abstract class SkinReloadableDrawable : CompositeDrawable
|
||||||
{
|
{
|
||||||
private Bindable<Skin> skin;
|
private ISkinSource skin;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether fallback to default skin should be allowed if the custom skin is missing this resource.
|
/// 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]
|
[BackgroundDependencyLoader]
|
||||||
private void load(SkinManager skinManager)
|
private void load(ISkinSource source)
|
||||||
{
|
{
|
||||||
skin = skinManager.CurrentSkin.GetBoundCopy();
|
skin = source;
|
||||||
skin.ValueChanged += skin => SkinChanged(skin, allowDefaultFallback || skin.SkinInfo == SkinInfo.Default);
|
skin.SourceChanged += onChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onChange() => SkinChanged(skin, allowDefaultFallback);
|
||||||
|
|
||||||
protected override void LoadAsyncComplete()
|
protected override void LoadAsyncComplete()
|
||||||
{
|
{
|
||||||
base.LoadAsyncComplete();
|
base.LoadAsyncComplete();
|
||||||
skin.TriggerChange();
|
onChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -46,7 +47,7 @@ namespace osu.Game.Skinning
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="skin">The new skin.</param>
|
/// <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>
|
/// <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;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SkinChanged(Skin skin, bool allowFallback)
|
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||||
{
|
{
|
||||||
var drawable = skin.GetDrawableComponent(componentName);
|
var drawable = skin.GetDrawableComponent(componentName);
|
||||||
if (drawable != null)
|
if (drawable != null)
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
public void Play() => channels?.ForEach(c => c.Play());
|
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 =>
|
channels = samples.Select(s =>
|
||||||
{
|
{
|
||||||
|
@ -874,8 +874,10 @@
|
|||||||
<Compile Include="Screens\Tournament\Teams\StorageBackedTeamList.cs" />
|
<Compile Include="Screens\Tournament\Teams\StorageBackedTeamList.cs" />
|
||||||
<Compile Include="Skinning\BeatmapSkin.cs" />
|
<Compile Include="Skinning\BeatmapSkin.cs" />
|
||||||
<Compile Include="Skinning\DefaultSkin.cs" />
|
<Compile Include="Skinning\DefaultSkin.cs" />
|
||||||
|
<Compile Include="Skinning\ISkinSource.cs" />
|
||||||
<Compile Include="Skinning\LegacySkin.cs" />
|
<Compile Include="Skinning\LegacySkin.cs" />
|
||||||
<Compile Include="Skinning\LegacySkinDecoder.cs" />
|
<Compile Include="Skinning\LegacySkinDecoder.cs" />
|
||||||
|
<Compile Include="Skinning\LocalSkinOverrideContainer.cs" />
|
||||||
<Compile Include="Skinning\Skin.cs" />
|
<Compile Include="Skinning\Skin.cs" />
|
||||||
<Compile Include="Skinning\SkinConfiguration.cs" />
|
<Compile Include="Skinning\SkinConfiguration.cs" />
|
||||||
<Compile Include="Skinning\SkinFileInfo.cs" />
|
<Compile Include="Skinning\SkinFileInfo.cs" />
|
||||||
|
Reference in New Issue
Block a user