diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index d5be5d9394..f5a7788359 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -55,25 +55,15 @@ protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnl if (Ruleset.CreateResourceStore() is IResourceStore resources) rulesetResourcesSkin = new ResourceStoreBackedSkin(resources, parent.Get(), parent.Get()); - var dependencies = base.CreateChildDependencies(parent); - - // ensure sources are populated and ready for use before childrens' asynchronous load flow. - UpdateSkinSources(); - - return dependencies; + return base.CreateChildDependencies(parent); } protected override void OnSourceChanged() - { - UpdateSkinSources(); - base.OnSourceChanged(); - } - - protected virtual void UpdateSkinSources() { ResetSources(); - var skinSources = new List(); + // Populate a local list first so we can adjust the returned order as we go. + var sources = new List(); Debug.Assert(ParentSource != null); @@ -82,26 +72,26 @@ protected virtual void UpdateSkinSources() switch (skin) { case LegacySkin legacySkin: - skinSources.Add(GetLegacyRulesetTransformedSkin(legacySkin)); + sources.Add(GetLegacyRulesetTransformedSkin(legacySkin)); break; default: - skinSources.Add(skin); + sources.Add(skin); break; } } - int lastDefaultSkinIndex = skinSources.IndexOf(skinSources.OfType().LastOrDefault()); + int lastDefaultSkinIndex = sources.IndexOf(sources.OfType().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) - skinSources.Insert(lastDefaultSkinIndex, rulesetResourcesSkin); + sources.Insert(lastDefaultSkinIndex, rulesetResourcesSkin); else - skinSources.Add(rulesetResourcesSkin); + sources.Add(rulesetResourcesSkin); - foreach (var skin in skinSources) + foreach (var skin in sources) AddSource(skin); } diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index 6b6fdce480..6033776979 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -64,6 +64,10 @@ protected SkinProvidingContainer() RelativeSizeAxes = Axes.Both; } + /// + /// Add a new skin to this provider. Will be added to the end of the lookup order precedence. + /// + /// The skin to add. protected void AddSource(ISkin skin) { skinSources.Add(skin, new DisableableSkinSource(skin, this)); @@ -72,14 +76,22 @@ protected void AddSource(ISkin skin) source.SourceChanged += anySourceChanged; } + /// + /// Remove a skin from this provider. + /// + /// The skin to remove. protected void RemoveSource(ISkin skin) { - skinSources.Remove(skin); + if (!skinSources.Remove(skin)) + return; if (skin is ISkinSource source) - source.SourceChanged += anySourceChanged; + source.SourceChanged -= anySourceChanged; } + /// + /// Clears all skin sources. + /// protected void ResetSources() { foreach (var skin in AllSources.ToArray()) @@ -176,7 +188,8 @@ public IBindable GetConfig(TLookup lookup) } /// - /// Invoked when any source has changed (either or + /// Invoked when any source has changed (either or a source registered via ). + /// This is also invoked once initially during to ensure sources are ready for children consumption. /// protected virtual void OnSourceChanged() { } @@ -190,6 +203,8 @@ protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnl dependencies.CacheAs(this); + anySourceChanged(); + return dependencies; }