mirror of
https://github.com/osukey/osukey.git
synced 2025-05-03 12:47:28 +09:00
Merge pull request #22673 from peppy/skin-per-ruleset-layouts
Add support for per-ruleset skin layouts
This commit is contained in:
commit
8818341047
@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
{
|
{
|
||||||
public partial class DrawableOsuJudgement : DrawableJudgement
|
public partial class DrawableOsuJudgement : DrawableJudgement
|
||||||
{
|
{
|
||||||
protected SkinnableLighting Lighting { get; private set; }
|
internal SkinnableLighting Lighting { get; private set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuConfigManager config { get; set; }
|
private OsuConfigManager config { get; set; }
|
||||||
|
@ -10,7 +10,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||||
{
|
{
|
||||||
public partial class SkinnableLighting : SkinnableSprite
|
internal partial class SkinnableLighting : SkinnableSprite
|
||||||
{
|
{
|
||||||
private DrawableHitObject targetObject;
|
private DrawableHitObject targetObject;
|
||||||
private JudgementResult targetResult;
|
private JudgementResult targetResult;
|
||||||
|
@ -66,9 +66,9 @@ namespace osu.Game.Tests.Skins
|
|||||||
{
|
{
|
||||||
var skin = new TestSkin(new SkinInfo(), null, storage);
|
var skin = new TestSkin(new SkinInfo(), null, storage);
|
||||||
|
|
||||||
foreach (var target in skin.DrawableComponentInfo)
|
foreach (var target in skin.LayoutInfos)
|
||||||
{
|
{
|
||||||
foreach (var info in target.Value)
|
foreach (var info in target.Value.AllDrawables)
|
||||||
instantiatedTypes.Add(info.Type);
|
instantiatedTypes.Add(info.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,8 +87,8 @@ namespace osu.Game.Tests.Skins
|
|||||||
{
|
{
|
||||||
var skin = new TestSkin(new SkinInfo(), null, storage);
|
var skin = new TestSkin(new SkinInfo(), null, storage);
|
||||||
|
|
||||||
Assert.That(skin.DrawableComponentInfo, Has.Count.EqualTo(2));
|
Assert.That(skin.LayoutInfos, Has.Count.EqualTo(2));
|
||||||
Assert.That(skin.DrawableComponentInfo[SkinComponentsContainerLookup.TargetArea.MainHUDComponents], Has.Length.EqualTo(9));
|
Assert.That(skin.LayoutInfos[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].AllDrawables.ToArray(), Has.Length.EqualTo(9));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,11 +100,11 @@ namespace osu.Game.Tests.Skins
|
|||||||
{
|
{
|
||||||
var skin = new TestSkin(new SkinInfo(), null, storage);
|
var skin = new TestSkin(new SkinInfo(), null, storage);
|
||||||
|
|
||||||
Assert.That(skin.DrawableComponentInfo, Has.Count.EqualTo(2));
|
Assert.That(skin.LayoutInfos, Has.Count.EqualTo(2));
|
||||||
Assert.That(skin.DrawableComponentInfo[SkinComponentsContainerLookup.TargetArea.MainHUDComponents], Has.Length.EqualTo(6));
|
Assert.That(skin.LayoutInfos[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].AllDrawables.ToArray(), Has.Length.EqualTo(6));
|
||||||
Assert.That(skin.DrawableComponentInfo[SkinComponentsContainerLookup.TargetArea.SongSelect], Has.Length.EqualTo(1));
|
Assert.That(skin.LayoutInfos[SkinComponentsContainerLookup.TargetArea.SongSelect].AllDrawables.ToArray(), Has.Length.EqualTo(1));
|
||||||
|
|
||||||
var skinnableInfo = skin.DrawableComponentInfo[SkinComponentsContainerLookup.TargetArea.SongSelect].First();
|
var skinnableInfo = skin.LayoutInfos[SkinComponentsContainerLookup.TargetArea.SongSelect].AllDrawables.First();
|
||||||
|
|
||||||
Assert.That(skinnableInfo.Type, Is.EqualTo(typeof(SkinnableSprite)));
|
Assert.That(skinnableInfo.Type, Is.EqualTo(typeof(SkinnableSprite)));
|
||||||
Assert.That(skinnableInfo.Settings.First().Key, Is.EqualTo("sprite_name"));
|
Assert.That(skinnableInfo.Settings.First().Key, Is.EqualTo("sprite_name"));
|
||||||
@ -115,10 +115,10 @@ namespace osu.Game.Tests.Skins
|
|||||||
using (var storage = new ZipArchiveReader(stream))
|
using (var storage = new ZipArchiveReader(stream))
|
||||||
{
|
{
|
||||||
var skin = new TestSkin(new SkinInfo(), null, storage);
|
var skin = new TestSkin(new SkinInfo(), null, storage);
|
||||||
Assert.That(skin.DrawableComponentInfo[SkinComponentsContainerLookup.TargetArea.MainHUDComponents], Has.Length.EqualTo(8));
|
Assert.That(skin.LayoutInfos[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].AllDrawables.ToArray(), Has.Length.EqualTo(8));
|
||||||
Assert.That(skin.DrawableComponentInfo[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].Select(i => i.Type), Contains.Item(typeof(UnstableRateCounter)));
|
Assert.That(skin.LayoutInfos[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].AllDrawables.Select(i => i.Type), Contains.Item(typeof(UnstableRateCounter)));
|
||||||
Assert.That(skin.DrawableComponentInfo[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].Select(i => i.Type), Contains.Item(typeof(ColourHitErrorMeter)));
|
Assert.That(skin.LayoutInfos[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].AllDrawables.Select(i => i.Type), Contains.Item(typeof(ColourHitErrorMeter)));
|
||||||
Assert.That(skin.DrawableComponentInfo[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].Select(i => i.Type), Contains.Item(typeof(LegacySongProgress)));
|
Assert.That(skin.LayoutInfos[SkinComponentsContainerLookup.TargetArea.MainHUDComponents].AllDrawables.Select(i => i.Type), Contains.Item(typeof(LegacySongProgress)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.EnumExtensions;
|
using osu.Framework.Extensions.EnumExtensions;
|
||||||
@ -26,6 +27,7 @@ using osu.Game.Screens.Play.HUD.JudgementCounter;
|
|||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play
|
namespace osu.Game.Screens.Play
|
||||||
{
|
{
|
||||||
@ -100,20 +102,22 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods, bool alwaysShowLeaderboard = true)
|
public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList<Mod> mods, bool alwaysShowLeaderboard = true)
|
||||||
{
|
{
|
||||||
|
Drawable rulesetComponents;
|
||||||
|
|
||||||
this.drawableRuleset = drawableRuleset;
|
this.drawableRuleset = drawableRuleset;
|
||||||
this.mods = mods;
|
this.mods = mods;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
CreateFailingLayer(),
|
CreateFailingLayer(),
|
||||||
//Needs to be initialized before skinnable drawables.
|
//Needs to be initialized before skinnable drawables.
|
||||||
tally = new JudgementTally(),
|
tally = new JudgementTally(),
|
||||||
mainComponents = new MainComponentsContainer
|
mainComponents = new HUDComponentsContainer { AlwaysPresent = true, },
|
||||||
{
|
rulesetComponents = drawableRuleset != null
|
||||||
AlwaysPresent = true,
|
? new HUDComponentsContainer(drawableRuleset.Ruleset.RulesetInfo) { AlwaysPresent = true, }
|
||||||
},
|
: Empty(),
|
||||||
topRightElements = new FillFlowContainer
|
topRightElements = new FillFlowContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
@ -155,7 +159,7 @@ namespace osu.Game.Screens.Play
|
|||||||
clicksPerSecondCalculator = new ClicksPerSecondCalculator(),
|
clicksPerSecondCalculator = new ClicksPerSecondCalculator(),
|
||||||
};
|
};
|
||||||
|
|
||||||
hideTargets = new List<Drawable> { mainComponents, KeyCounter, topRightElements };
|
hideTargets = new List<Drawable> { mainComponents, rulesetComponents, KeyCounter, topRightElements };
|
||||||
|
|
||||||
if (!alwaysShowLeaderboard)
|
if (!alwaysShowLeaderboard)
|
||||||
hideTargets.Add(LeaderboardFlow);
|
hideTargets.Add(LeaderboardFlow);
|
||||||
@ -390,15 +394,15 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private partial class MainComponentsContainer : SkinComponentsContainer
|
private partial class HUDComponentsContainer : SkinComponentsContainer
|
||||||
{
|
{
|
||||||
private Bindable<ScoringMode> scoringMode;
|
private Bindable<ScoringMode> scoringMode;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuConfigManager config { get; set; }
|
private OsuConfigManager config { get; set; }
|
||||||
|
|
||||||
public MainComponentsContainer()
|
public HUDComponentsContainer([CanBeNull] RulesetInfo ruleset = null)
|
||||||
: base(new SkinComponentsContainerLookup(SkinComponentsContainerLookup.TargetArea.MainHUDComponents))
|
: base(new SkinComponentsContainerLookup(SkinComponentsContainerLookup.TargetArea.MainHUDComponents, ruleset))
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,10 @@ namespace osu.Game.Skinning
|
|||||||
switch (lookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
case SkinComponentsContainerLookup containerLookup:
|
case SkinComponentsContainerLookup containerLookup:
|
||||||
|
// Only handle global level defaults for now.
|
||||||
|
if (containerLookup.Ruleset != null)
|
||||||
|
return null;
|
||||||
|
|
||||||
switch (containerLookup.Target)
|
switch (containerLookup.Target)
|
||||||
{
|
{
|
||||||
case SkinComponentsContainerLookup.TargetArea.SongSelect:
|
case SkinComponentsContainerLookup.TargetArea.SongSelect:
|
||||||
|
@ -344,10 +344,14 @@ namespace osu.Game.Skinning
|
|||||||
switch (lookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
case SkinComponentsContainerLookup containerLookup:
|
case SkinComponentsContainerLookup containerLookup:
|
||||||
|
// Only handle global level defaults for now.
|
||||||
|
if (containerLookup.Ruleset != null)
|
||||||
|
return null;
|
||||||
|
|
||||||
switch (containerLookup.Target)
|
switch (containerLookup.Target)
|
||||||
{
|
{
|
||||||
case SkinComponentsContainerLookup.TargetArea.MainHUDComponents:
|
case SkinComponentsContainerLookup.TargetArea.MainHUDComponents:
|
||||||
var skinnableTargetWrapper = new DefaultSkinComponentsContainer(container =>
|
return new DefaultSkinComponentsContainer(container =>
|
||||||
{
|
{
|
||||||
var score = container.OfType<LegacyScoreCounter>().FirstOrDefault();
|
var score = container.OfType<LegacyScoreCounter>().FirstOrDefault();
|
||||||
var accuracy = container.OfType<GameplayAccuracyCounter>().FirstOrDefault();
|
var accuracy = container.OfType<GameplayAccuracyCounter>().FirstOrDefault();
|
||||||
@ -387,8 +391,6 @@ namespace osu.Game.Skinning
|
|||||||
new BarHitErrorMeter(),
|
new BarHitErrorMeter(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return skinnableTargetWrapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Extensions;
|
using osu.Game.Extensions;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
@ -100,13 +101,18 @@ namespace osu.Game.Skinning
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type[] GetAllAvailableDrawables()
|
/// <summary>
|
||||||
|
/// Retrieve all types available which support serialisation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ruleset">The ruleset to filter results to. If <c>null</c>, global components will be returned instead.</param>
|
||||||
|
public static Type[] GetAllAvailableDrawables(RulesetInfo? ruleset = null)
|
||||||
{
|
{
|
||||||
return typeof(OsuGame).Assembly.GetTypes()
|
return (ruleset?.CreateInstance().GetType() ?? typeof(OsuGame))
|
||||||
.Where(t => !t.IsInterface && !t.IsAbstract)
|
.Assembly.GetTypes()
|
||||||
.Where(t => typeof(ISerialisableDrawable).IsAssignableFrom(t))
|
.Where(t => !t.IsInterface && !t.IsAbstract && t.IsPublic)
|
||||||
.OrderBy(t => t.Name)
|
.Where(t => typeof(ISerialisableDrawable).IsAssignableFrom(t))
|
||||||
.ToArray();
|
.OrderBy(t => t.Name)
|
||||||
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,10 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
public SkinConfiguration Configuration { get; set; }
|
public SkinConfiguration Configuration { get; set; }
|
||||||
|
|
||||||
public IDictionary<SkinComponentsContainerLookup.TargetArea, SerialisedDrawableInfo[]> DrawableComponentInfo => drawableComponentInfo;
|
public IDictionary<SkinComponentsContainerLookup.TargetArea, SkinLayoutInfo> LayoutInfos => layoutInfos;
|
||||||
|
|
||||||
private readonly Dictionary<SkinComponentsContainerLookup.TargetArea, SerialisedDrawableInfo[]> drawableComponentInfo = new Dictionary<SkinComponentsContainerLookup.TargetArea, SerialisedDrawableInfo[]>();
|
private readonly Dictionary<SkinComponentsContainerLookup.TargetArea, SkinLayoutInfo> layoutInfos =
|
||||||
|
new Dictionary<SkinComponentsContainerLookup.TargetArea, SkinLayoutInfo>();
|
||||||
|
|
||||||
public abstract ISample? GetSample(ISampleInfo sampleInfo);
|
public abstract ISample? GetSample(ISampleInfo sampleInfo);
|
||||||
|
|
||||||
@ -113,18 +114,41 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
string jsonContent = Encoding.UTF8.GetString(bytes);
|
string jsonContent = Encoding.UTF8.GetString(bytes);
|
||||||
|
|
||||||
// handle namespace changes...
|
SkinLayoutInfo? layoutInfo = null;
|
||||||
|
|
||||||
// can be removed 2023-01-31
|
try
|
||||||
jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.SongProgress", @"osu.Game.Screens.Play.HUD.DefaultSongProgress");
|
{
|
||||||
jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.HUD.LegacyComboCounter", @"osu.Game.Skinning.LegacyComboCounter");
|
// First attempt to deserialise using the new SkinLayoutInfo format
|
||||||
|
layoutInfo = JsonConvert.DeserializeObject<SkinLayoutInfo>(jsonContent);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
var deserializedContent = JsonConvert.DeserializeObject<IEnumerable<SerialisedDrawableInfo>>(jsonContent);
|
// Of note, the migration code below runs on read of skins, but there's nothing to
|
||||||
|
// force a rewrite after migration. Let's not remove these migration rules until we
|
||||||
|
// have something in place to ensure we don't end up breaking skins of users that haven't
|
||||||
|
// manually saved their skin since a change was implemented.
|
||||||
|
|
||||||
if (deserializedContent == null)
|
// If deserialisation using SkinLayoutInfo fails, attempt to deserialise using the old naked list.
|
||||||
continue;
|
if (layoutInfo == null)
|
||||||
|
{
|
||||||
|
// handle namespace changes...
|
||||||
|
jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.SongProgress", @"osu.Game.Screens.Play.HUD.DefaultSongProgress");
|
||||||
|
jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.HUD.LegacyComboCounter", @"osu.Game.Skinning.LegacyComboCounter");
|
||||||
|
|
||||||
DrawableComponentInfo[skinnableTarget] = deserializedContent.ToArray();
|
var deserializedContent = JsonConvert.DeserializeObject<IEnumerable<SerialisedDrawableInfo>>(jsonContent);
|
||||||
|
|
||||||
|
if (deserializedContent == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
layoutInfo = new SkinLayoutInfo();
|
||||||
|
layoutInfo.Update(null, deserializedContent.ToArray());
|
||||||
|
|
||||||
|
Logger.Log($"Ferrying {deserializedContent.Count()} components in {skinnableTarget} to global section of new {nameof(SkinLayoutInfo)} format");
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutInfos[skinnableTarget] = layoutInfo;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -145,7 +169,7 @@ namespace osu.Game.Skinning
|
|||||||
/// <param name="targetContainer">The target container to reset.</param>
|
/// <param name="targetContainer">The target container to reset.</param>
|
||||||
public void ResetDrawableTarget(SkinComponentsContainer targetContainer)
|
public void ResetDrawableTarget(SkinComponentsContainer targetContainer)
|
||||||
{
|
{
|
||||||
DrawableComponentInfo.Remove(targetContainer.Lookup.Target);
|
LayoutInfos.Remove(targetContainer.Lookup.Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -154,7 +178,10 @@ namespace osu.Game.Skinning
|
|||||||
/// <param name="targetContainer">The target container to serialise to this skin.</param>
|
/// <param name="targetContainer">The target container to serialise to this skin.</param>
|
||||||
public void UpdateDrawableTarget(SkinComponentsContainer targetContainer)
|
public void UpdateDrawableTarget(SkinComponentsContainer targetContainer)
|
||||||
{
|
{
|
||||||
DrawableComponentInfo[targetContainer.Lookup.Target] = ((ISerialisableDrawableContainer)targetContainer).CreateSerialisedInfo().ToArray();
|
if (!LayoutInfos.TryGetValue(targetContainer.Lookup.Target, out var layoutInfo))
|
||||||
|
layoutInfos[targetContainer.Lookup.Target] = layoutInfo = new SkinLayoutInfo();
|
||||||
|
|
||||||
|
layoutInfo.Update(targetContainer.Lookup.Ruleset, ((ISerialisableDrawableContainer)targetContainer).CreateSerialisedInfo().ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
public virtual Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
||||||
@ -166,18 +193,16 @@ namespace osu.Game.Skinning
|
|||||||
return this.GetAnimation(sprite.LookupName, false, false);
|
return this.GetAnimation(sprite.LookupName, false, false);
|
||||||
|
|
||||||
case SkinComponentsContainerLookup containerLookup:
|
case SkinComponentsContainerLookup containerLookup:
|
||||||
if (!DrawableComponentInfo.TryGetValue(containerLookup.Target, out var skinnableInfo))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var components = new List<Drawable>();
|
// It is important to return null if the user has not configured this yet.
|
||||||
|
// This allows skin transformers the opportunity to provide default components.
|
||||||
foreach (var i in skinnableInfo)
|
if (!LayoutInfos.TryGetValue(containerLookup.Target, out var layoutInfo)) return null;
|
||||||
components.Add(i.CreateInstance());
|
if (!layoutInfo.TryGetDrawableInfo(containerLookup.Ruleset, out var drawableInfos)) return null;
|
||||||
|
|
||||||
return new Container
|
return new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Children = components,
|
ChildrenEnumerable = drawableInfos.Select(i => i.CreateInstance())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,25 +66,20 @@ namespace osu.Game.Skinning
|
|||||||
components.Clear();
|
components.Clear();
|
||||||
ComponentsLoaded = false;
|
ComponentsLoaded = false;
|
||||||
|
|
||||||
if (componentsContainer == null)
|
content = componentsContainer ?? new Container
|
||||||
return;
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
content = componentsContainer;
|
};
|
||||||
|
|
||||||
cancellationSource?.Cancel();
|
cancellationSource?.Cancel();
|
||||||
cancellationSource = null;
|
cancellationSource = null;
|
||||||
|
|
||||||
if (content != null)
|
LoadComponentAsync(content, wrapper =>
|
||||||
{
|
{
|
||||||
LoadComponentAsync(content, wrapper =>
|
AddInternal(wrapper);
|
||||||
{
|
components.AddRange(wrapper.Children.OfType<ISerialisableDrawable>());
|
||||||
AddInternal(wrapper);
|
|
||||||
components.AddRange(wrapper.Children.OfType<ISerialisableDrawable>());
|
|
||||||
ComponentsLoaded = true;
|
|
||||||
}, (cancellationSource = new CancellationTokenSource()).Token);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ComponentsLoaded = true;
|
ComponentsLoaded = true;
|
||||||
|
}, (cancellationSource = new CancellationTokenSource()).Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="ISerialisableDrawableContainer"/>
|
/// <inheritdoc cref="ISerialisableDrawableContainer"/>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -13,9 +15,16 @@ namespace osu.Game.Skinning
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly TargetArea Target;
|
public readonly TargetArea Target;
|
||||||
|
|
||||||
public SkinComponentsContainerLookup(TargetArea target)
|
/// <summary>
|
||||||
|
/// The ruleset for which skin components should be returned.
|
||||||
|
/// A <see langword="null"/> value means that returned components are global and should be applied for all rulesets.
|
||||||
|
/// </summary>
|
||||||
|
public readonly RulesetInfo? Ruleset;
|
||||||
|
|
||||||
|
public SkinComponentsContainerLookup(TargetArea target, RulesetInfo? ruleset = null)
|
||||||
{
|
{
|
||||||
Target = target;
|
Target = target;
|
||||||
|
Ruleset = ruleset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -201,7 +201,7 @@ namespace osu.Game.Skinning
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Then serialise each of the drawable component groups into respective files.
|
// Then serialise each of the drawable component groups into respective files.
|
||||||
foreach (var drawableInfo in skin.DrawableComponentInfo)
|
foreach (var drawableInfo in skin.LayoutInfos)
|
||||||
{
|
{
|
||||||
string json = JsonConvert.SerializeObject(drawableInfo.Value, new JsonSerializerSettings { Formatting = Formatting.Indented });
|
string json = JsonConvert.SerializeObject(drawableInfo.Value, new JsonSerializerSettings { Formatting = Formatting.Indented });
|
||||||
|
|
||||||
|
37
osu.Game/Skinning/SkinLayoutInfo.cs
Normal file
37
osu.Game/Skinning/SkinLayoutInfo.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
|
namespace osu.Game.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A serialisable model describing layout of a <see cref="SkinComponentsContainer"/>.
|
||||||
|
/// May contain multiple configurations for different rulesets, each of which should manifest their own <see cref="SkinComponentsContainer"/> as required.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class SkinLayoutInfo
|
||||||
|
{
|
||||||
|
private const string global_identifier = @"global";
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IEnumerable<SerialisedDrawableInfo> AllDrawables => DrawableInfo.Values.SelectMany(v => v);
|
||||||
|
|
||||||
|
[JsonProperty]
|
||||||
|
public Dictionary<string, SerialisedDrawableInfo[]> DrawableInfo { get; set; } = new Dictionary<string, SerialisedDrawableInfo[]>();
|
||||||
|
|
||||||
|
public bool TryGetDrawableInfo(RulesetInfo? ruleset, [NotNullWhen(true)] out SerialisedDrawableInfo[]? components) =>
|
||||||
|
DrawableInfo.TryGetValue(ruleset?.ShortName ?? global_identifier, out components);
|
||||||
|
|
||||||
|
public void Reset(RulesetInfo? ruleset) =>
|
||||||
|
DrawableInfo.Remove(ruleset?.ShortName ?? global_identifier);
|
||||||
|
|
||||||
|
public void Update(RulesetInfo? ruleset, SerialisedDrawableInfo[] components) =>
|
||||||
|
DrawableInfo[ruleset?.ShortName ?? global_identifier] = components;
|
||||||
|
}
|
||||||
|
}
|
@ -69,6 +69,10 @@ namespace osu.Game.Skinning
|
|||||||
switch (lookup)
|
switch (lookup)
|
||||||
{
|
{
|
||||||
case SkinComponentsContainerLookup containerLookup:
|
case SkinComponentsContainerLookup containerLookup:
|
||||||
|
// Only handle global level defaults for now.
|
||||||
|
if (containerLookup.Ruleset != null)
|
||||||
|
return null;
|
||||||
|
|
||||||
switch (containerLookup.Target)
|
switch (containerLookup.Target)
|
||||||
{
|
{
|
||||||
case SkinComponentsContainerLookup.TargetArea.SongSelect:
|
case SkinComponentsContainerLookup.TargetArea.SongSelect:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user