osu/osu.Game/Skinning/RulesetSkinProvidingContain...

126 lines
4.3 KiB
C#

// 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.
#nullable disable
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.IO.Stores;
using osu.Framework.Platform;
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 partial class RulesetSkinProvidingContainer : SkinProvidingContainer
{
protected readonly Ruleset Ruleset;
protected readonly IBeatmap Beatmap;
[CanBeNull]
private readonly ISkin beatmapSkin;
/// <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; } = new Container
{
RelativeSizeAxes = Axes.Both,
};
public RulesetSkinProvidingContainer(Ruleset ruleset, IBeatmap beatmap, [CanBeNull] ISkin beatmapSkin)
{
Ruleset = ruleset;
Beatmap = beatmap;
this.beatmapSkin = beatmapSkin;
}
[BackgroundDependencyLoader]
private void load(SkinManager skinManager)
{
InternalChild = new BeatmapSkinProvidingContainer(GetRulesetTransformedSkin(beatmapSkin), GetRulesetTransformedSkin(skinManager.DefaultClassicSkin))
{
Child = Content,
};
}
private ResourceStoreBackedSkin rulesetResourcesSkin;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
if (Ruleset.CreateResourceStore() is IResourceStore<byte[]> resources)
rulesetResourcesSkin = new ResourceStoreBackedSkin(resources, parent.Get<GameHost>(), parent.Get<AudioManager>());
return base.CreateChildDependencies(parent);
}
protected override void RefreshSources()
{
// Populate a local list first so we can adjust the returned order as we go.
var sources = new List<ISkin>();
Debug.Assert(ParentSource != null);
foreach (var source in ParentSource.AllSources)
{
switch (source)
{
case Skin skin:
sources.Add(GetRulesetTransformedSkin(skin));
break;
default:
sources.Add(source);
break;
}
}
// TODO: check
int lastDefaultSkinIndex = sources.IndexOf(sources.OfType<TrianglesSkin>().LastOrDefault());
// Ruleset resources should be given the ability to override game-wide defaults
// This is achieved by placing them before the last instance of DefaultSkin.
// Note that DefaultSkin may not be present in some test scenes.
if (lastDefaultSkinIndex >= 0)
sources.Insert(lastDefaultSkinIndex, rulesetResourcesSkin);
else
sources.Add(rulesetResourcesSkin);
SetSources(sources);
}
protected ISkin GetRulesetTransformedSkin(ISkin skin)
{
if (skin == null)
return null;
var rulesetTransformed = Ruleset.CreateSkinTransformer(skin, Beatmap);
if (rulesetTransformed != null)
return rulesetTransformed;
return skin;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
rulesetResourcesSkin?.Dispose();
}
}
}