mirror of
https://github.com/ppy/osu.git
synced 2025-01-09 04:23:22 +08:00
Merge pull request #8513 from smoogipoo/mania-skinning-testability
Implement basis for mania skinning
This commit is contained in:
commit
da129ddf6a
@ -0,0 +1,38 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A container to be used in a <see cref="ManiaSkinnableTestScene"/> to provide a resolvable <see cref="Column"/> dependency.
|
||||||
|
/// </summary>
|
||||||
|
public class ColumnTestContainer : Container
|
||||||
|
{
|
||||||
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
|
private readonly Container content;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly Column column;
|
||||||
|
|
||||||
|
public ColumnTestContainer(int column, ManiaAction action)
|
||||||
|
{
|
||||||
|
this.column = new Column(column)
|
||||||
|
{
|
||||||
|
Action = { Value = action },
|
||||||
|
AccentColour = Color4.Orange
|
||||||
|
};
|
||||||
|
|
||||||
|
InternalChild = content = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A test scene for a mania hitobject.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ManiaHitObjectTestScene : ManiaSkinnableTestScene
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
SetContents(() => new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Height = 0.7f,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new ColumnTestContainer(0, ManiaAction.Key1)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 80,
|
||||||
|
Child = new ScrollingHitObjectContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Clock = new FramedClock(new StopwatchClock()),
|
||||||
|
}.With(c =>
|
||||||
|
{
|
||||||
|
c.Add(CreateHitObject().With(h => h.AccentColour.Value = Color4.Orange));
|
||||||
|
})
|
||||||
|
},
|
||||||
|
new ColumnTestContainer(1, ManiaAction.Key2)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 80,
|
||||||
|
Child = new ScrollingHitObjectContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Clock = new FramedClock(new StopwatchClock()),
|
||||||
|
}.With(c =>
|
||||||
|
{
|
||||||
|
c.Add(CreateHitObject().With(h => h.AccentColour.Value = Color4.Orange));
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract DrawableManiaHitObject CreateHitObject();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling.Algorithms;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A test scene for skinnable mania components.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ManiaSkinnableTestScene : SkinnableTestScene
|
||||||
|
{
|
||||||
|
[Cached(Type = typeof(IScrollingInfo))]
|
||||||
|
private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo();
|
||||||
|
|
||||||
|
protected ManiaSkinnableTestScene()
|
||||||
|
{
|
||||||
|
scrollingInfo.Direction.Value = ScrollingDirection.Down;
|
||||||
|
|
||||||
|
Add(new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.SlateGray.Opacity(0.2f),
|
||||||
|
Depth = 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestScrollingDown()
|
||||||
|
{
|
||||||
|
AddStep("change direction to down", () => scrollingInfo.Direction.Value = ScrollingDirection.Down);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestScrollingUp()
|
||||||
|
{
|
||||||
|
AddStep("change direction to up", () => scrollingInfo.Direction.Value = ScrollingDirection.Up);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestScrollingInfo : IScrollingInfo
|
||||||
|
{
|
||||||
|
public readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
IBindable<ScrollingDirection> IScrollingInfo.Direction => Direction;
|
||||||
|
IBindable<double> IScrollingInfo.TimeRange { get; } = new Bindable<double>(1000);
|
||||||
|
IScrollAlgorithm IScrollingInfo.Algorithm { get; } = new ConstantScrollAlgorithm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,13 +6,13 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
{
|
{
|
||||||
public class TestSceneDrawableJudgement : SkinnableTestScene
|
public class TestSceneDrawableJudgement : SkinnableTestScene
|
||||||
{
|
{
|
@ -16,4 +16,8 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
|
|
||||||
protected override string ComponentName => Component.ToString().ToLower();
|
protected override string ComponentName => Component.ToString().ToLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ManiaSkinComponents
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania
|
|
||||||
{
|
|
||||||
public enum ManiaSkinComponents
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
41
osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs
Normal file
41
osu.Game.Rulesets.Mania/Skinning/LegacyManiaColumnElement.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// 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 JetBrains.Annotations;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="CompositeDrawable"/> which is placed somewhere within a <see cref="Column"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class LegacyManiaColumnElement : CompositeDrawable
|
||||||
|
{
|
||||||
|
[Resolved(CanBeNull = true)]
|
||||||
|
[CanBeNull]
|
||||||
|
protected ManiaStage Stage { get; private set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
protected Column Column { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The column index to use for texture lookups, in the case of no user-provided configuration.
|
||||||
|
/// </summary>
|
||||||
|
protected int FallbackColumnIndex { get; private set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
if (Stage == null)
|
||||||
|
FallbackColumnIndex = Column.Index % 2 + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int dist = Math.Min(Column.Index, Stage.Columns.Count - Column.Index - 1);
|
||||||
|
FallbackColumnIndex = dist % 2 + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
// 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 System;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
@ -15,9 +16,19 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
{
|
{
|
||||||
private readonly ISkin source;
|
private readonly ISkin source;
|
||||||
|
|
||||||
public ManiaLegacySkinTransformer(ISkin source)
|
private Lazy<bool> isLegacySkin;
|
||||||
|
|
||||||
|
public ManiaLegacySkinTransformer(ISkinSource source)
|
||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
|
|
||||||
|
source.SourceChanged += sourceChanged;
|
||||||
|
sourceChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sourceChanged()
|
||||||
|
{
|
||||||
|
isLegacySkin = new Lazy<bool>(() => source.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Drawable GetDrawableComponent(ISkinComponent component)
|
public Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
@ -26,6 +37,12 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
{
|
{
|
||||||
case GameplaySkinComponent<HitResult> resultComponent:
|
case GameplaySkinComponent<HitResult> resultComponent:
|
||||||
return getResult(resultComponent);
|
return getResult(resultComponent);
|
||||||
|
|
||||||
|
case ManiaSkinComponent _:
|
||||||
|
if (!isLegacySkin.Value)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -19,6 +19,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI
|
namespace osu.Game.Rulesets.Mania.UI
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
public class Column : ScrollingPlayfield, IKeyBindingHandler<ManiaAction>, IHasAccentColour
|
public class Column : ScrollingPlayfield, IKeyBindingHandler<ManiaAction>, IHasAccentColour
|
||||||
{
|
{
|
||||||
public const float COLUMN_WIDTH = 80;
|
public const float COLUMN_WIDTH = 80;
|
||||||
|
@ -23,6 +23,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A collection of <see cref="Column"/>s.
|
/// A collection of <see cref="Column"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Cached]
|
||||||
public class ManiaStage : ScrollingPlayfield
|
public class ManiaStage : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
public const float COLUMN_SPACING = 1;
|
public const float COLUMN_SPACING = 1;
|
||||||
|
@ -17,9 +17,9 @@ namespace osu.Game.IO
|
|||||||
private readonly StreamReader streamReader;
|
private readonly StreamReader streamReader;
|
||||||
private readonly Queue<string> lineBuffer;
|
private readonly Queue<string> lineBuffer;
|
||||||
|
|
||||||
public LineBufferedReader(Stream stream)
|
public LineBufferedReader(Stream stream, bool leaveOpen = false)
|
||||||
{
|
{
|
||||||
streamReader = new StreamReader(stream);
|
streamReader = new StreamReader(stream, Encoding.UTF8, true, 1024, leaveOpen);
|
||||||
lineBuffer = new Queue<string>();
|
lineBuffer = new Queue<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
public class LegacyBeatmapSkin : LegacySkin
|
public class LegacyBeatmapSkin : LegacySkin
|
||||||
{
|
{
|
||||||
|
protected override bool AllowManiaSkin => false;
|
||||||
|
|
||||||
public LegacyBeatmapSkin(BeatmapInfo beatmap, IResourceStore<byte[]> storage, AudioManager audioManager)
|
public LegacyBeatmapSkin(BeatmapInfo beatmap, IResourceStore<byte[]> storage, AudioManager audioManager)
|
||||||
: base(createSkinInfo(beatmap), new LegacySkinResourceStore<BeatmapSetFileInfo>(beatmap.BeatmapSet, storage), audioManager, beatmap.Path)
|
: base(createSkinInfo(beatmap), new LegacySkinResourceStore<BeatmapSetFileInfo>(beatmap.BeatmapSet, storage), audioManager, beatmap.Path)
|
||||||
{
|
{
|
||||||
|
23
osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs
Normal file
23
osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace osu.Game.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyManiaSkinConfigurationLookup
|
||||||
|
{
|
||||||
|
public readonly int Keys;
|
||||||
|
public readonly LegacyManiaSkinConfigurationLookups Lookup;
|
||||||
|
public readonly int? TargetColumn;
|
||||||
|
|
||||||
|
public LegacyManiaSkinConfigurationLookup(int keys, LegacyManiaSkinConfigurationLookups lookup, int? targetColumn = null)
|
||||||
|
{
|
||||||
|
Keys = keys;
|
||||||
|
Lookup = lookup;
|
||||||
|
TargetColumn = targetColumn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LegacyManiaSkinConfigurationLookups
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -26,12 +26,16 @@ namespace osu.Game.Skinning
|
|||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
protected IResourceStore<SampleChannel> Samples;
|
protected IResourceStore<SampleChannel> Samples;
|
||||||
|
|
||||||
|
protected virtual bool AllowManiaSkin => true;
|
||||||
|
|
||||||
public new LegacySkinConfiguration Configuration
|
public new LegacySkinConfiguration Configuration
|
||||||
{
|
{
|
||||||
get => base.Configuration as LegacySkinConfiguration;
|
get => base.Configuration as LegacySkinConfiguration;
|
||||||
set => base.Configuration = value;
|
set => base.Configuration = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<int, LegacyManiaSkinConfiguration> maniaConfigurations = new Dictionary<int, LegacyManiaSkinConfiguration>();
|
||||||
|
|
||||||
public LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager)
|
public LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager)
|
||||||
: this(skin, new LegacySkinResourceStore<SkinFileInfo>(skin, storage), audioManager, "skin.ini")
|
: this(skin, new LegacySkinResourceStore<SkinFileInfo>(skin, storage), audioManager, "skin.ini")
|
||||||
{
|
{
|
||||||
@ -40,15 +44,26 @@ namespace osu.Game.Skinning
|
|||||||
protected LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager, string filename)
|
protected LegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager, string filename)
|
||||||
: base(skin)
|
: base(skin)
|
||||||
{
|
{
|
||||||
Stream stream = storage?.GetStream(filename);
|
using (var stream = storage?.GetStream(filename))
|
||||||
|
|
||||||
if (stream != null)
|
|
||||||
{
|
{
|
||||||
using (LineBufferedReader reader = new LineBufferedReader(stream))
|
if (stream != null)
|
||||||
Configuration = new LegacySkinDecoder().Decode(reader);
|
{
|
||||||
|
using (LineBufferedReader reader = new LineBufferedReader(stream, true))
|
||||||
|
Configuration = new LegacySkinDecoder().Decode(reader);
|
||||||
|
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
using (LineBufferedReader reader = new LineBufferedReader(stream))
|
||||||
|
{
|
||||||
|
var maniaList = new LegacyManiaSkinDecoder().Decode(reader);
|
||||||
|
|
||||||
|
foreach (var config in maniaList)
|
||||||
|
maniaConfigurations[config.Keys] = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION };
|
||||||
}
|
}
|
||||||
else
|
|
||||||
Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION };
|
|
||||||
|
|
||||||
if (storage != null)
|
if (storage != null)
|
||||||
{
|
{
|
||||||
@ -105,6 +120,15 @@ namespace osu.Game.Skinning
|
|||||||
case SkinCustomColourLookup customColour:
|
case SkinCustomColourLookup customColour:
|
||||||
return SkinUtils.As<TValue>(getCustomColour(customColour.Lookup.ToString()));
|
return SkinUtils.As<TValue>(getCustomColour(customColour.Lookup.ToString()));
|
||||||
|
|
||||||
|
case LegacyManiaSkinConfigurationLookup legacy:
|
||||||
|
if (!AllowManiaSkin)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!maniaConfigurations.TryGetValue(legacy.Keys, out _))
|
||||||
|
maniaConfigurations[legacy.Keys] = new LegacyManiaSkinConfiguration(legacy.Keys);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// handles lookups like GlobalSkinConfiguration
|
// handles lookups like GlobalSkinConfiguration
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user