mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 15:07:44 +08:00
Merge branch 'master' into rulesetstore-ruleset-dir
This commit is contained in:
commit
07a73ba83c
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="RiderProjectSettingsUpdater">
|
<component name="RiderProjectSettingsUpdater">
|
||||||
<option name="vcsConfiguration" value="1" />
|
<option name="vcsConfiguration" value="2" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -5,6 +5,6 @@
|
|||||||
"version": "3.1.100"
|
"version": "3.1.100"
|
||||||
},
|
},
|
||||||
"msbuild-sdks": {
|
"msbuild-sdks": {
|
||||||
"Microsoft.Build.Traversal": "2.0.32"
|
"Microsoft.Build.Traversal": "2.0.34"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -51,7 +51,7 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.331.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.412.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.331.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.421.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.0" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
||||||
<PackageReference Include="nunit" Version="3.12.0" />
|
<PackageReference Include="nunit" Version="3.12.0" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
|
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
21
osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs
Normal file
21
osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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 osu.Game.Rulesets.Catch.Skinning;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
|
{
|
||||||
|
public abstract class CatchSkinnableTestScene : SkinnableTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(CatchRuleset),
|
||||||
|
typeof(CatchLegacySkinTransformer),
|
||||||
|
};
|
||||||
|
|
||||||
|
protected override Ruleset CreateRulesetForSkinProvider() => new CatchRuleset();
|
||||||
|
}
|
||||||
|
}
|
@ -4,21 +4,21 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneCatcher : SkinnableTestScene
|
public class TestSceneCatcher : CatchSkinnableTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||||
{
|
{
|
||||||
typeof(CatcherArea),
|
typeof(CatcherArea),
|
||||||
typeof(CatcherSprite)
|
typeof(CatcherSprite)
|
||||||
};
|
}).ToList();
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -17,12 +17,11 @@ using osu.Game.Rulesets.Catch.UI;
|
|||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneCatcherArea : SkinnableTestScene
|
public class TestSceneCatcherArea : CatchSkinnableTestScene
|
||||||
{
|
{
|
||||||
private RulesetInfo catchRuleset;
|
private RulesetInfo catchRuleset;
|
||||||
|
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneFruitObjects : SkinnableTestScene
|
public class TestSceneFruitObjects : CatchSkinnableTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||||
{
|
{
|
||||||
typeof(CatchHitObject),
|
typeof(CatchHitObject),
|
||||||
typeof(Fruit),
|
typeof(Fruit),
|
||||||
@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
typeof(DrawableBanana),
|
typeof(DrawableBanana),
|
||||||
typeof(DrawableBananaShower),
|
typeof(DrawableBananaShower),
|
||||||
typeof(Pulp),
|
typeof(Pulp),
|
||||||
};
|
}).ToList();
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
|
132
osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs
Normal file
132
osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Catch.Skinning;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
|
{
|
||||||
|
public class TestSceneHyperDashColouring : OsuTestScene
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private SkinManager skins { get; set; }
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDefaultFruitColour()
|
||||||
|
{
|
||||||
|
var skin = new TestSkin();
|
||||||
|
|
||||||
|
checkHyperDashFruitColour(skin, Catcher.DEFAULT_HYPER_DASH_COLOUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCustomFruitColour()
|
||||||
|
{
|
||||||
|
var skin = new TestSkin
|
||||||
|
{
|
||||||
|
HyperDashFruitColour = Color4.Cyan
|
||||||
|
};
|
||||||
|
|
||||||
|
checkHyperDashFruitColour(skin, skin.HyperDashFruitColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCustomFruitColourPriority()
|
||||||
|
{
|
||||||
|
var skin = new TestSkin
|
||||||
|
{
|
||||||
|
HyperDashColour = Color4.Goldenrod,
|
||||||
|
HyperDashFruitColour = Color4.Cyan
|
||||||
|
};
|
||||||
|
|
||||||
|
checkHyperDashFruitColour(skin, skin.HyperDashFruitColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestFruitColourFallback()
|
||||||
|
{
|
||||||
|
var skin = new TestSkin
|
||||||
|
{
|
||||||
|
HyperDashColour = Color4.Goldenrod
|
||||||
|
};
|
||||||
|
|
||||||
|
checkHyperDashFruitColour(skin, skin.HyperDashColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkHyperDashFruitColour(ISkin skin, Color4 expectedColour)
|
||||||
|
{
|
||||||
|
DrawableFruit drawableFruit = null;
|
||||||
|
|
||||||
|
AddStep("create hyper-dash fruit", () =>
|
||||||
|
{
|
||||||
|
var fruit = new Fruit { HyperDashTarget = new Banana() };
|
||||||
|
fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||||
|
|
||||||
|
Child = setupSkinHierarchy(drawableFruit = new DrawableFruit(fruit)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(4f),
|
||||||
|
}, skin);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("hyper-dash colour is correct", () => checkLegacyFruitHyperDashColour(drawableFruit, expectedColour));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable setupSkinHierarchy(Drawable child, ISkin skin)
|
||||||
|
{
|
||||||
|
var legacySkinProvider = new SkinProvidingContainer(skins.GetSkin(DefaultLegacySkin.Info));
|
||||||
|
var testSkinProvider = new SkinProvidingContainer(skin);
|
||||||
|
var legacySkinTransformer = new SkinProvidingContainer(new CatchLegacySkinTransformer(testSkinProvider));
|
||||||
|
|
||||||
|
return legacySkinProvider
|
||||||
|
.WithChild(testSkinProvider
|
||||||
|
.WithChild(legacySkinTransformer
|
||||||
|
.WithChild(child)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool checkLegacyFruitHyperDashColour(DrawableFruit fruit, Color4 expectedColour) =>
|
||||||
|
fruit.ChildrenOfType<SkinnableDrawable>().First().Drawable.ChildrenOfType<Sprite>().Any(c => c.Colour == expectedColour);
|
||||||
|
|
||||||
|
private class TestSkin : LegacySkin
|
||||||
|
{
|
||||||
|
public Color4 HyperDashColour
|
||||||
|
{
|
||||||
|
get => Configuration.CustomColours[CatchSkinColour.HyperDash.ToString()];
|
||||||
|
set => Configuration.CustomColours[CatchSkinColour.HyperDash.ToString()] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color4 HyperDashAfterImageColour
|
||||||
|
{
|
||||||
|
get => Configuration.CustomColours[CatchSkinColour.HyperDashAfterImage.ToString()];
|
||||||
|
set => Configuration.CustomColours[CatchSkinColour.HyperDashAfterImage.ToString()] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color4 HyperDashFruitColour
|
||||||
|
{
|
||||||
|
get => Configuration.CustomColours[CatchSkinColour.HyperDashFruit.ToString()];
|
||||||
|
set => Configuration.CustomColours[CatchSkinColour.HyperDashFruit.ToString()] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestSkin()
|
||||||
|
: base(new SkinInfo(), null, null, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
||||||
|
|
||||||
public override ISkin CreateLegacySkinProvider(ISkinSource source) => new CatchLegacySkinTransformer(source);
|
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new CatchLegacySkinTransformer(source);
|
||||||
|
|
||||||
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new CatchPerformanceCalculator(this, beatmap, score);
|
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new CatchPerformanceCalculator(this, beatmap, score);
|
||||||
|
|
||||||
|
@ -9,17 +9,26 @@ using osu.Game.Rulesets.Catch.Objects;
|
|||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Mods
|
namespace osu.Game.Rulesets.Catch.Mods
|
||||||
{
|
{
|
||||||
public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset<CatchHitObject>
|
public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset<CatchHitObject>, IApplicableToPlayer
|
||||||
{
|
{
|
||||||
public override string Description => @"Use the mouse to control the catcher.";
|
public override string Description => @"Use the mouse to control the catcher.";
|
||||||
|
|
||||||
|
private DrawableRuleset<CatchHitObject> drawableRuleset;
|
||||||
|
|
||||||
public void ApplyToDrawableRuleset(DrawableRuleset<CatchHitObject> drawableRuleset)
|
public void ApplyToDrawableRuleset(DrawableRuleset<CatchHitObject> drawableRuleset)
|
||||||
{
|
{
|
||||||
drawableRuleset.Cursor.Add(new MouseInputHelper((CatchPlayfield)drawableRuleset.Playfield));
|
this.drawableRuleset = drawableRuleset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyToPlayer(Player player)
|
||||||
|
{
|
||||||
|
if (!drawableRuleset.HasReplayLoaded.Value)
|
||||||
|
drawableRuleset.Cursor.Add(new MouseInputHelper((CatchPlayfield)drawableRuleset.Playfield));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MouseInputHelper : Drawable, IKeyBindingHandler<CatchAction>, IRequireHighFrequencyMousePosition
|
private class MouseInputHelper : Drawable, IKeyBindingHandler<CatchAction>, IRequireHighFrequencyMousePosition
|
||||||
|
@ -70,6 +70,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
|||||||
|
|
||||||
public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale;
|
public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale;
|
||||||
|
|
||||||
|
protected override float SamplePlaybackPosition => HitObject.X;
|
||||||
|
|
||||||
protected DrawableCatchHitObject(CatchHitObject hitObject)
|
protected DrawableCatchHitObject(CatchHitObject hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
BorderColour = Color4.Red,
|
BorderColour = Catcher.DEFAULT_HYPER_DASH_COLOUR,
|
||||||
BorderThickness = 12f * RADIUS_ADJUST,
|
BorderThickness = 12f * RADIUS_ADJUST,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -77,7 +78,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
|||||||
Alpha = 0.3f,
|
Alpha = 0.3f,
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.Red,
|
Colour = Catcher.DEFAULT_HYPER_DASH_COLOUR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -65,6 +65,15 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
|||||||
|
|
||||||
public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample);
|
public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample);
|
||||||
|
|
||||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => source.GetConfig<TLookup, TValue>(lookup);
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
|
{
|
||||||
|
switch (lookup)
|
||||||
|
{
|
||||||
|
case CatchSkinColour colour:
|
||||||
|
return source.GetConfig<SkinCustomColourLookup, TValue>(new SkinCustomColourLookup(colour));
|
||||||
|
}
|
||||||
|
|
||||||
|
return source.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
osu.Game.Rulesets.Catch/Skinning/CatchSkinColour.cs
Normal file
23
osu.Game.Rulesets.Catch/Skinning/CatchSkinColour.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.Rulesets.Catch.Skinning
|
||||||
|
{
|
||||||
|
public enum CatchSkinColour
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The colour to be used for the catcher while in hyper-dashing state.
|
||||||
|
/// </summary>
|
||||||
|
HyperDash,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The colour to be used for fruits that grant the catcher the ability to hyper-dash.
|
||||||
|
/// </summary>
|
||||||
|
HyperDashFruit,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The colour to be used for the "exploding" catcher sprite on beginning of hyper-dashing.
|
||||||
|
/// </summary>
|
||||||
|
HyperDashAfterImage,
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -55,14 +56,16 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
|||||||
{
|
{
|
||||||
var hyperDash = new Sprite
|
var hyperDash = new Sprite
|
||||||
{
|
{
|
||||||
Texture = skin.GetTexture(lookupName),
|
|
||||||
Colour = Color4.Red,
|
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
Depth = 1,
|
Depth = 1,
|
||||||
Alpha = 0.7f,
|
Alpha = 0.7f,
|
||||||
Scale = new Vector2(1.2f)
|
Scale = new Vector2(1.2f),
|
||||||
|
Texture = skin.GetTexture(lookupName),
|
||||||
|
Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashFruit)?.Value ??
|
||||||
|
skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ??
|
||||||
|
Catcher.DEFAULT_HYPER_DASH_COLOUR,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddInternal(hyperDash);
|
AddInternal(hyperDash);
|
||||||
|
@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
||||||
{
|
{
|
||||||
|
public static readonly Color4 DEFAULT_HYPER_DASH_COLOUR = Color4.Red;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether we are hyper-dashing or not.
|
/// Whether we are hyper-dashing or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -384,7 +386,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentCatcher.Show();
|
currentCatcher.Show();
|
||||||
(currentCatcher.Drawable as IAnimation)?.GotoFrame(0);
|
(currentCatcher.Drawable as IFramedAnimation)?.GotoFrame(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void beginTrail()
|
private void beginTrail()
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public CatcherSprite(CatcherAnimationState state)
|
public CatcherSprite(CatcherAnimationState state)
|
||||||
: base(new CatchSkinComponent(componentFromState(state)), _ =>
|
: base(new CatchSkinComponent(componentFromState(state)), _ =>
|
||||||
new DefaultCatcherSprite(state), confineMode: ConfineMode.ScaleDownToFit)
|
new DefaultCatcherSprite(state), confineMode: ConfineMode.ScaleToFit)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.None;
|
RelativeSizeAxes = Axes.None;
|
||||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||||
|
50
osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs
Normal file
50
osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ManiaColumnTypeTest
|
||||||
|
{
|
||||||
|
[TestCase(new[]
|
||||||
|
{
|
||||||
|
ColumnType.Special
|
||||||
|
}, 1)]
|
||||||
|
[TestCase(new[]
|
||||||
|
{
|
||||||
|
ColumnType.Odd,
|
||||||
|
ColumnType.Even,
|
||||||
|
ColumnType.Even,
|
||||||
|
ColumnType.Odd
|
||||||
|
}, 4)]
|
||||||
|
[TestCase(new[]
|
||||||
|
{
|
||||||
|
ColumnType.Odd,
|
||||||
|
ColumnType.Even,
|
||||||
|
ColumnType.Odd,
|
||||||
|
ColumnType.Special,
|
||||||
|
ColumnType.Odd,
|
||||||
|
ColumnType.Even,
|
||||||
|
ColumnType.Odd
|
||||||
|
}, 7)]
|
||||||
|
public void Test(IEnumerable<ColumnType> expected, int columns)
|
||||||
|
{
|
||||||
|
var definition = new StageDefinition
|
||||||
|
{
|
||||||
|
Columns = columns
|
||||||
|
};
|
||||||
|
var results = getResults(definition);
|
||||||
|
Assert.AreEqual(expected, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<ColumnType> getResults(StageDefinition definition)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < definition.Columns; i++)
|
||||||
|
yield return definition.GetTypeOfColumn(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs
Normal file
51
osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// 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.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mania.Replays;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ManiaLegacyReplayTest
|
||||||
|
{
|
||||||
|
[TestCase(ManiaAction.Key1)]
|
||||||
|
[TestCase(ManiaAction.Key1, ManiaAction.Key2)]
|
||||||
|
[TestCase(ManiaAction.Special1)]
|
||||||
|
[TestCase(ManiaAction.Key8)]
|
||||||
|
public void TestEncodeDecodeSingleStage(params ManiaAction[] actions)
|
||||||
|
{
|
||||||
|
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 9 });
|
||||||
|
|
||||||
|
var frame = new ManiaReplayFrame(0, actions);
|
||||||
|
var legacyFrame = frame.ToLegacy(beatmap);
|
||||||
|
|
||||||
|
var decodedFrame = new ManiaReplayFrame();
|
||||||
|
decodedFrame.FromLegacy(legacyFrame, beatmap);
|
||||||
|
|
||||||
|
Assert.That(decodedFrame.Actions, Is.EquivalentTo(frame.Actions));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(ManiaAction.Key1)]
|
||||||
|
[TestCase(ManiaAction.Key1, ManiaAction.Key2)]
|
||||||
|
[TestCase(ManiaAction.Special1)]
|
||||||
|
[TestCase(ManiaAction.Special2)]
|
||||||
|
[TestCase(ManiaAction.Special1, ManiaAction.Special2)]
|
||||||
|
[TestCase(ManiaAction.Special1, ManiaAction.Key5)]
|
||||||
|
[TestCase(ManiaAction.Key8)]
|
||||||
|
public void TestEncodeDecodeDualStage(params ManiaAction[] actions)
|
||||||
|
{
|
||||||
|
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 5 });
|
||||||
|
beatmap.Stages.Add(new StageDefinition { Columns = 5 });
|
||||||
|
|
||||||
|
var frame = new ManiaReplayFrame(0, actions);
|
||||||
|
var legacyFrame = frame.ToLegacy(beatmap);
|
||||||
|
|
||||||
|
var decodedFrame = new ManiaReplayFrame();
|
||||||
|
decodedFrame.FromLegacy(legacyFrame, beatmap);
|
||||||
|
|
||||||
|
Assert.That(decodedFrame.Actions, Is.EquivalentTo(frame.Actions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,6 @@
|
|||||||
|
[General]
|
||||||
|
Version: 2.4
|
||||||
|
|
||||||
|
[Mania]
|
||||||
|
Keys: 4
|
||||||
|
ColumnLineWidth: 3,1,3,1,1
|
@ -4,6 +4,7 @@
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -26,7 +27,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
this.column = new Column(column)
|
this.column = new Column(column)
|
||||||
{
|
{
|
||||||
Action = { Value = action },
|
Action = { Value = action },
|
||||||
AccentColour = Color4.Orange
|
AccentColour = Color4.Orange,
|
||||||
|
ColumnType = column % 2 == 0 ? ColumnType.Even : ColumnType.Odd
|
||||||
};
|
};
|
||||||
|
|
||||||
InternalChild = content = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
InternalChild = content = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Timing;
|
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -37,10 +36,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
Child = new ScrollingHitObjectContainer
|
Child = new ScrollingHitObjectContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Clock = new FramedClock(new StopwatchClock()),
|
|
||||||
}.With(c =>
|
}.With(c =>
|
||||||
{
|
{
|
||||||
c.Add(CreateHitObject().With(h => h.AccentColour.Value = Color4.Orange));
|
c.Add(CreateHitObject().With(h =>
|
||||||
|
{
|
||||||
|
h.HitObject.StartTime = START_TIME;
|
||||||
|
h.AccentColour.Value = Color4.Orange;
|
||||||
|
}));
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
new ColumnTestContainer(1, ManiaAction.Key2)
|
new ColumnTestContainer(1, ManiaAction.Key2)
|
||||||
@ -52,10 +54,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
Child = new ScrollingHitObjectContainer
|
Child = new ScrollingHitObjectContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Clock = new FramedClock(new StopwatchClock()),
|
|
||||||
}.With(c =>
|
}.With(c =>
|
||||||
{
|
{
|
||||||
c.Add(CreateHitObject().With(h => h.AccentColour.Value = Color4.Orange));
|
c.Add(CreateHitObject().With(h =>
|
||||||
|
{
|
||||||
|
h.HitObject.StartTime = START_TIME;
|
||||||
|
h.AccentColour.Value = Color4.Orange;
|
||||||
|
}));
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
// 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 System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osu.Game.Rulesets.UI.Scrolling.Algorithms;
|
using osu.Game.Rulesets.UI.Scrolling.Algorithms;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
@ -19,9 +22,20 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ManiaSkinnableTestScene : SkinnableTestScene
|
public abstract class ManiaSkinnableTestScene : SkinnableTestScene
|
||||||
{
|
{
|
||||||
|
protected const double START_TIME = 1000000000;
|
||||||
|
|
||||||
[Cached(Type = typeof(IScrollingInfo))]
|
[Cached(Type = typeof(IScrollingInfo))]
|
||||||
private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo();
|
private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo();
|
||||||
|
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(ManiaRuleset),
|
||||||
|
typeof(ManiaLegacySkinTransformer),
|
||||||
|
typeof(ManiaSettingsSubsection)
|
||||||
|
};
|
||||||
|
|
||||||
|
protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset();
|
||||||
|
|
||||||
protected ManiaSkinnableTestScene()
|
protected ManiaSkinnableTestScene()
|
||||||
{
|
{
|
||||||
scrollingInfo.Direction.Value = ScrollingDirection.Down;
|
scrollingInfo.Direction.Value = ScrollingDirection.Down;
|
||||||
@ -52,7 +66,26 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
|
|
||||||
IBindable<ScrollingDirection> IScrollingInfo.Direction => Direction;
|
IBindable<ScrollingDirection> IScrollingInfo.Direction => Direction;
|
||||||
IBindable<double> IScrollingInfo.TimeRange { get; } = new Bindable<double>(1000);
|
IBindable<double> IScrollingInfo.TimeRange { get; } = new Bindable<double>(1000);
|
||||||
IScrollAlgorithm IScrollingInfo.Algorithm { get; } = new ConstantScrollAlgorithm();
|
IScrollAlgorithm IScrollingInfo.Algorithm { get; } = new ZeroScrollAlgorithm();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ZeroScrollAlgorithm : IScrollAlgorithm
|
||||||
|
{
|
||||||
|
public double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength)
|
||||||
|
=> double.MinValue;
|
||||||
|
|
||||||
|
public float GetLength(double startTime, double endTime, double timeRange, float scrollLength)
|
||||||
|
=> scrollLength;
|
||||||
|
|
||||||
|
public float PositionAt(double time, double currentTime, double timeRange, float scrollLength)
|
||||||
|
=> (float)((time - START_TIME) / timeRange) * scrollLength;
|
||||||
|
|
||||||
|
public double TimeAt(float position, double currentTime, double timeRange, float scrollLength)
|
||||||
|
=> 0;
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Width = 0.5f,
|
Width = 0.5f,
|
||||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground())
|
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground, 0), _ => new DefaultColumnBackground())
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Width = 0.5f,
|
Width = 0.5f,
|
||||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground())
|
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground, 1), _ => new DefaultColumnBackground())
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
// 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.Components;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
public class TestSceneColumnHitObjectArea : ManiaSkinnableTestScene
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
SetContents(() => new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(0.8f),
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new ColumnTestContainer(0, ManiaAction.Key1)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Width = 0.5f,
|
||||||
|
Child = new ColumnHitObjectArea(0, new HitObjectContainer())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new ColumnTestContainer(1, ManiaAction.Key2)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Width = 0.5f,
|
||||||
|
Child = new ColumnHitObjectArea(1, new HitObjectContainer())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,11 +10,10 @@ using osu.Game.Rulesets.Judgements;
|
|||||||
using osu.Game.Rulesets.Mania.UI;
|
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.Skinning
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
{
|
{
|
||||||
public class TestSceneDrawableJudgement : SkinnableTestScene
|
public class TestSceneDrawableJudgement : ManiaSkinnableTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestSceneHitExplosion : ManiaSkinnableTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(DrawableNote),
|
||||||
|
typeof(DrawableManiaHitObject),
|
||||||
|
};
|
||||||
|
|
||||||
|
public TestSceneHitExplosion()
|
||||||
|
{
|
||||||
|
int runcount = 0;
|
||||||
|
|
||||||
|
AddRepeatStep("explode", () =>
|
||||||
|
{
|
||||||
|
runcount++;
|
||||||
|
|
||||||
|
if (runcount % 15 > 12)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CreatedDrawables.OfType<Container>().ForEach(c =>
|
||||||
|
{
|
||||||
|
c.Add(new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HitExplosion, 0),
|
||||||
|
_ => new DefaultHitExplosion((runcount / 15) % 2 == 0 ? new Color4(94, 0, 57, 255) : new Color4(6, 84, 0, 255), runcount % 6 != 0)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
SetContents(() => new ColumnTestContainer(0, ManiaAction.Key1)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativePositionAxes = Axes.Y,
|
||||||
|
Y = -0.25f,
|
||||||
|
Size = new Vector2(Column.COLUMN_WIDTH, DefaultNotePiece.NOTE_HEIGHT),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs
Normal file
35
osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
public class TestSceneHoldNote : ManiaHitObjectTestScene
|
||||||
|
{
|
||||||
|
public TestSceneHoldNote()
|
||||||
|
{
|
||||||
|
AddToggleStep("toggle hitting", v =>
|
||||||
|
{
|
||||||
|
foreach (var holdNote in CreatedDrawables.SelectMany(d => d.ChildrenOfType<DrawableHoldNote>()))
|
||||||
|
{
|
||||||
|
((Bindable<bool>)holdNote.IsHitting).Value = v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DrawableManiaHitObject CreateHitObject()
|
||||||
|
{
|
||||||
|
var note = new HoldNote { Duration = 1000 };
|
||||||
|
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||||
|
|
||||||
|
return new DrawableHoldNote(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneKeyArea.cs
Normal file
58
osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneKeyArea.cs
Normal file
@ -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 System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning;
|
||||||
|
using osu.Game.Rulesets.Mania.UI.Components;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
public class TestSceneKeyArea : ManiaSkinnableTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(DefaultKeyArea),
|
||||||
|
typeof(LegacyKeyArea)
|
||||||
|
};
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
SetContents(() => new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(0.8f),
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new ColumnTestContainer(0, ManiaAction.Key1)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Width = 0.5f,
|
||||||
|
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea, 0), _ => new DefaultKeyArea())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new ColumnTestContainer(1, ManiaAction.Key2)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Width = 0.5f,
|
||||||
|
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea, 1), _ => new DefaultKeyArea())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs
Normal file
21
osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
public class TestSceneNote : ManiaHitObjectTestScene
|
||||||
|
{
|
||||||
|
protected override DrawableManiaHitObject CreateHitObject()
|
||||||
|
{
|
||||||
|
var note = new Note();
|
||||||
|
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||||
|
|
||||||
|
return new DrawableNote(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs
Normal file
52
osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
public class TestScenePlayfield : ManiaSkinnableTestScene
|
||||||
|
{
|
||||||
|
private List<StageDefinition> stageDefinitions = new List<StageDefinition>();
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSingleStage()
|
||||||
|
{
|
||||||
|
AddStep("create stage", () =>
|
||||||
|
{
|
||||||
|
stageDefinitions = new List<StageDefinition>
|
||||||
|
{
|
||||||
|
new StageDefinition { Columns = 2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
SetContents(() => new ManiaPlayfield(stageDefinitions));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDualStages()
|
||||||
|
{
|
||||||
|
AddStep("create stage", () =>
|
||||||
|
{
|
||||||
|
stageDefinitions = new List<StageDefinition>
|
||||||
|
{
|
||||||
|
new StageDefinition { Columns = 2 },
|
||||||
|
new StageDefinition { Columns = 2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
SetContents(() => new ManiaPlayfield(stageDefinitions));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IBeatmap CreateBeatmapForSkinProvider()
|
||||||
|
{
|
||||||
|
var maniaBeatmap = (ManiaBeatmap)base.CreateBeatmapForSkinProvider();
|
||||||
|
maniaBeatmap.Stages = stageDefinitions;
|
||||||
|
return maniaBeatmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs
Normal file
27
osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
public class TestSceneStage : ManiaSkinnableTestScene
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
SetContents(() =>
|
||||||
|
{
|
||||||
|
ManiaAction normalAction = ManiaAction.Key1;
|
||||||
|
ManiaAction specialAction = ManiaAction.Special1;
|
||||||
|
|
||||||
|
return new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
||||||
|
{
|
||||||
|
Child = new Stage(0, new StageDefinition { Columns = 4 }, ref normalAction, ref specialAction)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning;
|
||||||
|
using osu.Game.Rulesets.Mania.UI.Components;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
public class TestSceneStageBackground : ManiaSkinnableTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||||
|
{
|
||||||
|
typeof(DefaultStageBackground),
|
||||||
|
typeof(LegacyStageBackground),
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
SetContents(() => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground), _ => new DefaultStageBackground())
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Width = 0.5f,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
|
{
|
||||||
|
public class TestSceneStageForeground : ManiaSkinnableTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||||
|
{
|
||||||
|
typeof(LegacyStageForeground),
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
SetContents(() => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground), _ => null)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Width = 0.5f,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,8 +28,9 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
typeof(Column),
|
typeof(Column),
|
||||||
typeof(ColumnBackground),
|
typeof(ColumnBackground),
|
||||||
typeof(ColumnKeyArea),
|
typeof(ColumnHitObjectArea),
|
||||||
typeof(ColumnHitObjectArea)
|
typeof(DefaultKeyArea),
|
||||||
|
typeof(DefaultHitTarget)
|
||||||
};
|
};
|
||||||
|
|
||||||
[Cached(typeof(IReadOnlyList<Mod>))]
|
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||||
|
@ -1,62 +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.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class TestSceneHitExplosion : OsuTestScene
|
|
||||||
{
|
|
||||||
private ScrollingTestContainer scrolling;
|
|
||||||
|
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
|
||||||
{
|
|
||||||
typeof(DrawableNote),
|
|
||||||
typeof(DrawableManiaHitObject),
|
|
||||||
};
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
Child = scrolling = new ScrollingTestContainer(ScrollingDirection.Down)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativePositionAxes = Axes.Y,
|
|
||||||
Y = -0.25f,
|
|
||||||
Size = new Vector2(Column.COLUMN_WIDTH, NotePiece.NOTE_HEIGHT),
|
|
||||||
};
|
|
||||||
|
|
||||||
int runcount = 0;
|
|
||||||
|
|
||||||
AddRepeatStep("explode", () =>
|
|
||||||
{
|
|
||||||
runcount++;
|
|
||||||
|
|
||||||
if (runcount % 15 > 12)
|
|
||||||
return;
|
|
||||||
|
|
||||||
scrolling.AddRange(new Drawable[]
|
|
||||||
{
|
|
||||||
new HitExplosion((runcount / 15) % 2 == 0 ? new Color4(94, 0, 57, 255) : new Color4(6, 84, 0, 255), runcount % 6 != 0)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,7 +27,6 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
private const double time_after_tail = 5250;
|
private const double time_after_tail = 5250;
|
||||||
|
|
||||||
private List<JudgementResult> judgementResults;
|
private List<JudgementResult> judgementResults;
|
||||||
private bool allJudgedFired;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// -----[ ]-----
|
/// -----[ ]-----
|
||||||
@ -283,20 +282,15 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
if (currentPlayer == p) judgementResults.Add(result);
|
if (currentPlayer == p) judgementResults.Add(result);
|
||||||
};
|
};
|
||||||
p.ScoreProcessor.AllJudged += () =>
|
|
||||||
{
|
|
||||||
if (currentPlayer == p) allJudgedFired = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
LoadScreen(currentPlayer = p);
|
LoadScreen(currentPlayer = p);
|
||||||
allJudgedFired = false;
|
|
||||||
judgementResults = new List<JudgementResult>();
|
judgementResults = new List<JudgementResult>();
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0);
|
AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0);
|
||||||
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
|
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
|
||||||
AddUntilStep("Wait for all judged", () => allJudgedFired);
|
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ScoreAccessibleReplayPlayer : ReplayPlayer
|
private class ScoreAccessibleReplayPlayer : ReplayPlayer
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
[Cached(typeof(IReadOnlyList<Mod>))]
|
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||||
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
|
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
|
||||||
|
|
||||||
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
private readonly List<Stage> stages = new List<Stage>();
|
||||||
|
|
||||||
private FillFlowContainer<ScrollingTestContainer> fill;
|
private FillFlowContainer<ScrollingTestContainer> fill;
|
||||||
|
|
||||||
@ -81,9 +81,9 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
AddAssert("check bar anchors", () => barsInStageAreAnchored(stages[1], Anchor.TopCentre));
|
AddAssert("check bar anchors", () => barsInStageAreAnchored(stages[1], Anchor.TopCentre));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool notesInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.Columns.SelectMany(c => c.AllHitObjects).All(o => o.Anchor == anchor);
|
private bool notesInStageAreAnchored(Stage stage, Anchor anchor) => stage.Columns.SelectMany(c => c.AllHitObjects).All(o => o.Anchor == anchor);
|
||||||
|
|
||||||
private bool barsInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.AllHitObjects.Where(obj => obj is DrawableBarLine).All(o => o.Anchor == anchor);
|
private bool barsInStageAreAnchored(Stage stage, Anchor anchor) => stage.AllHitObjects.Where(obj => obj is DrawableBarLine).All(o => o.Anchor == anchor);
|
||||||
|
|
||||||
private void createNote()
|
private void createNote()
|
||||||
{
|
{
|
||||||
@ -133,7 +133,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
var specialAction = ManiaAction.Special1;
|
var specialAction = ManiaAction.Special1;
|
||||||
|
|
||||||
var stage = new ManiaStage(0, new StageDefinition { Columns = 2 }, ref action, ref specialAction);
|
var stage = new Stage(0, new StageDefinition { Columns = 2 }, ref action, ref specialAction);
|
||||||
stages.Add(stage);
|
stages.Add(stage);
|
||||||
|
|
||||||
return new ScrollingTestContainer(direction)
|
return new ScrollingTestContainer(direction)
|
||||||
|
12
osu.Game.Rulesets.Mania/Beatmaps/ColumnType.cs
Normal file
12
osu.Game.Rulesets.Mania/Beatmaps/ColumnType.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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.Beatmaps
|
||||||
|
{
|
||||||
|
public enum ColumnType
|
||||||
|
{
|
||||||
|
Even,
|
||||||
|
Odd,
|
||||||
|
Special
|
||||||
|
}
|
||||||
|
}
|
@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
{
|
{
|
||||||
TargetColumns = (int)Math.Max(1, roundedCircleSize);
|
TargetColumns = (int)Math.Max(1, roundedCircleSize);
|
||||||
|
|
||||||
if (TargetColumns >= 10)
|
if (TargetColumns > ManiaRuleset.MAX_STAGE_KEYS)
|
||||||
{
|
{
|
||||||
TargetColumns /= 2;
|
TargetColumns /= 2;
|
||||||
Dual = true;
|
Dual = true;
|
||||||
|
@ -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.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Beatmaps
|
namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||||
@ -21,5 +22,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
/// <param name="column">The 0-based column index.</param>
|
/// <param name="column">The 0-based column index.</param>
|
||||||
/// <returns>Whether the column is a special column.</returns>
|
/// <returns>Whether the column is a special column.</returns>
|
||||||
public bool IsSpecialColumn(int column) => Columns % 2 == 1 && column == Columns / 2;
|
public bool IsSpecialColumn(int column) => Columns % 2 == 1 && column == Columns / 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the type of column given a column index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="column">The 0-based column index.</param>
|
||||||
|
/// <returns>The type of the column.</returns>
|
||||||
|
public ColumnType GetTypeOfColumn(int column)
|
||||||
|
{
|
||||||
|
if (IsSpecialColumn(column))
|
||||||
|
return ColumnType.Special;
|
||||||
|
|
||||||
|
int distanceToEdge = Math.Min(column, (Columns - 1) - column);
|
||||||
|
return distanceToEdge % 2 == 0 ? ColumnType.Odd : ColumnType.Even;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.Configuration.Tracking;
|
using osu.Framework.Configuration.Tracking;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets.Configuration;
|
using osu.Game.Rulesets.Configuration;
|
||||||
@ -19,13 +20,14 @@ namespace osu.Game.Rulesets.Mania.Configuration
|
|||||||
{
|
{
|
||||||
base.InitialiseDefaults();
|
base.InitialiseDefaults();
|
||||||
|
|
||||||
Set(ManiaRulesetSetting.ScrollTime, 1500.0, 50.0, 5000.0, 50.0);
|
Set(ManiaRulesetSetting.ScrollTime, 1500.0, DrawableManiaRuleset.MIN_TIME_RANGE, DrawableManiaRuleset.MAX_TIME_RANGE, 1);
|
||||||
Set(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down);
|
Set(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override TrackedSettings CreateTrackedSettings() => new TrackedSettings
|
public override TrackedSettings CreateTrackedSettings() => new TrackedSettings
|
||||||
{
|
{
|
||||||
new TrackedSetting<double>(ManiaRulesetSetting.ScrollTime, v => new SettingDescription(v, "Scroll Time", $"{v}ms"))
|
new TrackedSetting<double>(ManiaRulesetSetting.ScrollTime,
|
||||||
|
v => new SettingDescription(v, "Scroll Speed", $"{(int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / v)} ({v}ms)"))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs
Normal file
64
osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania
|
||||||
|
{
|
||||||
|
public class DualStageVariantGenerator
|
||||||
|
{
|
||||||
|
private readonly int singleStageVariant;
|
||||||
|
private readonly InputKey[] stage1LeftKeys;
|
||||||
|
private readonly InputKey[] stage1RightKeys;
|
||||||
|
private readonly InputKey[] stage2LeftKeys;
|
||||||
|
private readonly InputKey[] stage2RightKeys;
|
||||||
|
|
||||||
|
public DualStageVariantGenerator(int singleStageVariant)
|
||||||
|
{
|
||||||
|
this.singleStageVariant = singleStageVariant;
|
||||||
|
|
||||||
|
// 10K is special because it expands towards the centre of the keyboard (VM/BN), rather than towards the edges of the keyboard.
|
||||||
|
if (singleStageVariant == 10)
|
||||||
|
{
|
||||||
|
stage1LeftKeys = new[] { InputKey.Q, InputKey.W, InputKey.E, InputKey.R, InputKey.V };
|
||||||
|
stage1RightKeys = new[] { InputKey.M, InputKey.I, InputKey.O, InputKey.P, InputKey.BracketLeft };
|
||||||
|
|
||||||
|
stage2LeftKeys = new[] { InputKey.S, InputKey.D, InputKey.F, InputKey.G, InputKey.B };
|
||||||
|
stage2RightKeys = new[] { InputKey.N, InputKey.J, InputKey.K, InputKey.L, InputKey.Semicolon };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stage1LeftKeys = new[] { InputKey.Q, InputKey.W, InputKey.E, InputKey.R };
|
||||||
|
stage1RightKeys = new[] { InputKey.I, InputKey.O, InputKey.P, InputKey.BracketLeft };
|
||||||
|
|
||||||
|
stage2LeftKeys = new[] { InputKey.S, InputKey.D, InputKey.F, InputKey.G };
|
||||||
|
stage2RightKeys = new[] { InputKey.J, InputKey.K, InputKey.L, InputKey.Semicolon };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<KeyBinding> GenerateMappings()
|
||||||
|
{
|
||||||
|
var stage1Bindings = new VariantMappingGenerator
|
||||||
|
{
|
||||||
|
LeftKeys = stage1LeftKeys,
|
||||||
|
RightKeys = stage1RightKeys,
|
||||||
|
SpecialKey = InputKey.V,
|
||||||
|
SpecialAction = ManiaAction.Special1,
|
||||||
|
NormalActionStart = ManiaAction.Key1
|
||||||
|
}.GenerateKeyBindingsFor(singleStageVariant, out var nextNormal);
|
||||||
|
|
||||||
|
var stage2Bindings = new VariantMappingGenerator
|
||||||
|
{
|
||||||
|
LeftKeys = stage2LeftKeys,
|
||||||
|
RightKeys = stage2RightKeys,
|
||||||
|
SpecialKey = InputKey.B,
|
||||||
|
SpecialAction = ManiaAction.Special2,
|
||||||
|
NormalActionStart = nextNormal
|
||||||
|
}.GenerateKeyBindingsFor(singleStageVariant, out _);
|
||||||
|
|
||||||
|
return stage1Bindings.Concat(stage2Bindings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,12 @@ using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components
|
namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components
|
||||||
{
|
{
|
||||||
public class EditBodyPiece : BodyPiece
|
public class EditBodyPiece : DefaultBodyPiece
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
AccentColour = colours.Yellow;
|
AccentColour.Value = colours.Yellow;
|
||||||
|
|
||||||
Background.Alpha = 0.5f;
|
Background.Alpha = 0.5f;
|
||||||
Foreground.Alpha = 0;
|
Foreground.Alpha = 0;
|
||||||
|
@ -12,12 +12,12 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components
|
|||||||
{
|
{
|
||||||
public EditNotePiece()
|
public EditNotePiece()
|
||||||
{
|
{
|
||||||
Height = NotePiece.NOTE_HEIGHT;
|
Height = DefaultNotePiece.NOTE_HEIGHT;
|
||||||
|
|
||||||
CornerRadius = 5;
|
CornerRadius = 5;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
|
|
||||||
InternalChild = new NotePiece();
|
InternalChild = new DefaultNotePiece();
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Primitives;
|
using osu.Framework.Graphics.Primitives;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||||
{
|
{
|
||||||
@ -42,11 +42,19 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
|||||||
{
|
{
|
||||||
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.Start),
|
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.Start),
|
||||||
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.End),
|
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.End),
|
||||||
new BodyPiece
|
new Container
|
||||||
{
|
{
|
||||||
AccentColour = Color4.Transparent,
|
RelativeSizeAxes = Axes.Both,
|
||||||
BorderColour = colours.Yellow
|
Masking = true,
|
||||||
},
|
BorderThickness = 1,
|
||||||
|
BorderColour = colours.Yellow,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,11 +122,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
|||||||
switch (scrollingInfo.Direction.Value)
|
switch (scrollingInfo.Direction.Value)
|
||||||
{
|
{
|
||||||
case ScrollingDirection.Up:
|
case ScrollingDirection.Up:
|
||||||
mousePosition.Y -= NotePiece.NOTE_HEIGHT / 2;
|
mousePosition.Y -= DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ScrollingDirection.Down:
|
case ScrollingDirection.Down:
|
||||||
mousePosition.Y += NotePiece.NOTE_HEIGHT / 2;
|
mousePosition.Y += DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,11 +143,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
|||||||
switch (scrollingInfo.Direction.Value)
|
switch (scrollingInfo.Direction.Value)
|
||||||
{
|
{
|
||||||
case ScrollingDirection.Up:
|
case ScrollingDirection.Up:
|
||||||
hitObjectPosition.Y += NotePiece.NOTE_HEIGHT / 2;
|
hitObjectPosition.Y += DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ScrollingDirection.Down:
|
case ScrollingDirection.Down:
|
||||||
hitObjectPosition.Y -= NotePiece.NOTE_HEIGHT / 2;
|
hitObjectPosition.Y -= DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,5 +78,11 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
|
|
||||||
[Description("Key 18")]
|
[Description("Key 18")]
|
||||||
Key18,
|
Key18,
|
||||||
|
|
||||||
|
[Description("Key 19")]
|
||||||
|
Key19,
|
||||||
|
|
||||||
|
[Description("Key 20")]
|
||||||
|
Key20,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,11 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
{
|
{
|
||||||
public class ManiaRuleset : Ruleset, ILegacyRuleset
|
public class ManiaRuleset : Ruleset, ILegacyRuleset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum number of supported keys in a single stage.
|
||||||
|
/// </summary>
|
||||||
|
public const int MAX_STAGE_KEYS = 10;
|
||||||
|
|
||||||
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => new DrawableManiaRuleset(this, beatmap, mods);
|
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => new DrawableManiaRuleset(this, beatmap, mods);
|
||||||
|
|
||||||
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor();
|
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor();
|
||||||
@ -47,7 +52,7 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
|
|
||||||
public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this);
|
public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this);
|
||||||
|
|
||||||
public override ISkin CreateLegacySkinProvider(ISkinSource source) => new ManiaLegacySkinTransformer(source);
|
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new ManiaLegacySkinTransformer(source, beatmap);
|
||||||
|
|
||||||
public override IEnumerable<Mod> ConvertFromLegacyMods(LegacyMods mods)
|
public override IEnumerable<Mod> ConvertFromLegacyMods(LegacyMods mods)
|
||||||
{
|
{
|
||||||
@ -202,6 +207,7 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
new ManiaModKey7(),
|
new ManiaModKey7(),
|
||||||
new ManiaModKey8(),
|
new ManiaModKey8(),
|
||||||
new ManiaModKey9(),
|
new ManiaModKey9(),
|
||||||
|
new ManiaModKey10(),
|
||||||
new ManiaModKey1(),
|
new ManiaModKey1(),
|
||||||
new ManiaModKey2(),
|
new ManiaModKey2(),
|
||||||
new ManiaModKey3()),
|
new ManiaModKey3()),
|
||||||
@ -250,9 +256,9 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
for (int i = 1; i <= 9; i++)
|
for (int i = 1; i <= MAX_STAGE_KEYS; i++)
|
||||||
yield return (int)PlayfieldType.Single + i;
|
yield return (int)PlayfieldType.Single + i;
|
||||||
for (int i = 2; i <= 18; i += 2)
|
for (int i = 2; i <= MAX_STAGE_KEYS * 2; i += 2)
|
||||||
yield return (int)PlayfieldType.Dual + i;
|
yield return (int)PlayfieldType.Dual + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,73 +268,10 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
switch (getPlayfieldType(variant))
|
switch (getPlayfieldType(variant))
|
||||||
{
|
{
|
||||||
case PlayfieldType.Single:
|
case PlayfieldType.Single:
|
||||||
return new VariantMappingGenerator
|
return new SingleStageVariantGenerator(variant).GenerateMappings();
|
||||||
{
|
|
||||||
LeftKeys = new[]
|
|
||||||
{
|
|
||||||
InputKey.A,
|
|
||||||
InputKey.S,
|
|
||||||
InputKey.D,
|
|
||||||
InputKey.F
|
|
||||||
},
|
|
||||||
RightKeys = new[]
|
|
||||||
{
|
|
||||||
InputKey.J,
|
|
||||||
InputKey.K,
|
|
||||||
InputKey.L,
|
|
||||||
InputKey.Semicolon
|
|
||||||
},
|
|
||||||
SpecialKey = InputKey.Space,
|
|
||||||
SpecialAction = ManiaAction.Special1,
|
|
||||||
NormalActionStart = ManiaAction.Key1,
|
|
||||||
}.GenerateKeyBindingsFor(variant, out _);
|
|
||||||
|
|
||||||
case PlayfieldType.Dual:
|
case PlayfieldType.Dual:
|
||||||
int keys = getDualStageKeyCount(variant);
|
return new DualStageVariantGenerator(getDualStageKeyCount(variant)).GenerateMappings();
|
||||||
|
|
||||||
var stage1Bindings = new VariantMappingGenerator
|
|
||||||
{
|
|
||||||
LeftKeys = new[]
|
|
||||||
{
|
|
||||||
InputKey.Q,
|
|
||||||
InputKey.W,
|
|
||||||
InputKey.E,
|
|
||||||
InputKey.R,
|
|
||||||
},
|
|
||||||
RightKeys = new[]
|
|
||||||
{
|
|
||||||
InputKey.X,
|
|
||||||
InputKey.C,
|
|
||||||
InputKey.V,
|
|
||||||
InputKey.B
|
|
||||||
},
|
|
||||||
SpecialKey = InputKey.S,
|
|
||||||
SpecialAction = ManiaAction.Special1,
|
|
||||||
NormalActionStart = ManiaAction.Key1
|
|
||||||
}.GenerateKeyBindingsFor(keys, out var nextNormal);
|
|
||||||
|
|
||||||
var stage2Bindings = new VariantMappingGenerator
|
|
||||||
{
|
|
||||||
LeftKeys = new[]
|
|
||||||
{
|
|
||||||
InputKey.Number7,
|
|
||||||
InputKey.Number8,
|
|
||||||
InputKey.Number9,
|
|
||||||
InputKey.Number0
|
|
||||||
},
|
|
||||||
RightKeys = new[]
|
|
||||||
{
|
|
||||||
InputKey.K,
|
|
||||||
InputKey.L,
|
|
||||||
InputKey.Semicolon,
|
|
||||||
InputKey.Quote
|
|
||||||
},
|
|
||||||
SpecialKey = InputKey.I,
|
|
||||||
SpecialAction = ManiaAction.Special2,
|
|
||||||
NormalActionStart = nextNormal
|
|
||||||
}.GenerateKeyBindingsFor(keys, out _);
|
|
||||||
|
|
||||||
return stage1Bindings.Concat(stage2Bindings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.Empty<KeyBinding>();
|
return Array.Empty<KeyBinding>();
|
||||||
@ -364,59 +307,6 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
{
|
{
|
||||||
return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderByDescending(i => i).First(v => variant >= v);
|
return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderByDescending(i => i).First(v => variant >= v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VariantMappingGenerator
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// All the <see cref="InputKey"/>s available to the left hand.
|
|
||||||
/// </summary>
|
|
||||||
public InputKey[] LeftKeys;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// All the <see cref="InputKey"/>s available to the right hand.
|
|
||||||
/// </summary>
|
|
||||||
public InputKey[] RightKeys;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="InputKey"/> for the special key.
|
|
||||||
/// </summary>
|
|
||||||
public InputKey SpecialKey;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="ManiaAction"/> at which the normal columns should begin.
|
|
||||||
/// </summary>
|
|
||||||
public ManiaAction NormalActionStart;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="ManiaAction"/> for the special column.
|
|
||||||
/// </summary>
|
|
||||||
public ManiaAction SpecialAction;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generates a list of <see cref="KeyBinding"/>s for a specific number of columns.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="columns">The number of columns that need to be bound.</param>
|
|
||||||
/// <param name="nextNormalAction">The next <see cref="ManiaAction"/> to use for normal columns.</param>
|
|
||||||
/// <returns>The keybindings.</returns>
|
|
||||||
public IEnumerable<KeyBinding> GenerateKeyBindingsFor(int columns, out ManiaAction nextNormalAction)
|
|
||||||
{
|
|
||||||
ManiaAction currentNormalAction = NormalActionStart;
|
|
||||||
|
|
||||||
var bindings = new List<KeyBinding>();
|
|
||||||
|
|
||||||
for (int i = LeftKeys.Length - columns / 2; i < LeftKeys.Length; i++)
|
|
||||||
bindings.Add(new KeyBinding(LeftKeys[i], currentNormalAction++));
|
|
||||||
|
|
||||||
if (columns % 2 == 1)
|
|
||||||
bindings.Add(new KeyBinding(SpecialKey, SpecialAction));
|
|
||||||
|
|
||||||
for (int i = 0; i < columns / 2; i++)
|
|
||||||
bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++));
|
|
||||||
|
|
||||||
nextNormalAction = currentNormalAction;
|
|
||||||
return bindings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PlayfieldType
|
public enum PlayfieldType
|
||||||
|
@ -1,15 +1,28 @@
|
|||||||
// 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.Mania.UI;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania
|
namespace osu.Game.Rulesets.Mania
|
||||||
{
|
{
|
||||||
public class ManiaSkinComponent : GameplaySkinComponent<ManiaSkinComponents>
|
public class ManiaSkinComponent : GameplaySkinComponent<ManiaSkinComponents>
|
||||||
{
|
{
|
||||||
public ManiaSkinComponent(ManiaSkinComponents component)
|
/// <summary>
|
||||||
|
/// The intended <see cref="Column"/> index for this component.
|
||||||
|
/// May be null if the component does not exist in a <see cref="Column"/>.
|
||||||
|
/// </summary>
|
||||||
|
public readonly int? TargetColumn;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="ManiaSkinComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="component">The component.</param>
|
||||||
|
/// <param name="targetColumn">The intended <see cref="Column"/> index for this component. May be null if the component does not exist in a <see cref="Column"/>.</param>
|
||||||
|
public ManiaSkinComponent(ManiaSkinComponents component, int? targetColumn = null)
|
||||||
: base(component)
|
: base(component)
|
||||||
{
|
{
|
||||||
|
TargetColumn = targetColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME;
|
protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME;
|
||||||
@ -19,6 +32,15 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
|
|
||||||
public enum ManiaSkinComponents
|
public enum ManiaSkinComponents
|
||||||
{
|
{
|
||||||
ColumnBackground
|
ColumnBackground,
|
||||||
|
HitTarget,
|
||||||
|
KeyArea,
|
||||||
|
Note,
|
||||||
|
HoldNoteHead,
|
||||||
|
HoldNoteTail,
|
||||||
|
HoldNoteBody,
|
||||||
|
HitExplosion,
|
||||||
|
StageBackground,
|
||||||
|
StageForeground,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs
Normal file
13
osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// 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.Mods
|
||||||
|
{
|
||||||
|
public class ManiaModKey10 : ManiaKeyMod
|
||||||
|
{
|
||||||
|
public override int KeyCount => 10;
|
||||||
|
public override string Name => "Ten Keys";
|
||||||
|
public override string Acronym => "10K";
|
||||||
|
public override string Description => @"Play with ten keys.";
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ using osu.Game.Rulesets.Objects;
|
|||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||||
{
|
{
|
||||||
@ -20,6 +21,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
{
|
{
|
||||||
public override bool DisplayResult => false;
|
public override bool DisplayResult => false;
|
||||||
|
|
||||||
|
public IBindable<bool> IsHitting => isHitting;
|
||||||
|
|
||||||
|
private readonly Bindable<bool> isHitting = new Bindable<bool>();
|
||||||
|
|
||||||
public DrawableHoldNoteHead Head => headContainer.Child;
|
public DrawableHoldNoteHead Head => headContainer.Child;
|
||||||
public DrawableHoldNoteTail Tail => tailContainer.Child;
|
public DrawableHoldNoteTail Tail => tailContainer.Child;
|
||||||
|
|
||||||
@ -27,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
private readonly Container<DrawableHoldNoteTail> tailContainer;
|
private readonly Container<DrawableHoldNoteTail> tailContainer;
|
||||||
private readonly Container<DrawableHoldNoteTick> tickContainer;
|
private readonly Container<DrawableHoldNoteTick> tickContainer;
|
||||||
|
|
||||||
private readonly BodyPiece bodyPiece;
|
private readonly Drawable bodyPiece;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
|
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
|
||||||
@ -44,18 +49,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
|
|
||||||
AddRangeInternal(new Drawable[]
|
AddRangeInternal(new[]
|
||||||
{
|
{
|
||||||
bodyPiece = new BodyPiece { RelativeSizeAxes = Axes.X },
|
bodyPiece = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HoldNoteBody, hitObject.Column), _ => new DefaultBodyPiece())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X
|
||||||
|
},
|
||||||
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
|
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
|
||||||
headContainer = new Container<DrawableHoldNoteHead> { RelativeSizeAxes = Axes.Both },
|
headContainer = new Container<DrawableHoldNoteHead> { RelativeSizeAxes = Axes.Both },
|
||||||
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
|
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
|
||||||
});
|
});
|
||||||
|
|
||||||
AccentColour.BindValueChanged(colour =>
|
|
||||||
{
|
|
||||||
bodyPiece.AccentColour = colour.NewValue;
|
|
||||||
}, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
||||||
@ -168,7 +171,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
HoldStartTime = Time.Current;
|
HoldStartTime = Time.Current;
|
||||||
bodyPiece.Hitting = true;
|
isHitting.Value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnReleased(ManiaAction action)
|
public void OnReleased(ManiaAction action)
|
||||||
@ -194,7 +197,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
private void endHold()
|
private void endHold()
|
||||||
{
|
{
|
||||||
HoldStartTime = null;
|
HoldStartTime = null;
|
||||||
bodyPiece.Hitting = false;
|
isHitting.Value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DrawableHoldNoteHead : DrawableNote
|
public class DrawableHoldNoteHead : DrawableNote
|
||||||
{
|
{
|
||||||
|
protected override ManiaSkinComponents Component => ManiaSkinComponents.HoldNoteHead;
|
||||||
|
|
||||||
public DrawableHoldNoteHead(DrawableHoldNote holdNote)
|
public DrawableHoldNoteHead(DrawableHoldNote holdNote)
|
||||||
: base(holdNote.HitObject.Head)
|
: base(holdNote.HitObject.Head)
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const double release_window_lenience = 1.5;
|
private const double release_window_lenience = 1.5;
|
||||||
|
|
||||||
|
protected override ManiaSkinComponents Component => ManiaSkinComponents.HoldNoteTail;
|
||||||
|
|
||||||
private readonly DrawableHoldNote holdNote;
|
private readonly DrawableHoldNote holdNote;
|
||||||
|
|
||||||
public DrawableHoldNoteTail(DrawableHoldNote holdNote)
|
public DrawableHoldNoteTail(DrawableHoldNote holdNote)
|
||||||
|
@ -7,6 +7,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||||
{
|
{
|
||||||
@ -24,6 +25,20 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
|
|
||||||
protected readonly IBindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
protected readonly IBindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
private ManiaPlayfield playfield { get; set; }
|
||||||
|
|
||||||
|
protected override float SamplePlaybackPosition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (playfield == null)
|
||||||
|
return base.SamplePlaybackPosition;
|
||||||
|
|
||||||
|
return (float)HitObject.Column / playfield.TotalColumns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected DrawableManiaHitObject(ManiaHitObject hitObject)
|
protected DrawableManiaHitObject(ManiaHitObject hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
{
|
{
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||||
{
|
{
|
||||||
@ -18,7 +17,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DrawableNote : DrawableManiaHitObject<Note>, IKeyBindingHandler<ManiaAction>
|
public class DrawableNote : DrawableManiaHitObject<Note>, IKeyBindingHandler<ManiaAction>
|
||||||
{
|
{
|
||||||
private readonly NotePiece headPiece;
|
protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note;
|
||||||
|
|
||||||
|
private readonly Drawable headPiece;
|
||||||
|
|
||||||
public DrawableNote(Note hitObject)
|
public DrawableNote(Note hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
@ -26,22 +27,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
AutoSizeAxes = Axes.Y;
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
CornerRadius = 5;
|
AddInternal(headPiece = new SkinnableDrawable(new ManiaSkinComponent(Component, hitObject.Column), _ => new DefaultNotePiece())
|
||||||
Masking = true;
|
|
||||||
|
|
||||||
AddInternal(headPiece = new NotePiece());
|
|
||||||
|
|
||||||
AccentColour.BindValueChanged(colour =>
|
|
||||||
{
|
{
|
||||||
headPiece.AccentColour = colour.NewValue;
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y
|
||||||
EdgeEffect = new EdgeEffectParameters
|
});
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Colour = colour.NewValue.Lighten(1f).Opacity(0.2f),
|
|
||||||
Radius = 10,
|
|
||||||
};
|
|
||||||
}, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e)
|
protected override void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e)
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// 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 System;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -9,26 +12,38 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Effects;
|
using osu.Framework.Graphics.Effects;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Layout;
|
using osu.Framework.Layout;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents length-wise portion of a hold note.
|
/// Represents length-wise portion of a hold note.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BodyPiece : Container, IHasAccentColour
|
public class DefaultBodyPiece : CompositeDrawable
|
||||||
{
|
{
|
||||||
private readonly Container subtractionLayer;
|
protected readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
protected readonly Drawable Background;
|
private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
|
||||||
protected readonly BufferedContainer Foreground;
|
private readonly IBindable<bool> isHitting = new Bindable<bool>();
|
||||||
private readonly BufferedContainer subtractionContainer;
|
|
||||||
|
|
||||||
public BodyPiece()
|
protected Drawable Background { get; private set; }
|
||||||
|
protected BufferedContainer Foreground { get; private set; }
|
||||||
|
|
||||||
|
private BufferedContainer subtractionContainer;
|
||||||
|
private Container subtractionLayer;
|
||||||
|
|
||||||
|
public DefaultBodyPiece()
|
||||||
{
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
Blending = BlendingParameters.Additive;
|
Blending = BlendingParameters.Additive;
|
||||||
|
|
||||||
Children = new[]
|
AddLayout(subtractionCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load([CanBeNull] DrawableHitObject drawableObject)
|
||||||
|
{
|
||||||
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
Background = new Box { RelativeSizeAxes = Axes.Both },
|
Background = new Box { RelativeSizeAxes = Axes.Both },
|
||||||
Foreground = new BufferedContainer
|
Foreground = new BufferedContainer
|
||||||
@ -66,43 +81,37 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AddLayout(subtractionCache);
|
if (drawableObject != null)
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
updateAccentColour();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get => accentColour;
|
|
||||||
set
|
|
||||||
{
|
{
|
||||||
if (accentColour == value)
|
var holdNote = (DrawableHoldNote)drawableObject;
|
||||||
return;
|
|
||||||
|
|
||||||
accentColour = value;
|
AccentColour.BindTo(drawableObject.AccentColour);
|
||||||
|
isHitting.BindTo(holdNote.IsHitting);
|
||||||
updateAccentColour();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AccentColour.BindValueChanged(onAccentChanged, true);
|
||||||
|
isHitting.BindValueChanged(_ => onAccentChanged(new ValueChangedEvent<Color4>(AccentColour.Value, AccentColour.Value)), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Hitting
|
private void onAccentChanged(ValueChangedEvent<Color4> accent)
|
||||||
{
|
{
|
||||||
get => hitting;
|
Foreground.Colour = accent.NewValue.Opacity(0.5f);
|
||||||
set
|
Background.Colour = accent.NewValue.Opacity(0.7f);
|
||||||
{
|
|
||||||
hitting = value;
|
|
||||||
updateAccentColour();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
|
const float animation_length = 50;
|
||||||
|
|
||||||
|
Foreground.ClearTransforms(false, nameof(Foreground.Colour));
|
||||||
|
|
||||||
|
if (isHitting.Value)
|
||||||
|
{
|
||||||
|
// wait for the next sync point
|
||||||
|
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
||||||
|
using (Foreground.BeginDelayedSequence(synchronisedOffset))
|
||||||
|
Foreground.FadeColour(accent.NewValue.Lighten(0.2f), animation_length).Then().FadeColour(Foreground.Colour, animation_length).Loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
subtractionCache.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
@ -125,30 +134,5 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
subtractionCache.Validate();
|
subtractionCache.Validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool hitting;
|
|
||||||
|
|
||||||
private void updateAccentColour()
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Foreground.Colour = AccentColour.Opacity(0.5f);
|
|
||||||
Background.Colour = AccentColour.Opacity(0.7f);
|
|
||||||
|
|
||||||
const float animation_length = 50;
|
|
||||||
|
|
||||||
Foreground.ClearTransforms(false, nameof(Foreground.Colour));
|
|
||||||
|
|
||||||
if (hitting)
|
|
||||||
{
|
|
||||||
// wait for the next sync point
|
|
||||||
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
|
||||||
using (Foreground.BeginDelayedSequence(synchronisedOffset))
|
|
||||||
Foreground.FadeColour(AccentColour.Lighten(0.2f), animation_length).Then().FadeColour(Foreground.Colour, animation_length).Loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
subtractionCache.Invalidate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
// 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 JetBrains.Annotations;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Effects;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the static hit markers of notes.
|
||||||
|
/// </summary>
|
||||||
|
internal class DefaultNotePiece : CompositeDrawable
|
||||||
|
{
|
||||||
|
public const float NOTE_HEIGHT = 12;
|
||||||
|
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
|
private readonly Box colouredBox;
|
||||||
|
|
||||||
|
public DefaultNotePiece()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Height = NOTE_HEIGHT;
|
||||||
|
|
||||||
|
CornerRadius = 5;
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
colouredBox = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = NOTE_HEIGHT / 2,
|
||||||
|
Alpha = 0.1f
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load([NotNull] IScrollingInfo scrollingInfo, [CanBeNull] DrawableHitObject drawableObject)
|
||||||
|
{
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
|
if (drawableObject != null)
|
||||||
|
{
|
||||||
|
accentColour.BindTo(drawableObject.AccentColour);
|
||||||
|
accentColour.BindValueChanged(onAccentChanged, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
colouredBox.Anchor = colouredBox.Origin = direction.NewValue == ScrollingDirection.Up
|
||||||
|
? Anchor.TopCentre
|
||||||
|
: Anchor.BottomCentre;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onAccentChanged(ValueChangedEvent<Color4> accent)
|
||||||
|
{
|
||||||
|
colouredBox.Colour = accent.NewValue.Lighten(0.9f);
|
||||||
|
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = accent.NewValue.Lighten(1f).Opacity(0.2f),
|
||||||
|
Radius = 10,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,73 +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.
|
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents the static hit markers of notes.
|
|
||||||
/// </summary>
|
|
||||||
internal class NotePiece : Container, IHasAccentColour
|
|
||||||
{
|
|
||||||
public const float NOTE_HEIGHT = 12;
|
|
||||||
|
|
||||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
|
||||||
|
|
||||||
private readonly Box colouredBox;
|
|
||||||
|
|
||||||
public NotePiece()
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X;
|
|
||||||
Height = NOTE_HEIGHT;
|
|
||||||
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both
|
|
||||||
},
|
|
||||||
colouredBox = new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = NOTE_HEIGHT / 2,
|
|
||||||
Alpha = 0.1f
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(IScrollingInfo scrollingInfo)
|
|
||||||
{
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
|
||||||
direction.BindValueChanged(dir =>
|
|
||||||
{
|
|
||||||
colouredBox.Anchor = colouredBox.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get => accentColour;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (accentColour == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
accentColour = value;
|
|
||||||
|
|
||||||
colouredBox.Colour = AccentColour.Lighten(0.9f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +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 System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Replays.Legacy;
|
using osu.Game.Replays.Legacy;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Replays
|
|||||||
|
|
||||||
while (activeColumns > 0)
|
while (activeColumns > 0)
|
||||||
{
|
{
|
||||||
var isSpecial = maniaBeatmap.Stages.First().IsSpecialColumn(counter);
|
bool isSpecial = isColumnAtIndexSpecial(maniaBeatmap, counter);
|
||||||
|
|
||||||
if ((activeColumns & 1) > 0)
|
if ((activeColumns & 1) > 0)
|
||||||
Actions.Add(isSpecial ? specialAction : normalAction);
|
Actions.Add(isSpecial ? specialAction : normalAction);
|
||||||
@ -58,33 +58,87 @@ namespace osu.Game.Rulesets.Mania.Replays
|
|||||||
|
|
||||||
int keys = 0;
|
int keys = 0;
|
||||||
|
|
||||||
var specialColumns = new List<int>();
|
|
||||||
|
|
||||||
for (int i = 0; i < maniaBeatmap.TotalColumns; i++)
|
|
||||||
{
|
|
||||||
if (maniaBeatmap.Stages.First().IsSpecialColumn(i))
|
|
||||||
specialColumns.Add(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var action in Actions)
|
foreach (var action in Actions)
|
||||||
{
|
{
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case ManiaAction.Special1:
|
case ManiaAction.Special1:
|
||||||
keys |= 1 << specialColumns[0];
|
keys |= 1 << getSpecialColumnIndex(maniaBeatmap, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ManiaAction.Special2:
|
case ManiaAction.Special2:
|
||||||
keys |= 1 << specialColumns[1];
|
keys |= 1 << getSpecialColumnIndex(maniaBeatmap, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
keys |= 1 << (action - ManiaAction.Key1);
|
// the index in lazer, which doesn't include special keys.
|
||||||
|
int nonSpecialKeyIndex = action - ManiaAction.Key1;
|
||||||
|
|
||||||
|
// the index inclusive of special keys.
|
||||||
|
int overallIndex = 0;
|
||||||
|
|
||||||
|
// iterate to find the index including special keys.
|
||||||
|
for (; overallIndex < maniaBeatmap.TotalColumns; overallIndex++)
|
||||||
|
{
|
||||||
|
// skip over special columns.
|
||||||
|
if (isColumnAtIndexSpecial(maniaBeatmap, overallIndex))
|
||||||
|
continue;
|
||||||
|
// found a non-special column to use.
|
||||||
|
if (nonSpecialKeyIndex == 0)
|
||||||
|
break;
|
||||||
|
// found a non-special column but not ours.
|
||||||
|
nonSpecialKeyIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys |= 1 << overallIndex;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LegacyReplayFrame(Time, keys, null, ReplayButtonState.None);
|
return new LegacyReplayFrame(Time, keys, null, ReplayButtonState.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find the overall index (across all stages) for a specified special key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="maniaBeatmap">The beatmap.</param>
|
||||||
|
/// <param name="specialOffset">The special key offset (0 is S1).</param>
|
||||||
|
/// <returns>The overall index for the special column.</returns>
|
||||||
|
private int getSpecialColumnIndex(ManiaBeatmap maniaBeatmap, int specialOffset)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < maniaBeatmap.TotalColumns; i++)
|
||||||
|
{
|
||||||
|
if (isColumnAtIndexSpecial(maniaBeatmap, i))
|
||||||
|
{
|
||||||
|
if (specialOffset == 0)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
specialOffset--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentException("Special key index is too high.", nameof(specialOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether the column at an overall index (across all stages) is a special column.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmap">The beatmap.</param>
|
||||||
|
/// <param name="index">The overall index to check.</param>
|
||||||
|
private bool isColumnAtIndexSpecial(ManiaBeatmap beatmap, int index)
|
||||||
|
{
|
||||||
|
foreach (var stage in beatmap.Stages)
|
||||||
|
{
|
||||||
|
if (index >= stage.Columns)
|
||||||
|
{
|
||||||
|
index -= stage.Columns;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stage.IsSpecialColumn(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentException("Column index is too high.", nameof(index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
41
osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs
Normal file
41
osu.Game.Rulesets.Mania/SingleStageVariantGenerator.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.Collections.Generic;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania
|
||||||
|
{
|
||||||
|
public class SingleStageVariantGenerator
|
||||||
|
{
|
||||||
|
private readonly int variant;
|
||||||
|
private readonly InputKey[] leftKeys;
|
||||||
|
private readonly InputKey[] rightKeys;
|
||||||
|
|
||||||
|
public SingleStageVariantGenerator(int variant)
|
||||||
|
{
|
||||||
|
this.variant = variant;
|
||||||
|
|
||||||
|
// 10K is special because it expands towards the centre of the keyboard (V/N), rather than towards the edges of the keyboard.
|
||||||
|
if (variant == 10)
|
||||||
|
{
|
||||||
|
leftKeys = new[] { InputKey.A, InputKey.S, InputKey.D, InputKey.F, InputKey.V };
|
||||||
|
rightKeys = new[] { InputKey.N, InputKey.J, InputKey.K, InputKey.L, InputKey.Semicolon };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
leftKeys = new[] { InputKey.A, InputKey.S, InputKey.D, InputKey.F };
|
||||||
|
rightKeys = new[] { InputKey.J, InputKey.K, InputKey.L, InputKey.Semicolon };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<KeyBinding> GenerateMappings() => new VariantMappingGenerator
|
||||||
|
{
|
||||||
|
LeftKeys = leftKeys,
|
||||||
|
RightKeys = rightKeys,
|
||||||
|
SpecialKey = InputKey.Space,
|
||||||
|
SpecialAction = ManiaAction.Special1,
|
||||||
|
NormalActionStart = ManiaAction.Key1,
|
||||||
|
}.GenerateKeyBindingsFor(variant, out _);
|
||||||
|
}
|
||||||
|
}
|
86
osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs
Normal file
86
osu.Game.Rulesets.Mania/Skinning/LegacyBodyPiece.cs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Animations;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyBodyPiece : LegacyManiaColumnElement
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
private readonly IBindable<bool> isHitting = new Bindable<bool>();
|
||||||
|
|
||||||
|
private Drawable sprite;
|
||||||
|
|
||||||
|
public LegacyBodyPiece()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo, DrawableHitObject drawableObject)
|
||||||
|
{
|
||||||
|
string imageName = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.HoldNoteBodyImage)?.Value
|
||||||
|
?? $"mania-note{FallbackColumnIndex}L";
|
||||||
|
|
||||||
|
sprite = skin.GetAnimation(imageName, true, true).With(d =>
|
||||||
|
{
|
||||||
|
if (d == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (d is TextureAnimation animation)
|
||||||
|
animation.IsPlaying = false;
|
||||||
|
|
||||||
|
d.Anchor = Anchor.TopCentre;
|
||||||
|
d.RelativeSizeAxes = Axes.Both;
|
||||||
|
d.Size = Vector2.One;
|
||||||
|
d.FillMode = FillMode.Stretch;
|
||||||
|
// Todo: Wrap
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sprite != null)
|
||||||
|
InternalChild = sprite;
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
|
var holdNote = (DrawableHoldNote)drawableObject;
|
||||||
|
isHitting.BindTo(holdNote.IsHitting);
|
||||||
|
isHitting.BindValueChanged(onIsHittingChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onIsHittingChanged(ValueChangedEvent<bool> isHitting)
|
||||||
|
{
|
||||||
|
if (!(sprite is TextureAnimation animation))
|
||||||
|
return;
|
||||||
|
|
||||||
|
animation.GotoFrame(0);
|
||||||
|
animation.IsPlaying = isHitting.NewValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (sprite == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
sprite.Origin = Anchor.BottomCentre;
|
||||||
|
sprite.Scale = new Vector2(1, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprite.Origin = Anchor.TopCentre;
|
||||||
|
sprite.Scale = Vector2.One;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -16,53 +15,60 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Skinning
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
{
|
{
|
||||||
public class LegacyColumnBackground : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
public class LegacyColumnBackground : LegacyManiaColumnElement, IKeyBindingHandler<ManiaAction>
|
||||||
{
|
{
|
||||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
private readonly bool isLastColumn;
|
||||||
|
|
||||||
private Container lightContainer;
|
private Container lightContainer;
|
||||||
private Sprite light;
|
private Sprite light;
|
||||||
|
|
||||||
[Resolved]
|
public LegacyColumnBackground(bool isLastColumn)
|
||||||
private Column column { get; set; }
|
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
|
||||||
private ManiaStage stage { get; set; }
|
|
||||||
|
|
||||||
public LegacyColumnBackground()
|
|
||||||
{
|
{
|
||||||
|
this.isLastColumn = isLastColumn;
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||||
{
|
{
|
||||||
string lightImage = skin.GetConfig<LegacyManiaSkinConfigurationLookup, string>(
|
string lightImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.LightImage, 0)?.Value
|
||||||
new LegacyManiaSkinConfigurationLookup(stage?.Columns.Count ?? 4, LegacyManiaSkinConfigurationLookups.LightImage, 0))?.Value
|
|
||||||
?? "mania-stage-light";
|
?? "mania-stage-light";
|
||||||
|
|
||||||
float leftLineWidth = skin.GetConfig<LegacyManiaSkinConfigurationLookup, float>(
|
float leftLineWidth = GetManiaSkinConfig<float>(skin, LegacyManiaSkinConfigurationLookups.LeftLineWidth)
|
||||||
new LegacyManiaSkinConfigurationLookup(stage?.Columns.Count ?? 4, LegacyManiaSkinConfigurationLookups.LeftLineWidth, column.Index))
|
?.Value ?? 1;
|
||||||
?.Value ?? 1;
|
float rightLineWidth = GetManiaSkinConfig<float>(skin, LegacyManiaSkinConfigurationLookups.RightLineWidth)
|
||||||
float rightLineWidth = skin.GetConfig<LegacyManiaSkinConfigurationLookup, float>(
|
?.Value ?? 1;
|
||||||
new LegacyManiaSkinConfigurationLookup(stage?.Columns.Count ?? 4, LegacyManiaSkinConfigurationLookups.RightLineWidth, column.Index))
|
|
||||||
?.Value ?? 1;
|
|
||||||
|
|
||||||
bool hasLeftLine = leftLineWidth > 0;
|
bool hasLeftLine = leftLineWidth > 0;
|
||||||
bool hasRightLine = rightLineWidth > 0 && skin.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.4m
|
bool hasRightLine = rightLineWidth > 0 && skin.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.4m
|
||||||
|| stage == null || column.Index == stage.Columns.Count - 1;
|
|| isLastColumn;
|
||||||
|
|
||||||
|
float lightPosition = GetManiaSkinConfig<float>(skin, LegacyManiaSkinConfigurationLookups.LightPosition)?.Value
|
||||||
|
?? 0;
|
||||||
|
|
||||||
|
Color4 lineColour = GetManiaSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.ColumnLineColour)?.Value
|
||||||
|
?? Color4.White;
|
||||||
|
|
||||||
|
Color4 backgroundColour = GetManiaSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour)?.Value
|
||||||
|
?? Color4.Black;
|
||||||
|
|
||||||
|
Color4 lightColour = GetManiaSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.ColumnLightColour)?.Value
|
||||||
|
?? Color4.White;
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.Black
|
Colour = backgroundColour
|
||||||
},
|
},
|
||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Width = leftLineWidth,
|
Width = leftLineWidth,
|
||||||
|
Scale = new Vector2(0.740f, 1),
|
||||||
|
Colour = lineColour,
|
||||||
Alpha = hasLeftLine ? 1 : 0
|
Alpha = hasLeftLine ? 1 : 0
|
||||||
},
|
},
|
||||||
new Box
|
new Box
|
||||||
@ -71,16 +77,20 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Width = rightLineWidth,
|
Width = rightLineWidth,
|
||||||
|
Scale = new Vector2(0.740f, 1),
|
||||||
|
Colour = lineColour,
|
||||||
Alpha = hasRightLine ? 1 : 0
|
Alpha = hasRightLine ? 1 : 0
|
||||||
},
|
},
|
||||||
lightContainer = new Container
|
lightContainer = new Container
|
||||||
{
|
{
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Bottom = lightPosition },
|
||||||
Child = light = new Sprite
|
Child = light = new Sprite
|
||||||
{
|
{
|
||||||
Anchor = Anchor.BottomCentre,
|
Anchor = Anchor.BottomCentre,
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
|
Colour = lightColour,
|
||||||
Texture = skin.GetTexture(lightImage),
|
Texture = skin.GetTexture(lightImage),
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Width = 1,
|
Width = 1,
|
||||||
@ -109,7 +119,7 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
|
|
||||||
public bool OnPressed(ManiaAction action)
|
public bool OnPressed(ManiaAction action)
|
||||||
{
|
{
|
||||||
if (action == column.Action.Value)
|
if (action == Column.Action.Value)
|
||||||
{
|
{
|
||||||
light.FadeIn();
|
light.FadeIn();
|
||||||
light.ScaleTo(Vector2.One);
|
light.ScaleTo(Vector2.One);
|
||||||
@ -123,7 +133,7 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
// Todo: Should be 400 * 100 / CurrentBPM
|
// Todo: Should be 400 * 100 / CurrentBPM
|
||||||
const double animation_length = 250;
|
const double animation_length = 250;
|
||||||
|
|
||||||
if (action == column.Action.Value)
|
if (action == Column.Action.Value)
|
||||||
{
|
{
|
||||||
light.FadeTo(0, animation_length);
|
light.FadeTo(0, animation_length);
|
||||||
light.ScaleTo(new Vector2(1, 0), animation_length);
|
light.ScaleTo(new Vector2(1, 0), animation_length);
|
||||||
|
73
osu.Game.Rulesets.Mania/Skinning/LegacyHitExplosion.cs
Normal file
73
osu.Game.Rulesets.Mania/Skinning/LegacyHitExplosion.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Animations;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyHitExplosion : LegacyManiaColumnElement
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Drawable explosion;
|
||||||
|
|
||||||
|
public LegacyHitExplosion()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
string imageName = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.ExplosionImage)?.Value
|
||||||
|
?? "lightingN";
|
||||||
|
|
||||||
|
float explosionScale = GetManiaSkinConfig<float>(skin, LegacyManiaSkinConfigurationLookups.ExplosionScale)?.Value
|
||||||
|
?? 1;
|
||||||
|
|
||||||
|
// Create a temporary animation to retrieve the number of frames, in an effort to calculate the intended frame length.
|
||||||
|
// This animation is discarded and re-queried with the appropriate frame length afterwards.
|
||||||
|
var tmp = skin.GetAnimation(imageName, true, false);
|
||||||
|
double frameLength = 0;
|
||||||
|
if (tmp is IFramedAnimation tmpAnimation && tmpAnimation.FrameCount > 0)
|
||||||
|
frameLength = Math.Max(1000 / 60.0, 170.0 / tmpAnimation.FrameCount);
|
||||||
|
|
||||||
|
explosion = skin.GetAnimation(imageName, true, false, frameLength: frameLength).With(d =>
|
||||||
|
{
|
||||||
|
if (d == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d.Origin = Anchor.Centre;
|
||||||
|
d.Blending = BlendingParameters.Additive;
|
||||||
|
d.Scale = new Vector2(explosionScale);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (explosion != null)
|
||||||
|
InternalChild = explosion;
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (explosion != null)
|
||||||
|
explosion.Anchor = direction.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
explosion?.FadeInFromZero(80)
|
||||||
|
.Then().FadeOut(120);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
osu.Game.Rulesets.Mania/Skinning/LegacyHitTarget.cs
Normal file
83
osu.Game.Rulesets.Mania/Skinning/LegacyHitTarget.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyHitTarget : LegacyManiaElement
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Container directionContainer;
|
||||||
|
|
||||||
|
public LegacyHitTarget()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
string targetImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.HitTargetImage)?.Value
|
||||||
|
?? "mania-stage-hint";
|
||||||
|
|
||||||
|
bool showJudgementLine = GetManiaSkinConfig<bool>(skin, LegacyManiaSkinConfigurationLookups.ShowJudgementLine)?.Value
|
||||||
|
?? true;
|
||||||
|
|
||||||
|
Color4 lineColour = GetManiaSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.JudgementLineColour)?.Value
|
||||||
|
?? Color4.White;
|
||||||
|
|
||||||
|
InternalChild = directionContainer = new Container
|
||||||
|
{
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture(targetImage),
|
||||||
|
Scale = new Vector2(1, 0.9f * 1.6025f),
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Width = 1
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 1,
|
||||||
|
Colour = lineColour,
|
||||||
|
Alpha = showJudgementLine ? 0.9f : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
directionContainer.Anchor = Anchor.TopLeft;
|
||||||
|
directionContainer.Scale = new Vector2(1, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
directionContainer.Anchor = Anchor.BottomLeft;
|
||||||
|
directionContainer.Scale = Vector2.One;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
osu.Game.Rulesets.Mania/Skinning/LegacyHoldNoteHeadPiece.cs
Normal file
18
osu.Game.Rulesets.Mania/Skinning/LegacyHoldNoteHeadPiece.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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.Graphics.Textures;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyHoldNoteHeadPiece : LegacyNotePiece
|
||||||
|
{
|
||||||
|
protected override Texture GetTexture(ISkinSource skin)
|
||||||
|
{
|
||||||
|
// TODO: Should fallback to the head from default legacy skin instead of note.
|
||||||
|
return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
|
||||||
|
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
osu.Game.Rulesets.Mania/Skinning/LegacyHoldNoteTailPiece.cs
Normal file
29
osu.Game.Rulesets.Mania/Skinning/LegacyHoldNoteTailPiece.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyHoldNoteTailPiece : LegacyNotePiece
|
||||||
|
{
|
||||||
|
protected override void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
// Invert the direction
|
||||||
|
base.OnDirectionChanged(direction.NewValue == ScrollingDirection.Up
|
||||||
|
? new ValueChangedEvent<ScrollingDirection>(ScrollingDirection.Down, ScrollingDirection.Down)
|
||||||
|
: new ValueChangedEvent<ScrollingDirection>(ScrollingDirection.Up, ScrollingDirection.Up));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Texture GetTexture(ISkinSource skin)
|
||||||
|
{
|
||||||
|
// TODO: Should fallback to the head from default legacy skin instead of note.
|
||||||
|
return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteTailImage)
|
||||||
|
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
|
||||||
|
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
106
osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs
Normal file
106
osu.Game.Rulesets.Mania/Skinning/LegacyKeyArea.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyKeyArea : LegacyManiaColumnElement, IKeyBindingHandler<ManiaAction>
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Container directionContainer;
|
||||||
|
private Sprite upSprite;
|
||||||
|
private Sprite downSprite;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Column column { get; set; }
|
||||||
|
|
||||||
|
public LegacyKeyArea()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
string upImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.KeyImage)?.Value
|
||||||
|
?? $"mania-key{FallbackColumnIndex}";
|
||||||
|
|
||||||
|
string downImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.KeyImageDown)?.Value
|
||||||
|
?? $"mania-key{FallbackColumnIndex}D";
|
||||||
|
|
||||||
|
InternalChild = directionContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
upSprite = new Sprite
|
||||||
|
{
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
Texture = skin.GetTexture(upImage),
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Width = 1
|
||||||
|
},
|
||||||
|
downSprite = new Sprite
|
||||||
|
{
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
Texture = skin.GetTexture(downImage),
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Width = 1,
|
||||||
|
Alpha = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
directionContainer.Anchor = directionContainer.Origin = Anchor.TopCentre;
|
||||||
|
upSprite.Anchor = downSprite.Anchor = Anchor.TopCentre;
|
||||||
|
upSprite.Scale = downSprite.Scale = new Vector2(1, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
directionContainer.Anchor = directionContainer.Origin = Anchor.BottomCentre;
|
||||||
|
upSprite.Anchor = downSprite.Anchor = Anchor.BottomCentre;
|
||||||
|
upSprite.Scale = downSprite.Scale = Vector2.One;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnPressed(ManiaAction action)
|
||||||
|
{
|
||||||
|
if (action == column.Action.Value)
|
||||||
|
{
|
||||||
|
upSprite.FadeTo(0);
|
||||||
|
downSprite.FadeTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(ManiaAction action)
|
||||||
|
{
|
||||||
|
if (action == column.Action.Value)
|
||||||
|
{
|
||||||
|
upSprite.FadeTo(1);
|
||||||
|
downSprite.FadeTo(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,41 +1,48 @@
|
|||||||
// 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 JetBrains.Annotations;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Skinning
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="CompositeDrawable"/> which is placed somewhere within a <see cref="Column"/>.
|
/// A <see cref="CompositeDrawable"/> which is placed somewhere within a <see cref="Column"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LegacyManiaColumnElement : CompositeDrawable
|
public class LegacyManiaColumnElement : LegacyManiaElement
|
||||||
{
|
{
|
||||||
[Resolved(CanBeNull = true)]
|
|
||||||
[CanBeNull]
|
|
||||||
protected ManiaStage Stage { get; private set; }
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
protected Column Column { get; private set; }
|
protected Column Column { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The column index to use for texture lookups, in the case of no user-provided configuration.
|
/// The column type identifier to use for texture lookups, in the case of no user-provided configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected int FallbackColumnIndex { get; private set; }
|
protected string FallbackColumnIndex { get; private set; }
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
if (Stage == null)
|
switch (Column.ColumnType)
|
||||||
FallbackColumnIndex = Column.Index % 2 + 1;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
int dist = Math.Min(Column.Index, Stage.Columns.Count - Column.Index - 1);
|
case ColumnType.Special:
|
||||||
FallbackColumnIndex = dist % 2 + 1;
|
FallbackColumnIndex = "S";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ColumnType.Odd:
|
||||||
|
FallbackColumnIndex = "1";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ColumnType.Even:
|
||||||
|
FallbackColumnIndex = "2";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override IBindable<T> GetManiaSkinConfig<T>(ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null)
|
||||||
|
=> base.GetManiaSkinConfig<T>(skin, lookup, index ?? Column.Index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
osu.Game.Rulesets.Mania/Skinning/LegacyManiaElement.cs
Normal file
25
osu.Game.Rulesets.Mania/Skinning/LegacyManiaElement.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A mania legacy skin element.
|
||||||
|
/// </summary>
|
||||||
|
public class LegacyManiaElement : CompositeDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve a per-column-count skin configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="skin">The skin from which configuration is retrieved.</param>
|
||||||
|
/// <param name="lookup">The value to retrieve.</param>
|
||||||
|
/// <param name="index">If not null, denotes the index of the column to which the entry applies.</param>
|
||||||
|
protected virtual IBindable<T> GetManiaSkinConfig<T>(ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null)
|
||||||
|
=> skin.GetConfig<ManiaSkinConfigurationLookup, T>(
|
||||||
|
new ManiaSkinConfigurationLookup(lookup, index));
|
||||||
|
}
|
||||||
|
}
|
98
osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs
Normal file
98
osu.Game.Rulesets.Mania/Skinning/LegacyNotePiece.cs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyNotePiece : LegacyManiaColumnElement
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Container directionContainer;
|
||||||
|
private Sprite noteSprite;
|
||||||
|
|
||||||
|
private float? minimumColumnWidth;
|
||||||
|
|
||||||
|
public LegacyNotePiece()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
minimumColumnWidth = skin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.MinimumColumnWidth))?.Value;
|
||||||
|
|
||||||
|
InternalChild = directionContainer = new Container
|
||||||
|
{
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Child = noteSprite = new Sprite { Texture = GetTexture(skin) }
|
||||||
|
};
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(OnDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (noteSprite.Texture != null)
|
||||||
|
{
|
||||||
|
// The height is scaled to the minimum column width, if provided.
|
||||||
|
float minimumWidth = minimumColumnWidth ?? DrawWidth;
|
||||||
|
|
||||||
|
noteSprite.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), noteSprite.Texture.DisplayWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
directionContainer.Anchor = Anchor.TopCentre;
|
||||||
|
directionContainer.Scale = new Vector2(1, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
directionContainer.Anchor = Anchor.BottomCentre;
|
||||||
|
directionContainer.Scale = Vector2.One;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Texture GetTexture(ISkinSource skin) => GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||||
|
|
||||||
|
protected Texture GetTextureFromLookup(ISkin skin, LegacyManiaSkinConfigurationLookups lookup)
|
||||||
|
{
|
||||||
|
string suffix = string.Empty;
|
||||||
|
|
||||||
|
switch (lookup)
|
||||||
|
{
|
||||||
|
case LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage:
|
||||||
|
suffix = "H";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LegacyManiaSkinConfigurationLookups.HoldNoteTailImage:
|
||||||
|
suffix = "T";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
string noteImage = GetManiaSkinConfig<string>(skin, lookup)?.Value
|
||||||
|
?? $"mania-note{FallbackColumnIndex}{suffix}";
|
||||||
|
|
||||||
|
return skin.GetTexture(noteImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
osu.Game.Rulesets.Mania/Skinning/LegacyStageBackground.cs
Normal file
61
osu.Game.Rulesets.Mania/Skinning/LegacyStageBackground.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// 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.Sprites;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyStageBackground : LegacyManiaElement
|
||||||
|
{
|
||||||
|
private Drawable leftSprite;
|
||||||
|
private Drawable rightSprite;
|
||||||
|
|
||||||
|
public LegacyStageBackground()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin)
|
||||||
|
{
|
||||||
|
string leftImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.LeftStageImage)?.Value
|
||||||
|
?? "mania-stage-left";
|
||||||
|
|
||||||
|
string rightImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.RightStageImage)?.Value
|
||||||
|
?? "mania-stage-right";
|
||||||
|
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
leftSprite = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
X = 0.05f,
|
||||||
|
Texture = skin.GetTexture(leftImage),
|
||||||
|
},
|
||||||
|
rightSprite = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
|
X = -0.05f,
|
||||||
|
Texture = skin.GetTexture(rightImage)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (leftSprite?.Height > 0)
|
||||||
|
leftSprite.Scale = new Vector2(DrawHeight / leftSprite.Height);
|
||||||
|
|
||||||
|
if (rightSprite?.Height > 0)
|
||||||
|
rightSprite.Scale = new Vector2(DrawHeight / rightSprite.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
osu.Game.Rulesets.Mania/Skinning/LegacyStageForeground.cs
Normal file
56
osu.Game.Rulesets.Mania/Skinning/LegacyStageForeground.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class LegacyStageForeground : LegacyManiaElement
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Drawable sprite;
|
||||||
|
|
||||||
|
public LegacyStageForeground()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
string bottomImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.BottomStageImage)?.Value
|
||||||
|
?? "mania-stage-bottom";
|
||||||
|
|
||||||
|
sprite = skin.GetAnimation(bottomImage, true, true)?.With(d =>
|
||||||
|
{
|
||||||
|
if (d == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d.Scale = new Vector2(1.6f);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sprite != null)
|
||||||
|
InternalChild = sprite;
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (sprite == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
sprite.Anchor = sprite.Origin = Anchor.TopCentre;
|
||||||
|
else
|
||||||
|
sprite.Anchor = sprite.Origin = Anchor.BottomCentre;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,8 @@ using osu.Framework.Audio.Sample;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Skinning
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
@ -15,12 +17,20 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
public class ManiaLegacySkinTransformer : ISkin
|
public class ManiaLegacySkinTransformer : ISkin
|
||||||
{
|
{
|
||||||
private readonly ISkin source;
|
private readonly ISkin source;
|
||||||
|
private readonly ManiaBeatmap beatmap;
|
||||||
|
|
||||||
private Lazy<bool> isLegacySkin;
|
private Lazy<bool> isLegacySkin;
|
||||||
|
|
||||||
public ManiaLegacySkinTransformer(ISkinSource source)
|
/// <summary>
|
||||||
|
/// Whether texture for the keys exists.
|
||||||
|
/// Used to determine if the mania ruleset is skinned.
|
||||||
|
/// </summary>
|
||||||
|
private Lazy<bool> hasKeyTexture;
|
||||||
|
|
||||||
|
public ManiaLegacySkinTransformer(ISkinSource source, IBeatmap beatmap)
|
||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
|
this.beatmap = (ManiaBeatmap)beatmap;
|
||||||
|
|
||||||
source.SourceChanged += sourceChanged;
|
source.SourceChanged += sourceChanged;
|
||||||
sourceChanged();
|
sourceChanged();
|
||||||
@ -29,6 +39,10 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
private void sourceChanged()
|
private void sourceChanged()
|
||||||
{
|
{
|
||||||
isLegacySkin = new Lazy<bool>(() => source.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version) != null);
|
isLegacySkin = new Lazy<bool>(() => source.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version) != null);
|
||||||
|
hasKeyTexture = new Lazy<bool>(() => source.GetAnimation(
|
||||||
|
GetConfig<ManiaSkinConfigurationLookup, string>(
|
||||||
|
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.KeyImage, 0))?.Value
|
||||||
|
?? "mania-key1", true, true) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Drawable GetDrawableComponent(ISkinComponent component)
|
public Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
@ -39,13 +53,40 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
return getResult(resultComponent);
|
return getResult(resultComponent);
|
||||||
|
|
||||||
case ManiaSkinComponent maniaComponent:
|
case ManiaSkinComponent maniaComponent:
|
||||||
if (!isLegacySkin.Value)
|
if (!isLegacySkin.Value || !hasKeyTexture.Value)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
switch (maniaComponent.Component)
|
switch (maniaComponent.Component)
|
||||||
{
|
{
|
||||||
case ManiaSkinComponents.ColumnBackground:
|
case ManiaSkinComponents.ColumnBackground:
|
||||||
return new LegacyColumnBackground();
|
return new LegacyColumnBackground(maniaComponent.TargetColumn == beatmap.TotalColumns - 1);
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HitTarget:
|
||||||
|
return new LegacyHitTarget();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.KeyArea:
|
||||||
|
return new LegacyKeyArea();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.Note:
|
||||||
|
return new LegacyNotePiece();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HoldNoteHead:
|
||||||
|
return new LegacyHoldNoteHeadPiece();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HoldNoteTail:
|
||||||
|
return new LegacyHoldNoteTailPiece();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HoldNoteBody:
|
||||||
|
return new LegacyBodyPiece();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HitExplosion:
|
||||||
|
return new LegacyHitExplosion();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.StageBackground:
|
||||||
|
return new LegacyStageBackground();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.StageForeground:
|
||||||
|
return new LegacyStageForeground();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -84,7 +125,12 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
|
|
||||||
public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample);
|
public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample);
|
||||||
|
|
||||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) =>
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
source.GetConfig<TLookup, TValue>(lookup);
|
{
|
||||||
|
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||||
|
return source.GetConfig<LegacyManiaSkinConfigurationLookup, TValue>(new LegacyManiaSkinConfigurationLookup(beatmap.TotalColumns, maniaLookup.Lookup, maniaLookup.TargetColumn));
|
||||||
|
|
||||||
|
return source.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
// 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.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning
|
||||||
|
{
|
||||||
|
public class ManiaSkinConfigurationLookup
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The configuration lookup value.
|
||||||
|
/// </summary>
|
||||||
|
public readonly LegacyManiaSkinConfigurationLookups Lookup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The intended <see cref="Column"/> index for the configuration.
|
||||||
|
/// May be null if the configuration does not apply to a <see cref="Column"/>.
|
||||||
|
/// </summary>
|
||||||
|
public readonly int? TargetColumn;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="ManiaSkinConfigurationLookup"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lookup">The lookup value.</param>
|
||||||
|
/// <param name="targetColumn">The intended <see cref="Column"/> index for the configuration. May be null if the configuration does not apply to a <see cref="Column"/>.</param>
|
||||||
|
public ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups lookup, int? targetColumn = null)
|
||||||
|
{
|
||||||
|
Lookup = lookup;
|
||||||
|
TargetColumn = targetColumn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,11 +12,11 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
|
||||||
using osu.Game.Rulesets.Mania.UI.Components;
|
using osu.Game.Rulesets.Mania.UI.Components;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI
|
namespace osu.Game.Rulesets.Mania.UI
|
||||||
{
|
{
|
||||||
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
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;
|
||||||
private const float special_column_width = 70;
|
public const float SPECIAL_COLUMN_WIDTH = 70;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The index of this column as part of the whole playfield.
|
/// The index of this column as part of the whole playfield.
|
||||||
@ -33,11 +33,9 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
public readonly Bindable<ManiaAction> Action = new Bindable<ManiaAction>();
|
public readonly Bindable<ManiaAction> Action = new Bindable<ManiaAction>();
|
||||||
|
|
||||||
private readonly ColumnKeyArea keyArea;
|
|
||||||
private readonly ColumnHitObjectArea hitObjectArea;
|
private readonly ColumnHitObjectArea hitObjectArea;
|
||||||
|
|
||||||
internal readonly Container TopLevelContainer;
|
internal readonly Container TopLevelContainer;
|
||||||
private readonly Container explosionContainer;
|
|
||||||
|
|
||||||
public Column(int index)
|
public Column(int index)
|
||||||
{
|
{
|
||||||
@ -46,97 +44,34 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
RelativeSizeAxes = Axes.Y;
|
RelativeSizeAxes = Axes.Y;
|
||||||
Width = COLUMN_WIDTH;
|
Width = COLUMN_WIDTH;
|
||||||
|
|
||||||
Drawable background = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground())
|
Drawable background = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground, Index), _ => new DefaultColumnBackground())
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
};
|
};
|
||||||
|
|
||||||
Container hitTargetContainer;
|
|
||||||
|
|
||||||
InternalChildren = new[]
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
// For input purposes, the background is added at the highest depth, but is then proxied back below all other elements
|
// For input purposes, the background is added at the highest depth, but is then proxied back below all other elements
|
||||||
background.CreateProxy(),
|
background.CreateProxy(),
|
||||||
hitTargetContainer = new Container
|
hitObjectArea = new ColumnHitObjectArea(Index, HitObjectContainer) { RelativeSizeAxes = Axes.Both },
|
||||||
|
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea, Index), _ => new DefaultKeyArea())
|
||||||
{
|
{
|
||||||
Name = "Hit target + hit objects",
|
RelativeSizeAxes = Axes.Both
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
hitObjectArea = new ColumnHitObjectArea(HitObjectContainer)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
explosionContainer = new Container
|
|
||||||
{
|
|
||||||
Name = "Hit explosions",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
keyArea = new ColumnKeyArea
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = ManiaStage.HIT_TARGET_POSITION,
|
|
||||||
},
|
},
|
||||||
background,
|
background,
|
||||||
TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
|
TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||||
};
|
};
|
||||||
|
|
||||||
TopLevelContainer.Add(explosionContainer.CreateProxy());
|
TopLevelContainer.Add(hitObjectArea.Explosions.CreateProxy());
|
||||||
|
|
||||||
Direction.BindValueChanged(dir =>
|
|
||||||
{
|
|
||||||
hitTargetContainer.Padding = new MarginPadding
|
|
||||||
{
|
|
||||||
Top = dir.NewValue == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0,
|
|
||||||
Bottom = dir.NewValue == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
explosionContainer.Padding = new MarginPadding
|
|
||||||
{
|
|
||||||
Top = dir.NewValue == ScrollingDirection.Up ? NotePiece.NOTE_HEIGHT / 2 : 0,
|
|
||||||
Bottom = dir.NewValue == ScrollingDirection.Down ? NotePiece.NOTE_HEIGHT / 2 : 0
|
|
||||||
};
|
|
||||||
|
|
||||||
keyArea.Anchor = keyArea.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
|
||||||
}, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Axes RelativeSizeAxes => Axes.Y;
|
public override Axes RelativeSizeAxes => Axes.Y;
|
||||||
|
|
||||||
private bool isSpecial;
|
public ColumnType ColumnType { get; set; }
|
||||||
|
|
||||||
public bool IsSpecial
|
public bool IsSpecial => ColumnType == ColumnType.Special;
|
||||||
{
|
|
||||||
get => isSpecial;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (isSpecial == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
isSpecial = value;
|
public Color4 AccentColour { get; set; }
|
||||||
|
|
||||||
Width = isSpecial ? special_column_width : COLUMN_WIDTH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get => accentColour;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (accentColour == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
accentColour = value;
|
|
||||||
|
|
||||||
keyArea.AccentColour = value;
|
|
||||||
hitObjectArea.AccentColour = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
{
|
{
|
||||||
@ -171,11 +106,15 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements.Value)
|
if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements.Value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
explosionContainer.Add(new HitExplosion(judgedObject.AccentColour.Value, judgedObject is DrawableHoldNoteTick)
|
var explosion = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HitExplosion, Index), _ =>
|
||||||
|
new DefaultHitExplosion(judgedObject.AccentColour.Value, judgedObject is DrawableHoldNoteTick))
|
||||||
{
|
{
|
||||||
Anchor = Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre,
|
RelativeSizeAxes = Axes.Both
|
||||||
Origin = Anchor.Centre
|
};
|
||||||
});
|
|
||||||
|
hitObjectArea.Explosions.Add(explosion);
|
||||||
|
|
||||||
|
explosion.Delay(200).Expire(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnPressed(ManiaAction action)
|
public bool OnPressed(ManiaAction action)
|
||||||
@ -200,6 +139,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||||
// This probably shouldn't exist as is, but the columns in the stage are separated by a 1px border
|
// This probably shouldn't exist as is, but the columns in the stage are separated by a 1px border
|
||||||
=> DrawRectangle.Inflate(new Vector2(ManiaStage.COLUMN_SPACING / 2, 0)).Contains(ToLocalSpace(screenSpacePos));
|
=> DrawRectangle.Inflate(new Vector2(Stage.COLUMN_SPACING / 2, 0)).Contains(ToLocalSpace(screenSpacePos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,145 +1,45 @@
|
|||||||
// 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.Framework.Allocation;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osuTK.Graphics;
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||||
{
|
{
|
||||||
public class ColumnHitObjectArea : CompositeDrawable, IHasAccentColour
|
public class ColumnHitObjectArea : HitObjectArea
|
||||||
{
|
{
|
||||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
public readonly Container Explosions;
|
||||||
|
|
||||||
private readonly Drawable hitTarget;
|
private readonly Drawable hitTarget;
|
||||||
|
|
||||||
public ColumnHitObjectArea(HitObjectContainer hitObjectContainer)
|
public ColumnHitObjectArea(int columnIndex, HitObjectContainer hitObjectContainer)
|
||||||
|
: base(hitObjectContainer)
|
||||||
{
|
{
|
||||||
InternalChildren = new[]
|
AddRangeInternal(new[]
|
||||||
{
|
{
|
||||||
hitTarget = new DefaultHitTarget
|
hitTarget = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HitTarget, columnIndex), _ => new DefaultHitTarget())
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Depth = 1
|
||||||
},
|
},
|
||||||
hitObjectContainer
|
Explosions = new Container
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(IScrollingInfo scrollingInfo)
|
|
||||||
{
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
|
||||||
direction.BindValueChanged(dir =>
|
|
||||||
{
|
|
||||||
Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
|
||||||
|
|
||||||
hitTarget.Anchor = hitTarget.Origin = anchor;
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get => accentColour;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (accentColour == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
accentColour = value;
|
|
||||||
|
|
||||||
if (hitTarget is IHasAccentColour colouredHitTarget)
|
|
||||||
colouredHitTarget.AccentColour = accentColour;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DefaultHitTarget : CompositeDrawable, IHasAccentColour
|
|
||||||
{
|
|
||||||
private const float hit_target_bar_height = 2;
|
|
||||||
|
|
||||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
|
||||||
|
|
||||||
private readonly Container hitTargetLine;
|
|
||||||
private readonly Drawable hitTargetBar;
|
|
||||||
|
|
||||||
public DefaultHitTarget()
|
|
||||||
{
|
|
||||||
InternalChildren = new[]
|
|
||||||
{
|
{
|
||||||
hitTargetBar = new Box
|
RelativeSizeAxes = Axes.Both,
|
||||||
{
|
Depth = -1,
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = NotePiece.NOTE_HEIGHT,
|
|
||||||
Alpha = 0.6f,
|
|
||||||
Colour = Color4.Black
|
|
||||||
},
|
|
||||||
hitTargetLine = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = hit_target_bar_height,
|
|
||||||
Masking = true,
|
|
||||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(IScrollingInfo scrollingInfo)
|
|
||||||
{
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
|
||||||
direction.BindValueChanged(dir =>
|
|
||||||
{
|
|
||||||
Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
|
||||||
|
|
||||||
hitTargetBar.Anchor = hitTargetBar.Origin = anchor;
|
|
||||||
hitTargetLine.Anchor = hitTargetLine.Origin = anchor;
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
updateColours();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get => accentColour;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (accentColour == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
accentColour = value;
|
|
||||||
|
|
||||||
updateColours();
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void updateColours()
|
protected override void UpdateHitPosition()
|
||||||
{
|
{
|
||||||
if (!IsLoaded)
|
base.UpdateHitPosition();
|
||||||
return;
|
|
||||||
|
|
||||||
hitTargetLine.EdgeEffect = new EdgeEffectParameters
|
if (Direction.Value == ScrollingDirection.Up)
|
||||||
{
|
hitTarget.Anchor = hitTarget.Origin = Anchor.TopLeft;
|
||||||
Type = EdgeEffectType.Glow,
|
else
|
||||||
Radius = 5,
|
hitTarget.Anchor = hitTarget.Origin = Anchor.BottomLeft;
|
||||||
Colour = accentColour.Opacity(0.5f),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,124 +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.
|
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Colour;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Input.Bindings;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
|
||||||
{
|
|
||||||
public class ColumnKeyArea : CompositeDrawable, IKeyBindingHandler<ManiaAction>, IHasAccentColour
|
|
||||||
{
|
|
||||||
private const float key_icon_size = 10;
|
|
||||||
private const float key_icon_corner_radius = 3;
|
|
||||||
|
|
||||||
private readonly IBindable<ManiaAction> action = new Bindable<ManiaAction>();
|
|
||||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
|
||||||
|
|
||||||
private Container keyIcon;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(IBindable<ManiaAction> action, IScrollingInfo scrollingInfo)
|
|
||||||
{
|
|
||||||
this.action.BindTo(action);
|
|
||||||
|
|
||||||
Drawable gradient;
|
|
||||||
|
|
||||||
InternalChildren = new[]
|
|
||||||
{
|
|
||||||
gradient = new Box
|
|
||||||
{
|
|
||||||
Name = "Key gradient",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0.5f
|
|
||||||
},
|
|
||||||
keyIcon = new Container
|
|
||||||
{
|
|
||||||
Name = "Key icon",
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Size = new Vector2(key_icon_size),
|
|
||||||
Masking = true,
|
|
||||||
CornerRadius = key_icon_corner_radius,
|
|
||||||
BorderThickness = 2,
|
|
||||||
BorderColour = Color4.White, // Not true
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
|
||||||
direction.BindValueChanged(dir =>
|
|
||||||
{
|
|
||||||
gradient.Colour = ColourInfo.GradientVertical(
|
|
||||||
dir.NewValue == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0),
|
|
||||||
dir.NewValue == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black);
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
updateColours();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get => accentColour;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (accentColour == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
accentColour = value;
|
|
||||||
|
|
||||||
updateColours();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateColours()
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
keyIcon.EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Radius = 5,
|
|
||||||
Colour = accentColour.Opacity(0.5f),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnPressed(ManiaAction action)
|
|
||||||
{
|
|
||||||
if (action == this.action.Value)
|
|
||||||
keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnReleased(ManiaAction action)
|
|
||||||
{
|
|
||||||
if (action == this.action.Value)
|
|
||||||
keyIcon.ScaleTo(1f, 125, Easing.OutQuint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
80
osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs
Normal file
80
osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Effects;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||||
|
{
|
||||||
|
public class DefaultHitTarget : CompositeDrawable
|
||||||
|
{
|
||||||
|
private const float hit_target_bar_height = 2;
|
||||||
|
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Container hitTargetLine;
|
||||||
|
private Drawable hitTargetBar;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Column column { get; set; }
|
||||||
|
|
||||||
|
public DefaultHitTarget()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
hitTargetBar = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = DefaultNotePiece.NOTE_HEIGHT,
|
||||||
|
Alpha = 0.6f,
|
||||||
|
Colour = Color4.Black
|
||||||
|
},
|
||||||
|
hitTargetLine = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = hit_target_bar_height,
|
||||||
|
Masking = true,
|
||||||
|
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
hitTargetLine.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Radius = 5,
|
||||||
|
Colour = column.AccentColour.Opacity(0.5f),
|
||||||
|
};
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
hitTargetBar.Anchor = hitTargetBar.Origin = Anchor.TopLeft;
|
||||||
|
hitTargetLine.Anchor = hitTargetLine.Origin = Anchor.TopLeft;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hitTargetBar.Anchor = hitTargetBar.Origin = Anchor.BottomLeft;
|
||||||
|
hitTargetLine.Anchor = hitTargetLine.Origin = Anchor.BottomLeft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs
Normal file
117
osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Effects;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||||
|
{
|
||||||
|
public class DefaultKeyArea : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||||
|
{
|
||||||
|
private const float key_icon_size = 10;
|
||||||
|
private const float key_icon_corner_radius = 3;
|
||||||
|
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Container directionContainer;
|
||||||
|
private Container keyIcon;
|
||||||
|
private Drawable gradient;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Column column { get; set; }
|
||||||
|
|
||||||
|
public DefaultKeyArea()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
InternalChild = directionContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = Stage.HIT_TARGET_POSITION,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
gradient = new Box
|
||||||
|
{
|
||||||
|
Name = "Key gradient",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0.5f
|
||||||
|
},
|
||||||
|
keyIcon = new Container
|
||||||
|
{
|
||||||
|
Name = "Key icon",
|
||||||
|
Size = new Vector2(key_icon_size),
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = key_icon_corner_radius,
|
||||||
|
BorderThickness = 2,
|
||||||
|
BorderColour = Color4.White, // Not true
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
keyIcon.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Radius = 5,
|
||||||
|
Colour = column.AccentColour.Opacity(0.5f),
|
||||||
|
};
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
keyIcon.Anchor = Anchor.BottomCentre;
|
||||||
|
keyIcon.Y = -20;
|
||||||
|
directionContainer.Anchor = directionContainer.Origin = Anchor.TopLeft;
|
||||||
|
gradient.Colour = ColourInfo.GradientVertical(Color4.Black, Color4.Black.Opacity(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keyIcon.Anchor = Anchor.TopCentre;
|
||||||
|
keyIcon.Y = 20;
|
||||||
|
directionContainer.Anchor = directionContainer.Origin = Anchor.BottomLeft;
|
||||||
|
gradient.Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Color4.Black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnPressed(ManiaAction action)
|
||||||
|
{
|
||||||
|
if (action == column.Action.Value)
|
||||||
|
keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(ManiaAction action)
|
||||||
|
{
|
||||||
|
if (action == column.Action.Value)
|
||||||
|
keyIcon.ScaleTo(1f, 125, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
// 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.Graphics.Shapes;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||||
|
{
|
||||||
|
public class DefaultStageBackground : CompositeDrawable
|
||||||
|
{
|
||||||
|
public DefaultStageBackground()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChild = new Box
|
||||||
|
{
|
||||||
|
Name = "Background",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Black
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs
Normal file
55
osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||||
|
{
|
||||||
|
public class HitObjectArea : SkinReloadableDrawable
|
||||||
|
{
|
||||||
|
protected readonly IBindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
public HitObjectArea(HitObjectContainer hitObjectContainer)
|
||||||
|
{
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
hitObjectContainer,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
Direction.BindTo(scrollingInfo.Direction);
|
||||||
|
Direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||||
|
{
|
||||||
|
base.SkinChanged(skin, allowFallback);
|
||||||
|
UpdateHitPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
UpdateHitPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateHitPosition()
|
||||||
|
{
|
||||||
|
float hitPosition = CurrentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||||
|
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.HitPosition))?.Value
|
||||||
|
?? Stage.HIT_TARGET_POSITION;
|
||||||
|
|
||||||
|
Padding = Direction.Value == ScrollingDirection.Up
|
||||||
|
? new MarginPadding { Top = hitPosition }
|
||||||
|
: new MarginPadding { Bottom = hitPosition };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +1,35 @@
|
|||||||
// 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.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
using osu.Framework.Graphics.Effects;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI
|
namespace osu.Game.Rulesets.Mania.UI
|
||||||
{
|
{
|
||||||
internal class HitExplosion : CompositeDrawable
|
public class DefaultHitExplosion : CompositeDrawable
|
||||||
{
|
{
|
||||||
public override bool RemoveWhenNotAlive => true;
|
public override bool RemoveWhenNotAlive => true;
|
||||||
|
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
private readonly CircularContainer largeFaint;
|
private readonly CircularContainer largeFaint;
|
||||||
private readonly CircularContainer mainGlow1;
|
private readonly CircularContainer mainGlow1;
|
||||||
|
|
||||||
public HitExplosion(Color4 objectColour, bool isSmall = false)
|
public DefaultHitExplosion(Color4 objectColour, bool isSmall = false)
|
||||||
{
|
{
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = NotePiece.NOTE_HEIGHT;
|
Height = DefaultNotePiece.NOTE_HEIGHT;
|
||||||
|
|
||||||
// scale roughly in-line with visual appearance of notes
|
// scale roughly in-line with visual appearance of notes
|
||||||
Scale = new Vector2(1f, 0.6f);
|
Scale = new Vector2(1f, 0.6f);
|
||||||
@ -109,6 +116,13 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
const double duration = 200;
|
const double duration = 200;
|
||||||
@ -122,7 +136,20 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
mainGlow1.ScaleTo(1.4f, duration, Easing.OutQuint);
|
mainGlow1.ScaleTo(1.4f, duration, Easing.OutQuint);
|
||||||
|
|
||||||
this.FadeOut(duration, Easing.Out);
|
this.FadeOut(duration, Easing.Out);
|
||||||
Expire(true);
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre;
|
||||||
|
Y = DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomCentre;
|
||||||
|
Y = -DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,8 +5,10 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Input.Handlers;
|
using osu.Game.Input.Handlers;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
@ -25,6 +27,16 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
{
|
{
|
||||||
public class DrawableManiaRuleset : DrawableScrollingRuleset<ManiaHitObject>
|
public class DrawableManiaRuleset : DrawableScrollingRuleset<ManiaHitObject>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum time range. This occurs at a <see cref="relativeTimeRange"/> of 40.
|
||||||
|
/// </summary>
|
||||||
|
public const double MIN_TIME_RANGE = 150;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum time range. This occurs at a <see cref="relativeTimeRange"/> of 1.
|
||||||
|
/// </summary>
|
||||||
|
public const double MAX_TIME_RANGE = 6000;
|
||||||
|
|
||||||
protected new ManiaPlayfield Playfield => (ManiaPlayfield)base.Playfield;
|
protected new ManiaPlayfield Playfield => (ManiaPlayfield)base.Playfield;
|
||||||
|
|
||||||
public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap;
|
public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap;
|
||||||
@ -46,6 +58,19 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
|
bool isForCurrentRuleset = Beatmap.BeatmapInfo.Ruleset.Equals(Ruleset.RulesetInfo);
|
||||||
|
|
||||||
|
foreach (var p in ControlPoints)
|
||||||
|
{
|
||||||
|
// Mania doesn't care about global velocity
|
||||||
|
p.Velocity = 1;
|
||||||
|
p.BaseBeatLength *= Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier;
|
||||||
|
|
||||||
|
// For non-mania beatmap, speed changes should only happen through timing points
|
||||||
|
if (!isForCurrentRuleset)
|
||||||
|
p.DifficultyPoint = new DifficultyControlPoint();
|
||||||
|
}
|
||||||
|
|
||||||
BarLines.ForEach(Playfield.Add);
|
BarLines.ForEach(Playfield.Add);
|
||||||
|
|
||||||
Config.BindWith(ManiaRulesetSetting.ScrollDirection, configDirection);
|
Config.BindWith(ManiaRulesetSetting.ScrollDirection, configDirection);
|
||||||
@ -54,6 +79,17 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
Config.BindWith(ManiaRulesetSetting.ScrollTime, TimeRange);
|
Config.BindWith(ManiaRulesetSetting.ScrollTime, TimeRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void AdjustScrollSpeed(int amount)
|
||||||
|
{
|
||||||
|
this.TransformTo(nameof(relativeTimeRange), relativeTimeRange + amount, 200, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double relativeTimeRange
|
||||||
|
{
|
||||||
|
get => MAX_TIME_RANGE / TimeRange.Value;
|
||||||
|
set => TimeRange.Value = MAX_TIME_RANGE / value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the column that intersects a screen-space position.
|
/// Retrieves the column that intersects a screen-space position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -6,6 +6,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -14,9 +15,10 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI
|
namespace osu.Game.Rulesets.Mania.UI
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
public class ManiaPlayfield : ScrollingPlayfield
|
public class ManiaPlayfield : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
private readonly List<Stage> stages = new List<Stage>();
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos));
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos));
|
||||||
|
|
||||||
@ -41,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
for (int i = 0; i < stageDefinitions.Count; i++)
|
for (int i = 0; i < stageDefinitions.Count; i++)
|
||||||
{
|
{
|
||||||
var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction);
|
var newStage = new Stage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction);
|
||||||
|
|
||||||
playfieldGrid.Content[0][i] = newStage;
|
playfieldGrid.Content[0][i] = newStage;
|
||||||
|
|
||||||
@ -90,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int TotalColumns => stages.Sum(s => s.Columns.Count);
|
public int TotalColumns => stages.Sum(s => s.Columns.Count);
|
||||||
|
|
||||||
private ManiaStage getStageByColumn(int column)
|
private Stage getStageByColumn(int column)
|
||||||
{
|
{
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI
|
namespace osu.Game.Rulesets.Mania.UI
|
||||||
{
|
{
|
||||||
@ -13,8 +12,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
Size = new Vector2(1, 0.8f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
// 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 System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning;
|
||||||
|
using osu.Game.Rulesets.Mania.UI.Components;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -23,31 +24,33 @@ 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 Stage : ScrollingPlayfield
|
||||||
public class ManiaStage : ScrollingPlayfield
|
|
||||||
{
|
{
|
||||||
public const float COLUMN_SPACING = 1;
|
public const float COLUMN_SPACING = 1;
|
||||||
|
|
||||||
public const float HIT_TARGET_POSITION = 50;
|
public const float HIT_TARGET_POSITION = 110;
|
||||||
|
|
||||||
public IReadOnlyList<Column> Columns => columnFlow.Children;
|
public IReadOnlyList<Column> Columns => columnFlow.Children;
|
||||||
private readonly FillFlowContainer<Column> columnFlow;
|
private readonly FillFlowContainer<Column> columnFlow;
|
||||||
|
|
||||||
private readonly Container barLineContainer;
|
|
||||||
|
|
||||||
public Container<DrawableManiaJudgement> Judgements => judgements;
|
public Container<DrawableManiaJudgement> Judgements => judgements;
|
||||||
private readonly JudgementContainer<DrawableManiaJudgement> judgements;
|
private readonly JudgementContainer<DrawableManiaJudgement> judgements;
|
||||||
|
|
||||||
|
private readonly Drawable barLineContainer;
|
||||||
private readonly Container topLevelContainer;
|
private readonly Container topLevelContainer;
|
||||||
|
|
||||||
private List<Color4> normalColumnColours = new List<Color4>();
|
private readonly Dictionary<ColumnType, Color4> columnColours = new Dictionary<ColumnType, Color4>
|
||||||
private Color4 specialColumnColour;
|
{
|
||||||
|
{ ColumnType.Even, new Color4(6, 84, 0, 255) },
|
||||||
|
{ ColumnType.Odd, new Color4(94, 0, 57, 255) },
|
||||||
|
{ ColumnType.Special, new Color4(0, 48, 63, 255) }
|
||||||
|
};
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Columns.Any(c => c.ReceivePositionalInputAt(screenSpacePos));
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Columns.Any(c => c.ReceivePositionalInputAt(screenSpacePos));
|
||||||
|
|
||||||
private readonly int firstColumnIndex;
|
private readonly int firstColumnIndex;
|
||||||
|
|
||||||
public ManiaStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction)
|
public Stage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction)
|
||||||
{
|
{
|
||||||
this.firstColumnIndex = firstColumnIndex;
|
this.firstColumnIndex = firstColumnIndex;
|
||||||
|
|
||||||
@ -68,31 +71,17 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
AutoSizeAxes = Axes.X,
|
AutoSizeAxes = Axes.X,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container
|
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground), _ => new DefaultStageBackground())
|
||||||
{
|
{
|
||||||
Name = "Columns mask",
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
columnFlow = new FillFlowContainer<Column>
|
||||||
|
{
|
||||||
|
Name = "Columns",
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
AutoSizeAxes = Axes.X,
|
AutoSizeAxes = Axes.X,
|
||||||
Masking = true,
|
Direction = FillDirection.Horizontal,
|
||||||
CornerRadius = 5,
|
Padding = new MarginPadding { Left = COLUMN_SPACING, Right = COLUMN_SPACING },
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Name = "Background",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.Black
|
|
||||||
},
|
|
||||||
columnFlow = new FillFlowContainer<Column>
|
|
||||||
{
|
|
||||||
Name = "Columns",
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
AutoSizeAxes = Axes.X,
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
Padding = new MarginPadding { Left = COLUMN_SPACING, Right = COLUMN_SPACING },
|
|
||||||
Spacing = new Vector2(COLUMN_SPACING, 0)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
@ -103,15 +92,18 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
Width = 1366, // Bar lines should only be masked on the vertical axis
|
Width = 1366, // Bar lines should only be masked on the vertical axis
|
||||||
BypassAutoSizeAxes = Axes.Both,
|
BypassAutoSizeAxes = Axes.Both,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Child = barLineContainer = new Container
|
Child = barLineContainer = new HitObjectArea(HitObjectContainer)
|
||||||
{
|
{
|
||||||
Name = "Bar lines",
|
Name = "Bar lines",
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Child = HitObjectContainer
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground), _ => null)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
judgements = new JudgementContainer<DrawableManiaJudgement>
|
judgements = new JudgementContainer<DrawableManiaJudgement>
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
@ -126,24 +118,52 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
for (int i = 0; i < definition.Columns; i++)
|
for (int i = 0; i < definition.Columns; i++)
|
||||||
{
|
{
|
||||||
var isSpecial = definition.IsSpecialColumn(i);
|
var columnType = definition.GetTypeOfColumn(i);
|
||||||
var column = new Column(firstColumnIndex + i)
|
var column = new Column(firstColumnIndex + i)
|
||||||
{
|
{
|
||||||
IsSpecial = isSpecial,
|
ColumnType = columnType,
|
||||||
Action = { Value = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ }
|
AccentColour = columnColours[columnType],
|
||||||
|
Action = { Value = columnType == ColumnType.Special ? specialColumnStartAction++ : normalColumnStartAction++ }
|
||||||
};
|
};
|
||||||
|
|
||||||
AddColumn(column);
|
AddColumn(column);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Direction.BindValueChanged(dir =>
|
private ISkin currentSkin;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin)
|
||||||
|
{
|
||||||
|
currentSkin = skin;
|
||||||
|
skin.SourceChanged += onSkinChanged;
|
||||||
|
|
||||||
|
onSkinChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSkinChanged()
|
||||||
|
{
|
||||||
|
foreach (var col in columnFlow)
|
||||||
{
|
{
|
||||||
barLineContainer.Padding = new MarginPadding
|
if (col.Index > 0)
|
||||||
{
|
{
|
||||||
Top = dir.NewValue == ScrollingDirection.Up ? HIT_TARGET_POSITION : 0,
|
float spacing = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||||
Bottom = dir.NewValue == ScrollingDirection.Down ? HIT_TARGET_POSITION : 0,
|
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.ColumnSpacing, col.Index - 1))
|
||||||
};
|
?.Value ?? COLUMN_SPACING;
|
||||||
}, true);
|
|
||||||
|
col.Margin = new MarginPadding { Left = spacing };
|
||||||
|
}
|
||||||
|
|
||||||
|
float? width = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||||
|
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.ColumnWidth, col.Index))
|
||||||
|
?.Value;
|
||||||
|
|
||||||
|
if (width == null)
|
||||||
|
// only used by default skin (legacy skins get defaults set in LegacyManiaSkinConfiguration)
|
||||||
|
col.Width = col.IsSpecial ? Column.SPECIAL_COLUMN_WIDTH : Column.COLUMN_WIDTH;
|
||||||
|
else
|
||||||
|
col.Width = width.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddColumn(Column c)
|
public void AddColumn(Column c)
|
||||||
@ -196,38 +216,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
normalColumnColours = new List<Color4>
|
|
||||||
{
|
|
||||||
new Color4(94, 0, 57, 255),
|
|
||||||
new Color4(6, 84, 0, 255)
|
|
||||||
};
|
|
||||||
|
|
||||||
specialColumnColour = new Color4(0, 48, 63, 255);
|
|
||||||
|
|
||||||
// Set the special column + colour + key
|
|
||||||
foreach (var column in Columns)
|
|
||||||
{
|
|
||||||
if (!column.IsSpecial)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
column.AccentColour = specialColumnColour;
|
|
||||||
}
|
|
||||||
|
|
||||||
var nonSpecialColumns = Columns.Where(c => !c.IsSpecial).ToList();
|
|
||||||
|
|
||||||
// We'll set the colours of the non-special columns in a separate loop, because the non-special
|
|
||||||
// column colours are mirrored across their centre and special styles mess with this
|
|
||||||
for (int i = 0; i < Math.Ceiling(nonSpecialColumns.Count / 2f); i++)
|
|
||||||
{
|
|
||||||
Color4 colour = normalColumnColours[i % normalColumnColours.Count];
|
|
||||||
nonSpecialColumns[i].AccentColour = colour;
|
|
||||||
nonSpecialColumns[nonSpecialColumns.Count - 1 - i].AccentColour = colour;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
// Due to masking differences, it is not possible to get the width of the columns container automatically
|
// Due to masking differences, it is not possible to get the width of the columns container automatically
|
61
osu.Game.Rulesets.Mania/VariantMappingGenerator.cs
Normal file
61
osu.Game.Rulesets.Mania/VariantMappingGenerator.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania
|
||||||
|
{
|
||||||
|
public class VariantMappingGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// All the <see cref="InputKey"/>s available to the left hand.
|
||||||
|
/// </summary>
|
||||||
|
public InputKey[] LeftKeys;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All the <see cref="InputKey"/>s available to the right hand.
|
||||||
|
/// </summary>
|
||||||
|
public InputKey[] RightKeys;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="InputKey"/> for the special key.
|
||||||
|
/// </summary>
|
||||||
|
public InputKey SpecialKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="ManiaAction"/> at which the normal columns should begin.
|
||||||
|
/// </summary>
|
||||||
|
public ManiaAction NormalActionStart;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="ManiaAction"/> for the special column.
|
||||||
|
/// </summary>
|
||||||
|
public ManiaAction SpecialAction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a list of <see cref="KeyBinding"/>s for a specific number of columns.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="columns">The number of columns that need to be bound.</param>
|
||||||
|
/// <param name="nextNormalAction">The next <see cref="ManiaAction"/> to use for normal columns.</param>
|
||||||
|
/// <returns>The keybindings.</returns>
|
||||||
|
public IEnumerable<KeyBinding> GenerateKeyBindingsFor(int columns, out ManiaAction nextNormalAction)
|
||||||
|
{
|
||||||
|
ManiaAction currentNormalAction = NormalActionStart;
|
||||||
|
|
||||||
|
var bindings = new List<KeyBinding>();
|
||||||
|
|
||||||
|
for (int i = LeftKeys.Length - columns / 2; i < LeftKeys.Length; i++)
|
||||||
|
bindings.Add(new KeyBinding(LeftKeys[i], currentNormalAction++));
|
||||||
|
|
||||||
|
if (columns % 2 == 1)
|
||||||
|
bindings.Add(new KeyBinding(SpecialKey, SpecialAction));
|
||||||
|
|
||||||
|
for (int i = 0; i < columns / 2; i++)
|
||||||
|
bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++));
|
||||||
|
|
||||||
|
nextNormalAction = currentNormalAction;
|
||||||
|
return bindings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
106
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs
Normal file
106
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneOsuModHidden : ModTestScene
|
||||||
|
{
|
||||||
|
public TestSceneOsuModHidden()
|
||||||
|
: base(new OsuRuleset())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDefaultBeatmapTest() => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModHidden(),
|
||||||
|
Autoplay = true,
|
||||||
|
PassCondition = checkSomeHit
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FirstCircleAfterTwoSpinners() => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModHidden(),
|
||||||
|
Autoplay = true,
|
||||||
|
Beatmap = new Beatmap
|
||||||
|
{
|
||||||
|
HitObjects = new List<HitObject>
|
||||||
|
{
|
||||||
|
new Spinner
|
||||||
|
{
|
||||||
|
Position = new Vector2(256, 192),
|
||||||
|
EndTime = 1000,
|
||||||
|
},
|
||||||
|
new Spinner
|
||||||
|
{
|
||||||
|
Position = new Vector2(256, 192),
|
||||||
|
StartTime = 1200,
|
||||||
|
EndTime = 2200,
|
||||||
|
},
|
||||||
|
new HitCircle
|
||||||
|
{
|
||||||
|
Position = new Vector2(300, 192),
|
||||||
|
StartTime = 3200,
|
||||||
|
},
|
||||||
|
new HitCircle
|
||||||
|
{
|
||||||
|
Position = new Vector2(384, 192),
|
||||||
|
StartTime = 4200,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PassCondition = checkSomeHit
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FirstSliderAfterTwoSpinners() => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModHidden(),
|
||||||
|
Autoplay = true,
|
||||||
|
Beatmap = new Beatmap
|
||||||
|
{
|
||||||
|
HitObjects = new List<HitObject>
|
||||||
|
{
|
||||||
|
new Spinner
|
||||||
|
{
|
||||||
|
Position = new Vector2(256, 192),
|
||||||
|
EndTime = 1000,
|
||||||
|
},
|
||||||
|
new Spinner
|
||||||
|
{
|
||||||
|
Position = new Vector2(256, 192),
|
||||||
|
StartTime = 1200,
|
||||||
|
EndTime = 2200,
|
||||||
|
},
|
||||||
|
new Slider
|
||||||
|
{
|
||||||
|
StartTime = 3200,
|
||||||
|
Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(100, 0), })
|
||||||
|
},
|
||||||
|
new Slider
|
||||||
|
{
|
||||||
|
StartTime = 5200,
|
||||||
|
Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(100, 0), })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PassCondition = checkSomeHit
|
||||||
|
});
|
||||||
|
|
||||||
|
private bool checkSomeHit()
|
||||||
|
{
|
||||||
|
return Player.ScoreProcessor.JudgedHits >= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs
Normal file
21
osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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 osu.Game.Rulesets.Osu.Skinning;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
|
{
|
||||||
|
public abstract class OsuSkinnableTestScene : SkinnableTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(OsuRuleset),
|
||||||
|
typeof(OsuLegacySkinTransformer),
|
||||||
|
};
|
||||||
|
|
||||||
|
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
|
||||||
|
}
|
||||||
|
}
|
BIN
osu.Game.Rulesets.Osu.Tests/Resources/special-skin/sliderb0.png
Normal file
BIN
osu.Game.Rulesets.Osu.Tests/Resources/special-skin/sliderb0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
@ -10,17 +10,16 @@ using osu.Game.Rulesets.Judgements;
|
|||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneDrawableJudgement : SkinnableTestScene
|
public class TestSceneDrawableJudgement : OsuSkinnableTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||||
{
|
{
|
||||||
typeof(DrawableJudgement),
|
typeof(DrawableJudgement),
|
||||||
typeof(DrawableOsuJudgement)
|
typeof(DrawableOsuJudgement)
|
||||||
};
|
}).ToList();
|
||||||
|
|
||||||
public TestSceneDrawableJudgement()
|
public TestSceneDrawableJudgement()
|
||||||
{
|
{
|
||||||
|
@ -3,26 +3,32 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Testing.Input;
|
using osu.Framework.Testing.Input;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Osu.Skinning;
|
||||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneGameplayCursor : SkinnableTestScene
|
public class TestSceneGameplayCursor : OsuSkinnableTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||||
{
|
{
|
||||||
|
typeof(GameplayCursorContainer),
|
||||||
typeof(OsuCursorContainer),
|
typeof(OsuCursorContainer),
|
||||||
|
typeof(OsuCursor),
|
||||||
|
typeof(LegacyCursor),
|
||||||
|
typeof(LegacyCursorTrail),
|
||||||
typeof(CursorTrail)
|
typeof(CursorTrail)
|
||||||
};
|
}).ToList();
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap;
|
private GameplayBeatmap gameplayBeatmap;
|
||||||
|
@ -14,12 +14,11 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneHitCircle : SkinnableTestScene
|
public class TestSceneHitCircle : OsuSkinnableTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
|
447
osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs
Normal file
447
osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Extensions.TypeExtensions;
|
||||||
|
using osu.Framework.Screens;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Replays;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Replays;
|
||||||
|
using osu.Game.Rulesets.Replays;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
|
{
|
||||||
|
public class TestSceneOutOfOrderHits : RateAdjustedBeatmapTestScene
|
||||||
|
{
|
||||||
|
private const double early_miss_window = 1000; // time after -1000 to -500 is considered a miss
|
||||||
|
private const double late_miss_window = 500; // time after +500 is considered a miss
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests clicking a future circle before the first circle's start time, while the first circle HAS NOT been judged.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestClickSecondCircleBeforeFirstCircleTime()
|
||||||
|
{
|
||||||
|
const double time_first_circle = 1500;
|
||||||
|
const double time_second_circle = 1600;
|
||||||
|
Vector2 positionFirstCircle = Vector2.Zero;
|
||||||
|
Vector2 positionSecondCircle = new Vector2(80);
|
||||||
|
|
||||||
|
var hitObjects = new List<OsuHitObject>
|
||||||
|
{
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_first_circle,
|
||||||
|
Position = positionFirstCircle
|
||||||
|
},
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_second_circle,
|
||||||
|
Position = positionSecondCircle
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(hitObjects, new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Time = time_first_circle - 100, Position = positionSecondCircle, Actions = { OsuAction.LeftButton } }
|
||||||
|
});
|
||||||
|
|
||||||
|
addJudgementAssert(hitObjects[0], HitResult.Miss);
|
||||||
|
addJudgementAssert(hitObjects[1], HitResult.Miss);
|
||||||
|
addJudgementOffsetAssert(hitObjects[0], late_miss_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests clicking a future circle at the first circle's start time, while the first circle HAS NOT been judged.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestClickSecondCircleAtFirstCircleTime()
|
||||||
|
{
|
||||||
|
const double time_first_circle = 1500;
|
||||||
|
const double time_second_circle = 1600;
|
||||||
|
Vector2 positionFirstCircle = Vector2.Zero;
|
||||||
|
Vector2 positionSecondCircle = new Vector2(80);
|
||||||
|
|
||||||
|
var hitObjects = new List<OsuHitObject>
|
||||||
|
{
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_first_circle,
|
||||||
|
Position = positionFirstCircle
|
||||||
|
},
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_second_circle,
|
||||||
|
Position = positionSecondCircle
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(hitObjects, new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Time = time_first_circle, Position = positionSecondCircle, Actions = { OsuAction.LeftButton } }
|
||||||
|
});
|
||||||
|
|
||||||
|
addJudgementAssert(hitObjects[0], HitResult.Miss);
|
||||||
|
addJudgementAssert(hitObjects[1], HitResult.Great);
|
||||||
|
addJudgementOffsetAssert(hitObjects[0], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests clicking a future circle after the first circle's start time, while the first circle HAS NOT been judged.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestClickSecondCircleAfterFirstCircleTime()
|
||||||
|
{
|
||||||
|
const double time_first_circle = 1500;
|
||||||
|
const double time_second_circle = 1600;
|
||||||
|
Vector2 positionFirstCircle = Vector2.Zero;
|
||||||
|
Vector2 positionSecondCircle = new Vector2(80);
|
||||||
|
|
||||||
|
var hitObjects = new List<OsuHitObject>
|
||||||
|
{
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_first_circle,
|
||||||
|
Position = positionFirstCircle
|
||||||
|
},
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_second_circle,
|
||||||
|
Position = positionSecondCircle
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(hitObjects, new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Time = time_first_circle + 100, Position = positionSecondCircle, Actions = { OsuAction.LeftButton } }
|
||||||
|
});
|
||||||
|
|
||||||
|
addJudgementAssert(hitObjects[0], HitResult.Miss);
|
||||||
|
addJudgementAssert(hitObjects[1], HitResult.Great);
|
||||||
|
addJudgementOffsetAssert(hitObjects[0], 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests clicking a future circle before the first circle's start time, while the first circle HAS been judged.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestClickSecondCircleBeforeFirstCircleTimeWithFirstCircleJudged()
|
||||||
|
{
|
||||||
|
const double time_first_circle = 1500;
|
||||||
|
const double time_second_circle = 1600;
|
||||||
|
Vector2 positionFirstCircle = Vector2.Zero;
|
||||||
|
Vector2 positionSecondCircle = new Vector2(80);
|
||||||
|
|
||||||
|
var hitObjects = new List<OsuHitObject>
|
||||||
|
{
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_first_circle,
|
||||||
|
Position = positionFirstCircle
|
||||||
|
},
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_second_circle,
|
||||||
|
Position = positionSecondCircle
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(hitObjects, new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Time = time_first_circle - 200, Position = positionFirstCircle, Actions = { OsuAction.LeftButton } },
|
||||||
|
new OsuReplayFrame { Time = time_first_circle - 100, Position = positionSecondCircle, Actions = { OsuAction.RightButton } }
|
||||||
|
});
|
||||||
|
|
||||||
|
addJudgementAssert(hitObjects[0], HitResult.Great);
|
||||||
|
addJudgementAssert(hitObjects[1], HitResult.Great);
|
||||||
|
addJudgementOffsetAssert(hitObjects[0], -200); // time_first_circle - 200
|
||||||
|
addJudgementOffsetAssert(hitObjects[0], -200); // time_second_circle - first_circle_time - 100
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests clicking a future circle after a slider's start time, but hitting all slider ticks.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestMissSliderHeadAndHitAllSliderTicks()
|
||||||
|
{
|
||||||
|
const double time_slider = 1500;
|
||||||
|
const double time_circle = 1510;
|
||||||
|
Vector2 positionCircle = Vector2.Zero;
|
||||||
|
Vector2 positionSlider = new Vector2(80);
|
||||||
|
|
||||||
|
var hitObjects = new List<OsuHitObject>
|
||||||
|
{
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_circle,
|
||||||
|
Position = positionCircle
|
||||||
|
},
|
||||||
|
new TestSlider
|
||||||
|
{
|
||||||
|
StartTime = time_slider,
|
||||||
|
Position = positionSlider,
|
||||||
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
|
{
|
||||||
|
Vector2.Zero,
|
||||||
|
new Vector2(25, 0),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(hitObjects, new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Time = time_slider, Position = positionCircle, Actions = { OsuAction.LeftButton } },
|
||||||
|
new OsuReplayFrame { Time = time_slider + 10, Position = positionSlider, Actions = { OsuAction.RightButton } }
|
||||||
|
});
|
||||||
|
|
||||||
|
addJudgementAssert(hitObjects[0], HitResult.Great);
|
||||||
|
addJudgementAssert(hitObjects[1], HitResult.Great);
|
||||||
|
addJudgementAssert("slider head", () => ((Slider)hitObjects[1]).HeadCircle, HitResult.Miss);
|
||||||
|
addJudgementAssert("slider tick", () => ((Slider)hitObjects[1]).NestedHitObjects[1] as SliderTick, HitResult.Great);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests clicking hitting future slider ticks before a circle.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestHitSliderTicksBeforeCircle()
|
||||||
|
{
|
||||||
|
const double time_slider = 1500;
|
||||||
|
const double time_circle = 1510;
|
||||||
|
Vector2 positionCircle = Vector2.Zero;
|
||||||
|
Vector2 positionSlider = new Vector2(80);
|
||||||
|
|
||||||
|
var hitObjects = new List<OsuHitObject>
|
||||||
|
{
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_circle,
|
||||||
|
Position = positionCircle
|
||||||
|
},
|
||||||
|
new TestSlider
|
||||||
|
{
|
||||||
|
StartTime = time_slider,
|
||||||
|
Position = positionSlider,
|
||||||
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
|
{
|
||||||
|
Vector2.Zero,
|
||||||
|
new Vector2(25, 0),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(hitObjects, new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Time = time_slider, Position = positionSlider, Actions = { OsuAction.LeftButton } },
|
||||||
|
new OsuReplayFrame { Time = time_circle + late_miss_window - 100, Position = positionCircle, Actions = { OsuAction.RightButton } },
|
||||||
|
new OsuReplayFrame { Time = time_circle + late_miss_window - 90, Position = positionSlider, Actions = { OsuAction.LeftButton } },
|
||||||
|
});
|
||||||
|
|
||||||
|
addJudgementAssert(hitObjects[0], HitResult.Great);
|
||||||
|
addJudgementAssert(hitObjects[1], HitResult.Great);
|
||||||
|
addJudgementAssert("slider head", () => ((Slider)hitObjects[1]).HeadCircle, HitResult.Great);
|
||||||
|
addJudgementAssert("slider tick", () => ((Slider)hitObjects[1]).NestedHitObjects[1] as SliderTick, HitResult.Great);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests clicking a future circle before a spinner.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestHitCircleBeforeSpinner()
|
||||||
|
{
|
||||||
|
const double time_spinner = 1500;
|
||||||
|
const double time_circle = 1800;
|
||||||
|
Vector2 positionCircle = Vector2.Zero;
|
||||||
|
|
||||||
|
var hitObjects = new List<OsuHitObject>
|
||||||
|
{
|
||||||
|
new TestSpinner
|
||||||
|
{
|
||||||
|
StartTime = time_spinner,
|
||||||
|
Position = new Vector2(256, 192),
|
||||||
|
EndTime = time_spinner + 1000,
|
||||||
|
},
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_circle,
|
||||||
|
Position = positionCircle
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(hitObjects, new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Time = time_spinner - 100, Position = positionCircle, Actions = { OsuAction.LeftButton } },
|
||||||
|
new OsuReplayFrame { Time = time_spinner + 10, Position = new Vector2(236, 192), Actions = { OsuAction.RightButton } },
|
||||||
|
new OsuReplayFrame { Time = time_spinner + 20, Position = new Vector2(256, 172), Actions = { OsuAction.RightButton } },
|
||||||
|
new OsuReplayFrame { Time = time_spinner + 30, Position = new Vector2(276, 192), Actions = { OsuAction.RightButton } },
|
||||||
|
new OsuReplayFrame { Time = time_spinner + 40, Position = new Vector2(256, 212), Actions = { OsuAction.RightButton } },
|
||||||
|
new OsuReplayFrame { Time = time_spinner + 50, Position = new Vector2(236, 192), Actions = { OsuAction.RightButton } },
|
||||||
|
});
|
||||||
|
|
||||||
|
addJudgementAssert(hitObjects[0], HitResult.Great);
|
||||||
|
addJudgementAssert(hitObjects[1], HitResult.Great);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHitSliderHeadBeforeHitCircle()
|
||||||
|
{
|
||||||
|
const double time_circle = 1000;
|
||||||
|
const double time_slider = 1200;
|
||||||
|
Vector2 positionCircle = Vector2.Zero;
|
||||||
|
Vector2 positionSlider = new Vector2(80);
|
||||||
|
|
||||||
|
var hitObjects = new List<OsuHitObject>
|
||||||
|
{
|
||||||
|
new TestHitCircle
|
||||||
|
{
|
||||||
|
StartTime = time_circle,
|
||||||
|
Position = positionCircle
|
||||||
|
},
|
||||||
|
new TestSlider
|
||||||
|
{
|
||||||
|
StartTime = time_slider,
|
||||||
|
Position = positionSlider,
|
||||||
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
|
{
|
||||||
|
Vector2.Zero,
|
||||||
|
new Vector2(25, 0),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(hitObjects, new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new OsuReplayFrame { Time = time_circle - 100, Position = positionSlider, Actions = { OsuAction.LeftButton } },
|
||||||
|
new OsuReplayFrame { Time = time_circle, Position = positionCircle, Actions = { OsuAction.RightButton } },
|
||||||
|
new OsuReplayFrame { Time = time_slider, Position = positionSlider, Actions = { OsuAction.LeftButton } },
|
||||||
|
});
|
||||||
|
|
||||||
|
addJudgementAssert(hitObjects[0], HitResult.Great);
|
||||||
|
addJudgementAssert(hitObjects[1], HitResult.Great);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addJudgementAssert(OsuHitObject hitObject, HitResult result)
|
||||||
|
{
|
||||||
|
AddAssert($"({hitObject.GetType().ReadableName()} @ {hitObject.StartTime}) judgement is {result}",
|
||||||
|
() => judgementResults.Single(r => r.HitObject == hitObject).Type == result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addJudgementAssert(string name, Func<OsuHitObject> hitObject, HitResult result)
|
||||||
|
{
|
||||||
|
AddAssert($"{name} judgement is {result}",
|
||||||
|
() => judgementResults.Single(r => r.HitObject == hitObject()).Type == result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addJudgementOffsetAssert(OsuHitObject hitObject, double offset)
|
||||||
|
{
|
||||||
|
AddAssert($"({hitObject.GetType().ReadableName()} @ {hitObject.StartTime}) judged at {offset}",
|
||||||
|
() => Precision.AlmostEquals(judgementResults.Single(r => r.HitObject == hitObject).TimeOffset, offset, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScoreAccessibleReplayPlayer currentPlayer;
|
||||||
|
private List<JudgementResult> judgementResults;
|
||||||
|
|
||||||
|
private void performTest(List<OsuHitObject> hitObjects, List<ReplayFrame> frames)
|
||||||
|
{
|
||||||
|
AddStep("load player", () =>
|
||||||
|
{
|
||||||
|
Beatmap.Value = CreateWorkingBeatmap(new Beatmap<OsuHitObject>
|
||||||
|
{
|
||||||
|
HitObjects = hitObjects,
|
||||||
|
BeatmapInfo =
|
||||||
|
{
|
||||||
|
BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 },
|
||||||
|
Ruleset = new OsuRuleset().RulesetInfo
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Beatmap.Value.Beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f });
|
||||||
|
|
||||||
|
var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } });
|
||||||
|
|
||||||
|
p.OnLoadComplete += _ =>
|
||||||
|
{
|
||||||
|
p.ScoreProcessor.NewJudgement += result =>
|
||||||
|
{
|
||||||
|
if (currentPlayer == p) judgementResults.Add(result);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
LoadScreen(currentPlayer = p);
|
||||||
|
judgementResults = new List<JudgementResult>();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0);
|
||||||
|
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
|
||||||
|
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestHitCircle : HitCircle
|
||||||
|
{
|
||||||
|
protected override HitWindows CreateHitWindows() => new TestHitWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestSlider : Slider
|
||||||
|
{
|
||||||
|
public TestSlider()
|
||||||
|
{
|
||||||
|
DefaultsApplied += () =>
|
||||||
|
{
|
||||||
|
HeadCircle.HitWindows = new TestHitWindows();
|
||||||
|
TailCircle.HitWindows = new TestHitWindows();
|
||||||
|
|
||||||
|
HeadCircle.HitWindows.SetDifficulty(0);
|
||||||
|
TailCircle.HitWindows.SetDifficulty(0);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestSpinner : Spinner
|
||||||
|
{
|
||||||
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||||
|
{
|
||||||
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
SpinsRequired = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestHitWindows : HitWindows
|
||||||
|
{
|
||||||
|
private static readonly DifficultyRange[] ranges =
|
||||||
|
{
|
||||||
|
new DifficultyRange(HitResult.Great, 500, 500, 500),
|
||||||
|
new DifficultyRange(HitResult.Miss, early_miss_window, early_miss_window, early_miss_window),
|
||||||
|
};
|
||||||
|
|
||||||
|
public override bool IsHitResultAllowed(HitResult result) => result == HitResult.Great || result == HitResult.Miss;
|
||||||
|
|
||||||
|
protected override DifficultyRange[] GetRanges() => ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScoreAccessibleReplayPlayer : ReplayPlayer
|
||||||
|
{
|
||||||
|
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||||
|
|
||||||
|
protected override bool PauseOnFocusLost => false;
|
||||||
|
|
||||||
|
public ScoreAccessibleReplayPlayer(Score score)
|
||||||
|
: base(score, false, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user