2019-07-26 10:29:06 +00:00
|
|
|
// 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;
|
2020-02-17 07:37:09 +00:00
|
|
|
using System.Collections.Generic;
|
2019-08-20 08:39:16 +00:00
|
|
|
using System.Text.RegularExpressions;
|
2020-04-23 10:25:06 +00:00
|
|
|
using JetBrains.Annotations;
|
2019-07-26 10:29:06 +00:00
|
|
|
using osu.Framework.Allocation;
|
|
|
|
using osu.Framework.Audio;
|
|
|
|
using osu.Framework.Graphics;
|
|
|
|
using osu.Framework.Graphics.Containers;
|
2020-07-17 07:54:30 +00:00
|
|
|
using osu.Framework.Graphics.OpenGL.Textures;
|
2020-02-17 07:09:31 +00:00
|
|
|
using osu.Framework.Graphics.Shapes;
|
2019-08-20 08:39:16 +00:00
|
|
|
using osu.Framework.Graphics.Textures;
|
2019-07-26 10:29:06 +00:00
|
|
|
using osu.Framework.IO.Stores;
|
2020-12-21 06:14:32 +00:00
|
|
|
using osu.Framework.Platform;
|
2020-04-02 09:39:49 +00:00
|
|
|
using osu.Game.Beatmaps;
|
2021-12-14 05:19:43 +00:00
|
|
|
using osu.Game.Database;
|
2020-02-17 07:09:31 +00:00
|
|
|
using osu.Game.Graphics.Sprites;
|
2020-12-21 06:14:32 +00:00
|
|
|
using osu.Game.IO;
|
2020-04-23 10:25:06 +00:00
|
|
|
using osu.Game.Rulesets;
|
2019-07-26 10:29:06 +00:00
|
|
|
using osu.Game.Skinning;
|
2020-02-17 07:09:31 +00:00
|
|
|
using osuTK;
|
|
|
|
using osuTK.Graphics;
|
2019-07-26 10:29:06 +00:00
|
|
|
|
2020-02-17 05:19:39 +00:00
|
|
|
namespace osu.Game.Tests.Visual
|
2019-07-26 10:29:06 +00:00
|
|
|
{
|
2020-12-21 06:14:32 +00:00
|
|
|
public abstract class SkinnableTestScene : OsuGridTestScene, IStorageResourceProvider
|
2019-07-26 10:29:06 +00:00
|
|
|
{
|
|
|
|
private Skin metricsSkin;
|
|
|
|
private Skin defaultSkin;
|
|
|
|
private Skin specialSkin;
|
2019-12-12 13:27:11 +00:00
|
|
|
private Skin oldSkin;
|
2019-07-26 10:29:06 +00:00
|
|
|
|
2020-12-21 06:14:32 +00:00
|
|
|
[Resolved]
|
|
|
|
private GameHost host { get; set; }
|
|
|
|
|
2019-07-30 12:53:28 +00:00
|
|
|
protected SkinnableTestScene()
|
2019-12-12 13:27:11 +00:00
|
|
|
: base(2, 3)
|
2019-07-30 12:53:28 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-07-26 10:29:06 +00:00
|
|
|
[BackgroundDependencyLoader]
|
2022-01-15 00:06:39 +00:00
|
|
|
private void load()
|
2019-07-26 10:29:06 +00:00
|
|
|
{
|
2020-04-07 09:55:03 +00:00
|
|
|
var dllStore = new DllResourceStore(DynamicCompilationOriginal.GetType().Assembly);
|
2019-07-26 10:29:06 +00:00
|
|
|
|
2020-12-21 06:14:32 +00:00
|
|
|
metricsSkin = new TestLegacySkin(new SkinInfo { Name = "metrics-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), this, true);
|
2021-05-31 09:58:40 +00:00
|
|
|
defaultSkin = new DefaultLegacySkin(this);
|
2020-12-21 06:14:32 +00:00
|
|
|
specialSkin = new TestLegacySkin(new SkinInfo { Name = "special-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/special_skin"), this, true);
|
|
|
|
oldSkin = new TestLegacySkin(new SkinInfo { Name = "old-skin" }, new NamespacedResourceStore<byte[]>(dllStore, "Resources/old_skin"), this, true);
|
2019-07-26 10:29:06 +00:00
|
|
|
}
|
|
|
|
|
2020-02-17 07:37:09 +00:00
|
|
|
private readonly List<Drawable> createdDrawables = new List<Drawable>();
|
|
|
|
|
2021-06-02 07:04:53 +00:00
|
|
|
protected void SetContents(Func<ISkin, Drawable> creationFunction)
|
2019-07-26 10:29:06 +00:00
|
|
|
{
|
2020-02-17 07:37:09 +00:00
|
|
|
createdDrawables.Clear();
|
|
|
|
|
2020-04-02 09:39:49 +00:00
|
|
|
var beatmap = CreateBeatmapForSkinProvider();
|
|
|
|
|
|
|
|
Cell(0).Child = createProvider(null, creationFunction, beatmap);
|
|
|
|
Cell(1).Child = createProvider(metricsSkin, creationFunction, beatmap);
|
|
|
|
Cell(2).Child = createProvider(defaultSkin, creationFunction, beatmap);
|
|
|
|
Cell(3).Child = createProvider(specialSkin, creationFunction, beatmap);
|
|
|
|
Cell(4).Child = createProvider(oldSkin, creationFunction, beatmap);
|
2019-08-26 03:31:51 +00:00
|
|
|
}
|
|
|
|
|
2020-02-17 07:37:09 +00:00
|
|
|
protected IEnumerable<Drawable> CreatedDrawables => createdDrawables;
|
|
|
|
|
2021-06-01 07:13:56 +00:00
|
|
|
private Drawable createProvider(Skin skin, Func<ISkin, Drawable> creationFunction, IBeatmap beatmap)
|
2019-08-26 03:31:51 +00:00
|
|
|
{
|
2021-06-01 07:13:56 +00:00
|
|
|
var created = creationFunction(skin);
|
2020-02-17 07:37:09 +00:00
|
|
|
|
2020-11-05 07:37:47 +00:00
|
|
|
createdDrawables.Add(created);
|
2019-08-26 03:31:51 +00:00
|
|
|
|
2020-11-05 07:37:47 +00:00
|
|
|
SkinProvidingContainer mainProvider;
|
|
|
|
Container childContainer;
|
|
|
|
OutlineBox outlineBox;
|
|
|
|
SkinProvidingContainer skinProvider;
|
2020-02-17 07:09:31 +00:00
|
|
|
|
2020-11-05 07:37:47 +00:00
|
|
|
var children = new Container
|
2020-02-17 07:09:31 +00:00
|
|
|
{
|
|
|
|
RelativeSizeAxes = Axes.Both,
|
|
|
|
BorderColour = Color4.White,
|
|
|
|
BorderThickness = 5,
|
|
|
|
Masking = true,
|
|
|
|
|
|
|
|
Children = new Drawable[]
|
|
|
|
{
|
|
|
|
new Box
|
|
|
|
{
|
|
|
|
AlwaysPresent = true,
|
|
|
|
Alpha = 0,
|
|
|
|
RelativeSizeAxes = Axes.Both,
|
|
|
|
},
|
|
|
|
new OsuSpriteText
|
|
|
|
{
|
2021-11-29 08:57:17 +00:00
|
|
|
Text = skin?.SkinInfo?.Value.Name ?? "none",
|
2020-02-17 07:09:31 +00:00
|
|
|
Scale = new Vector2(1.5f),
|
|
|
|
Padding = new MarginPadding(5),
|
|
|
|
},
|
2020-11-05 07:37:47 +00:00
|
|
|
childContainer = new Container
|
2020-02-17 07:09:31 +00:00
|
|
|
{
|
|
|
|
Anchor = Anchor.Centre,
|
|
|
|
Origin = Anchor.Centre,
|
|
|
|
Children = new Drawable[]
|
|
|
|
{
|
2020-11-05 07:37:47 +00:00
|
|
|
outlineBox = new OutlineBox(),
|
|
|
|
(mainProvider = new SkinProvidingContainer(skin)).WithChild(
|
|
|
|
skinProvider = new SkinProvidingContainer(Ruleset.Value.CreateInstance().CreateLegacySkinProvider(mainProvider, beatmap))
|
2020-02-17 07:09:31 +00:00
|
|
|
{
|
|
|
|
Child = created,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
};
|
2020-11-05 07:37:47 +00:00
|
|
|
|
2020-11-05 08:24:59 +00:00
|
|
|
// run this once initially to bring things into a sane state as early as possible.
|
|
|
|
updateSizing();
|
|
|
|
|
|
|
|
// run this once after construction to handle the case the changes are made in a BDL/LoadComplete call.
|
|
|
|
Schedule(updateSizing);
|
|
|
|
|
|
|
|
return children;
|
|
|
|
|
|
|
|
void updateSizing()
|
2020-11-05 07:37:47 +00:00
|
|
|
{
|
2021-10-27 04:04:41 +00:00
|
|
|
bool autoSize = created.RelativeSizeAxes == Axes.None;
|
2020-11-05 07:37:47 +00:00
|
|
|
|
|
|
|
foreach (var c in new[] { mainProvider, childContainer, skinProvider })
|
|
|
|
{
|
2020-11-05 08:26:41 +00:00
|
|
|
c.RelativeSizeAxes = Axes.None;
|
|
|
|
c.AutoSizeAxes = Axes.None;
|
|
|
|
|
2020-11-05 07:37:47 +00:00
|
|
|
c.RelativeSizeAxes = !autoSize ? Axes.Both : Axes.None;
|
|
|
|
c.AutoSizeAxes = autoSize ? Axes.Both : Axes.None;
|
|
|
|
}
|
|
|
|
|
|
|
|
outlineBox.Alpha = autoSize ? 1 : 0;
|
2020-11-05 08:24:59 +00:00
|
|
|
}
|
2020-02-17 07:09:31 +00:00
|
|
|
}
|
|
|
|
|
2020-06-03 20:43:18 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Creates the ruleset for adding the corresponding skin transforming component.
|
|
|
|
/// </summary>
|
|
|
|
[NotNull]
|
|
|
|
protected abstract Ruleset CreateRulesetForSkinProvider();
|
|
|
|
|
|
|
|
protected sealed override Ruleset CreateRuleset() => CreateRulesetForSkinProvider();
|
|
|
|
|
2020-04-02 09:39:49 +00:00
|
|
|
protected virtual IBeatmap CreateBeatmapForSkinProvider() => CreateWorkingBeatmap(Ruleset.Value).GetPlayableBeatmap(Ruleset.Value);
|
|
|
|
|
2020-12-22 03:01:09 +00:00
|
|
|
#region IResourceStorageProvider
|
|
|
|
|
2020-12-21 06:14:32 +00:00
|
|
|
public AudioManager AudioManager => Audio;
|
|
|
|
public IResourceStore<byte[]> Files => null;
|
2021-05-31 09:37:32 +00:00
|
|
|
public new IResourceStore<byte[]> Resources => base.Resources;
|
2020-12-21 06:14:32 +00:00
|
|
|
public IResourceStore<TextureUpload> CreateTextureLoaderStore(IResourceStore<byte[]> underlyingStore) => host.CreateTextureLoaderStore(underlyingStore);
|
2021-12-14 05:19:43 +00:00
|
|
|
RealmContextFactory IStorageResourceProvider.RealmContextFactory => null;
|
2020-12-21 06:14:32 +00:00
|
|
|
|
2020-12-22 03:01:09 +00:00
|
|
|
#endregion
|
|
|
|
|
2020-02-17 07:09:31 +00:00
|
|
|
private class OutlineBox : CompositeDrawable
|
|
|
|
{
|
|
|
|
public OutlineBox()
|
|
|
|
{
|
|
|
|
BorderColour = Color4.IndianRed;
|
|
|
|
BorderThickness = 5;
|
|
|
|
Masking = true;
|
|
|
|
RelativeSizeAxes = Axes.Both;
|
|
|
|
|
|
|
|
InternalChild = new Box
|
2019-08-26 03:31:51 +00:00
|
|
|
{
|
2020-02-17 07:09:31 +00:00
|
|
|
RelativeSizeAxes = Axes.Both,
|
|
|
|
Alpha = 0,
|
|
|
|
Colour = Color4.Brown,
|
|
|
|
AlwaysPresent = true
|
|
|
|
};
|
|
|
|
}
|
2019-07-26 10:29:06 +00:00
|
|
|
}
|
|
|
|
|
2019-08-20 08:39:16 +00:00
|
|
|
private class TestLegacySkin : LegacySkin
|
2019-07-26 10:29:06 +00:00
|
|
|
{
|
2019-08-20 08:39:16 +00:00
|
|
|
private readonly bool extrapolateAnimations;
|
2019-07-30 12:53:28 +00:00
|
|
|
|
2020-12-21 06:14:32 +00:00
|
|
|
public TestLegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, IStorageResourceProvider resources, bool extrapolateAnimations)
|
|
|
|
: base(skin, storage, resources, "skin.ini")
|
2019-08-20 08:39:16 +00:00
|
|
|
{
|
|
|
|
this.extrapolateAnimations = extrapolateAnimations;
|
|
|
|
}
|
2019-07-30 12:53:28 +00:00
|
|
|
|
2020-07-17 07:54:30 +00:00
|
|
|
public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
2019-08-20 08:39:16 +00:00
|
|
|
{
|
2020-09-22 04:32:00 +00:00
|
|
|
var lookup = base.GetTexture(componentName, wrapModeS, wrapModeT);
|
2019-07-30 12:53:28 +00:00
|
|
|
|
2020-09-22 04:32:00 +00:00
|
|
|
if (lookup != null)
|
|
|
|
return lookup;
|
2020-08-03 18:43:03 +00:00
|
|
|
|
2020-09-22 04:32:00 +00:00
|
|
|
// extrapolate frames to test longer animations
|
|
|
|
if (extrapolateAnimations)
|
|
|
|
{
|
|
|
|
var match = Regex.Match(componentName, "-([0-9]*)");
|
2020-08-03 18:43:03 +00:00
|
|
|
|
2021-10-27 04:04:41 +00:00
|
|
|
if (match.Length > 0 && int.TryParse(match.Groups[1].Value, out int number) && number < 60)
|
2020-09-22 04:32:00 +00:00
|
|
|
return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}"), wrapModeS, wrapModeT);
|
|
|
|
}
|
2020-08-03 18:43:03 +00:00
|
|
|
|
2020-09-22 04:32:00 +00:00
|
|
|
return null;
|
2020-08-03 18:43:03 +00:00
|
|
|
}
|
2019-07-26 10:29:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|