mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 08:27:49 +08:00
Merge branch 'master' into stamina-available-fingers
This commit is contained in:
commit
4342521bc1
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -88,7 +88,7 @@ jobs:
|
|||||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
|
run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" -- NUnit.ConsoleOut=0
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
# Attempt to upload results even if test fails.
|
# Attempt to upload results even if test fails.
|
||||||
|
@ -15,6 +15,8 @@ M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Gen
|
|||||||
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
|
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
|
||||||
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
|
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
|
||||||
M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever.
|
M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever.
|
||||||
|
M:System.Char.ToLower(System.Char);char.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
|
||||||
|
M:System.Char.ToUpper(System.Char);char.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
|
||||||
M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
||||||
M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
||||||
M:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead.
|
M:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead.
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
<GenerateProgramFile>false</GenerateProgramFile>
|
<GenerateProgramFile>false</GenerateProgramFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.EmptyFreeform\osu.Game.Rulesets.EmptyFreeform.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.EmptyFreeform\osu.Game.Rulesets.EmptyFreeform.csproj" />
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
<GenerateProgramFile>false</GenerateProgramFile>
|
<GenerateProgramFile>false</GenerateProgramFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
<GenerateProgramFile>false</GenerateProgramFile>
|
<GenerateProgramFile>false</GenerateProgramFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.EmptyScrolling\osu.Game.Rulesets.EmptyScrolling.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.EmptyScrolling\osu.Game.Rulesets.EmptyScrolling.csproj" />
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
<GenerateProgramFile>false</GenerateProgramFile>
|
<GenerateProgramFile>false</GenerateProgramFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
||||||
|
@ -51,11 +51,11 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.831.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1021.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.922.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.1022.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||||
<PackageReference Include="Realm" Version="10.15.1" />
|
<PackageReference Include="Realm" Version="10.17.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -137,12 +137,13 @@ namespace osu.Desktop
|
|||||||
{
|
{
|
||||||
base.SetHost(host);
|
base.SetHost(host);
|
||||||
|
|
||||||
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
|
||||||
|
|
||||||
var desktopWindow = (SDL2DesktopWindow)host.Window;
|
var desktopWindow = (SDL2DesktopWindow)host.Window;
|
||||||
|
|
||||||
|
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
||||||
|
if (iconStream != null)
|
||||||
|
desktopWindow.SetIconFromStream(iconStream);
|
||||||
|
|
||||||
desktopWindow.CursorState |= CursorState.Hidden;
|
desktopWindow.CursorState |= CursorState.Hidden;
|
||||||
desktopWindow.SetIconFromStream(iconStream);
|
|
||||||
desktopWindow.Title = Name;
|
desktopWindow.Title = Name;
|
||||||
desktopWindow.DragDrop += f => fileDrop(new[] { f });
|
desktopWindow.DragDrop += f => fileDrop(new[] { f });
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
|
||||||
<PackageReference Include="nunit" Version="3.13.3" />
|
<PackageReference Include="nunit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Rulesets.Catch.Mods;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneCatchModFlashlight : ModTestScene
|
||||||
|
{
|
||||||
|
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
|
||||||
|
|
||||||
|
[TestCase(1f)]
|
||||||
|
[TestCase(0.5f)]
|
||||||
|
[TestCase(1.25f)]
|
||||||
|
[TestCase(1.5f)]
|
||||||
|
public void TestSizeMultiplier(float sizeMultiplier) => CreateModTest(new ModTestData { Mod = new CatchModFlashlight { SizeMultiplier = { Value = sizeMultiplier } }, PassCondition = () => true });
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new CatchModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true });
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Catch.Mods;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
@ -12,11 +17,11 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneCatchTouchInput : OsuTestScene
|
public class TestSceneCatchTouchInput : OsuTestScene
|
||||||
{
|
{
|
||||||
private CatchTouchInputMapper catchTouchInputMapper = null!;
|
[Test]
|
||||||
|
public void TestBasic()
|
||||||
[SetUpSteps]
|
|
||||||
public void SetUpSteps()
|
|
||||||
{
|
{
|
||||||
|
CatchTouchInputMapper catchTouchInputMapper = null!;
|
||||||
|
|
||||||
AddStep("create input overlay", () =>
|
AddStep("create input overlay", () =>
|
||||||
{
|
{
|
||||||
Child = new CatchInputManager(new CatchRuleset().RulesetInfo)
|
Child = new CatchInputManager(new CatchRuleset().RulesetInfo)
|
||||||
@ -32,12 +37,30 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AddStep("show overlay", () => catchTouchInputMapper.Show());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestBasic()
|
public void TestWithoutRelax()
|
||||||
{
|
{
|
||||||
AddStep("show overlay", () => catchTouchInputMapper.Show());
|
AddStep("create drawable ruleset without relax mod", () =>
|
||||||
|
{
|
||||||
|
Child = new DrawableCatchRuleset(new CatchRuleset(), new CatchBeatmap(), new List<Mod>());
|
||||||
|
});
|
||||||
|
AddUntilStep("wait for load", () => Child.IsLoaded);
|
||||||
|
AddAssert("check touch input is shown", () => this.ChildrenOfType<CatchTouchInputMapper>().Any());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestWithRelax()
|
||||||
|
{
|
||||||
|
AddStep("create drawable ruleset with relax mod", () =>
|
||||||
|
{
|
||||||
|
Child = new DrawableCatchRuleset(new CatchRuleset(), new CatchBeatmap(), new List<Mod> { new CatchModRelax() });
|
||||||
|
});
|
||||||
|
AddUntilStep("wait for load", () => Child.IsLoaded);
|
||||||
|
AddAssert("check touch input is not shown", () => !this.ChildrenOfType<CatchTouchInputMapper>().Any());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
@ -12,6 +12,8 @@ using osu.Game.Rulesets.Catch.Objects.Drawables;
|
|||||||
using osu.Game.Rulesets.Catch.UI;
|
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.Screens.Play;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -19,15 +21,28 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
public class TestSceneComboCounter : CatchSkinnableTestScene
|
public class TestSceneComboCounter : CatchSkinnableTestScene
|
||||||
{
|
{
|
||||||
private ScoreProcessor scoreProcessor;
|
private ScoreProcessor scoreProcessor = null!;
|
||||||
|
|
||||||
private Color4 judgedObjectColour = Color4.White;
|
private Color4 judgedObjectColour = Color4.White;
|
||||||
|
|
||||||
|
private readonly Bindable<bool> showHud = new Bindable<bool>(true);
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Dependencies.CacheAs<Player>(new TestPlayer
|
||||||
|
{
|
||||||
|
ShowingOverlayComponents = { BindTarget = showHud },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
scoreProcessor = new ScoreProcessor(new CatchRuleset());
|
scoreProcessor = new ScoreProcessor(new CatchRuleset());
|
||||||
|
|
||||||
|
showHud.Value = true;
|
||||||
|
|
||||||
SetContents(_ => new CatchComboDisplay
|
SetContents(_ => new CatchComboDisplay
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
@ -51,9 +66,15 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
1f
|
1f
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AddStep("set hud to never show", () => showHud.Value = false);
|
||||||
|
AddRepeatStep("perform hit", () => performJudgement(HitResult.Great), 5);
|
||||||
|
|
||||||
|
AddStep("set hud to show", () => showHud.Value = true);
|
||||||
|
AddRepeatStep("perform hit", () => performJudgement(HitResult.Great), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void performJudgement(HitResult type, Judgement judgement = null)
|
private void performJudgement(HitResult type, Judgement? judgement = null)
|
||||||
{
|
{
|
||||||
var judgedObject = new DrawableFruit(new Fruit()) { AccentColour = { Value = judgedObjectColour } };
|
var judgedObject = new DrawableFruit(new Fruit()) { AccentColour = { Value = judgedObjectColour } };
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Import Project="..\osu.TestProject.props" />
|
<Import Project="..\osu.TestProject.props" />
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
|
@ -36,5 +36,7 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
|
|
||||||
return base.CreateHitObjectBlueprintFor(hitObject);
|
return base.CreateHitObjectBlueprintFor(hitObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected sealed override DragBox CreateDragBox() => new ScrollingDragBox(Composer.Playfield);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 System;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Edit
|
||||||
|
{
|
||||||
|
public class CatchEditorPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
|
||||||
|
{
|
||||||
|
protected override Container<Drawable> Content => content;
|
||||||
|
private readonly Container content;
|
||||||
|
|
||||||
|
public CatchEditorPlayfieldAdjustmentContainer()
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre;
|
||||||
|
Origin = Anchor.TopCentre;
|
||||||
|
Size = new Vector2(0.8f, 0.9f);
|
||||||
|
|
||||||
|
InternalChild = new ScalingContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Child = content = new Container { RelativeSizeAxes = Axes.Both },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScalingContainer : Container
|
||||||
|
{
|
||||||
|
public ScalingContainer()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
Width = CatchPlayfield.WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
Scale = new Vector2(Math.Min(Parent.ChildSize.X / CatchPlayfield.WIDTH, Parent.ChildSize.Y / CatchPlayfield.HEIGHT));
|
||||||
|
Height = 1 / Scale.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@ -10,10 +11,11 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.EnumExtensions;
|
using osu.Framework.Extensions.EnumExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
@ -21,7 +23,6 @@ using osu.Game.Rulesets.Edit.Tools;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Edit.Components.TernaryButtons;
|
|
||||||
using osu.Game.Screens.Edit.Compose.Components;
|
using osu.Game.Screens.Edit.Compose.Components;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -33,10 +34,14 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
|
|
||||||
private CatchDistanceSnapGrid distanceSnapGrid;
|
private CatchDistanceSnapGrid distanceSnapGrid;
|
||||||
|
|
||||||
private readonly Bindable<TernaryState> distanceSnapToggle = new Bindable<TernaryState>();
|
|
||||||
|
|
||||||
private InputManager inputManager;
|
private InputManager inputManager;
|
||||||
|
|
||||||
|
private readonly BindableDouble timeRangeMultiplier = new BindableDouble(1)
|
||||||
|
{
|
||||||
|
MinValue = 1,
|
||||||
|
MaxValue = 10,
|
||||||
|
};
|
||||||
|
|
||||||
public CatchHitObjectComposer(CatchRuleset ruleset)
|
public CatchHitObjectComposer(CatchRuleset ruleset)
|
||||||
: base(ruleset)
|
: base(ruleset)
|
||||||
{
|
{
|
||||||
@ -51,7 +56,10 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
|
|
||||||
LayerBelowRuleset.Add(new PlayfieldBorder
|
LayerBelowRuleset.Add(new PlayfieldBorder
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.BottomCentre,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = CatchPlayfield.HEIGHT,
|
||||||
PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Corners }
|
PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Corners }
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -70,6 +78,19 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
inputManager = GetContainingInputManager();
|
inputManager = GetContainingInputManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override double ReadCurrentDistanceSnap(HitObject before, HitObject after)
|
||||||
|
{
|
||||||
|
// osu!catch's distance snap implementation is limited, in that a custom spacing cannot be specified.
|
||||||
|
// Therefore this functionality is not currently used.
|
||||||
|
//
|
||||||
|
// The implementation below is probably correct but should be checked if/when exposed via controls.
|
||||||
|
|
||||||
|
float expectedDistance = DurationToDistance(before, after.StartTime - before.GetEndTime());
|
||||||
|
float actualDistance = Math.Abs(((CatchHitObject)before).EffectiveX - ((CatchHitObject)after).EffectiveX);
|
||||||
|
|
||||||
|
return actualDistance / expectedDistance;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
@ -77,8 +98,30 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
updateDistanceSnapGrid();
|
updateDistanceSnapGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
|
{
|
||||||
|
switch (e.Action)
|
||||||
|
{
|
||||||
|
// Note that right now these are hard to use as the default key bindings conflict with existing editor key bindings.
|
||||||
|
// In the future we will want to expose this via UI and potentially change the key bindings to be editor-specific.
|
||||||
|
// May be worth considering standardising "zoom" behaviour with what the timeline uses (ie. alt-wheel) but that may cause new conflicts.
|
||||||
|
case GlobalAction.IncreaseScrollSpeed:
|
||||||
|
this.TransformBindableTo(timeRangeMultiplier, timeRangeMultiplier.Value - 1, 200, Easing.OutQuint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GlobalAction.DecreaseScrollSpeed:
|
||||||
|
this.TransformBindableTo(timeRangeMultiplier, timeRangeMultiplier.Value + 1, 200, Easing.OutQuint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnPressed(e);
|
||||||
|
}
|
||||||
|
|
||||||
protected override DrawableRuleset<CatchHitObject> CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null) =>
|
protected override DrawableRuleset<CatchHitObject> CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null) =>
|
||||||
new DrawableCatchEditorRuleset(ruleset, beatmap, mods);
|
new DrawableCatchEditorRuleset(ruleset, beatmap, mods)
|
||||||
|
{
|
||||||
|
TimeRangeMultiplier = { BindTarget = timeRangeMultiplier, }
|
||||||
|
};
|
||||||
|
|
||||||
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]
|
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]
|
||||||
{
|
{
|
||||||
@ -87,11 +130,6 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
new BananaShowerCompositionTool()
|
new BananaShowerCompositionTool()
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override IEnumerable<TernaryButton> CreateTernaryButtons() => base.CreateTernaryButtons().Concat(new[]
|
|
||||||
{
|
|
||||||
new TernaryButton(distanceSnapToggle, "Distance Snap", () => new SpriteIcon { Icon = FontAwesome.Solid.Ruler })
|
|
||||||
});
|
|
||||||
|
|
||||||
public override SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.All)
|
public override SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.All)
|
||||||
{
|
{
|
||||||
var result = base.FindSnappedPositionAndTime(screenSpacePosition, snapType);
|
var result = base.FindSnappedPositionAndTime(screenSpacePosition, snapType);
|
||||||
@ -163,7 +201,7 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
|
|
||||||
private void updateDistanceSnapGrid()
|
private void updateDistanceSnapGrid()
|
||||||
{
|
{
|
||||||
if (distanceSnapToggle.Value != TernaryState.True)
|
if (DistanceSnapToggle.Value != TernaryState.True)
|
||||||
{
|
{
|
||||||
distanceSnapGrid.Hide();
|
distanceSnapGrid.Hide();
|
||||||
return;
|
return;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
@ -13,11 +14,24 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
{
|
{
|
||||||
public class DrawableCatchEditorRuleset : DrawableCatchRuleset
|
public class DrawableCatchEditorRuleset : DrawableCatchRuleset
|
||||||
{
|
{
|
||||||
|
public readonly BindableDouble TimeRangeMultiplier = new BindableDouble(1);
|
||||||
|
|
||||||
public DrawableCatchEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
public DrawableCatchEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
double gamePlayTimeRange = GetTimeRange(Beatmap.Difficulty.ApproachRate);
|
||||||
|
float playfieldStretch = Playfield.DrawHeight / CatchPlayfield.HEIGHT;
|
||||||
|
TimeRange.Value = gamePlayTimeRange * TimeRangeMultiplier.Value * playfieldStretch;
|
||||||
|
}
|
||||||
|
|
||||||
protected override Playfield CreatePlayfield() => new CatchEditorPlayfield(Beatmap.Difficulty);
|
protected override Playfield CreatePlayfield() => new CatchEditorPlayfield(Beatmap.Difficulty);
|
||||||
|
|
||||||
|
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new CatchEditorPlayfieldAdjustmentContainer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
|
|
||||||
public override BindableBool ComboBasedSize { get; } = new BindableBool(true);
|
public override BindableBool ComboBasedSize { get; } = new BindableBool(true);
|
||||||
|
|
||||||
public override float DefaultFlashlightSize => 350;
|
public override float DefaultFlashlightSize => 325;
|
||||||
|
|
||||||
protected override Flashlight CreateFlashlight() => new CatchFlashlight(this, playfield);
|
protected override Flashlight CreateFlashlight() => new CatchFlashlight(this, playfield);
|
||||||
|
|
||||||
@ -44,7 +44,19 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
: base(modFlashlight)
|
: base(modFlashlight)
|
||||||
{
|
{
|
||||||
this.playfield = playfield;
|
this.playfield = playfield;
|
||||||
FlashlightSize = new Vector2(0, GetSizeFor(0));
|
|
||||||
|
FlashlightSize = new Vector2(0, GetSize());
|
||||||
|
FlashlightSmoothness = 1.4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override float GetComboScaleFor(int combo)
|
||||||
|
{
|
||||||
|
if (combo >= 200)
|
||||||
|
return 0.770f;
|
||||||
|
if (combo >= 100)
|
||||||
|
return 0.885f;
|
||||||
|
|
||||||
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
@ -54,9 +66,9 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
FlashlightPosition = playfield.CatcherArea.ToSpaceOfOtherDrawable(playfield.Catcher.DrawPosition, this);
|
FlashlightPosition = playfield.CatcherArea.ToSpaceOfOtherDrawable(playfield.Catcher.DrawPosition, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnComboChange(ValueChangedEvent<int> e)
|
protected override void UpdateFlashlightSize(float size)
|
||||||
{
|
{
|
||||||
this.TransformTo(nameof(FlashlightSize), new Vector2(0, GetSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION);
|
this.TransformTo(nameof(FlashlightSize), new Vector2(0, size), FLASHLIGHT_FADE_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string FragmentShader => "CircularFlashlight";
|
protected override string FragmentShader => "CircularFlashlight";
|
||||||
|
@ -19,17 +19,20 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
{
|
{
|
||||||
public override LocalisableString Description => @"Use the mouse to control the catcher.";
|
public override LocalisableString Description => @"Use the mouse to control the catcher.";
|
||||||
|
|
||||||
private DrawableRuleset<CatchHitObject> drawableRuleset = null!;
|
private DrawableCatchRuleset drawableRuleset = null!;
|
||||||
|
|
||||||
public void ApplyToDrawableRuleset(DrawableRuleset<CatchHitObject> drawableRuleset)
|
public void ApplyToDrawableRuleset(DrawableRuleset<CatchHitObject> drawableRuleset)
|
||||||
{
|
{
|
||||||
this.drawableRuleset = drawableRuleset;
|
this.drawableRuleset = (DrawableCatchRuleset)drawableRuleset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyToPlayer(Player player)
|
public void ApplyToPlayer(Player player)
|
||||||
{
|
{
|
||||||
if (!drawableRuleset.HasReplayLoaded.Value)
|
if (!drawableRuleset.HasReplayLoaded.Value)
|
||||||
drawableRuleset.Cursor.Add(new MouseInputHelper((CatchPlayfield)drawableRuleset.Playfield));
|
{
|
||||||
|
var catchPlayfield = (CatchPlayfield)drawableRuleset.Playfield;
|
||||||
|
catchPlayfield.CatcherArea.Add(new MouseInputHelper(catchPlayfield.CatcherArea));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MouseInputHelper : Drawable, IKeyBindingHandler<CatchAction>, IRequireHighFrequencyMousePosition
|
private class MouseInputHelper : Drawable, IKeyBindingHandler<CatchAction>, IRequireHighFrequencyMousePosition
|
||||||
@ -38,9 +41,10 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
|
||||||
|
|
||||||
public MouseInputHelper(CatchPlayfield playfield)
|
public MouseInputHelper(CatcherArea catcherArea)
|
||||||
{
|
{
|
||||||
catcherArea = playfield.CatcherArea;
|
this.catcherArea = catcherArea;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
{
|
{
|
||||||
public class CatchLegacySkinTransformer : LegacySkinTransformer
|
public class CatchLegacySkinTransformer : LegacySkinTransformer
|
||||||
{
|
{
|
||||||
|
public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasPear;
|
||||||
|
|
||||||
|
private bool hasPear => GetTexture("fruit-pear") != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For simplicity, let's use legacy combo font texture existence as a way to identify legacy skins from default.
|
/// For simplicity, let's use legacy combo font texture existence as a way to identify legacy skins from default.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -49,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
switch (catchSkinComponent.Component)
|
switch (catchSkinComponent.Component)
|
||||||
{
|
{
|
||||||
case CatchSkinComponents.Fruit:
|
case CatchSkinComponents.Fruit:
|
||||||
if (GetTexture("fruit-pear") != null)
|
if (hasPear)
|
||||||
return new LegacyFruitPiece();
|
return new LegacyFruitPiece();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using JetBrains.Annotations;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -19,14 +20,29 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
private int currentCombo;
|
private int currentCombo;
|
||||||
|
|
||||||
[CanBeNull]
|
public ICatchComboCounter? ComboCounter => Drawable as ICatchComboCounter;
|
||||||
public ICatchComboCounter ComboCounter => Drawable as ICatchComboCounter;
|
|
||||||
|
private readonly IBindable<bool> showCombo = new BindableBool(true);
|
||||||
|
|
||||||
public CatchComboDisplay()
|
public CatchComboDisplay()
|
||||||
: base(new CatchSkinComponent(CatchSkinComponents.CatchComboCounter), _ => Empty())
|
: base(new CatchSkinComponent(CatchSkinComponents.CatchComboCounter), _ => Empty())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
private Player? player { get; set; }
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
showCombo.BindTo(player.ShowingOverlayComponents);
|
||||||
|
showCombo.BindValueChanged(s => this.FadeTo(s.NewValue ? 1 : 0, HUDOverlay.FADE_DURATION, HUDOverlay.FADE_EASING), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void SkinChanged(ISkinSource skin)
|
protected override void SkinChanged(ISkinSource skin)
|
||||||
{
|
{
|
||||||
base.SkinChanged(skin);
|
base.SkinChanged(skin);
|
||||||
|
@ -23,6 +23,12 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const float WIDTH = 512;
|
public const float WIDTH = 512;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The height of the playfield.
|
||||||
|
/// This doesn't include the catcher area.
|
||||||
|
/// </summary>
|
||||||
|
public const float HEIGHT = 384;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The center position of the playfield.
|
/// The center position of the playfield.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -30,15 +31,19 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
Direction.Value = ScrollingDirection.Down;
|
Direction.Value = ScrollingDirection.Down;
|
||||||
TimeRange.Value = IBeatmapDifficultyInfo.DifficultyRange(beatmap.Difficulty.ApproachRate, 1800, 1200, 450);
|
TimeRange.Value = GetTimeRange(beatmap.Difficulty.ApproachRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
KeyBindingInputManager.Add(new CatchTouchInputMapper());
|
// With relax mod, input maps directly to x position and left/right buttons are not used.
|
||||||
|
if (!Mods.Any(m => m is ModRelax))
|
||||||
|
KeyBindingInputManager.Add(new CatchTouchInputMapper());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected double GetTimeRange(float approachRate) => IBeatmapDifficultyInfo.DifficultyRange(approachRate, 1800, 1200, 450);
|
||||||
|
|
||||||
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
|
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
|
||||||
|
|
||||||
protected override ReplayRecorder CreateReplayRecorder(Score score) => new CatchReplayRecorder(score, (CatchPlayfield)Playfield);
|
protected override ReplayRecorder CreateReplayRecorder(Score score) => new CatchReplayRecorder(score, (CatchPlayfield)Playfield);
|
||||||
|
@ -10,6 +10,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
@ -30,15 +31,18 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
[Cached(typeof(IScrollingInfo))]
|
[Cached(typeof(IScrollingInfo))]
|
||||||
private IScrollingInfo scrollingInfo;
|
private IScrollingInfo scrollingInfo;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly StageDefinition stage = new StageDefinition(5);
|
||||||
|
|
||||||
protected ManiaPlacementBlueprintTestScene()
|
protected ManiaPlacementBlueprintTestScene()
|
||||||
{
|
{
|
||||||
scrollingInfo = ((ScrollingTestContainer)HitObjectContainer).ScrollingInfo;
|
scrollingInfo = ((ScrollingTestContainer)HitObjectContainer).ScrollingInfo;
|
||||||
|
|
||||||
Add(column = new Column(0)
|
Add(column = new Column(0, false)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
AccentColour = Color4.OrangeRed,
|
AccentColour = { Value = Color4.OrangeRed },
|
||||||
Clock = new FramedClock(new StopwatchClock()), // No scroll
|
Clock = new FramedClock(new StopwatchClock()), // No scroll
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
|
|
||||||
protected ManiaSelectionBlueprintTestScene(int columns)
|
protected ManiaSelectionBlueprintTestScene(int columns)
|
||||||
{
|
{
|
||||||
var stageDefinitions = new List<StageDefinition> { new StageDefinition { Columns = columns } };
|
var stageDefinitions = new List<StageDefinition> { new StageDefinition(columns) };
|
||||||
base.Content.Child = scrollingTestContainer = new ScrollingTestContainer(ScrollingDirection.Up)
|
base.Content.Child = scrollingTestContainer = new ScrollingTestContainer(ScrollingDirection.Up)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
private ScrollingTestContainer.TestScrollingInfo scrollingInfo = new ScrollingTestContainer.TestScrollingInfo();
|
private ScrollingTestContainer.TestScrollingInfo scrollingInfo = new ScrollingTestContainer.TestScrollingInfo();
|
||||||
|
|
||||||
[Cached(typeof(EditorBeatmap))]
|
[Cached(typeof(EditorBeatmap))]
|
||||||
private EditorBeatmap editorBeatmap = new EditorBeatmap(new ManiaBeatmap(new StageDefinition())
|
private EditorBeatmap editorBeatmap = new EditorBeatmap(new ManiaBeatmap(new StageDefinition(2))
|
||||||
{
|
{
|
||||||
BeatmapInfo =
|
BeatmapInfo =
|
||||||
{
|
{
|
||||||
@ -56,8 +56,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
{
|
{
|
||||||
Playfield = new ManiaPlayfield(new List<StageDefinition>
|
Playfield = new ManiaPlayfield(new List<StageDefinition>
|
||||||
{
|
{
|
||||||
new StageDefinition { Columns = 4 },
|
new StageDefinition(4),
|
||||||
new StageDefinition { Columns = 3 }
|
new StageDefinition(3)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
Clock = new FramedClock(new StopwatchClock())
|
Clock = new FramedClock(new StopwatchClock())
|
||||||
|
@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
{
|
{
|
||||||
AddStep("setup compose screen", () =>
|
AddStep("setup compose screen", () =>
|
||||||
{
|
{
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 4 })
|
var beatmap = new ManiaBeatmap(new StageDefinition(4))
|
||||||
{
|
{
|
||||||
BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo },
|
BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo },
|
||||||
};
|
};
|
||||||
|
@ -205,7 +205,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
{
|
{
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
EditorBeatmap = new EditorBeatmap(new ManiaBeatmap(new StageDefinition { Columns = 4 })
|
EditorBeatmap = new EditorBeatmap(new ManiaBeatmap(new StageDefinition(4))
|
||||||
{
|
{
|
||||||
BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }
|
BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }
|
||||||
}),
|
}),
|
||||||
|
@ -1,52 +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.
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
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 (int i = 0; i < definition.Columns; i++)
|
|
||||||
yield return definition.GetTypeOfColumn(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests
|
namespace osu.Game.Rulesets.Mania.Tests
|
||||||
@ -37,7 +39,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ReloadMappings()
|
protected override void ReloadMappings(IQueryable<RealmKeyBinding> realmKeyBindings)
|
||||||
{
|
{
|
||||||
KeyBindings = DefaultKeyBindings;
|
KeyBindings = DefaultKeyBindings;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
[TestCase(ManiaAction.Key8)]
|
[TestCase(ManiaAction.Key8)]
|
||||||
public void TestEncodeDecodeSingleStage(params ManiaAction[] actions)
|
public void TestEncodeDecodeSingleStage(params ManiaAction[] actions)
|
||||||
{
|
{
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 9 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(9));
|
||||||
|
|
||||||
var frame = new ManiaReplayFrame(0, actions);
|
var frame = new ManiaReplayFrame(0, actions);
|
||||||
var legacyFrame = frame.ToLegacy(beatmap);
|
var legacyFrame = frame.ToLegacy(beatmap);
|
||||||
@ -38,8 +38,8 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
[TestCase(ManiaAction.Key8)]
|
[TestCase(ManiaAction.Key8)]
|
||||||
public void TestEncodeDecodeDualStage(params ManiaAction[] actions)
|
public void TestEncodeDecodeDualStage(params ManiaAction[] actions)
|
||||||
{
|
{
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 5 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(5));
|
||||||
beatmap.Stages.Add(new StageDefinition { Columns = 5 });
|
beatmap.Stages.Add(new StageDefinition(5));
|
||||||
|
|
||||||
var frame = new ManiaReplayFrame(0, actions);
|
var frame = new ManiaReplayFrame(0, actions);
|
||||||
var legacyFrame = frame.ToLegacy(beatmap);
|
var legacyFrame = frame.ToLegacy(beatmap);
|
||||||
|
49
osu.Game.Rulesets.Mania.Tests/ManiaSpecialColumnTest.cs
Normal file
49
osu.Game.Rulesets.Mania.Tests/ManiaSpecialColumnTest.cs
Normal file
@ -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.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ManiaSpecialColumnTest
|
||||||
|
{
|
||||||
|
[TestCase(new[]
|
||||||
|
{
|
||||||
|
true
|
||||||
|
}, 1)]
|
||||||
|
[TestCase(new[]
|
||||||
|
{
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
}, 4)]
|
||||||
|
[TestCase(new[]
|
||||||
|
{
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
}, 7)]
|
||||||
|
public void Test(IEnumerable<bool> special, int columns)
|
||||||
|
{
|
||||||
|
var definition = new StageDefinition(columns);
|
||||||
|
var results = getResults(definition);
|
||||||
|
Assert.AreEqual(special, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<bool> getResults(StageDefinition definition)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < definition.Columns; i++)
|
||||||
|
yield return definition.IsSpecialColumn(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Rulesets.Mania.Mods;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneManiaModFlashlight : ModTestScene
|
||||||
|
{
|
||||||
|
protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset();
|
||||||
|
|
||||||
|
[TestCase(1f)]
|
||||||
|
[TestCase(0.5f)]
|
||||||
|
[TestCase(1.5f)]
|
||||||
|
[TestCase(3f)]
|
||||||
|
public void TestSizeMultiplier(float sizeMultiplier) => CreateModTest(new ModTestData { Mod = new ManiaModFlashlight { SizeMultiplier = { Value = sizeMultiplier } }, PassCondition = () => true });
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new ManiaModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true });
|
||||||
|
}
|
||||||
|
}
|
@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods
|
|||||||
|
|
||||||
private static ManiaBeatmap createRawBeatmap()
|
private static ManiaBeatmap createRawBeatmap()
|
||||||
{
|
{
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(1));
|
||||||
beatmap.ControlPointInfo.Add(0.0, new TimingControlPoint { BeatLength = 1000 }); // Set BPM to 60
|
beatmap.ControlPointInfo.Add(0.0, new TimingControlPoint { BeatLength = 1000 }); // Set BPM to 60
|
||||||
|
|
||||||
// Add test hit objects
|
// Add test hit objects
|
||||||
|
@ -8,7 +8,6 @@ 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.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
{
|
{
|
||||||
@ -24,15 +23,16 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
[Cached]
|
[Cached]
|
||||||
private readonly Column column;
|
private readonly Column column;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly StageDefinition stageDefinition = new StageDefinition(5);
|
||||||
|
|
||||||
public ColumnTestContainer(int column, ManiaAction action, bool showColumn = false)
|
public ColumnTestContainer(int column, ManiaAction action, bool showColumn = false)
|
||||||
{
|
{
|
||||||
InternalChildren = new[]
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
this.column = new Column(column)
|
this.column = new Column(column, false)
|
||||||
{
|
{
|
||||||
Action = { Value = action },
|
Action = { Value = action },
|
||||||
AccentColour = Color4.Orange,
|
|
||||||
ColumnType = column % 2 == 0 ? ColumnType.Even : ColumnType.Odd,
|
|
||||||
Alpha = showColumn ? 1 : 0
|
Alpha = showColumn ? 1 : 0
|
||||||
},
|
},
|
||||||
content = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
content = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
||||||
|
@ -61,7 +61,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
c.Add(CreateHitObject().With(h =>
|
c.Add(CreateHitObject().With(h =>
|
||||||
{
|
{
|
||||||
h.HitObject.StartTime = Time.Current + 5000;
|
h.HitObject.StartTime = Time.Current + 5000;
|
||||||
h.AccentColour.Value = Color4.Orange;
|
|
||||||
}));
|
}));
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -9,6 +9,7 @@ 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.Beatmaps;
|
||||||
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;
|
||||||
@ -24,6 +25,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
[Cached(Type = typeof(IScrollingInfo))]
|
[Cached(Type = typeof(IScrollingInfo))]
|
||||||
private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo();
|
private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo();
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly StageDefinition stage = new StageDefinition(4);
|
||||||
|
|
||||||
protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset();
|
protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset();
|
||||||
|
|
||||||
protected ManiaSkinnableTestScene()
|
protected ManiaSkinnableTestScene()
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
{
|
{
|
||||||
var stageDefinitions = new List<StageDefinition>
|
var stageDefinitions = new List<StageDefinition>
|
||||||
{
|
{
|
||||||
new StageDefinition { Columns = 4 },
|
new StageDefinition(4),
|
||||||
};
|
};
|
||||||
|
|
||||||
SetContents(_ => new ManiaPlayfield(stageDefinitions).With(s =>
|
SetContents(_ => new ManiaPlayfield(stageDefinitions).With(s =>
|
||||||
|
@ -1,51 +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.
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Rulesets.Mania.UI.Components;
|
|
||||||
using osu.Game.Skinning;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|
||||||
{
|
|
||||||
public class TestSceneKeyArea : 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 SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea), _ => new DefaultKeyArea())
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both
|
|
||||||
},
|
|
||||||
},
|
|
||||||
new ColumnTestContainer(1, ManiaAction.Key2)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Width = 0.5f,
|
|
||||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea), _ => new DefaultKeyArea())
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
{
|
{
|
||||||
stageDefinitions = new List<StageDefinition>
|
stageDefinitions = new List<StageDefinition>
|
||||||
{
|
{
|
||||||
new StageDefinition { Columns = 2 }
|
new StageDefinition(2)
|
||||||
};
|
};
|
||||||
|
|
||||||
SetContents(_ => new ManiaPlayfield(stageDefinitions));
|
SetContents(_ => new ManiaPlayfield(stageDefinitions));
|
||||||
@ -36,8 +36,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
{
|
{
|
||||||
stageDefinitions = new List<StageDefinition>
|
stageDefinitions = new List<StageDefinition>
|
||||||
{
|
{
|
||||||
new StageDefinition { Columns = 2 },
|
new StageDefinition(2),
|
||||||
new StageDefinition { Columns = 2 }
|
new StageDefinition(2)
|
||||||
};
|
};
|
||||||
|
|
||||||
SetContents(_ => new ManiaPlayfield(stageDefinitions));
|
SetContents(_ => new ManiaPlayfield(stageDefinitions));
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
|
|
||||||
return new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
return new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
||||||
{
|
{
|
||||||
Child = new Stage(0, new StageDefinition { Columns = 4 }, ref normalAction, ref specialAction)
|
Child = new Stage(0, new StageDefinition(4), ref normalAction, ref specialAction)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Mania.UI.Components;
|
using osu.Game.Rulesets.Mania.UI.Components;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
@ -16,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
SetContents(_ => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground, stageDefinition: new StageDefinition { Columns = 4 }),
|
SetContents(_ => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground),
|
||||||
_ => new DefaultStageBackground())
|
_ => new DefaultStageBackground())
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||||
@ -15,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
SetContents(_ => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground, stageDefinition: new StageDefinition { Columns = 4 }), _ => null)
|
SetContents(_ => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground), _ => null)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
// | - |
|
// | - |
|
||||||
// | |
|
// | |
|
||||||
|
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(1));
|
||||||
beatmap.HitObjects.Add(new Note { StartTime = 1000 });
|
beatmap.HitObjects.Add(new Note { StartTime = 1000 });
|
||||||
|
|
||||||
var generated = new ManiaAutoGenerator(beatmap).Generate();
|
var generated = new ManiaAutoGenerator(beatmap).Generate();
|
||||||
@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
// | * |
|
// | * |
|
||||||
// | |
|
// | |
|
||||||
|
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(1));
|
||||||
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 });
|
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 });
|
||||||
|
|
||||||
var generated = new ManiaAutoGenerator(beatmap).Generate();
|
var generated = new ManiaAutoGenerator(beatmap).Generate();
|
||||||
@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
// | - | - |
|
// | - | - |
|
||||||
// | | |
|
// | | |
|
||||||
|
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(2));
|
||||||
beatmap.HitObjects.Add(new Note { StartTime = 1000 });
|
beatmap.HitObjects.Add(new Note { StartTime = 1000 });
|
||||||
beatmap.HitObjects.Add(new Note { StartTime = 1000, Column = 1 });
|
beatmap.HitObjects.Add(new Note { StartTime = 1000, Column = 1 });
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
// | * | * |
|
// | * | * |
|
||||||
// | | |
|
// | | |
|
||||||
|
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(2));
|
||||||
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 });
|
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 });
|
||||||
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000, Column = 1 });
|
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000, Column = 1 });
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
// | - | |
|
// | - | |
|
||||||
// | | |
|
// | | |
|
||||||
|
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(2));
|
||||||
beatmap.HitObjects.Add(new Note { StartTime = 1000 });
|
beatmap.HitObjects.Add(new Note { StartTime = 1000 });
|
||||||
beatmap.HitObjects.Add(new Note { StartTime = 2000, Column = 1 });
|
beatmap.HitObjects.Add(new Note { StartTime = 2000, Column = 1 });
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
// | * | |
|
// | * | |
|
||||||
// | | |
|
// | | |
|
||||||
|
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(2));
|
||||||
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 });
|
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 });
|
||||||
beatmap.HitObjects.Add(new HoldNote { StartTime = 2000, Duration = 2000, Column = 1 });
|
beatmap.HitObjects.Add(new HoldNote { StartTime = 2000, Duration = 2000, Column = 1 });
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
// | * | |
|
// | * | |
|
||||||
// | | |
|
// | | |
|
||||||
|
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 });
|
var beatmap = new ManiaBeatmap(new StageDefinition(2));
|
||||||
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 });
|
beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 });
|
||||||
beatmap.HitObjects.Add(new Note { StartTime = 3000, Column = 1 });
|
beatmap.HitObjects.Add(new Note { StartTime = 3000, Column = 1 });
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
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.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
@ -28,6 +29,9 @@ 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>();
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly StageDefinition stage = new StageDefinition(1);
|
||||||
|
|
||||||
private readonly List<Column> columns = new List<Column>();
|
private readonly List<Column> columns = new List<Column>();
|
||||||
|
|
||||||
public TestSceneColumn()
|
public TestSceneColumn()
|
||||||
@ -84,12 +88,12 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
|
|
||||||
private Drawable createColumn(ScrollingDirection direction, ManiaAction action, int index)
|
private Drawable createColumn(ScrollingDirection direction, ManiaAction action, int index)
|
||||||
{
|
{
|
||||||
var column = new Column(index)
|
var column = new Column(index, false)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Height = 0.85f,
|
Height = 0.85f,
|
||||||
AccentColour = Color4.OrangeRed,
|
AccentColour = { Value = Color4.OrangeRed },
|
||||||
Action = { Value = action },
|
Action = { Value = action },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
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.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
@ -24,6 +26,9 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
|
|
||||||
private Column column;
|
private Column column;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly StageDefinition stage = new StageDefinition(1);
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
@ -35,11 +40,11 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
TimeRange = 2000,
|
TimeRange = 2000,
|
||||||
Clock = new FramedClock(clock),
|
Clock = new FramedClock(clock),
|
||||||
Child = column = new Column(0)
|
Child = column = new Column(0, false)
|
||||||
{
|
{
|
||||||
Action = { Value = ManiaAction.Key1 },
|
Action = { Value = ManiaAction.Key1 },
|
||||||
Height = 0.85f,
|
Height = 0.85f,
|
||||||
AccentColour = Color4.Gray
|
AccentColour = { Value = Color4.Gray },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
assertHeadJudgement(HitResult.Miss);
|
assertHeadJudgement(HitResult.Miss);
|
||||||
assertTickJudgement(HitResult.LargeTickMiss);
|
assertTickJudgement(HitResult.LargeTickMiss);
|
||||||
assertTailJudgement(HitResult.Miss);
|
assertTailJudgement(HitResult.Miss);
|
||||||
assertNoteJudgement(HitResult.IgnoreHit);
|
assertNoteJudgement(HitResult.IgnoreMiss);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -76,8 +76,8 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
|
|
||||||
performTest(objects, new List<ReplayFrame>());
|
performTest(objects, new List<ReplayFrame>());
|
||||||
|
|
||||||
addJudgementAssert(objects[0], HitResult.IgnoreHit);
|
addJudgementAssert(objects[0], HitResult.IgnoreMiss);
|
||||||
addJudgementAssert(objects[1], HitResult.IgnoreHit);
|
addJudgementAssert(objects[1], HitResult.IgnoreMiss);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -141,7 +141,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
AddStep("load player", () =>
|
AddStep("load player", () =>
|
||||||
{
|
{
|
||||||
Beatmap.Value = CreateWorkingBeatmap(new ManiaBeatmap(new StageDefinition { Columns = 4 })
|
Beatmap.Value = CreateWorkingBeatmap(new ManiaBeatmap(new StageDefinition(4))
|
||||||
{
|
{
|
||||||
HitObjects = hitObjects,
|
HitObjects = hitObjects,
|
||||||
BeatmapInfo =
|
BeatmapInfo =
|
||||||
|
@ -135,7 +135,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
var specialAction = ManiaAction.Special1;
|
var specialAction = ManiaAction.Special1;
|
||||||
|
|
||||||
var stage = new Stage(0, new StageDefinition { Columns = 2 }, ref action, ref specialAction);
|
var stage = new Stage(0, new StageDefinition(2), ref action, ref specialAction);
|
||||||
stages.Add(stage);
|
stages.Add(stage);
|
||||||
|
|
||||||
return new ScrollingTestContainer(direction)
|
return new ScrollingTestContainer(direction)
|
||||||
|
@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
{
|
{
|
||||||
const double beat_length = 500;
|
const double beat_length = 500;
|
||||||
|
|
||||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 })
|
var beatmap = new ManiaBeatmap(new StageDefinition(1))
|
||||||
{
|
{
|
||||||
HitObjects =
|
HitObjects =
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Import Project="..\osu.TestProject.props" />
|
<Import Project="..\osu.TestProject.props" />
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
|
@ -1,14 +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.
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Beatmaps
|
|
||||||
{
|
|
||||||
public enum ColumnType
|
|
||||||
{
|
|
||||||
Even,
|
|
||||||
Odd,
|
|
||||||
Special
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -60,5 +61,18 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StageDefinition GetStageForColumnIndex(int column)
|
||||||
|
{
|
||||||
|
foreach (var stage in Stages)
|
||||||
|
{
|
||||||
|
if (column < stage.Columns)
|
||||||
|
return stage;
|
||||||
|
|
||||||
|
column -= stage.Columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(column), "Provided index exceeds all available stages");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,10 +93,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
|
|
||||||
protected override Beatmap<ManiaHitObject> CreateBeatmap()
|
protected override Beatmap<ManiaHitObject> CreateBeatmap()
|
||||||
{
|
{
|
||||||
beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns }, originalTargetColumns);
|
beatmap = new ManiaBeatmap(new StageDefinition(TargetColumns), originalTargetColumns);
|
||||||
|
|
||||||
if (Dual)
|
if (Dual)
|
||||||
beatmap.Stages.Add(new StageDefinition { Columns = TargetColumns });
|
beatmap.Stages.Add(new StageDefinition(TargetColumns));
|
||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
@ -11,32 +11,26 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines properties for each stage in a <see cref="ManiaPlayfield"/>.
|
/// Defines properties for each stage in a <see cref="ManiaPlayfield"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct StageDefinition
|
public class StageDefinition
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of <see cref="Column"/>s which this stage contains.
|
/// The number of <see cref="Column"/>s which this stage contains.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Columns;
|
public readonly int Columns;
|
||||||
|
|
||||||
|
public StageDefinition(int columns)
|
||||||
|
{
|
||||||
|
if (columns < 1)
|
||||||
|
throw new ArgumentException("Column count must be above zero.", nameof(columns));
|
||||||
|
|
||||||
|
Columns = columns;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the column index is a special column for this stage.
|
/// Whether the column index is a special column for this stage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <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 readonly 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 readonly 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
countOk = score.Statistics.GetValueOrDefault(HitResult.Ok);
|
countOk = score.Statistics.GetValueOrDefault(HitResult.Ok);
|
||||||
countMeh = score.Statistics.GetValueOrDefault(HitResult.Meh);
|
countMeh = score.Statistics.GetValueOrDefault(HitResult.Meh);
|
||||||
countMiss = score.Statistics.GetValueOrDefault(HitResult.Miss);
|
countMiss = score.Statistics.GetValueOrDefault(HitResult.Miss);
|
||||||
scoreAccuracy = customAccuracy;
|
scoreAccuracy = calculateCustomAccuracy();
|
||||||
|
|
||||||
// Arbitrary initial value for scaling pp in order to standardize distributions across game modes.
|
// Arbitrary initial value for scaling pp in order to standardize distributions across game modes.
|
||||||
// The specific number has no intrinsic meaning and can be adjusted as needed.
|
// The specific number has no intrinsic meaning and can be adjusted as needed.
|
||||||
@ -73,6 +73,12 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Accuracy used to weight judgements independently from the score's actual accuracy.
|
/// Accuracy used to weight judgements independently from the score's actual accuracy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private double customAccuracy => (countPerfect * 320 + countGreat * 300 + countGood * 200 + countOk * 100 + countMeh * 50) / (totalHits * 320);
|
private double calculateCustomAccuracy()
|
||||||
|
{
|
||||||
|
if (totalHits == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (countPerfect * 320 + countGreat * 300 + countGood * 200 + countOk * 100 + countMeh * 50) / (totalHits * 320);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,5 +33,7 @@ namespace osu.Game.Rulesets.Mania.Edit
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override SelectionHandler<HitObject> CreateSelectionHandler() => new ManiaSelectionHandler();
|
protected override SelectionHandler<HitObject> CreateSelectionHandler() => new ManiaSelectionHandler();
|
||||||
|
|
||||||
|
protected sealed override DragBox CreateDragBox() => new ScrollingDragBox(Composer.Playfield);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@ using osu.Game.Rulesets.Mania.Edit.Setup;
|
|||||||
using osu.Game.Rulesets.Mania.Mods;
|
using osu.Game.Rulesets.Mania.Mods;
|
||||||
using osu.Game.Rulesets.Mania.Replays;
|
using osu.Game.Rulesets.Mania.Replays;
|
||||||
using osu.Game.Rulesets.Mania.Scoring;
|
using osu.Game.Rulesets.Mania.Scoring;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning.Argon;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||||
using osu.Game.Rulesets.Mania.Skinning.Legacy;
|
using osu.Game.Rulesets.Mania.Skinning.Legacy;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
@ -66,6 +68,15 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
{
|
{
|
||||||
switch (skin)
|
switch (skin)
|
||||||
{
|
{
|
||||||
|
case TrianglesSkin:
|
||||||
|
return new ManiaTrianglesSkinTransformer(skin, beatmap);
|
||||||
|
|
||||||
|
case ArgonSkin:
|
||||||
|
return new ManiaArgonSkinTransformer(skin, beatmap);
|
||||||
|
|
||||||
|
case DefaultLegacySkin:
|
||||||
|
return new ManiaClassicSkinTransformer(skin, beatmap);
|
||||||
|
|
||||||
case LegacySkin:
|
case LegacySkin:
|
||||||
return new ManiaLegacySkinTransformer(skin, beatmap);
|
return new ManiaLegacySkinTransformer(skin, beatmap);
|
||||||
}
|
}
|
||||||
|
@ -3,29 +3,19 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
|
||||||
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>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The intended <see cref="StageDefinition"/> for this component.
|
|
||||||
/// May be null if the component is not a direct member of a <see cref="Stage"/>.
|
|
||||||
/// </summary>
|
|
||||||
public readonly StageDefinition? StageDefinition;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="ManiaSkinComponent"/>.
|
/// Creates a new <see cref="ManiaSkinComponent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="component">The component.</param>
|
/// <param name="component">The component.</param>
|
||||||
/// <param name="stageDefinition">The intended <see cref="StageDefinition"/> for this component. May be null if the component is not a direct member of a <see cref="Stage"/>.</param>
|
public ManiaSkinComponent(ManiaSkinComponents component)
|
||||||
public ManiaSkinComponent(ManiaSkinComponents component, StageDefinition? stageDefinition = null)
|
|
||||||
: base(component)
|
: base(component)
|
||||||
{
|
{
|
||||||
StageDefinition = stageDefinition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME;
|
protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME;
|
||||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public ManiaFlashlight(ManiaModFlashlight modFlashlight)
|
public ManiaFlashlight(ManiaModFlashlight modFlashlight)
|
||||||
: base(modFlashlight)
|
: base(modFlashlight)
|
||||||
{
|
{
|
||||||
FlashlightSize = new Vector2(DrawWidth, GetSizeFor(0));
|
FlashlightSize = new Vector2(DrawWidth, GetSize());
|
||||||
|
|
||||||
AddLayout(flashlightProperties);
|
AddLayout(flashlightProperties);
|
||||||
}
|
}
|
||||||
@ -54,9 +54,9 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnComboChange(ValueChangedEvent<int> e)
|
protected override void UpdateFlashlightSize(float size)
|
||||||
{
|
{
|
||||||
this.TransformTo(nameof(FlashlightSize), new Vector2(DrawWidth, GetSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION);
|
this.TransformTo(nameof(FlashlightSize), new Vector2(DrawWidth, size), FLASHLIGHT_FADE_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string FragmentShader => "RectangularFlashlight";
|
protected override string FragmentShader => "RectangularFlashlight";
|
||||||
|
@ -54,10 +54,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateInitialTransforms()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateStartTimeStateTransforms() => this.FadeOut(150);
|
protected override void UpdateStartTimeStateTransforms() => this.FadeOut(150);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,14 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
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.Containers;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Audio;
|
||||||
using osu.Game.Rulesets.Mania.Skinning.Default;
|
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -38,6 +40,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
private Container<DrawableHoldNoteTail> tailContainer;
|
private Container<DrawableHoldNoteTail> tailContainer;
|
||||||
private Container<DrawableHoldNoteTick> tickContainer;
|
private Container<DrawableHoldNoteTick> tickContainer;
|
||||||
|
|
||||||
|
private PausableSkinnableSound slidingSample;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the size of the hold note covering the whole head/tail bounds. The size of this container changes as the hold note is being pressed.
|
/// Contains the size of the hold note covering the whole head/tail bounds. The size of this container changes as the hold note is being pressed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -65,6 +69,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private double? releaseTime;
|
private double? releaseTime;
|
||||||
|
|
||||||
|
public override double MaximumJudgementOffset => Tail.MaximumJudgementOffset;
|
||||||
|
|
||||||
public DrawableHoldNote()
|
public DrawableHoldNote()
|
||||||
: this(null)
|
: this(null)
|
||||||
{
|
{
|
||||||
@ -108,6 +114,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
},
|
},
|
||||||
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
|
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
|
||||||
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
|
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
|
||||||
|
slidingSample = new PausableSkinnableSound { Looping = true }
|
||||||
});
|
});
|
||||||
|
|
||||||
maskedContents.AddRange(new[]
|
maskedContents.AddRange(new[]
|
||||||
@ -118,6 +125,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
isHitting.BindValueChanged(updateSlidingSample, true);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnApply()
|
protected override void OnApply()
|
||||||
{
|
{
|
||||||
base.OnApply();
|
base.OnApply();
|
||||||
@ -248,7 +262,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
tick.MissForcefully();
|
tick.MissForcefully();
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyResult(r => r.Type = r.Judgement.MaxResult);
|
ApplyResult(r => r.Type = Tail.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult);
|
||||||
endHold();
|
endHold();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,5 +336,38 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
HoldStartTime = null;
|
HoldStartTime = null;
|
||||||
isHitting.Value = false;
|
isHitting.Value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void LoadSamples()
|
||||||
|
{
|
||||||
|
// Note: base.LoadSamples() isn't called since the slider plays the tail's hitsounds for the time being.
|
||||||
|
|
||||||
|
if (HitObject.SampleControlPoint == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}."
|
||||||
|
+ $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
slidingSample.Samples = HitObject.CreateSlidingSamples().Select(s => HitObject.SampleControlPoint.ApplyTo(s)).Cast<ISampleInfo>().ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void StopAllSamples()
|
||||||
|
{
|
||||||
|
base.StopAllSamples();
|
||||||
|
slidingSample?.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
|
||||||
|
{
|
||||||
|
if (tracking.NewValue)
|
||||||
|
slidingSample?.Play();
|
||||||
|
else
|
||||||
|
slidingSample?.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnFree()
|
||||||
|
{
|
||||||
|
slidingSample.Samples = null;
|
||||||
|
base.OnFree();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,20 +30,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
|
|
||||||
public bool UpdateResult() => base.UpdateResult(true);
|
public bool UpdateResult() => base.UpdateResult(true);
|
||||||
|
|
||||||
protected override void UpdateInitialTransforms()
|
|
||||||
{
|
|
||||||
base.UpdateInitialTransforms();
|
|
||||||
|
|
||||||
// This hitobject should never expire, so this is just a safe maximum.
|
|
||||||
LifetimeEnd = LifetimeStart + 30000;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateHitStateTransforms(ArmedState state)
|
protected override void UpdateHitStateTransforms(ArmedState state)
|
||||||
{
|
{
|
||||||
// suppress the base call explicitly.
|
// suppress the base call explicitly.
|
||||||
// the hold note head should never change its visual state on its own due to the "freezing" mechanic
|
// the hold note head should never change its visual state on its own due to the "freezing" mechanic
|
||||||
// (when hit, it remains visible in place at the judgement line; when dropped, it will scroll past the line).
|
// (when hit, it remains visible in place at the judgement line; when dropped, it will scroll past the line).
|
||||||
// it will be hidden along with its parenting hold note when required.
|
// it will be hidden along with its parenting hold note when required.
|
||||||
|
|
||||||
|
// Set `LifetimeEnd` explicitly to a non-`double.MaxValue` because otherwise this DHO is automatically expired.
|
||||||
|
LifetimeEnd = double.PositiveInfinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool OnPressed(KeyBindingPressEvent<ManiaAction> e) => false; // Handled by the hold note
|
public override bool OnPressed(KeyBindingPressEvent<ManiaAction> e) => false; // Handled by the hold note
|
||||||
|
@ -23,10 +23,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
|
|
||||||
protected readonly IBindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
protected readonly IBindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
// Leaving the default (10s) makes hitobjects not appear, as this offset is used for the initial state transforms.
|
|
||||||
// Calculated as DrawableManiaRuleset.MAX_TIME_RANGE + some additional allowance for velocity < 1.
|
|
||||||
protected override double InitialLifetimeOffset => 30000;
|
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private ManiaPlayfield playfield { get; set; }
|
private ManiaPlayfield playfield { get; set; }
|
||||||
|
|
||||||
@ -69,22 +65,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
Direction.BindValueChanged(OnDirectionChanged, true);
|
Direction.BindValueChanged(OnDirectionChanged, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnApply()
|
|
||||||
{
|
|
||||||
base.OnApply();
|
|
||||||
|
|
||||||
if (ParentHitObject != null)
|
|
||||||
AccentColour.BindTo(ParentHitObject.AccentColour);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnFree()
|
|
||||||
{
|
|
||||||
base.OnFree();
|
|
||||||
|
|
||||||
if (ParentHitObject != null)
|
|
||||||
AccentColour.UnbindFrom(ParentHitObject.AccentColour);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e)
|
protected virtual void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e)
|
||||||
{
|
{
|
||||||
Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
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;
|
||||||
@ -12,26 +10,38 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
{
|
{
|
||||||
public class ColumnBackground : CompositeDrawable, IKeyBindingHandler<ManiaAction>, IHasAccentColour
|
public class ArgonColumnBackground : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||||
{
|
{
|
||||||
private readonly IBindable<ManiaAction> action = new Bindable<ManiaAction>();
|
|
||||||
|
|
||||||
private Box background;
|
|
||||||
private Box backgroundOverlay;
|
|
||||||
|
|
||||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
private Color4 brightColour;
|
||||||
private void load(IBindable<ManiaAction> action, IScrollingInfo scrollingInfo)
|
private Color4 dimColour;
|
||||||
{
|
|
||||||
this.action.BindTo(action);
|
|
||||||
|
|
||||||
|
private Box background = null!;
|
||||||
|
private Box backgroundOverlay = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Column column { get; set; } = null!;
|
||||||
|
|
||||||
|
private Bindable<Color4> accentColour = null!;
|
||||||
|
|
||||||
|
public ArgonColumnBackground()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = ArgonNotePiece.CORNER_RADIUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
InternalChildren = new[]
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
background = new Box
|
background = new Box
|
||||||
@ -49,61 +59,42 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
accentColour = column.AccentColour.GetBoundCopy();
|
||||||
direction.BindValueChanged(dir =>
|
accentColour.BindValueChanged(colour =>
|
||||||
{
|
{
|
||||||
backgroundOverlay.Anchor = backgroundOverlay.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
background.Colour = colour.NewValue.Darken(3).Opacity(0.8f);
|
||||||
updateColours();
|
brightColour = colour.NewValue.Opacity(0.6f);
|
||||||
|
dimColour = colour.NewValue.Opacity(0);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
updateColours();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get => accentColour;
|
|
||||||
set
|
|
||||||
{
|
{
|
||||||
if (accentColour == value)
|
backgroundOverlay.Anchor = backgroundOverlay.Origin = Anchor.TopLeft;
|
||||||
return;
|
backgroundOverlay.Colour = ColourInfo.GradientVertical(brightColour, dimColour);
|
||||||
|
}
|
||||||
accentColour = value;
|
else
|
||||||
|
{
|
||||||
updateColours();
|
backgroundOverlay.Anchor = backgroundOverlay.Origin = Anchor.BottomLeft;
|
||||||
|
backgroundOverlay.Colour = ColourInfo.GradientVertical(dimColour, brightColour);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void updateColours()
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
background.Colour = AccentColour.Darken(5);
|
|
||||||
|
|
||||||
var brightPoint = AccentColour.Opacity(0.6f);
|
|
||||||
var dimPoint = AccentColour.Opacity(0);
|
|
||||||
|
|
||||||
backgroundOverlay.Colour = ColourInfo.GradientVertical(
|
|
||||||
direction.Value == ScrollingDirection.Up ? brightPoint : dimPoint,
|
|
||||||
direction.Value == ScrollingDirection.Up ? dimPoint : brightPoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<ManiaAction> e)
|
public bool OnPressed(KeyBindingPressEvent<ManiaAction> e)
|
||||||
{
|
{
|
||||||
if (e.Action == action.Value)
|
if (e.Action == column.Action.Value)
|
||||||
backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint);
|
backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnReleased(KeyBindingReleaseEvent<ManiaAction> e)
|
public void OnReleased(KeyBindingReleaseEvent<ManiaAction> e)
|
||||||
{
|
{
|
||||||
if (e.Action == action.Value)
|
if (e.Action == column.Action.Value)
|
||||||
backgroundOverlay.FadeTo(0, 250, Easing.OutQuint);
|
backgroundOverlay.FadeTo(0, 250, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
97
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs
Normal file
97
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// 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.Effects;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
public class ArgonHitExplosion : CompositeDrawable, IHitExplosion
|
||||||
|
{
|
||||||
|
public override bool RemoveWhenNotAlive => true;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Column column { get; set; } = null!;
|
||||||
|
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Container largeFaint = null!;
|
||||||
|
|
||||||
|
private Bindable<Color4> accentColour = null!;
|
||||||
|
|
||||||
|
public ArgonHitExplosion()
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Height = ArgonNotePiece.NOTE_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
largeFaint = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = ArgonNotePiece.CORNER_RADIUS,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
Colour = Color4.White,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
|
accentColour = column.AccentColour.GetBoundCopy();
|
||||||
|
accentColour.BindValueChanged(colour =>
|
||||||
|
{
|
||||||
|
largeFaint.Colour = Interpolation.ValueAt(0.8f, colour.NewValue, Color4.White, 0, 1);
|
||||||
|
|
||||||
|
largeFaint.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = colour.NewValue,
|
||||||
|
Roundness = 40,
|
||||||
|
Radius = 60,
|
||||||
|
};
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
if (direction.NewValue == ScrollingDirection.Up)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre;
|
||||||
|
Y = ArgonNotePiece.NOTE_HEIGHT / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomCentre;
|
||||||
|
Y = -ArgonNotePiece.NOTE_HEIGHT / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Animate(JudgementResult result)
|
||||||
|
{
|
||||||
|
this.FadeOutFromOne(PoolableHitExplosion.DURATION, Easing.Out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs
Normal file
47
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// 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.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
public class ArgonHitTarget : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Height = ArgonNotePiece.NOTE_HEIGHT;
|
||||||
|
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = ArgonNotePiece.CORNER_RADIUS;
|
||||||
|
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0.3f,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Colour = Color4.White
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
Anchor = Origin = direction.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
97
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs
Normal file
97
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// 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.Shapes;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents length-wise portion of a hold note.
|
||||||
|
/// </summary>
|
||||||
|
public class ArgonHoldBodyPiece : CompositeDrawable, IHoldNoteBody
|
||||||
|
{
|
||||||
|
protected readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||||
|
protected readonly IBindable<bool> IsHitting = new Bindable<bool>();
|
||||||
|
|
||||||
|
private Drawable background = null!;
|
||||||
|
private Box foreground = null!;
|
||||||
|
|
||||||
|
public ArgonHoldBodyPiece()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
// Without this, the width of the body will be slightly larger than the head/tail.
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = ArgonNotePiece.CORNER_RADIUS;
|
||||||
|
Blending = BlendingParameters.Additive;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(DrawableHitObject? drawableObject)
|
||||||
|
{
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
background = new Box { RelativeSizeAxes = Axes.Both },
|
||||||
|
foreground = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Alpha = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (drawableObject != null)
|
||||||
|
{
|
||||||
|
var holdNote = (DrawableHoldNote)drawableObject;
|
||||||
|
|
||||||
|
AccentColour.BindTo(holdNote.AccentColour);
|
||||||
|
IsHitting.BindTo(holdNote.IsHitting);
|
||||||
|
}
|
||||||
|
|
||||||
|
AccentColour.BindValueChanged(colour =>
|
||||||
|
{
|
||||||
|
background.Colour = colour.NewValue.Darken(1.2f);
|
||||||
|
foreground.Colour = colour.NewValue.Opacity(0.2f);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
IsHitting.BindValueChanged(hitting =>
|
||||||
|
{
|
||||||
|
const float animation_length = 50;
|
||||||
|
|
||||||
|
foreground.ClearTransforms();
|
||||||
|
|
||||||
|
if (hitting.NewValue)
|
||||||
|
{
|
||||||
|
// wait for the next sync point
|
||||||
|
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
||||||
|
|
||||||
|
using (foreground.BeginDelayedSequence(synchronisedOffset))
|
||||||
|
{
|
||||||
|
foreground.FadeTo(1, animation_length).Then()
|
||||||
|
.FadeTo(0.5f, animation_length)
|
||||||
|
.Loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreground.FadeOut(animation_length);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Recycle()
|
||||||
|
{
|
||||||
|
foreground.ClearTransforms();
|
||||||
|
foreground.Alpha = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
// 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.Shapes;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
internal class ArgonHoldNoteTailPiece : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
|
private readonly Box colouredBox;
|
||||||
|
private readonly Box shadow;
|
||||||
|
|
||||||
|
public ArgonHoldNoteTailPiece()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Height = ArgonNotePiece.NOTE_HEIGHT;
|
||||||
|
|
||||||
|
CornerRadius = ArgonNotePiece.CORNER_RADIUS;
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
shadow = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Height = 0.82f,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = ArgonNotePiece.CORNER_RADIUS,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
colouredBox = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Circle
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = ArgonNotePiece.CORNER_RADIUS * 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(IScrollingInfo scrollingInfo, 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 = ColourInfo.GradientVertical(
|
||||||
|
accent.NewValue,
|
||||||
|
accent.NewValue.Darken(0.1f)
|
||||||
|
);
|
||||||
|
|
||||||
|
shadow.Colour = accent.NewValue.Darken(0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
193
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs
Normal file
193
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
// 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.Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
public class ArgonJudgementPiece : CompositeDrawable, IAnimatableJudgement
|
||||||
|
{
|
||||||
|
protected readonly HitResult Result;
|
||||||
|
|
||||||
|
protected SpriteText JudgementText { get; private set; } = null!;
|
||||||
|
|
||||||
|
private RingExplosion? ringExplosion;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; } = null!;
|
||||||
|
|
||||||
|
public ArgonJudgementPiece(HitResult result)
|
||||||
|
{
|
||||||
|
Result = result;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
Y = 160;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
JudgementText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Text = Result.GetDescription().ToUpperInvariant(),
|
||||||
|
Colour = colours.ForHitResult(Result),
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Spacing = new Vector2(10, 0),
|
||||||
|
Font = OsuFont.Default.With(size: 28, weight: FontWeight.Regular),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Result.IsHit())
|
||||||
|
{
|
||||||
|
AddInternal(ringExplosion = new RingExplosion(Result)
|
||||||
|
{
|
||||||
|
Colour = colours.ForHitResult(Result),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Plays the default animation for this judgement piece.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The base implementation only handles fade (for all result types) and misses.
|
||||||
|
/// Individual rulesets are recommended to implement their appropriate hit animations.
|
||||||
|
/// </remarks>
|
||||||
|
public virtual void PlayAnimation()
|
||||||
|
{
|
||||||
|
switch (Result)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
JudgementText
|
||||||
|
.ScaleTo(Vector2.One)
|
||||||
|
.ScaleTo(new Vector2(1.4f), 1800, Easing.OutQuint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HitResult.Miss:
|
||||||
|
this.ScaleTo(1.6f);
|
||||||
|
this.ScaleTo(1, 100, Easing.In);
|
||||||
|
|
||||||
|
this.MoveTo(Vector2.Zero);
|
||||||
|
this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint);
|
||||||
|
|
||||||
|
this.RotateTo(0);
|
||||||
|
this.RotateTo(40, 800, Easing.InQuint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.FadeOutFromOne(800);
|
||||||
|
|
||||||
|
ringExplosion?.PlayAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable? GetAboveHitObjectsProxiedContent() => null;
|
||||||
|
|
||||||
|
private class RingExplosion : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly float travel = 52;
|
||||||
|
|
||||||
|
public RingExplosion(HitResult result)
|
||||||
|
{
|
||||||
|
const float thickness = 4;
|
||||||
|
|
||||||
|
const float small_size = 9;
|
||||||
|
const float large_size = 14;
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
Blending = BlendingParameters.Additive;
|
||||||
|
|
||||||
|
int countSmall = 0;
|
||||||
|
int countLarge = 0;
|
||||||
|
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case HitResult.Meh:
|
||||||
|
countSmall = 3;
|
||||||
|
travel *= 0.3f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HitResult.Ok:
|
||||||
|
case HitResult.Good:
|
||||||
|
countSmall = 4;
|
||||||
|
travel *= 0.6f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HitResult.Great:
|
||||||
|
case HitResult.Perfect:
|
||||||
|
countSmall = 4;
|
||||||
|
countLarge = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < countSmall; i++)
|
||||||
|
AddInternal(new RingPiece(thickness) { Size = new Vector2(small_size) });
|
||||||
|
|
||||||
|
for (int i = 0; i < countLarge; i++)
|
||||||
|
AddInternal(new RingPiece(thickness) { Size = new Vector2(large_size) });
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayAnimation()
|
||||||
|
{
|
||||||
|
foreach (var c in InternalChildren)
|
||||||
|
{
|
||||||
|
const float start_position_ratio = 0.3f;
|
||||||
|
|
||||||
|
float direction = RNG.NextSingle(0, 360);
|
||||||
|
float distance = RNG.NextSingle(travel / 2, travel);
|
||||||
|
|
||||||
|
c.MoveTo(new Vector2(
|
||||||
|
MathF.Cos(direction) * distance * start_position_ratio,
|
||||||
|
MathF.Sin(direction) * distance * start_position_ratio
|
||||||
|
));
|
||||||
|
|
||||||
|
c.MoveTo(new Vector2(
|
||||||
|
MathF.Cos(direction) * distance,
|
||||||
|
MathF.Sin(direction) * distance
|
||||||
|
), 600, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.FadeOutFromOne(1000, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RingPiece : CircularContainer
|
||||||
|
{
|
||||||
|
public RingPiece(float thickness = 9)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
Masking = true;
|
||||||
|
BorderThickness = thickness;
|
||||||
|
BorderColour = Color4.White;
|
||||||
|
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0,
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
272
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonKeyArea.cs
Normal file
272
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonKeyArea.cs
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
// 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.Framework.Input.Bindings;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
public class ArgonKeyArea : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||||
|
{
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
|
||||||
|
private Container directionContainer = null!;
|
||||||
|
private Drawable background = null!;
|
||||||
|
|
||||||
|
private Circle hitTargetLine = null!;
|
||||||
|
|
||||||
|
private Container<Circle> bottomIcon = null!;
|
||||||
|
private CircularContainer topIcon = null!;
|
||||||
|
|
||||||
|
private Bindable<Color4> accentColour = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Column column { get; set; } = null!;
|
||||||
|
|
||||||
|
public ArgonKeyArea()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IScrollingInfo scrollingInfo)
|
||||||
|
{
|
||||||
|
const float icon_circle_size = 8;
|
||||||
|
const float icon_spacing = 7;
|
||||||
|
const float icon_vertical_offset = -30;
|
||||||
|
|
||||||
|
InternalChild = directionContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
// Ensure the area is tall enough to put the target line in the correct location.
|
||||||
|
// This is to also allow the main background component to overlap the target line
|
||||||
|
// and avoid an inner corner radius being shown below the target line.
|
||||||
|
Height = Stage.HIT_TARGET_POSITION + ArgonNotePiece.CORNER_RADIUS * 2,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Masking = true,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
CornerRadius = ArgonNotePiece.CORNER_RADIUS,
|
||||||
|
Child = background = new Box
|
||||||
|
{
|
||||||
|
Name = "Key gradient",
|
||||||
|
Alpha = 0,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hitTargetLine = new Circle
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Colour = OsuColour.Gray(196 / 255f),
|
||||||
|
Height = ArgonNotePiece.CORNER_RADIUS * 2,
|
||||||
|
Masking = true,
|
||||||
|
EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow },
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Name = "Icons",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
bottomIcon = new Container<Circle>
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Y = icon_vertical_offset,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Circle
|
||||||
|
{
|
||||||
|
Size = new Vector2(icon_circle_size),
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow },
|
||||||
|
},
|
||||||
|
new Circle
|
||||||
|
{
|
||||||
|
X = -icon_spacing,
|
||||||
|
Y = icon_spacing * 1.2f,
|
||||||
|
Size = new Vector2(icon_circle_size),
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow },
|
||||||
|
},
|
||||||
|
new Circle
|
||||||
|
{
|
||||||
|
X = icon_spacing,
|
||||||
|
Y = icon_spacing * 1.2f,
|
||||||
|
Size = new Vector2(icon_circle_size),
|
||||||
|
Anchor = Anchor.BottomCentre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
topIcon = new CircularContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Y = -icon_vertical_offset,
|
||||||
|
Size = new Vector2(22, 14),
|
||||||
|
Masking = true,
|
||||||
|
BorderThickness = 4,
|
||||||
|
BorderColour = Color4.White,
|
||||||
|
EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow },
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
|
accentColour = column.AccentColour.GetBoundCopy();
|
||||||
|
accentColour.BindValueChanged(colour =>
|
||||||
|
{
|
||||||
|
background.Colour = colour.NewValue.Darken(0.2f);
|
||||||
|
bottomIcon.Colour = colour.NewValue;
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
|
||||||
|
// Yes, proxy everything.
|
||||||
|
column.TopLevelContainer.Add(CreateProxy());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
{
|
||||||
|
switch (direction.NewValue)
|
||||||
|
{
|
||||||
|
case ScrollingDirection.Up:
|
||||||
|
directionContainer.Scale = new Vector2(1, -1);
|
||||||
|
directionContainer.Anchor = Anchor.TopLeft;
|
||||||
|
directionContainer.Origin = Anchor.BottomLeft;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ScrollingDirection.Down:
|
||||||
|
directionContainer.Scale = new Vector2(1, 1);
|
||||||
|
directionContainer.Anchor = Anchor.BottomLeft;
|
||||||
|
directionContainer.Origin = Anchor.BottomLeft;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnPressed(KeyBindingPressEvent<ManiaAction> e)
|
||||||
|
{
|
||||||
|
if (e.Action != column.Action.Value) return false;
|
||||||
|
|
||||||
|
const double lighting_fade_in_duration = 70;
|
||||||
|
Color4 lightingColour = getLightingColour();
|
||||||
|
|
||||||
|
background
|
||||||
|
.FlashColour(accentColour.Value.Lighten(0.8f), 200, Easing.OutQuint)
|
||||||
|
.FadeTo(1, lighting_fade_in_duration, Easing.OutQuint)
|
||||||
|
.Then()
|
||||||
|
.FadeTo(0.8f, 500);
|
||||||
|
|
||||||
|
hitTargetLine.FadeColour(Color4.White, lighting_fade_in_duration, Easing.OutQuint);
|
||||||
|
hitTargetLine.TransformTo(nameof(EdgeEffect), new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = lightingColour.Opacity(0.4f),
|
||||||
|
Radius = 20,
|
||||||
|
}, lighting_fade_in_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
topIcon.ScaleTo(0.9f, lighting_fade_in_duration, Easing.OutQuint);
|
||||||
|
topIcon.TransformTo(nameof(EdgeEffect), new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = lightingColour.Opacity(0.1f),
|
||||||
|
Radius = 20,
|
||||||
|
}, lighting_fade_in_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
bottomIcon.FadeColour(Color4.White, lighting_fade_in_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
foreach (var circle in bottomIcon)
|
||||||
|
{
|
||||||
|
circle.TransformTo(nameof(EdgeEffect), new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = lightingColour.Opacity(0.2f),
|
||||||
|
Radius = 60,
|
||||||
|
}, lighting_fade_in_duration, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(KeyBindingReleaseEvent<ManiaAction> e)
|
||||||
|
{
|
||||||
|
if (e.Action != column.Action.Value) return;
|
||||||
|
|
||||||
|
const double lighting_fade_out_duration = 800;
|
||||||
|
|
||||||
|
Color4 lightingColour = getLightingColour().Opacity(0);
|
||||||
|
|
||||||
|
// background fades out faster than lighting elements to give better definition to the player.
|
||||||
|
background.FadeTo(0.3f, 50, Easing.OutQuint)
|
||||||
|
.Then()
|
||||||
|
.FadeOut(lighting_fade_out_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
topIcon.ScaleTo(1f, 200, Easing.OutQuint);
|
||||||
|
topIcon.TransformTo(nameof(EdgeEffect), new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = lightingColour,
|
||||||
|
Radius = 20,
|
||||||
|
}, lighting_fade_out_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
hitTargetLine.FadeColour(OsuColour.Gray(196 / 255f), lighting_fade_out_duration, Easing.OutQuint);
|
||||||
|
hitTargetLine.TransformTo(nameof(EdgeEffect), new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = lightingColour,
|
||||||
|
Radius = 25,
|
||||||
|
}, lighting_fade_out_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
bottomIcon.FadeColour(accentColour.Value, lighting_fade_out_duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
foreach (var circle in bottomIcon)
|
||||||
|
{
|
||||||
|
circle.TransformTo(nameof(EdgeEffect), new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = lightingColour,
|
||||||
|
Radius = 30,
|
||||||
|
}, lighting_fade_out_duration, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color4 getLightingColour() => Interpolation.ValueAt(0.2f, accentColour.Value, Color4.White, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
110
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs
Normal file
110
osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// 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.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
internal class ArgonNotePiece : CompositeDrawable
|
||||||
|
{
|
||||||
|
public const float NOTE_HEIGHT = 42;
|
||||||
|
|
||||||
|
public const float CORNER_RADIUS = 3.4f;
|
||||||
|
|
||||||
|
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||||
|
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
|
private readonly Box colouredBox;
|
||||||
|
private readonly Box shadow;
|
||||||
|
|
||||||
|
public ArgonNotePiece()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
Height = NOTE_HEIGHT;
|
||||||
|
|
||||||
|
CornerRadius = CORNER_RADIUS;
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
shadow = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Height = 0.82f,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = CORNER_RADIUS,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
colouredBox = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Circle
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = CORNER_RADIUS * 2,
|
||||||
|
},
|
||||||
|
new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Y = 4,
|
||||||
|
Icon = FontAwesome.Solid.AngleDown,
|
||||||
|
Size = new Vector2(20),
|
||||||
|
Scale = new Vector2(1, 0.7f)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(IScrollingInfo scrollingInfo, 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 = ColourInfo.GradientVertical(
|
||||||
|
accent.NewValue.Lighten(0.1f),
|
||||||
|
accent.NewValue
|
||||||
|
);
|
||||||
|
|
||||||
|
shadow.Colour = accent.NewValue.Darken(0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
public class ArgonStageBackground : CompositeDrawable
|
||||||
|
{
|
||||||
|
public ArgonStageBackground()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,141 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||||
|
{
|
||||||
|
public class ManiaArgonSkinTransformer : SkinTransformer
|
||||||
|
{
|
||||||
|
private readonly ManiaBeatmap beatmap;
|
||||||
|
|
||||||
|
public ManiaArgonSkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||||
|
: base(skin)
|
||||||
|
{
|
||||||
|
this.beatmap = (ManiaBeatmap)beatmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Drawable? GetDrawableComponent(ISkinComponent component)
|
||||||
|
{
|
||||||
|
switch (component)
|
||||||
|
{
|
||||||
|
case GameplaySkinComponent<HitResult> resultComponent:
|
||||||
|
return new ArgonJudgementPiece(resultComponent.Component);
|
||||||
|
|
||||||
|
case ManiaSkinComponent maniaComponent:
|
||||||
|
// TODO: Once everything is finalised, consider throwing UnsupportedSkinComponentException on missing entries.
|
||||||
|
switch (maniaComponent.Component)
|
||||||
|
{
|
||||||
|
case ManiaSkinComponents.StageBackground:
|
||||||
|
return new ArgonStageBackground();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.ColumnBackground:
|
||||||
|
return new ArgonColumnBackground();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HoldNoteBody:
|
||||||
|
return new ArgonHoldBodyPiece();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HoldNoteTail:
|
||||||
|
return new ArgonHoldNoteTailPiece();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HoldNoteHead:
|
||||||
|
case ManiaSkinComponents.Note:
|
||||||
|
return new ArgonNotePiece();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HitTarget:
|
||||||
|
return new ArgonHitTarget();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.KeyArea:
|
||||||
|
return new ArgonKeyArea();
|
||||||
|
|
||||||
|
case ManiaSkinComponents.HitExplosion:
|
||||||
|
return new ArgonHitExplosion();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetDrawableComponent(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IBindable<TValue>? GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
|
{
|
||||||
|
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||||
|
{
|
||||||
|
int column = maniaLookup.ColumnIndex ?? 0;
|
||||||
|
var stage = beatmap.GetStageForColumnIndex(column);
|
||||||
|
|
||||||
|
switch (maniaLookup.Lookup)
|
||||||
|
{
|
||||||
|
case LegacyManiaSkinConfigurationLookups.ColumnSpacing:
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<float>(2));
|
||||||
|
|
||||||
|
case LegacyManiaSkinConfigurationLookups.StagePaddingBottom:
|
||||||
|
case LegacyManiaSkinConfigurationLookups.StagePaddingTop:
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<float>(30));
|
||||||
|
|
||||||
|
case LegacyManiaSkinConfigurationLookups.ColumnWidth:
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<float>(
|
||||||
|
stage.IsSpecialColumn(column) ? 120 : 60
|
||||||
|
));
|
||||||
|
|
||||||
|
case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour:
|
||||||
|
|
||||||
|
Color4 colour;
|
||||||
|
|
||||||
|
const int total_colours = 7;
|
||||||
|
|
||||||
|
if (stage.IsSpecialColumn(column))
|
||||||
|
colour = new Color4(159, 101, 255, 255);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (column % total_colours)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
colour = new Color4(240, 216, 0, 255);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
colour = new Color4(240, 101, 0, 255);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
colour = new Color4(240, 0, 130, 255);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
colour = new Color4(192, 0, 240, 255);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
colour = new Color4(0, 96, 240, 255);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
colour = new Color4(0, 226, 240, 255);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
colour = new Color4(0, 240, 96, 255);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<Color4>(colour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 System;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Default
|
||||||
|
{
|
||||||
|
public class ManiaTrianglesSkinTransformer : SkinTransformer
|
||||||
|
{
|
||||||
|
private readonly ManiaBeatmap beatmap;
|
||||||
|
|
||||||
|
public ManiaTrianglesSkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||||
|
: base(skin)
|
||||||
|
{
|
||||||
|
this.beatmap = (ManiaBeatmap)beatmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Color4 colourEven = new Color4(6, 84, 0, 255);
|
||||||
|
private readonly Color4 colourOdd = new Color4(94, 0, 57, 255);
|
||||||
|
private readonly Color4 colourSpecial = new Color4(0, 48, 63, 255);
|
||||||
|
|
||||||
|
public override IBindable<TValue>? GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
|
{
|
||||||
|
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||||
|
{
|
||||||
|
switch (maniaLookup.Lookup)
|
||||||
|
{
|
||||||
|
case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour:
|
||||||
|
int column = maniaLookup.ColumnIndex ?? 0;
|
||||||
|
|
||||||
|
var stage = beatmap.GetStageForColumnIndex(column);
|
||||||
|
|
||||||
|
if (stage.IsSpecialColumn(column))
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<Color4>(colourSpecial));
|
||||||
|
|
||||||
|
int distanceToEdge = Math.Min(column, (stage.Columns - 1) - column);
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<Color4>(distanceToEdge % 2 == 0 ? colourOdd : colourEven));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -20,6 +21,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
protected Column Column { get; private set; }
|
protected Column Column { get; private set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private StageDefinition stage { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The column type identifier 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>
|
||||||
@ -28,19 +32,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
switch (Column.ColumnType)
|
if (Column.IsSpecial)
|
||||||
|
FallbackColumnIndex = "S";
|
||||||
|
else
|
||||||
{
|
{
|
||||||
case ColumnType.Special:
|
int distanceToEdge = Math.Min(Column.Index, (stage.Columns - 1) - Column.Index);
|
||||||
FallbackColumnIndex = "S";
|
FallbackColumnIndex = distanceToEdge % 2 == 0 ? "1" : "2";
|
||||||
break;
|
|
||||||
|
|
||||||
case ColumnType.Odd:
|
|
||||||
FallbackColumnIndex = "1";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ColumnType.Even:
|
|
||||||
FallbackColumnIndex = "2";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,20 +18,17 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
{
|
{
|
||||||
public class LegacyStageBackground : CompositeDrawable
|
public class LegacyStageBackground : CompositeDrawable
|
||||||
{
|
{
|
||||||
private readonly StageDefinition stageDefinition;
|
|
||||||
|
|
||||||
private Drawable leftSprite;
|
private Drawable leftSprite;
|
||||||
private Drawable rightSprite;
|
private Drawable rightSprite;
|
||||||
private ColumnFlow<Drawable> columnBackgrounds;
|
private ColumnFlow<Drawable> columnBackgrounds;
|
||||||
|
|
||||||
public LegacyStageBackground(StageDefinition stageDefinition)
|
public LegacyStageBackground()
|
||||||
{
|
{
|
||||||
this.stageDefinition = stageDefinition;
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ISkinSource skin)
|
private void load(ISkinSource skin, StageDefinition stageDefinition)
|
||||||
{
|
{
|
||||||
string leftImage = skin.GetManiaSkinConfig<string>(LegacyManiaSkinConfigurationLookups.LeftStageImage)?.Value
|
string leftImage = skin.GetManiaSkinConfig<string>(LegacyManiaSkinConfigurationLookups.LeftStageImage)?.Value
|
||||||
?? "mania-stage-left";
|
?? "mania-stage-left";
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||||
|
{
|
||||||
|
public class ManiaClassicSkinTransformer : ManiaLegacySkinTransformer
|
||||||
|
{
|
||||||
|
public ManiaClassicSkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||||
|
: base(skin, beatmap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
|
{
|
||||||
|
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||||
|
{
|
||||||
|
var baseLookup = base.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
|
||||||
|
if (baseLookup != null)
|
||||||
|
return baseLookup;
|
||||||
|
|
||||||
|
// default provisioning.
|
||||||
|
switch (maniaLookup.Lookup)
|
||||||
|
{
|
||||||
|
case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour:
|
||||||
|
return SkinUtils.As<TValue>(new Bindable<Color4>(Color4.Black));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
{
|
{
|
||||||
public class ManiaLegacySkinTransformer : LegacySkinTransformer
|
public class ManiaLegacySkinTransformer : LegacySkinTransformer
|
||||||
{
|
{
|
||||||
private readonly ManiaBeatmap beatmap;
|
public override bool IsProvidingLegacyResources => base.IsProvidingLegacyResources || hasKeyTexture.Value;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mapping of <see cref="HitResult"/> to their corresponding
|
/// Mapping of <see cref="HitResult"/> to their corresponding
|
||||||
@ -60,6 +59,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Lazy<bool> hasKeyTexture;
|
private readonly Lazy<bool> hasKeyTexture;
|
||||||
|
|
||||||
|
private readonly ManiaBeatmap beatmap;
|
||||||
|
|
||||||
public ManiaLegacySkinTransformer(ISkin skin, IBeatmap beatmap)
|
public ManiaLegacySkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||||
: base(skin)
|
: base(skin)
|
||||||
{
|
{
|
||||||
@ -113,8 +114,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
return new LegacyHitExplosion();
|
return new LegacyHitExplosion();
|
||||||
|
|
||||||
case ManiaSkinComponents.StageBackground:
|
case ManiaSkinComponents.StageBackground:
|
||||||
Debug.Assert(maniaComponent.StageDefinition != null);
|
return new LegacyStageBackground();
|
||||||
return new LegacyStageBackground(maniaComponent.StageDefinition.Value);
|
|
||||||
|
|
||||||
case ManiaSkinComponents.StageForeground:
|
case ManiaSkinComponents.StageForeground:
|
||||||
return new LegacyStageForeground();
|
return new LegacyStageForeground();
|
||||||
@ -151,7 +151,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
public override IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||||
{
|
{
|
||||||
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||||
return base.GetConfig<LegacyManiaSkinConfigurationLookup, TValue>(new LegacyManiaSkinConfigurationLookup(beatmap.TotalColumns, maniaLookup.Lookup, maniaLookup.TargetColumn));
|
{
|
||||||
|
return base.GetConfig<LegacyManiaSkinConfigurationLookup, TValue>(new LegacyManiaSkinConfigurationLookup(beatmap.TotalColumns, maniaLookup.Lookup, maniaLookup.ColumnIndex));
|
||||||
|
}
|
||||||
|
|
||||||
return base.GetConfig<TLookup, TValue>(lookup);
|
return base.GetConfig<TLookup, TValue>(lookup);
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,9 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="skin">The skin from which configuration is retrieved.</param>
|
/// <param name="skin">The skin from which configuration is retrieved.</param>
|
||||||
/// <param name="lookup">The value to retrieve.</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>
|
/// <param name="columnIndex">If not null, denotes the index of the column to which the entry applies.</param>
|
||||||
public static IBindable<T> GetManiaSkinConfig<T>(this ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null)
|
public static IBindable<T> GetManiaSkinConfig<T>(this ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? columnIndex = null)
|
||||||
=> skin.GetConfig<ManiaSkinConfigurationLookup, T>(
|
=> skin.GetConfig<ManiaSkinConfigurationLookup, T>(
|
||||||
new ManiaSkinConfigurationLookup(lookup, index));
|
new ManiaSkinConfigurationLookup(lookup, columnIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,20 +16,21 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
|||||||
public readonly LegacyManiaSkinConfigurationLookups Lookup;
|
public readonly LegacyManiaSkinConfigurationLookups Lookup;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The intended <see cref="Column"/> index for the configuration.
|
/// The column which is being looked up.
|
||||||
/// May be null if the configuration does not apply to a <see cref="Column"/>.
|
/// May be null if the configuration does not apply to a <see cref="Column"/>.
|
||||||
|
/// Note that this is the absolute index across all stages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly int? TargetColumn;
|
public readonly int? ColumnIndex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="ManiaSkinConfigurationLookup"/>.
|
/// Creates a new <see cref="ManiaSkinConfigurationLookup"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lookup">The lookup value.</param>
|
/// <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>
|
/// <param name="columnIndex">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)
|
public ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups lookup, int? columnIndex = null)
|
||||||
{
|
{
|
||||||
Lookup = lookup;
|
Lookup = lookup;
|
||||||
TargetColumn = targetColumn;
|
ColumnIndex = columnIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,30 +3,30 @@
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Mania.Skinning;
|
||||||
using osu.Game.Rulesets.Mania.UI.Components;
|
using osu.Game.Rulesets.Mania.UI.Components;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.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;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osuTK.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
|
||||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
|
||||||
using osu.Game.Rulesets.UI;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI
|
namespace osu.Game.Rulesets.Mania.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class Column : ScrollingPlayfield, IKeyBindingHandler<ManiaAction>, IHasAccentColour
|
public class Column : ScrollingPlayfield, IKeyBindingHandler<ManiaAction>
|
||||||
{
|
{
|
||||||
public const float COLUMN_WIDTH = 80;
|
public const float COLUMN_WIDTH = 80;
|
||||||
public const float SPECIAL_COLUMN_WIDTH = 70;
|
public const float SPECIAL_COLUMN_WIDTH = 70;
|
||||||
@ -39,23 +39,46 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
public readonly Bindable<ManiaAction> Action = new Bindable<ManiaAction>();
|
public readonly Bindable<ManiaAction> Action = new Bindable<ManiaAction>();
|
||||||
|
|
||||||
public readonly ColumnHitObjectArea HitObjectArea;
|
public readonly ColumnHitObjectArea HitObjectArea;
|
||||||
internal readonly Container TopLevelContainer;
|
internal readonly Container TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both };
|
||||||
private readonly DrawablePool<PoolableHitExplosion> hitExplosionPool;
|
private DrawablePool<PoolableHitExplosion> hitExplosionPool;
|
||||||
private readonly OrderedHitPolicy hitPolicy;
|
private readonly OrderedHitPolicy hitPolicy;
|
||||||
public Container UnderlayElements => HitObjectArea.UnderlayElements;
|
public Container UnderlayElements => HitObjectArea.UnderlayElements;
|
||||||
|
|
||||||
private readonly GameplaySampleTriggerSource sampleTriggerSource;
|
private GameplaySampleTriggerSource sampleTriggerSource;
|
||||||
|
|
||||||
public Column(int index)
|
/// <summary>
|
||||||
|
/// Whether this is a special (ie. scratch) column.
|
||||||
|
/// </summary>
|
||||||
|
public readonly bool IsSpecial;
|
||||||
|
|
||||||
|
public readonly Bindable<Color4> AccentColour = new Bindable<Color4>(Color4.Black);
|
||||||
|
|
||||||
|
public Column(int index, bool isSpecial)
|
||||||
{
|
{
|
||||||
Index = index;
|
Index = index;
|
||||||
|
IsSpecial = isSpecial;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Y;
|
RelativeSizeAxes = Axes.Y;
|
||||||
Width = COLUMN_WIDTH;
|
Width = COLUMN_WIDTH;
|
||||||
|
|
||||||
|
hitPolicy = new OrderedHitPolicy(HitObjectContainer);
|
||||||
|
HitObjectArea = new ColumnHitObjectArea(HitObjectContainer) { RelativeSizeAxes = Axes.Both };
|
||||||
|
}
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private ISkinSource skin { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(GameHost host)
|
||||||
|
{
|
||||||
|
SkinnableDrawable keyArea;
|
||||||
|
|
||||||
|
skin.SourceChanged += onSourceChanged;
|
||||||
|
onSourceChanged();
|
||||||
|
|
||||||
Drawable background = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground())
|
Drawable background = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground())
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both,
|
||||||
};
|
};
|
||||||
|
|
||||||
InternalChildren = new[]
|
InternalChildren = new[]
|
||||||
@ -64,17 +87,18 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
sampleTriggerSource = new GameplaySampleTriggerSource(HitObjectContainer),
|
sampleTriggerSource = new GameplaySampleTriggerSource(HitObjectContainer),
|
||||||
// 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(),
|
||||||
HitObjectArea = new ColumnHitObjectArea(HitObjectContainer) { RelativeSizeAxes = Axes.Both },
|
HitObjectArea,
|
||||||
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea), _ => new DefaultKeyArea())
|
keyArea = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea), _ => new DefaultKeyArea())
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
background,
|
background,
|
||||||
TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both },
|
TopLevelContainer,
|
||||||
new ColumnTouchInputArea(this)
|
new ColumnTouchInputArea(this)
|
||||||
};
|
};
|
||||||
|
|
||||||
hitPolicy = new OrderedHitPolicy(HitObjectContainer);
|
applyGameWideClock(background);
|
||||||
|
applyGameWideClock(keyArea);
|
||||||
|
|
||||||
TopLevelContainer.Add(HitObjectArea.Explosions.CreateProxy());
|
TopLevelContainer.Add(HitObjectArea.Explosions.CreateProxy());
|
||||||
|
|
||||||
@ -83,20 +107,38 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
RegisterPool<HeadNote, DrawableHoldNoteHead>(10, 50);
|
RegisterPool<HeadNote, DrawableHoldNoteHead>(10, 50);
|
||||||
RegisterPool<TailNote, DrawableHoldNoteTail>(10, 50);
|
RegisterPool<TailNote, DrawableHoldNoteTail>(10, 50);
|
||||||
RegisterPool<HoldNoteTick, DrawableHoldNoteTick>(50, 250);
|
RegisterPool<HoldNoteTick, DrawableHoldNoteTick>(50, 250);
|
||||||
|
|
||||||
|
// Some elements don't handle rewind correctly and fixing them is non-trivial.
|
||||||
|
// In the future we need a better solution to this, but as a temporary work-around, give these components the game-wide
|
||||||
|
// clock so they don't need to worry about rewind.
|
||||||
|
// This only works because they handle OnPressed/OnReleased which results in a correct state while rewinding.
|
||||||
|
//
|
||||||
|
// This is kinda dodgy (and will cause weirdness when pausing gameplay) but is better than completely broken rewind.
|
||||||
|
void applyGameWideClock(Drawable drawable)
|
||||||
|
{
|
||||||
|
drawable.Clock = host.UpdateThread.Clock;
|
||||||
|
drawable.ProcessCustomClock = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSourceChanged()
|
||||||
|
{
|
||||||
|
AccentColour.Value = skin.GetManiaSkinConfig<Color4>(LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour, Index)?.Value ?? Color4.Black;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
NewResult += OnNewResult;
|
NewResult += OnNewResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColumnType ColumnType { get; set; }
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
public bool IsSpecial => ColumnType == ColumnType.Special;
|
if (skin != null)
|
||||||
|
skin.SourceChanged -= onSourceChanged;
|
||||||
public Color4 AccentColour { get; set; }
|
}
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
{
|
{
|
||||||
@ -111,7 +153,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
DrawableManiaHitObject maniaObject = (DrawableManiaHitObject)drawableHitObject;
|
DrawableManiaHitObject maniaObject = (DrawableManiaHitObject)drawableHitObject;
|
||||||
|
|
||||||
maniaObject.AccentColour.Value = AccentColour;
|
maniaObject.AccentColour.BindTo(AccentColour);
|
||||||
maniaObject.CheckHittable = hitPolicy.IsHittable;
|
maniaObject.CheckHittable = hitPolicy.IsHittable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
AutoSizeAxes = Axes.X;
|
AutoSizeAxes = Axes.X;
|
||||||
|
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
InternalChild = columns = new FillFlowContainer<Container>
|
InternalChild = columns = new FillFlowContainer<Container>
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private Column column { get; set; }
|
private Column column { get; set; }
|
||||||
|
|
||||||
|
private Bindable<Color4> accentColour;
|
||||||
|
|
||||||
public DefaultColumnBackground()
|
public DefaultColumnBackground()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
@ -55,9 +57,13 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
background.Colour = column.AccentColour.Darken(5);
|
accentColour = column.AccentColour.GetBoundCopy();
|
||||||
brightColour = column.AccentColour.Opacity(0.6f);
|
accentColour.BindValueChanged(colour =>
|
||||||
dimColour = column.AccentColour.Opacity(0);
|
{
|
||||||
|
background.Colour = colour.NewValue.Darken(5);
|
||||||
|
brightColour = colour.NewValue.Opacity(0.6f);
|
||||||
|
dimColour = colour.NewValue.Opacity(0);
|
||||||
|
}, true);
|
||||||
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
direction.BindValueChanged(onDirectionChanged, true);
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
|||||||
private Container hitTargetLine;
|
private Container hitTargetLine;
|
||||||
private Drawable hitTargetBar;
|
private Drawable hitTargetBar;
|
||||||
|
|
||||||
|
private Bindable<Color4> accentColour;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private Column column { get; set; }
|
private Column column { get; set; }
|
||||||
|
|
||||||
@ -54,12 +56,16 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
hitTargetLine.EdgeEffect = new EdgeEffectParameters
|
accentColour = column.AccentColour.GetBoundCopy();
|
||||||
|
accentColour.BindValueChanged(colour =>
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
hitTargetLine.EdgeEffect = new EdgeEffectParameters
|
||||||
Radius = 5,
|
{
|
||||||
Colour = column.AccentColour.Opacity(0.5f),
|
Type = EdgeEffectType.Glow,
|
||||||
};
|
Radius = 5,
|
||||||
|
Colour = colour.NewValue.Opacity(0.5f),
|
||||||
|
};
|
||||||
|
}, true);
|
||||||
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
direction.BindValueChanged(onDirectionChanged, true);
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
|||||||
private Container keyIcon;
|
private Container keyIcon;
|
||||||
private Drawable gradient;
|
private Drawable gradient;
|
||||||
|
|
||||||
|
private Bindable<Color4> accentColour;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private Column column { get; set; }
|
private Column column { get; set; }
|
||||||
|
|
||||||
@ -75,15 +77,19 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
keyIcon.EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Radius = 5,
|
|
||||||
Colour = column.AccentColour.Opacity(0.5f),
|
|
||||||
};
|
|
||||||
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
direction.BindValueChanged(onDirectionChanged, true);
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
|
accentColour = column.AccentColour.GetBoundCopy();
|
||||||
|
accentColour.BindValueChanged(colour =>
|
||||||
|
{
|
||||||
|
keyIcon.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Radius = 5,
|
||||||
|
Colour = colour.NewValue.Opacity(0.5f),
|
||||||
|
};
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
@ -32,6 +32,10 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
private CircularContainer largeFaint;
|
private CircularContainer largeFaint;
|
||||||
private CircularContainer mainGlow1;
|
private CircularContainer mainGlow1;
|
||||||
|
private CircularContainer mainGlow2;
|
||||||
|
private CircularContainer mainGlow3;
|
||||||
|
|
||||||
|
private Bindable<Color4> accentColour;
|
||||||
|
|
||||||
public DefaultHitExplosion()
|
public DefaultHitExplosion()
|
||||||
{
|
{
|
||||||
@ -48,8 +52,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
const float roundness = 80;
|
const float roundness = 80;
|
||||||
const float initial_height = 10;
|
const float initial_height = 10;
|
||||||
|
|
||||||
var colour = Interpolation.ValueAt(0.4f, column.AccentColour, Color4.White, 0, 1);
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
largeFaint = new CircularContainer
|
largeFaint = new CircularContainer
|
||||||
@ -61,13 +63,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
// we want our size to be very small so the glow dominates it.
|
// we want our size to be very small so the glow dominates it.
|
||||||
Size = new Vector2(default_large_faint_size),
|
Size = new Vector2(default_large_faint_size),
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Colour = Interpolation.ValueAt(0.1f, column.AccentColour, Color4.White, 0, 1).Opacity(0.3f),
|
|
||||||
Roundness = 160,
|
|
||||||
Radius = 200,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
mainGlow1 = new CircularContainer
|
mainGlow1 = new CircularContainer
|
||||||
{
|
{
|
||||||
@ -76,15 +71,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Colour = Interpolation.ValueAt(0.6f, column.AccentColour, Color4.White, 0, 1),
|
|
||||||
Roundness = 20,
|
|
||||||
Radius = 50,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
new CircularContainer
|
mainGlow2 = new CircularContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -93,15 +81,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
Size = new Vector2(0.01f, initial_height),
|
Size = new Vector2(0.01f, initial_height),
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
Rotation = RNG.NextSingle(-angle_variance, angle_variance),
|
Rotation = RNG.NextSingle(-angle_variance, angle_variance),
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Colour = colour,
|
|
||||||
Roundness = roundness,
|
|
||||||
Radius = 40,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
new CircularContainer
|
mainGlow3 = new CircularContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -110,18 +91,44 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
Size = new Vector2(0.01f, initial_height),
|
Size = new Vector2(0.01f, initial_height),
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
Rotation = RNG.NextSingle(-angle_variance, angle_variance),
|
Rotation = RNG.NextSingle(-angle_variance, angle_variance),
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Colour = colour,
|
|
||||||
Roundness = roundness,
|
|
||||||
Radius = 40,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
direction.BindValueChanged(onDirectionChanged, true);
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
|
accentColour = column.AccentColour.GetBoundCopy();
|
||||||
|
accentColour.BindValueChanged(colour =>
|
||||||
|
{
|
||||||
|
largeFaint.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = Interpolation.ValueAt(0.1f, colour.NewValue, Color4.White, 0, 1).Opacity(0.3f),
|
||||||
|
Roundness = 160,
|
||||||
|
Radius = 200,
|
||||||
|
};
|
||||||
|
mainGlow1.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = Interpolation.ValueAt(0.6f, colour.NewValue, Color4.White, 0, 1),
|
||||||
|
Roundness = 20,
|
||||||
|
Radius = 50,
|
||||||
|
};
|
||||||
|
mainGlow2.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = Interpolation.ValueAt(0.4f, colour.NewValue, Color4.White, 0, 1),
|
||||||
|
Roundness = roundness,
|
||||||
|
Radius = 40,
|
||||||
|
};
|
||||||
|
mainGlow3.EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = Interpolation.ValueAt(0.4f, colour.NewValue, Color4.White, 0, 1),
|
||||||
|
Roundness = roundness,
|
||||||
|
Radius = 40,
|
||||||
|
};
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||||
|
@ -42,6 +42,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
{
|
{
|
||||||
base.PrepareForUse();
|
base.PrepareForUse();
|
||||||
|
|
||||||
|
LifetimeStart = Time.Current;
|
||||||
|
|
||||||
(skinnableExplosion?.Drawable as IHitExplosion)?.Animate(Result);
|
(skinnableExplosion?.Drawable as IHitExplosion)?.Animate(Result);
|
||||||
|
|
||||||
this.Delay(DURATION).Then().Expire();
|
this.Delay(DURATION).Then().Expire();
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
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.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
@ -12,6 +13,7 @@ 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.Mania.UI.Components;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -19,7 +21,6 @@ using osu.Game.Rulesets.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;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.UI
|
namespace osu.Game.Rulesets.Mania.UI
|
||||||
{
|
{
|
||||||
@ -28,6 +29,9 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Stage : ScrollingPlayfield
|
public class Stage : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
|
public readonly StageDefinition Definition;
|
||||||
|
|
||||||
public const float COLUMN_SPACING = 1;
|
public const float COLUMN_SPACING = 1;
|
||||||
|
|
||||||
public const float HIT_TARGET_POSITION = 110;
|
public const float HIT_TARGET_POSITION = 110;
|
||||||
@ -40,13 +44,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
private readonly Drawable barLineContainer;
|
private readonly Drawable barLineContainer;
|
||||||
|
|
||||||
private readonly Dictionary<ColumnType, Color4> columnColours = new Dictionary<ColumnType, Color4>
|
|
||||||
{
|
|
||||||
{ 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;
|
||||||
@ -54,6 +51,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
public Stage(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;
|
||||||
|
Definition = definition;
|
||||||
|
|
||||||
Name = "Stage";
|
Name = "Stage";
|
||||||
|
|
||||||
@ -75,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
AutoSizeAxes = Axes.X,
|
AutoSizeAxes = Axes.X,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground, stageDefinition: definition), _ => new DefaultStageBackground())
|
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground), _ => new DefaultStageBackground())
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
},
|
},
|
||||||
@ -100,7 +98,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground, stageDefinition: definition), _ => null)
|
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground), _ => null)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
},
|
},
|
||||||
@ -118,15 +116,13 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
for (int i = 0; i < definition.Columns; i++)
|
for (int i = 0; i < definition.Columns; i++)
|
||||||
{
|
{
|
||||||
var columnType = definition.GetTypeOfColumn(i);
|
bool isSpecial = definition.IsSpecialColumn(i);
|
||||||
|
|
||||||
var column = new Column(firstColumnIndex + i)
|
var column = new Column(firstColumnIndex + i, isSpecial)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Width = 1,
|
Width = 1,
|
||||||
ColumnType = columnType,
|
Action = { Value = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ }
|
||||||
AccentColour = columnColours[columnType],
|
|
||||||
Action = { Value = columnType == ColumnType.Special ? specialColumnStartAction++ : normalColumnStartAction++ }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
topLevelContainer.Add(column.TopLevelContainer.CreateProxy());
|
topLevelContainer.Add(column.TopLevelContainer.CreateProxy());
|
||||||
@ -135,6 +131,37 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ISkinSource currentSkin;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(ISkinSource skin)
|
||||||
|
{
|
||||||
|
currentSkin = skin;
|
||||||
|
|
||||||
|
skin.SourceChanged += onSkinChanged;
|
||||||
|
onSkinChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSkinChanged()
|
||||||
|
{
|
||||||
|
float paddingTop = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.StagePaddingTop))?.Value ?? 0;
|
||||||
|
float paddingBottom = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.StagePaddingBottom))?.Value ?? 0;
|
||||||
|
|
||||||
|
Padding = new MarginPadding
|
||||||
|
{
|
||||||
|
Top = paddingTop,
|
||||||
|
Bottom = paddingBottom,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
|
if (currentSkin != null)
|
||||||
|
currentSkin.SourceChanged -= onSkinChanged;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
@ -4,14 +4,18 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
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.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
using osu.Game.Rulesets.Osu.Edit;
|
using osu.Game.Rulesets.Osu.Edit;
|
||||||
@ -33,6 +37,9 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
[Cached(typeof(IBeatSnapProvider))]
|
[Cached(typeof(IBeatSnapProvider))]
|
||||||
private readonly EditorBeatmap editorBeatmap;
|
private readonly EditorBeatmap editorBeatmap;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly EditorClock editorClock;
|
private readonly EditorClock editorClock;
|
||||||
|
|
||||||
@ -48,6 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
};
|
};
|
||||||
|
|
||||||
private OsuDistanceSnapGrid grid;
|
private OsuDistanceSnapGrid grid;
|
||||||
|
private SnappingCursorContainer cursor;
|
||||||
|
|
||||||
public TestSceneOsuDistanceSnapGrid()
|
public TestSceneOsuDistanceSnapGrid()
|
||||||
{
|
{
|
||||||
@ -84,8 +92,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.SlateGray
|
Colour = Color4.SlateGray
|
||||||
},
|
},
|
||||||
|
cursor = new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position },
|
||||||
grid = new OsuDistanceSnapGrid(new HitCircle { Position = grid_position }),
|
grid = new OsuDistanceSnapGrid(new HitCircle { Position = grid_position }),
|
||||||
new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position }
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -150,6 +158,37 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
assertSnappedDistance(expectedDistance);
|
assertSnappedDistance(expectedDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestReferenceObjectNotOnSnapGrid()
|
||||||
|
{
|
||||||
|
AddStep("create grid", () =>
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.SlateGray
|
||||||
|
},
|
||||||
|
cursor = new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position },
|
||||||
|
grid = new OsuDistanceSnapGrid(new HitCircle
|
||||||
|
{
|
||||||
|
Position = grid_position,
|
||||||
|
// This is important. It sets the reference object to a point in time that isn't on the current snap divisor's grid.
|
||||||
|
// We are testing that the grid's display is offset correctly.
|
||||||
|
StartTime = 40,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("move mouse to point", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position + new Vector2(beat_length, 0) * 2)));
|
||||||
|
|
||||||
|
AddAssert("Ensure cursor is on a grid line", () =>
|
||||||
|
{
|
||||||
|
return grid.ChildrenOfType<CircularProgress>().Any(p => Precision.AlmostEquals(p.ScreenSpaceDrawQuad.TopRight.X, grid.ToScreenSpace(cursor.LastSnappedPosition).X));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestLimitedDistance()
|
public void TestLimitedDistance()
|
||||||
{
|
{
|
||||||
@ -162,8 +201,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.SlateGray
|
Colour = Color4.SlateGray
|
||||||
},
|
},
|
||||||
|
cursor = new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position },
|
||||||
grid = new OsuDistanceSnapGrid(new HitCircle { Position = grid_position }, new HitCircle { StartTime = 200 }),
|
grid = new OsuDistanceSnapGrid(new HitCircle { Position = grid_position }, new HitCircle { StartTime = 200 }),
|
||||||
new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position }
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -182,6 +221,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
{
|
{
|
||||||
public Func<Vector2, Vector2> GetSnapPosition;
|
public Func<Vector2, Vector2> GetSnapPosition;
|
||||||
|
|
||||||
|
public Vector2 LastSnappedPosition { get; private set; }
|
||||||
|
|
||||||
private readonly Drawable cursor;
|
private readonly Drawable cursor;
|
||||||
|
|
||||||
private InputManager inputManager;
|
private InputManager inputManager;
|
||||||
@ -210,7 +251,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
cursor.Position = GetSnapPosition.Invoke(inputManager.CurrentState.Mouse.Position);
|
cursor.Position = LastSnappedPosition = GetSnapPosition.Invoke(inputManager.CurrentState.Mouse.Position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,20 +20,49 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestGridExclusivity()
|
public void TestGridToggles()
|
||||||
{
|
{
|
||||||
AddStep("enable distance snap grid", () => InputManager.Key(Key.T));
|
AddStep("enable distance snap grid", () => InputManager.Key(Key.T));
|
||||||
AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
|
AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
|
||||||
|
|
||||||
AddUntilStep("distance snap grid visible", () => this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
AddUntilStep("distance snap grid visible", () => this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
||||||
rectangularGridActive(false);
|
rectangularGridActive(false);
|
||||||
|
|
||||||
AddStep("enable rectangular grid", () => InputManager.Key(Key.Y));
|
AddStep("enable rectangular grid", () => InputManager.Key(Key.Y));
|
||||||
AddUntilStep("distance snap grid hidden", () => !this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
|
||||||
|
AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
|
||||||
|
AddUntilStep("distance snap grid still visible", () => this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
||||||
rectangularGridActive(true);
|
rectangularGridActive(true);
|
||||||
|
|
||||||
AddStep("enable distance snap grid", () => InputManager.Key(Key.T));
|
AddStep("disable distance snap grid", () => InputManager.Key(Key.T));
|
||||||
|
AddUntilStep("distance snap grid hidden", () => !this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
||||||
AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
|
AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
|
||||||
|
rectangularGridActive(true);
|
||||||
|
|
||||||
|
AddStep("disable rectangular grid", () => InputManager.Key(Key.Y));
|
||||||
|
AddUntilStep("distance snap grid still hidden", () => !this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
||||||
|
rectangularGridActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDistanceSnapMomentaryToggle()
|
||||||
|
{
|
||||||
|
AddStep("select second object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.ElementAt(1)));
|
||||||
|
|
||||||
|
AddUntilStep("distance snap grid hidden", () => !this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
||||||
|
AddStep("hold alt", () => InputManager.PressKey(Key.AltLeft));
|
||||||
AddUntilStep("distance snap grid visible", () => this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
AddUntilStep("distance snap grid visible", () => this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
||||||
|
AddStep("release alt", () => InputManager.ReleaseKey(Key.AltLeft));
|
||||||
|
AddUntilStep("distance snap grid hidden", () => !this.ChildrenOfType<OsuDistanceSnapGrid>().Any());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGridSnapMomentaryToggle()
|
||||||
|
{
|
||||||
|
rectangularGridActive(false);
|
||||||
|
AddStep("hold shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||||
|
rectangularGridActive(true);
|
||||||
|
AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft));
|
||||||
rectangularGridActive(false);
|
rectangularGridActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +79,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
AddAssert("placement blueprint at (0, 0)", () => Precision.AlmostEquals(Editor.ChildrenOfType<HitCirclePlacementBlueprint>().Single().HitObject.Position, new Vector2(0, 0)));
|
AddAssert("placement blueprint at (0, 0)", () => Precision.AlmostEquals(Editor.ChildrenOfType<HitCirclePlacementBlueprint>().Single().HitObject.Position, new Vector2(0, 0)));
|
||||||
else
|
else
|
||||||
AddAssert("placement blueprint at (1, 1)", () => Precision.AlmostEquals(Editor.ChildrenOfType<HitCirclePlacementBlueprint>().Single().HitObject.Position, new Vector2(1, 1)));
|
AddAssert("placement blueprint at (1, 1)", () => Precision.AlmostEquals(Editor.ChildrenOfType<HitCirclePlacementBlueprint>().Single().HitObject.Position, new Vector2(1, 1)));
|
||||||
|
|
||||||
AddStep("choose selection tool", () => InputManager.Key(Key.Number1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -148,6 +148,37 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestFloatEdgeCaseConversion()
|
||||||
|
{
|
||||||
|
Slider slider = null;
|
||||||
|
|
||||||
|
AddStep("select first slider", () =>
|
||||||
|
{
|
||||||
|
slider = (Slider)EditorBeatmap.HitObjects.First(h => h is Slider);
|
||||||
|
EditorClock.Seek(slider.StartTime);
|
||||||
|
EditorBeatmap.SelectedHitObjects.Add(slider);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("change to these specific circumstances", () =>
|
||||||
|
{
|
||||||
|
EditorBeatmap.Difficulty.SliderMultiplier = 1;
|
||||||
|
var timingPoint = EditorBeatmap.ControlPointInfo.TimingPointAt(slider.StartTime);
|
||||||
|
timingPoint.BeatLength = 352.941176470588;
|
||||||
|
slider.Path.ControlPoints[^1].Position = new Vector2(-110, 16);
|
||||||
|
slider.Path.ExpectedDistance.Value = 100;
|
||||||
|
});
|
||||||
|
|
||||||
|
convertToStream();
|
||||||
|
|
||||||
|
AddAssert("stream created", () => streamCreatedFor(slider,
|
||||||
|
(time: 0, pathPosition: 0),
|
||||||
|
(time: 0.25, pathPosition: 0.25),
|
||||||
|
(time: 0.5, pathPosition: 0.5),
|
||||||
|
(time: 0.75, pathPosition: 0.75),
|
||||||
|
(time: 1, pathPosition: 1)));
|
||||||
|
}
|
||||||
|
|
||||||
private bool streamCreatedFor(Slider slider, params (double time, double pathPosition)[] expectedCircles)
|
private bool streamCreatedFor(Slider slider, params (double time, double pathPosition)[] expectedCircles)
|
||||||
{
|
{
|
||||||
if (EditorBeatmap.HitObjects.Contains(slider))
|
if (EditorBeatmap.HitObjects.Contains(slider))
|
||||||
|
@ -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 NUnit.Framework;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneOsuModFlashlight : OsuModTestScene
|
||||||
|
{
|
||||||
|
[TestCase(600)]
|
||||||
|
[TestCase(120)]
|
||||||
|
[TestCase(1200)]
|
||||||
|
public void TestFollowDelay(double followDelay) => CreateModTest(new ModTestData { Mod = new OsuModFlashlight { FollowDelay = { Value = followDelay } }, PassCondition = () => true });
|
||||||
|
|
||||||
|
[TestCase(1f)]
|
||||||
|
[TestCase(0.5f)]
|
||||||
|
[TestCase(1.5f)]
|
||||||
|
[TestCase(2f)]
|
||||||
|
public void TestSizeMultiplier(float sizeMultiplier) => CreateModTest(new ModTestData { Mod = new OsuModFlashlight { SizeMultiplier = { Value = sizeMultiplier } }, PassCondition = () => true });
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new OsuModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true });
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
// 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.Osu.Mods;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneOsuModFreezeFrame : OsuModTestScene
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestFreezeFrame()
|
||||||
|
{
|
||||||
|
CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModFreezeFrame(),
|
||||||
|
PassCondition = () => true,
|
||||||
|
Autoplay = false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Extensions.ObjectExtensions;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -12,6 +13,7 @@ using osu.Game.Rulesets.Objects;
|
|||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
@ -145,6 +147,10 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
|||||||
|
|
||||||
private bool isBreak() => Player.IsBreakTime.Value;
|
private bool isBreak() => Player.IsBreakTime.Value;
|
||||||
|
|
||||||
private bool cursorAlphaAlmostEquals(float alpha) => Precision.AlmostEquals(Player.DrawableRuleset.Cursor.Alpha, alpha, 0.1f);
|
private OsuPlayfield playfield => (OsuPlayfield)Player.DrawableRuleset.Playfield;
|
||||||
|
|
||||||
|
private bool cursorAlphaAlmostEquals(float alpha) =>
|
||||||
|
Precision.AlmostEquals(playfield.Cursor.AsNonNull().Alpha, alpha, 0.1f) &&
|
||||||
|
Precision.AlmostEquals(playfield.Smoke.Alpha, alpha, 0.1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 251 B |
BIN
osu.Game.Rulesets.Osu.Tests/Resources/old-skin/cursor-smoke.png
Normal file
BIN
osu.Game.Rulesets.Osu.Tests/Resources/old-skin/cursor-smoke.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
@ -377,7 +377,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
private void addJudgementAssert(OsuHitObject hitObject, HitResult result)
|
private void addJudgementAssert(OsuHitObject hitObject, HitResult result)
|
||||||
{
|
{
|
||||||
AddAssert($"({hitObject.GetType().ReadableName()} @ {hitObject.StartTime}) judgement is {result}",
|
AddAssert($"({hitObject.GetType().ReadableName()} @ {hitObject.StartTime}) judgement is {result}",
|
||||||
() => judgementResults.Single(r => r.HitObject == hitObject).Type == result);
|
() => judgementResults.Single(r => r.HitObject == hitObject).Type, () => Is.EqualTo(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addJudgementAssert(string name, Func<OsuHitObject> hitObject, HitResult result)
|
private void addJudgementAssert(string name, Func<OsuHitObject> hitObject, HitResult result)
|
||||||
|
@ -1,21 +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.
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests
|
|
||||||
{
|
|
||||||
public class TestSceneOsuFlashlight : TestSceneOsuPlayer
|
|
||||||
{
|
|
||||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
|
||||||
{
|
|
||||||
SelectedMods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), };
|
|
||||||
|
|
||||||
return base.CreatePlayer(ruleset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user