Merge branch 'master' into show-loved-pp
2
.github/ISSUE_TEMPLATE/01-bug-issues.md
vendored
@ -9,6 +9,8 @@ about: Issues regarding encountered bugs.
|
|||||||
**osu!lazer version:**
|
**osu!lazer version:**
|
||||||
|
|
||||||
**Logs:**
|
**Logs:**
|
||||||
|
<!--
|
||||||
*please attach logs here, which are located at:*
|
*please attach logs here, which are located at:*
|
||||||
- `%AppData%/osu/logs` *(on Windows),*
|
- `%AppData%/osu/logs` *(on Windows),*
|
||||||
- `~/.local/share/osu/logs` *(on Linux & macOS).*
|
- `~/.local/share/osu/logs` *(on Linux & macOS).*
|
||||||
|
-->
|
||||||
|
2
.github/ISSUE_TEMPLATE/02-crash-issues.md
vendored
@ -9,8 +9,10 @@ about: Issues regarding crashes or permanent freezes.
|
|||||||
**osu!lazer version:**
|
**osu!lazer version:**
|
||||||
|
|
||||||
**Logs:**
|
**Logs:**
|
||||||
|
<!--
|
||||||
*please attach logs here, which are located at:*
|
*please attach logs here, which are located at:*
|
||||||
- `%AppData%/osu/logs` *(on Windows),*
|
- `%AppData%/osu/logs` *(on Windows),*
|
||||||
- `~/.local/share/osu/logs` *(on Linux & macOS).*
|
- `~/.local/share/osu/logs` *(on Linux & macOS).*
|
||||||
|
-->
|
||||||
|
|
||||||
**Computer Specifications:**
|
**Computer Specifications:**
|
||||||
|
40
.vscode/launch.json
vendored
@ -11,11 +11,6 @@
|
|||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build osu! (Debug)",
|
"preLaunchTask": "Build osu! (Debug)",
|
||||||
"linux": {
|
|
||||||
"env": {
|
|
||||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -28,11 +23,6 @@
|
|||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build osu! (Release)",
|
"preLaunchTask": "Build osu! (Release)",
|
||||||
"linux": {
|
|
||||||
"env": {
|
|
||||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -45,11 +35,6 @@
|
|||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build tests (Debug)",
|
"preLaunchTask": "Build tests (Debug)",
|
||||||
"linux": {
|
|
||||||
"env": {
|
|
||||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -62,11 +47,6 @@
|
|||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build tests (Release)",
|
"preLaunchTask": "Build tests (Release)",
|
||||||
"linux": {
|
|
||||||
"env": {
|
|
||||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -80,11 +60,6 @@
|
|||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build osu! (Debug)",
|
"preLaunchTask": "Build osu! (Debug)",
|
||||||
"linux": {
|
|
||||||
"env": {
|
|
||||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -98,11 +73,6 @@
|
|||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build osu! (Release)",
|
"preLaunchTask": "Build osu! (Release)",
|
||||||
"linux": {
|
|
||||||
"env": {
|
|
||||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -116,11 +86,6 @@
|
|||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build tournament tests (Debug)",
|
"preLaunchTask": "Build tournament tests (Debug)",
|
||||||
"linux": {
|
|
||||||
"env": {
|
|
||||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -134,11 +99,6 @@
|
|||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build tournament tests (Release)",
|
"preLaunchTask": "Build tournament tests (Release)",
|
||||||
"linux": {
|
|
||||||
"env": {
|
|
||||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,7 @@ If you are looking to install or test osu! without setting up a development envi
|
|||||||
|
|
||||||
**Latest build:**
|
**Latest build:**
|
||||||
|
|
||||||
| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.x86_64.AppImage) | [iOS(iOS 10+)](https://osu.ppy.sh/home/testflight) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk)
|
| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS(iOS 10+)](https://osu.ppy.sh/home/testflight) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk)
|
||||||
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||||
|
|
||||||
- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/install/dependencies?tabs=netcore31&pivots=os-windows)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs.
|
- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/install/dependencies?tabs=netcore31&pivots=os-windows)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs.
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
<Optimize>False</Optimize>
|
<Optimize>False</Optimize>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<EnableLLVM>false</EnableLLVM>
|
|
||||||
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
||||||
<AndroidUseSharedRuntime>true</AndroidUseSharedRuntime>
|
<AndroidUseSharedRuntime>true</AndroidUseSharedRuntime>
|
||||||
<EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk>
|
<EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk>
|
||||||
@ -34,7 +33,6 @@
|
|||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>false</DebugSymbols>
|
||||||
<DebugType>None</DebugType>
|
<DebugType>None</DebugType>
|
||||||
<Optimize>True</Optimize>
|
<Optimize>True</Optimize>
|
||||||
<EnableLLVM>true</EnableLLVM>
|
|
||||||
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
||||||
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
|
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
|
||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||||
@ -53,7 +51,7 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.221.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.221.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.310.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -30,11 +30,6 @@ namespace osu.Android
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
Add(new SimpleUpdateManager());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@
|
|||||||
<AssemblyName>osu.Android</AssemblyName>
|
<AssemblyName>osu.Android</AssemblyName>
|
||||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
||||||
|
<EnableLLVM>false</EnableLLVM> <!-- This currently causes random lockups during gameplay. https://github.com/mono/mono/issues/18973 -->
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<MandroidI18n>cjk;mideast;other;rare;west</MandroidI18n>
|
<MandroidI18n>cjk;mideast;other;rare;west</MandroidI18n>
|
||||||
|
@ -47,20 +47,25 @@ namespace osu.Desktop
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override UpdateManager CreateUpdateManager()
|
||||||
|
{
|
||||||
|
switch (RuntimeInfo.OS)
|
||||||
|
{
|
||||||
|
case RuntimeInfo.Platform.Windows:
|
||||||
|
return new SquirrelUpdateManager();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return new SimpleUpdateManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
if (!noVersionOverlay)
|
if (!noVersionOverlay)
|
||||||
{
|
|
||||||
LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, Add);
|
LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, Add);
|
||||||
|
|
||||||
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows)
|
|
||||||
Add(new SquirrelUpdateManager());
|
|
||||||
else
|
|
||||||
Add(new SimpleUpdateManager());
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadComponentAsync(new DiscordRichPresence(), Add);
|
LoadComponentAsync(new DiscordRichPresence(), Add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
// 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.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneCatchModPerfect : ModPerfectTestScene
|
||||||
|
{
|
||||||
|
public TestSceneCatchModPerfect()
|
||||||
|
: base(new CatchRuleset(), new CatchModPerfect())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestBananaShower(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new BananaShower { StartTime = 1000, EndTime = 3000 }, false), shouldMiss);
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestFruit(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Fruit { StartTime = 1000 }), shouldMiss);
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestJuiceStream(bool shouldMiss)
|
||||||
|
{
|
||||||
|
var stream = new JuiceStream
|
||||||
|
{
|
||||||
|
StartTime = 1000,
|
||||||
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
|
{
|
||||||
|
Vector2.Zero,
|
||||||
|
new Vector2(100, 0),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateHitObjectTest(new HitObjectTestData(stream), shouldMiss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only care about testing misses, hits are tested via JuiceStream
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Droplet { StartTime = 1000 }), shouldMiss);
|
||||||
|
|
||||||
|
// We only care about testing misses, hits are tested via JuiceStream
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestTinyDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new TinyDroplet { StartTime = 1000 }), shouldMiss);
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 130 KiB |
@ -7,7 +7,6 @@ using osu.Game.Rulesets.Catch.Objects;
|
|||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||||
return base.CreatePlayer(ruleset);
|
return base.CreatePlayer(ruleset);
|
||||||
|
@ -29,6 +29,12 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBananaShower()
|
||||||
|
{
|
||||||
|
AddUntilStep("player is done", () => !Player.ValidForResume);
|
||||||
|
}
|
||||||
|
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||||
{
|
{
|
||||||
var beatmap = new Beatmap
|
var beatmap = new Beatmap
|
||||||
@ -40,7 +46,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 5000, NewCombo = true });
|
beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 3000, NewCombo = true });
|
||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(CatcherArea),
|
typeof(CatcherArea),
|
||||||
|
typeof(CatcherSprite)
|
||||||
};
|
};
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -42,6 +42,9 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
AddStep("show droplet", () => SetContents(createDrawableDroplet));
|
AddStep("show droplet", () => SetContents(createDrawableDroplet));
|
||||||
|
|
||||||
AddStep("show tiny droplet", () => SetContents(createDrawableTinyDroplet));
|
AddStep("show tiny droplet", () => SetContents(createDrawableTinyDroplet));
|
||||||
|
|
||||||
|
foreach (FruitVisualRepresentation rep in Enum.GetValues(typeof(FruitVisualRepresentation)))
|
||||||
|
AddStep($"show hyperdash {rep}", () => SetContents(() => createDrawable(rep, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Drawable createDrawableTinyDroplet()
|
private Drawable createDrawableTinyDroplet()
|
||||||
@ -82,9 +85,13 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Drawable createDrawable(FruitVisualRepresentation rep)
|
private Drawable createDrawable(FruitVisualRepresentation rep, bool hyperdash = false)
|
||||||
{
|
{
|
||||||
Fruit fruit = new TestCatchFruit(rep) { Scale = 1.5f };
|
Fruit fruit = new TestCatchFruit(rep)
|
||||||
|
{
|
||||||
|
Scale = 1.5f,
|
||||||
|
HyperDashTarget = hyperdash ? new Banana() : null
|
||||||
|
};
|
||||||
|
|
||||||
return new DrawableFruit(fruit)
|
return new DrawableFruit(fruit)
|
||||||
{
|
{
|
||||||
|
@ -1,9 +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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
@ -22,7 +26,16 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
public void TestHyperDash()
|
public void TestHyperDash()
|
||||||
{
|
{
|
||||||
AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash);
|
AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash);
|
||||||
|
AddUntilStep("wait for left hyperdash", () => getCatcher().Scale.X < 0 && getCatcher().HyperDashing);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
AddUntilStep("wait for right hyperdash", () => getCatcher().Scale.X > 0 && getCatcher().HyperDashing);
|
||||||
|
AddUntilStep("wait for left hyperdash", () => getCatcher().Scale.X < 0 && getCatcher().HyperDashing);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CatcherArea.Catcher getCatcher() => Player.ChildrenOfType<CatcherArea>().First().MovableCatcher;
|
||||||
|
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||||
{
|
{
|
||||||
@ -35,17 +48,40 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Should produce a hyper-dash
|
// Should produce a hyper-dash (edge case test)
|
||||||
beatmap.HitObjects.Add(new Fruit { StartTime = 816, X = 308 / 512f, NewCombo = true });
|
beatmap.HitObjects.Add(new Fruit { StartTime = 1816, X = 308 / 512f, NewCombo = true });
|
||||||
beatmap.HitObjects.Add(new Fruit { StartTime = 1008, X = 56 / 512f, });
|
beatmap.HitObjects.Add(new JuiceStream { StartTime = 2008, X = 56 / 512f, });
|
||||||
|
|
||||||
for (int i = 0; i < 512; i++)
|
double startTime = 3000;
|
||||||
{
|
|
||||||
if (i % 5 < 3)
|
const float left_x = 0.02f;
|
||||||
beatmap.HitObjects.Add(new Fruit { X = i % 10 < 5 ? 0.02f : 0.98f, StartTime = 2000 + i * 100, NewCombo = i % 8 == 0 });
|
const float right_x = 0.98f;
|
||||||
}
|
|
||||||
|
createObjects(() => new Fruit(), left_x);
|
||||||
|
createObjects(() => new JuiceStream(), right_x);
|
||||||
|
createObjects(() => new JuiceStream(), left_x);
|
||||||
|
createObjects(() => new Fruit(), right_x);
|
||||||
|
createObjects(() => new Fruit(), left_x);
|
||||||
|
createObjects(() => new Fruit(), right_x);
|
||||||
|
createObjects(() => new JuiceStream(), left_x);
|
||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
|
|
||||||
|
void createObjects(Func<CatchHitObject> createObject, float x)
|
||||||
|
{
|
||||||
|
const float spacing = 140;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
var hitObject = createObject();
|
||||||
|
hitObject.X = x;
|
||||||
|
hitObject.StartTime = startTime + i * spacing;
|
||||||
|
|
||||||
|
beatmap.HitObjects.Add(hitObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime += 700;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
56
osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
|
{
|
||||||
|
public class TestSceneJuiceStream : PlayerTestScene
|
||||||
|
{
|
||||||
|
public TestSceneJuiceStream()
|
||||||
|
: base(new CatchRuleset())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestJuiceStreamEndingCombo()
|
||||||
|
{
|
||||||
|
AddUntilStep("player is done", () => !Player.ValidForResume);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = new BeatmapInfo
|
||||||
|
{
|
||||||
|
BaseDifficulty = new BeatmapDifficulty { CircleSize = 5, SliderMultiplier = 2 },
|
||||||
|
Ruleset = ruleset
|
||||||
|
},
|
||||||
|
HitObjects = new List<HitObject>
|
||||||
|
{
|
||||||
|
new JuiceStream
|
||||||
|
{
|
||||||
|
X = 0.5f,
|
||||||
|
Path = new SliderPath(PathType.Linear, new[]
|
||||||
|
{
|
||||||
|
Vector2.Zero,
|
||||||
|
new Vector2(0, 100)
|
||||||
|
}),
|
||||||
|
StartTime = 200
|
||||||
|
},
|
||||||
|
new Banana
|
||||||
|
{
|
||||||
|
X = 0.5f,
|
||||||
|
StartTime = 1000,
|
||||||
|
NewCombo = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
FruitGrapes,
|
FruitGrapes,
|
||||||
FruitOrange,
|
FruitOrange,
|
||||||
FruitPear,
|
FruitPear,
|
||||||
Droplet
|
Droplet,
|
||||||
|
CatcherIdle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Rulesets.Catch.Judgements;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Mods
|
namespace osu.Game.Rulesets.Catch.Mods
|
||||||
{
|
{
|
||||||
public class CatchModPerfect : ModPerfect
|
public class CatchModPerfect : ModPerfect
|
||||||
{
|
{
|
||||||
|
protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
|
||||||
|
=> !(result.Judgement is CatchBananaJudgement)
|
||||||
|
&& base.FailCondition(healthProcessor, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects
|
namespace osu.Game.Rulesets.Catch.Objects
|
||||||
@ -11,6 +12,8 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
|
|
||||||
public override bool LastInCombo => true;
|
public override bool LastInCombo => true;
|
||||||
|
|
||||||
|
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||||
|
|
||||||
protected override void CreateNestedHitObjects()
|
protected override void CreateNestedHitObjects()
|
||||||
{
|
{
|
||||||
base.CreateNestedHitObjects();
|
base.CreateNestedHitObjects();
|
||||||
|
@ -7,9 +7,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
@ -64,15 +62,24 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
|||||||
|
|
||||||
if (hitObject.HyperDash)
|
if (hitObject.HyperDash)
|
||||||
{
|
{
|
||||||
AddInternal(new Pulp
|
AddInternal(new Circle
|
||||||
{
|
{
|
||||||
RelativePositionAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
AccentColour = { Value = Color4.Red },
|
BorderColour = Color4.Red,
|
||||||
|
BorderThickness = 12f * RADIUS_ADJUST,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0.3f,
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
Alpha = 0.5f,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Scale = new Vector2(1.333f)
|
Colour = Color4.Red,
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using osu.Game.Audio;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
|
||||||
@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const float base_scoring_distance = 100;
|
private const float base_scoring_distance = 100;
|
||||||
|
|
||||||
|
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||||
|
|
||||||
public int RepeatCount { get; set; }
|
public int RepeatCount { get; set; }
|
||||||
|
|
||||||
public double Velocity;
|
public double Velocity;
|
||||||
|
@ -44,6 +44,10 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
|||||||
return new LegacyFruitPiece("fruit-drop") { Scale = new Vector2(0.8f) };
|
return new LegacyFruitPiece("fruit-drop") { Scale = new Vector2(0.8f) };
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CatchSkinComponents.CatcherIdle:
|
||||||
|
return this.GetAnimation("fruit-catcher-idle", true, true, true) ??
|
||||||
|
this.GetAnimation("fruit-ryuuta", true, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics.Sprites;
|
|||||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Skinning
|
namespace osu.Game.Rulesets.Catch.Skinning
|
||||||
@ -49,6 +50,23 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
|||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (drawableCatchObject.HitObject.HyperDash)
|
||||||
|
{
|
||||||
|
var hyperDash = new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture(lookupName),
|
||||||
|
Colour = Color4.Red,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Depth = 1,
|
||||||
|
Alpha = 0.7f,
|
||||||
|
Scale = new Vector2(1.2f)
|
||||||
|
};
|
||||||
|
|
||||||
|
AddInternal(hyperDash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
|
@ -50,6 +50,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public void OnResult(DrawableCatchHitObject fruit, JudgementResult result)
|
public void OnResult(DrawableCatchHitObject fruit, JudgementResult result)
|
||||||
{
|
{
|
||||||
|
if (result.Judgement is IgnoreJudgement)
|
||||||
|
return;
|
||||||
|
|
||||||
void runAfterLoaded(Action action)
|
void runAfterLoaded(Action action)
|
||||||
{
|
{
|
||||||
if (lastPlateableFruit == null)
|
if (lastPlateableFruit == null)
|
||||||
@ -89,7 +92,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
if (fruit.HitObject.LastInCombo)
|
if (fruit.HitObject.LastInCombo)
|
||||||
{
|
{
|
||||||
if (((CatchJudgement)result.Judgement).ShouldExplodeFor(result))
|
if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result))
|
||||||
runAfterLoaded(() => MovableCatcher.Explode());
|
runAfterLoaded(() => MovableCatcher.Explode());
|
||||||
else
|
else
|
||||||
MovableCatcher.Drop();
|
MovableCatcher.Drop();
|
||||||
@ -152,7 +155,10 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
},
|
},
|
||||||
createCatcherSprite(),
|
createCatcherSprite().With(c =>
|
||||||
|
{
|
||||||
|
c.Anchor = Anchor.TopCentre;
|
||||||
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,12 +208,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
var additive = createCatcherSprite();
|
var additive = createCatcherSprite();
|
||||||
|
|
||||||
additive.Anchor = Anchor;
|
additive.Anchor = Anchor;
|
||||||
additive.OriginPosition += new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly.
|
|
||||||
additive.Position = Position;
|
|
||||||
additive.Scale = Scale;
|
additive.Scale = Scale;
|
||||||
additive.Colour = HyperDashing ? Color4.Red : Color4.White;
|
additive.Colour = HyperDashing ? Color4.Red : Color4.White;
|
||||||
additive.RelativePositionAxes = RelativePositionAxes;
|
|
||||||
additive.Blending = BlendingParameters.Additive;
|
additive.Blending = BlendingParameters.Additive;
|
||||||
|
additive.RelativePositionAxes = RelativePositionAxes;
|
||||||
|
additive.Position = Position;
|
||||||
|
|
||||||
AdditiveTarget.Add(additive);
|
AdditiveTarget.Add(additive);
|
||||||
|
|
||||||
@ -267,6 +272,10 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
catchObjectPosition >= catcherPosition - halfCatchWidth &&
|
catchObjectPosition >= catcherPosition - halfCatchWidth &&
|
||||||
catchObjectPosition <= catcherPosition + halfCatchWidth;
|
catchObjectPosition <= catcherPosition + halfCatchWidth;
|
||||||
|
|
||||||
|
// only update hyperdash state if we are catching a fruit.
|
||||||
|
// exceptions are Droplets and JuiceStreams.
|
||||||
|
if (!(fruit is Fruit)) return validCatch;
|
||||||
|
|
||||||
if (validCatch && fruit.HyperDash)
|
if (validCatch && fruit.HyperDash)
|
||||||
{
|
{
|
||||||
var target = fruit.HyperDashTarget;
|
var target = fruit.HyperDashTarget;
|
||||||
|
@ -3,31 +3,35 @@
|
|||||||
|
|
||||||
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.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.UI
|
namespace osu.Game.Rulesets.Catch.UI
|
||||||
{
|
{
|
||||||
public class CatcherSprite : CompositeDrawable
|
public class CatcherSprite : SkinnableDrawable
|
||||||
{
|
{
|
||||||
|
protected override bool ApplySizeRestrictionsToDefault => true;
|
||||||
|
|
||||||
public CatcherSprite()
|
public CatcherSprite()
|
||||||
|
: base(new CatchSkinComponent(CatchSkinComponents.CatcherIdle), _ =>
|
||||||
|
new DefaultCatcherSprite(), confineMode: ConfineMode.ScaleDownToFit)
|
||||||
{
|
{
|
||||||
|
RelativeSizeAxes = Axes.None;
|
||||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||||
|
|
||||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||||
OriginPosition = new Vector2(-0.02f, 0.06f) * CatcherArea.CATCHER_SIZE;
|
OriginPosition = new Vector2(0.5f, 0.06f) * CatcherArea.CATCHER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DefaultCatcherSprite : Sprite
|
||||||
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(TextureStore textures)
|
||||||
{
|
{
|
||||||
InternalChild = new SkinnableSprite("Gameplay/catch/fruit-catcher-idle", confineMode: ConfineMode.ScaleDownToFit)
|
Texture = textures.Get("Gameplay/catch/fruit-catcher-idle");
|
||||||
{
|
}
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
// 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.Rulesets.Mania.Objects;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneManiaModPerfect : ModPerfectTestScene
|
||||||
|
{
|
||||||
|
public TestSceneManiaModPerfect()
|
||||||
|
: base(new ManiaRuleset(), new ManiaModPerfect())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Note { StartTime = 1000 }), shouldMiss);
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestHoldNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HoldNote { StartTime = 1000, EndTime = 3000 }), shouldMiss);
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
|
||||||
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Judgements
|
|
||||||
{
|
|
||||||
public class HoldNoteJudgement : ManiaJudgement
|
|
||||||
{
|
|
||||||
public override bool AffectsCombo => false;
|
|
||||||
|
|
||||||
protected override int NumericResultFor(HitResult result) => 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Caching;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Layout;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -22,21 +22,13 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
|
|
||||||
private class ManiaFlashlight : Flashlight
|
private class ManiaFlashlight : Flashlight
|
||||||
{
|
{
|
||||||
private readonly Cached flashlightProperties = new Cached();
|
private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.DrawSize);
|
||||||
|
|
||||||
public ManiaFlashlight()
|
public ManiaFlashlight()
|
||||||
{
|
{
|
||||||
FlashlightSize = new Vector2(0, default_flashlight_size);
|
FlashlightSize = new Vector2(0, default_flashlight_size);
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
AddLayout(flashlightProperties);
|
||||||
{
|
|
||||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
|
||||||
{
|
|
||||||
flashlightProperties.Invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.Invalidate(invalidation, source, shallPropagate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects
|
namespace osu.Game.Rulesets.Mania.Objects
|
||||||
@ -8,5 +9,7 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
public class BarLine : ManiaHitObject, IBarLine
|
public class BarLine : ManiaHitObject, IBarLine
|
||||||
{
|
{
|
||||||
public bool Major { get; set; }
|
public bool Major { get; set; }
|
||||||
|
|
||||||
|
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateStateTransforms(ArmedState state)
|
protected override void UpdateStateTransforms(ArmedState state) => this.FadeOut(150);
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Caching;
|
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
using osu.Framework.Graphics.Effects;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Layout;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||||
@ -65,6 +65,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddLayout(subtractionCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -100,15 +102,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Cached subtractionCache = new Cached();
|
private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
|
||||||
|
|
||||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
|
||||||
{
|
|
||||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
|
||||||
subtractionCache.Invalidate();
|
|
||||||
|
|
||||||
return base.Invalidate(invalidation, source, shallPropagate);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mania.Judgements;
|
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
@ -103,7 +102,7 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Judgement CreateJudgement() => new HoldNoteJudgement();
|
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||||
|
|
||||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||||
}
|
}
|
||||||
|
@ -115,9 +115,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
AutoSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Y = HIT_TARGET_POSITION + 150,
|
Y = HIT_TARGET_POSITION + 150,
|
||||||
BypassAutoSizeAxes = Axes.Both
|
|
||||||
},
|
},
|
||||||
topLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
|
topLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneOsuModDifficultyAdjust : ModTestScene
|
||||||
|
{
|
||||||
|
public TestSceneOsuModDifficultyAdjust()
|
||||||
|
: base(new OsuRuleset())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNoAdjustment() => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModDifficultyAdjust(),
|
||||||
|
Autoplay = true,
|
||||||
|
PassCondition = checkSomeHit
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCircleSize1() => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 1 } },
|
||||||
|
Autoplay = true,
|
||||||
|
PassCondition = () => checkSomeHit() && checkObjectsScale(0.78f)
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCircleSize10() => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 10 } },
|
||||||
|
Autoplay = true,
|
||||||
|
PassCondition = () => checkSomeHit() && checkObjectsScale(0.15f)
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestApproachRate1() => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } },
|
||||||
|
Autoplay = true,
|
||||||
|
PassCondition = () => checkSomeHit() && checkObjectsPreempt(1680)
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestApproachRate10() => CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 10 } },
|
||||||
|
Autoplay = true,
|
||||||
|
PassCondition = () => checkSomeHit() && checkObjectsPreempt(450)
|
||||||
|
});
|
||||||
|
|
||||||
|
private bool checkObjectsPreempt(double target)
|
||||||
|
{
|
||||||
|
var objects = Player.ChildrenOfType<DrawableHitCircle>();
|
||||||
|
if (!objects.Any())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return objects.All(o => o.HitObject.TimePreempt == target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool checkObjectsScale(float target)
|
||||||
|
{
|
||||||
|
var objects = Player.ChildrenOfType<DrawableHitCircle>();
|
||||||
|
if (!objects.Any())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return objects.All(o => Precision.AlmostEquals(o.ChildrenOfType<ShakeContainer>().First().Children.OfType<Container>().Single().Scale.X, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool checkSomeHit()
|
||||||
|
{
|
||||||
|
return Player.ScoreProcessor.JudgedHits >= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneOsuModDoubleTime : ModTestScene
|
||||||
|
{
|
||||||
|
public TestSceneOsuModDoubleTime()
|
||||||
|
: base(new OsuRuleset())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(0.5)]
|
||||||
|
[TestCase(1.01)]
|
||||||
|
[TestCase(1.5)]
|
||||||
|
[TestCase(2)]
|
||||||
|
[TestCase(5)]
|
||||||
|
public void TestSpeedChangeCustomisation(double rate)
|
||||||
|
{
|
||||||
|
var mod = new OsuModDoubleTime { SpeedChange = { Value = rate } };
|
||||||
|
|
||||||
|
CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = mod,
|
||||||
|
PassCondition = () => Player.ScoreProcessor.JudgedHits >= 2 &&
|
||||||
|
Precision.AlmostEquals(Player.GameplayClockContainer.GameplayClock.Rate, mod.SpeedChange.Value)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneOsuModPerfect : ModPerfectTestScene
|
||||||
|
{
|
||||||
|
public TestSceneOsuModPerfect()
|
||||||
|
: base(new OsuRuleset(), new OsuModPerfect())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestHitCircle(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HitCircle { StartTime = 1000 }), shouldMiss);
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestSlider(bool shouldMiss)
|
||||||
|
{
|
||||||
|
var slider = new Slider
|
||||||
|
{
|
||||||
|
StartTime = 1000,
|
||||||
|
Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(100, 0), })
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateHitObjectTest(new HitObjectTestData(slider), shouldMiss);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestSpinner(bool shouldMiss)
|
||||||
|
{
|
||||||
|
var spinner = new Spinner
|
||||||
|
{
|
||||||
|
StartTime = 1000,
|
||||||
|
EndTime = 3000,
|
||||||
|
Position = new Vector2(256, 192)
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateHitObjectTest(new HitObjectTestData(spinner), shouldMiss);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,12 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
@ -114,6 +117,22 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
assertGroups();
|
assertGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestStackedObjects()
|
||||||
|
{
|
||||||
|
addObjectsStep(() => new OsuHitObject[]
|
||||||
|
{
|
||||||
|
new HitCircle { Position = new Vector2(300, 100) },
|
||||||
|
new HitCircle
|
||||||
|
{
|
||||||
|
Position = new Vector2(300, 300),
|
||||||
|
StackHeight = 20
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assertDirections();
|
||||||
|
}
|
||||||
|
|
||||||
private void addMultipleObjectsStep() => addObjectsStep(() => new OsuHitObject[]
|
private void addMultipleObjectsStep() => addObjectsStep(() => new OsuHitObject[]
|
||||||
{
|
{
|
||||||
new HitCircle { Position = new Vector2(100, 100) },
|
new HitCircle { Position = new Vector2(100, 100) },
|
||||||
@ -207,6 +226,33 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertDirections()
|
||||||
|
{
|
||||||
|
AddAssert("group directions are correct", () =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < hitObjectContainer.Count; i++)
|
||||||
|
{
|
||||||
|
DrawableOsuHitObject expectedStart = getObject(i);
|
||||||
|
DrawableOsuHitObject expectedEnd = i < hitObjectContainer.Count - 1 ? getObject(i + 1) : null;
|
||||||
|
|
||||||
|
if (expectedEnd == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var points = getGroup(i).ChildrenOfType<FollowPoint>().ToArray();
|
||||||
|
if (points.Length == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float expectedDirection = MathF.Atan2(expectedStart.Position.Y - expectedEnd.Position.Y, expectedStart.Position.X - expectedEnd.Position.X);
|
||||||
|
float realDirection = MathF.Atan2(expectedStart.Position.Y - points[^1].Position.Y, expectedStart.Position.X - points[^1].Position.X);
|
||||||
|
|
||||||
|
if (!Precision.AlmostEquals(expectedDirection, realDirection))
|
||||||
|
throw new AssertionException($"Expected group {i} in direction {expectedDirection}, but was {realDirection}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index];
|
private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index];
|
||||||
|
|
||||||
private FollowPointConnection getGroup(int index) => followPointRenderer.Connections[index];
|
private FollowPointConnection getGroup(int index) => followPointRenderer.Connections[index];
|
||||||
|
108
osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
|
{
|
||||||
|
public class TestSceneHitCircleArea : ManualInputManagerTestScene
|
||||||
|
{
|
||||||
|
private HitCircle hitCircle;
|
||||||
|
private DrawableHitCircle drawableHitCircle;
|
||||||
|
private DrawableHitCircle.HitReceptor hitAreaReceptor => drawableHitCircle.HitArea;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public new void SetUp()
|
||||||
|
{
|
||||||
|
base.SetUp();
|
||||||
|
|
||||||
|
Schedule(() =>
|
||||||
|
{
|
||||||
|
hitCircle = new HitCircle
|
||||||
|
{
|
||||||
|
Position = new Vector2(100, 100),
|
||||||
|
StartTime = Time.Current + 500
|
||||||
|
};
|
||||||
|
|
||||||
|
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||||
|
|
||||||
|
Child = new SkinProvidingContainer(new DefaultSkin())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Child = drawableHitCircle = new DrawableHitCircle(hitCircle)
|
||||||
|
{
|
||||||
|
Size = new Vector2(100)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCircleHitCentre()
|
||||||
|
{
|
||||||
|
AddStep("move mouse to centre", () => InputManager.MoveMouseTo(hitAreaReceptor.ScreenSpaceDrawQuad.Centre));
|
||||||
|
scheduleHit();
|
||||||
|
|
||||||
|
AddAssert("hit registered", () => hitAreaReceptor.HitAction == OsuAction.LeftButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCircleHitLeftEdge()
|
||||||
|
{
|
||||||
|
AddStep("move mouse to left edge", () =>
|
||||||
|
{
|
||||||
|
var drawQuad = hitAreaReceptor.ScreenSpaceDrawQuad;
|
||||||
|
var mousePosition = new Vector2(drawQuad.TopLeft.X, drawQuad.Centre.Y);
|
||||||
|
|
||||||
|
InputManager.MoveMouseTo(mousePosition);
|
||||||
|
});
|
||||||
|
scheduleHit();
|
||||||
|
|
||||||
|
AddAssert("hit registered", () => hitAreaReceptor.HitAction == OsuAction.LeftButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(0.95f, OsuAction.LeftButton)]
|
||||||
|
[TestCase(1.05f, null)]
|
||||||
|
public void TestHitsCloseToEdge(float relativeDistanceFromCentre, OsuAction? expectedAction)
|
||||||
|
{
|
||||||
|
AddStep("move mouse to top left circle edge", () =>
|
||||||
|
{
|
||||||
|
var drawQuad = hitAreaReceptor.ScreenSpaceDrawQuad;
|
||||||
|
// sqrt(2) / 2 = sin(45deg) = cos(45deg)
|
||||||
|
// draw width halved to get radius
|
||||||
|
float correction = relativeDistanceFromCentre * (float)Math.Sqrt(2) / 2 * (drawQuad.Width / 2);
|
||||||
|
var mousePosition = new Vector2(drawQuad.Centre.X - correction, drawQuad.Centre.Y - correction);
|
||||||
|
|
||||||
|
InputManager.MoveMouseTo(mousePosition);
|
||||||
|
});
|
||||||
|
scheduleHit();
|
||||||
|
|
||||||
|
AddAssert($"hit {(expectedAction == null ? "not " : string.Empty)}registered", () => hitAreaReceptor.HitAction == expectedAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCircleMissBoundingBoxCorner()
|
||||||
|
{
|
||||||
|
AddStep("move mouse to top left corner of bounding box", () => InputManager.MoveMouseTo(hitAreaReceptor.ScreenSpaceDrawQuad.TopLeft));
|
||||||
|
scheduleHit();
|
||||||
|
|
||||||
|
AddAssert("hit not registered", () => hitAreaReceptor.HitAction == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleHit() => AddStep("schedule action", () =>
|
||||||
|
{
|
||||||
|
var delay = hitCircle.StartTime - hitCircle.HitWindows.WindowFor(HitResult.Great) - Time.Current;
|
||||||
|
Scheduler.AddDelayed(() => hitAreaReceptor.OnPressed(OsuAction.LeftButton), delay);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
101
osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// 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.Beatmaps;
|
||||||
|
using osu.Game.Replays;
|
||||||
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Replays;
|
||||||
|
using osu.Game.Rulesets.Osu.Scoring;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
|
{
|
||||||
|
public class TestSceneMissHitWindowJudgements : ModTestScene
|
||||||
|
{
|
||||||
|
public TestSceneMissHitWindowJudgements()
|
||||||
|
: base(new OsuRuleset())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMissViaEarlyHit()
|
||||||
|
{
|
||||||
|
var beatmap = new Beatmap
|
||||||
|
{
|
||||||
|
HitObjects = { new HitCircle { Position = new Vector2(256, 192) } }
|
||||||
|
};
|
||||||
|
|
||||||
|
var hitWindows = new OsuHitWindows();
|
||||||
|
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
||||||
|
|
||||||
|
CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Autoplay = false,
|
||||||
|
Mod = new TestAutoMod(),
|
||||||
|
Beatmap = new Beatmap
|
||||||
|
{
|
||||||
|
HitObjects = { new HitCircle { Position = new Vector2(256, 192) } }
|
||||||
|
},
|
||||||
|
PassCondition = () => Player.Results.Count > 0 && Player.Results[0].TimeOffset < -hitWindows.WindowFor(HitResult.Meh) && Player.Results[0].Type == HitResult.Miss
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMissViaNotHitting()
|
||||||
|
{
|
||||||
|
var beatmap = new Beatmap
|
||||||
|
{
|
||||||
|
HitObjects = { new HitCircle { Position = new Vector2(256, 192) } }
|
||||||
|
};
|
||||||
|
|
||||||
|
var hitWindows = new OsuHitWindows();
|
||||||
|
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
||||||
|
|
||||||
|
CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Autoplay = false,
|
||||||
|
Beatmap = beatmap,
|
||||||
|
PassCondition = () => Player.Results.Count > 0 && Player.Results[0].TimeOffset >= hitWindows.WindowFor(HitResult.Meh) && Player.Results[0].Type == HitResult.Miss
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestAutoMod : OsuModAutoplay
|
||||||
|
{
|
||||||
|
public override Score CreateReplayScore(IBeatmap beatmap) => new Score
|
||||||
|
{
|
||||||
|
ScoreInfo = new ScoreInfo { User = new User { Username = "Autoplay" } },
|
||||||
|
Replay = new MissingAutoGenerator(beatmap).Generate()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MissingAutoGenerator : OsuAutoGeneratorBase
|
||||||
|
{
|
||||||
|
public new OsuBeatmap Beatmap => (OsuBeatmap)base.Beatmap;
|
||||||
|
|
||||||
|
public MissingAutoGenerator(IBeatmap beatmap)
|
||||||
|
: base(beatmap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Replay Generate()
|
||||||
|
{
|
||||||
|
AddFrameToReplay(new OsuReplayFrame(-100000, new Vector2(256, 500)));
|
||||||
|
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 1500, new Vector2(256, 500)));
|
||||||
|
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 1500, new Vector2(256, 500)));
|
||||||
|
|
||||||
|
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 450, Beatmap.HitObjects[0].StackedPosition));
|
||||||
|
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 350, Beatmap.HitObjects[0].StackedPosition, OsuAction.LeftButton));
|
||||||
|
AddFrameToReplay(new OsuReplayFrame(Beatmap.HitObjects[0].StartTime - 325, Beatmap.HitObjects[0].StackedPosition));
|
||||||
|
|
||||||
|
return Replay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneOsuFlashlight : TestSceneOsuPlayer
|
public class TestSceneOsuFlashlight : TestSceneOsuPlayer
|
||||||
{
|
{
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
SelectedMods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), };
|
SelectedMods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), };
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ using osu.Game.Configuration;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Storyboards;
|
using osu.Game.Storyboards;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
@ -56,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
private void checkNextHitObject(string skin) =>
|
private void checkNextHitObject(string skin) =>
|
||||||
AddUntilStep($"check skin from {skin}", () =>
|
AddUntilStep($"check skin from {skin}", () =>
|
||||||
{
|
{
|
||||||
var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType<DrawableHitCircle>().FirstOrDefault();
|
var firstObject = Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType<DrawableHitCircle>().FirstOrDefault();
|
||||||
|
|
||||||
if (firstObject == null)
|
if (firstObject == null)
|
||||||
return false;
|
return false;
|
||||||
@ -75,7 +74,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private AudioManager audio { get; set; }
|
private AudioManager audio { get; set; }
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
|
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
|
||||||
|
|
||||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, audio, testBeatmapSkin);
|
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, audio, testBeatmapSkin);
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
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.Tests.Visual;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
base.SetUpSteps();
|
base.SetUpSteps();
|
||||||
|
|
||||||
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
||||||
AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First());
|
AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)Player.DrawableRuleset.Playfield.AllHitObjects.First());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -89,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
{
|
{
|
||||||
AddStep($"seek to {time}", () => track.Seek(time));
|
AddStep($"seek to {time}", () => track.Seek(time));
|
||||||
|
|
||||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, ((TestPlayer)Player).DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
|
||||||
|
@ -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.
|
|
||||||
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Judgements
|
|
||||||
{
|
|
||||||
public class OsuSliderTailJudgement : OsuJudgement
|
|
||||||
{
|
|
||||||
public override bool AffectsCombo => false;
|
|
||||||
|
|
||||||
protected override int NumericResultFor(HitResult result) => 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
private const int spacing = 32;
|
private const int spacing = 32;
|
||||||
private const double preempt = 800;
|
private const double preempt = 800;
|
||||||
|
|
||||||
|
public override bool RemoveWhenNotAlive => false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The start time of <see cref="Start"/>.
|
/// The start time of <see cref="Start"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -79,27 +81,31 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
drawableObject.HitObject.DefaultsApplied += scheduleRefresh;
|
drawableObject.HitObject.DefaultsApplied += scheduleRefresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleRefresh() => Scheduler.AddOnce(refresh);
|
private void scheduleRefresh()
|
||||||
|
{
|
||||||
|
Scheduler.AddOnce(refresh);
|
||||||
|
}
|
||||||
|
|
||||||
private void refresh()
|
private void refresh()
|
||||||
{
|
{
|
||||||
ClearInternal();
|
ClearInternal();
|
||||||
|
|
||||||
if (End == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
OsuHitObject osuStart = Start.HitObject;
|
OsuHitObject osuStart = Start.HitObject;
|
||||||
OsuHitObject osuEnd = End.HitObject;
|
|
||||||
|
|
||||||
if (osuEnd.NewCombo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (osuStart is Spinner || osuEnd is Spinner)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Vector2 startPosition = osuStart.EndPosition;
|
|
||||||
Vector2 endPosition = osuEnd.Position;
|
|
||||||
double startTime = osuStart.GetEndTime();
|
double startTime = osuStart.GetEndTime();
|
||||||
|
|
||||||
|
LifetimeStart = startTime;
|
||||||
|
|
||||||
|
OsuHitObject osuEnd = End?.HitObject;
|
||||||
|
|
||||||
|
if (osuEnd == null || osuEnd.NewCombo || osuStart is Spinner || osuEnd is Spinner)
|
||||||
|
{
|
||||||
|
// ensure we always set a lifetime for full LifetimeManagementContainer benefits
|
||||||
|
LifetimeEnd = LifetimeStart;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 startPosition = osuStart.StackedEndPosition;
|
||||||
|
Vector2 endPosition = osuEnd.StackedPosition;
|
||||||
double endTime = osuEnd.StartTime;
|
double endTime = osuEnd.StartTime;
|
||||||
|
|
||||||
Vector2 distanceVector = endPosition - startPosition;
|
Vector2 distanceVector = endPosition - startPosition;
|
||||||
@ -107,6 +113,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI));
|
float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI));
|
||||||
double duration = endTime - startTime;
|
double duration = endTime - startTime;
|
||||||
|
|
||||||
|
double? firstTransformStartTime = null;
|
||||||
|
double finalTransformEndTime = startTime;
|
||||||
|
|
||||||
for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing)
|
for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing)
|
||||||
{
|
{
|
||||||
float fraction = (float)d / distance;
|
float fraction = (float)d / distance;
|
||||||
@ -125,16 +134,23 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
Scale = new Vector2(1.5f * osuEnd.Scale),
|
Scale = new Vector2(1.5f * osuEnd.Scale),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (firstTransformStartTime == null)
|
||||||
|
firstTransformStartTime = fadeInTime;
|
||||||
|
|
||||||
using (fp.BeginAbsoluteSequence(fadeInTime))
|
using (fp.BeginAbsoluteSequence(fadeInTime))
|
||||||
{
|
{
|
||||||
fp.FadeIn(osuEnd.TimeFadeIn);
|
fp.FadeIn(osuEnd.TimeFadeIn);
|
||||||
fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out);
|
fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out);
|
||||||
fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out);
|
fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out);
|
||||||
fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn);
|
fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn);
|
||||||
|
|
||||||
|
finalTransformEndTime = fadeOutTime + osuEnd.TimeFadeIn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fp.Expire(true);
|
// todo: use Expire() on FollowPoints and take lifetime from them when https://github.com/ppy/osu-framework/issues/3300 is fixed.
|
||||||
}
|
LifetimeStart = firstTransformStartTime ?? startTime;
|
||||||
|
LifetimeEnd = finalTransformEndTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visualises connections between <see cref="DrawableOsuHitObject"/>s.
|
/// Visualises connections between <see cref="DrawableOsuHitObject"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FollowPointRenderer : CompositeDrawable
|
public class FollowPointRenderer : LifetimeManagementContainer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All the <see cref="FollowPointConnection"/>s contained by this <see cref="FollowPointRenderer"/>.
|
/// All the <see cref="FollowPointConnection"/>s contained by this <see cref="FollowPointRenderer"/>.
|
||||||
@ -45,8 +45,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
/// <returns>The index of <paramref name="connection"/> in <see cref="connections"/>.</returns>
|
/// <returns>The index of <paramref name="connection"/> in <see cref="connections"/>.</returns>
|
||||||
private void addConnection(FollowPointConnection connection)
|
private void addConnection(FollowPointConnection connection)
|
||||||
{
|
{
|
||||||
AddInternal(connection);
|
|
||||||
|
|
||||||
// Groups are sorted by their start time when added such that the index can be used to post-process other surrounding connections
|
// Groups are sorted by their start time when added such that the index can be used to post-process other surrounding connections
|
||||||
int index = connections.AddInPlace(connection, Comparer<FollowPointConnection>.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value)));
|
int index = connections.AddInPlace(connection, Comparer<FollowPointConnection>.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value)));
|
||||||
|
|
||||||
@ -74,6 +72,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
FollowPointConnection previousConnection = connections[index - 1];
|
FollowPointConnection previousConnection = connections[index - 1];
|
||||||
previousConnection.End = connection.Start;
|
previousConnection.End = connection.Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddInternal(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
public Drawable ProxiedLayer => ApproachCircle;
|
public Drawable ProxiedLayer => ApproachCircle;
|
||||||
|
|
||||||
public class HitReceptor : Drawable, IKeyBindingHandler<OsuAction>
|
public class HitReceptor : CompositeDrawable, IKeyBindingHandler<OsuAction>
|
||||||
{
|
{
|
||||||
// IsHovered is used
|
// IsHovered is used
|
||||||
public override bool HandlePositionalInput => true;
|
public override bool HandlePositionalInput => true;
|
||||||
@ -185,6 +185,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
CornerRadius = OsuHitObject.OBJECT_RADIUS;
|
||||||
|
CornerExponent = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnPressed(OsuAction action)
|
public bool OnPressed(OsuAction action)
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Judgements;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects
|
namespace osu.Game.Rulesets.Osu.Objects
|
||||||
@ -23,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
pathVersion.BindValueChanged(_ => Position = slider.EndPosition);
|
pathVersion.BindValueChanged(_ => Position = slider.EndPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Judgement CreateJudgement() => new OsuSliderTailJudgement();
|
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||||
|
|
||||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
|||||||
new DifficultyRange(HitResult.Great, 80, 50, 20),
|
new DifficultyRange(HitResult.Great, 80, 50, 20),
|
||||||
new DifficultyRange(HitResult.Good, 140, 100, 60),
|
new DifficultyRange(HitResult.Good, 140, 100, 60),
|
||||||
new DifficultyRange(HitResult.Meh, 200, 150, 100),
|
new DifficultyRange(HitResult.Meh, 200, 150, 100),
|
||||||
new DifficultyRange(HitResult.Miss, 200, 200, 200),
|
new DifficultyRange(HitResult.Miss, 400, 400, 400),
|
||||||
};
|
};
|
||||||
|
|
||||||
public override bool IsHitResultAllowed(HitResult result)
|
public override bool IsHitResultAllowed(HitResult result)
|
||||||
|
@ -5,7 +5,6 @@ using System;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Caching;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Batches;
|
using osu.Framework.Graphics.Batches;
|
||||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||||
@ -14,6 +13,7 @@ using osu.Framework.Graphics.Shaders;
|
|||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Framework.Layout;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -43,6 +43,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
// -1 signals that the part is unusable, and should not be drawn
|
// -1 signals that the part is unusable, and should not be drawn
|
||||||
parts[i].InvalidationID = -1;
|
parts[i].InvalidationID = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddLayout(partSizeCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -72,20 +74,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Cached<Vector2> partSizeCache = new Cached<Vector2>();
|
private readonly LayoutValue<Vector2> partSizeCache = new LayoutValue<Vector2>(Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit | Invalidation.Presence);
|
||||||
|
|
||||||
private Vector2 partSize => partSizeCache.IsValid
|
private Vector2 partSize => partSizeCache.IsValid
|
||||||
? partSizeCache.Value
|
? partSizeCache.Value
|
||||||
: (partSizeCache.Value = new Vector2(Texture.DisplayWidth, Texture.DisplayHeight) * DrawInfo.Matrix.ExtractScale().Xy);
|
: (partSizeCache.Value = new Vector2(Texture.DisplayWidth, Texture.DisplayHeight) * DrawInfo.Matrix.ExtractScale().Xy);
|
||||||
|
|
||||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
|
||||||
{
|
|
||||||
if ((invalidation & (Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit | Invalidation.Presence)) > 0)
|
|
||||||
partSizeCache.Invalidate();
|
|
||||||
|
|
||||||
return base.Invalidate(invalidation, source, shallPropagate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of time to fade the cursor trail pieces.
|
/// The amount of time to fade the cursor trail pieces.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -97,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
Invalidate(Invalidation.DrawNode, shallPropagate: false);
|
Invalidate(Invalidation.DrawNode);
|
||||||
|
|
||||||
const int fade_clock_reset_threshold = 1000000;
|
const int fade_clock_reset_threshold = 1000000;
|
||||||
|
|
||||||
|
@ -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 NUnit.Framework;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Taiko.Mods;
|
||||||
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
|
using osu.Game.Rulesets.Taiko.Scoring;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.Tests.Mods
|
||||||
|
{
|
||||||
|
public class TestSceneTaikoModPerfect : ModPerfectTestScene
|
||||||
|
{
|
||||||
|
public TestSceneTaikoModPerfect()
|
||||||
|
: base(new TestTaikoRuleset(), new TaikoModPerfect())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestHit(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new CentreHit { StartTime = 1000 }), shouldMiss);
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestDrumRoll(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new DrumRoll { StartTime = 1000, EndTime = 3000 }), shouldMiss);
|
||||||
|
|
||||||
|
[TestCase(false)]
|
||||||
|
[TestCase(true)]
|
||||||
|
public void TestSwell(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Swell { StartTime = 1000, EndTime = 3000 }), shouldMiss);
|
||||||
|
|
||||||
|
private class TestTaikoRuleset : TaikoRuleset
|
||||||
|
{
|
||||||
|
public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new TestTaikoHealthProcessor();
|
||||||
|
|
||||||
|
private class TestTaikoHealthProcessor : TaikoHealthProcessor
|
||||||
|
{
|
||||||
|
protected override void Reset(bool storeResults)
|
||||||
|
{
|
||||||
|
base.Reset(storeResults);
|
||||||
|
|
||||||
|
Health.Value = 1; // Don't care about the health condition (only the mod condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,16 @@
|
|||||||
// 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 System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Rulesets.Taiko.Judgements;
|
|
||||||
using osu.Game.Rulesets.Taiko.Objects;
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Tests
|
namespace osu.Game.Rulesets.Taiko.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneSwellJudgements : PlayerTestScene
|
public class TestSceneSwellJudgements : PlayerTestScene
|
||||||
{
|
{
|
||||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
|
||||||
|
|
||||||
public TestSceneSwellJudgements()
|
public TestSceneSwellJudgements()
|
||||||
: base(new TaikoRuleset())
|
: base(new TaikoRuleset())
|
||||||
{
|
{
|
||||||
@ -28,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
public void TestZeroTickTimeOffsets()
|
public void TestZeroTickTimeOffsets()
|
||||||
{
|
{
|
||||||
AddUntilStep("gameplay finished", () => Player.ScoreProcessor.HasCompleted);
|
AddUntilStep("gameplay finished", () => Player.ScoreProcessor.HasCompleted);
|
||||||
AddAssert("all tick offsets are 0", () => Player.Results.Where(r => r.Judgement is TaikoSwellTickJudgement).All(r => r.TimeOffset == 0));
|
AddAssert("all tick offsets are 0", () => Player.Results.Where(r => r.HitObject is SwellTick).All(r => r.TimeOffset == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool Autoplay => true;
|
protected override bool Autoplay => true;
|
||||||
@ -50,25 +42,5 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer();
|
|
||||||
|
|
||||||
protected class TestPlayer : Player
|
|
||||||
{
|
|
||||||
public readonly List<JudgementResult> Results = new List<JudgementResult>();
|
|
||||||
|
|
||||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
|
||||||
|
|
||||||
public TestPlayer()
|
|
||||||
: base(false, false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
ScoreProcessor.NewJudgement += r => Results.Add(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,9 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||||
using osu.Game.Rulesets.Taiko.Mods;
|
using osu.Game.Rulesets.Taiko.Mods;
|
||||||
using osu.Game.Rulesets.Taiko.Objects;
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Tests
|
namespace osu.Game.Rulesets.Taiko.Tests
|
||||||
@ -22,10 +20,10 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
|
|
||||||
protected override bool AllowFail => true;
|
protected override bool AllowFail => true;
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray();
|
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray();
|
||||||
return new ScoreAccessiblePlayer();
|
return base.CreatePlayer(ruleset);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) =>
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) =>
|
||||||
@ -49,20 +47,10 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
AddStep("Setup judgements", () =>
|
AddStep("Setup judgements", () =>
|
||||||
{
|
{
|
||||||
judged = false;
|
judged = false;
|
||||||
((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true;
|
Player.ScoreProcessor.NewJudgement += b => judged = true;
|
||||||
});
|
});
|
||||||
AddUntilStep("swell judged", () => judged);
|
AddUntilStep("swell judged", () => judged);
|
||||||
AddAssert("not failed", () => !Player.HasFailed);
|
AddAssert("not failed", () => !Player.HasFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ScoreAccessiblePlayer : TestPlayer
|
|
||||||
{
|
|
||||||
public ScoreAccessiblePlayer()
|
|
||||||
: base(false, false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Caching;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Layout;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Taiko.Objects;
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
using osu.Game.Rulesets.Taiko.UI;
|
using osu.Game.Rulesets.Taiko.UI;
|
||||||
@ -30,13 +30,15 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
|||||||
|
|
||||||
private class TaikoFlashlight : Flashlight
|
private class TaikoFlashlight : Flashlight
|
||||||
{
|
{
|
||||||
private readonly Cached flashlightProperties = new Cached();
|
private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.DrawSize);
|
||||||
private readonly TaikoPlayfield taikoPlayfield;
|
private readonly TaikoPlayfield taikoPlayfield;
|
||||||
|
|
||||||
public TaikoFlashlight(TaikoPlayfield taikoPlayfield)
|
public TaikoFlashlight(TaikoPlayfield taikoPlayfield)
|
||||||
{
|
{
|
||||||
this.taikoPlayfield = taikoPlayfield;
|
this.taikoPlayfield = taikoPlayfield;
|
||||||
FlashlightSize = new Vector2(0, getSizeFor(0));
|
FlashlightSize = new Vector2(0, getSizeFor(0));
|
||||||
|
|
||||||
|
AddLayout(flashlightProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getSizeFor(int combo)
|
private float getSizeFor(int combo)
|
||||||
@ -56,16 +58,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
|||||||
|
|
||||||
protected override string FragmentShader => "CircularFlashlight";
|
protected override string FragmentShader => "CircularFlashlight";
|
||||||
|
|
||||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
|
||||||
{
|
|
||||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
|
||||||
{
|
|
||||||
flashlightProperties.Invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.Invalidate(invalidation, source, shallPropagate);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Objects
|
namespace osu.Game.Rulesets.Taiko.Objects
|
||||||
@ -8,5 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
|||||||
public class BarLine : TaikoHitObject, IBarLine
|
public class BarLine : TaikoHitObject, IBarLine
|
||||||
{
|
{
|
||||||
public bool Major { get; set; }
|
public bool Major { get; set; }
|
||||||
|
|
||||||
|
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,5 +54,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
Alpha = 0.75f
|
Alpha = 0.75f
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void UpdateStateTransforms(ArmedState state) => this.FadeOut(150);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.Taiko.Judgements;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Objects
|
namespace osu.Game.Rulesets.Taiko.Objects
|
||||||
{
|
{
|
||||||
public class SwellTick : TaikoHitObject
|
public class SwellTick : TaikoHitObject
|
||||||
{
|
{
|
||||||
public override Judgement CreateJudgement() => new TaikoSwellTickJudgement();
|
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||||
|
|
||||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -39,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
{
|
{
|
||||||
base.ApplyBeatmap(beatmap);
|
base.ApplyBeatmap(beatmap);
|
||||||
|
|
||||||
hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.OfType<Hit>().Count() * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
|
hpMultiplier = 1 / (object_count_factor * Math.Max(1, beatmap.HitObjects.OfType<Hit>().Count()) * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
|
||||||
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
|
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
var storyboard = decoder.Decode(stream);
|
var storyboard = decoder.Decode(stream);
|
||||||
|
|
||||||
StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3);
|
StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3);
|
||||||
Assert.AreEqual(123456, ((StoryboardSprite)background.Elements.Single()).InitialPosition.X);
|
Assert.AreEqual(3456, ((StoryboardSprite)background.Elements.Single()).InitialPosition.X);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,6 +154,7 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
private class JudgeableHitObject : HitObject
|
private class JudgeableHitObject : HitObject
|
||||||
{
|
{
|
||||||
public override Judgement CreateJudgement() => new Judgement();
|
public override Judgement CreateJudgement() => new Judgement();
|
||||||
|
protected override HitWindows CreateHitWindows() => new HitWindows();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
@ -78,7 +78,7 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestHitObjectWithCombo : HitObject, IHasComboInformation
|
private class TestHitObjectWithCombo : ConvertHitObject, IHasComboInformation
|
||||||
{
|
{
|
||||||
public bool NewCombo { get; } = false;
|
public bool NewCombo { get; } = false;
|
||||||
public int ComboOffset { get; } = 0;
|
public int ComboOffset { get; } = 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[Variables]
|
[Variables]
|
||||||
$var=1234
|
$var=34
|
||||||
|
|
||||||
[Events]
|
[Events]
|
||||||
Sprite,Background,TopCentre,"img.jpg",$var56,240
|
Sprite,Background,TopCentre,"img.jpg",$var56,240
|
||||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
|
|
||||||
private DummySongSelect songSelect;
|
private DummySongSelect songSelect;
|
||||||
private TestPlayerLoader playerLoader;
|
private TestPlayerLoader playerLoader;
|
||||||
private TestPlayer player;
|
private LoadBlockingTestPlayer player;
|
||||||
private BeatmapManager manager;
|
private BeatmapManager manager;
|
||||||
private RulesetStore rulesets;
|
private RulesetStore rulesets;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
public void PlayerLoaderSettingsHoverTest()
|
public void PlayerLoaderSettingsHoverTest()
|
||||||
{
|
{
|
||||||
setupUserSettings();
|
setupUserSettings();
|
||||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer { BlockLoad = true })));
|
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer { BlockLoad = true })));
|
||||||
AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false);
|
AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false);
|
||||||
AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent());
|
AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent());
|
||||||
AddStep("Trigger background preview", () =>
|
AddStep("Trigger background preview", () =>
|
||||||
@ -268,7 +268,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
{
|
{
|
||||||
setupUserSettings();
|
setupUserSettings();
|
||||||
|
|
||||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer(allowPause))));
|
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer(allowPause))));
|
||||||
|
|
||||||
AddUntilStep("Wait for Player Loader to load", () => playerLoader.IsLoaded);
|
AddUntilStep("Wait for Player Loader to load", () => playerLoader.IsLoaded);
|
||||||
AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
|
AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
|
||||||
@ -347,7 +347,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestPlayer : Visual.TestPlayer
|
private class LoadBlockingTestPlayer : TestPlayer
|
||||||
{
|
{
|
||||||
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
||||||
|
|
||||||
@ -360,7 +360,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
public readonly Bindable<bool> ReplacesBackground = new Bindable<bool>();
|
public readonly Bindable<bool> ReplacesBackground = new Bindable<bool>();
|
||||||
public readonly Bindable<bool> IsPaused = new Bindable<bool>();
|
public readonly Bindable<bool> IsPaused = new Bindable<bool>();
|
||||||
|
|
||||||
public TestPlayer(bool allowPause = true)
|
public LoadBlockingTestPlayer(bool allowPause = true)
|
||||||
: base(allowPause)
|
: base(allowPause)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -3,53 +3,32 @@
|
|||||||
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Storyboards;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
[Description("Player instantiated with an autoplay mod.")]
|
[Description("Player instantiated with an autoplay mod.")]
|
||||||
public class TestSceneAutoplay : TestSceneAllRulesetPlayers
|
public class TestSceneAutoplay : TestSceneAllRulesetPlayers
|
||||||
{
|
{
|
||||||
private ClockBackedTestWorkingBeatmap.TrackVirtualManual track;
|
protected new TestPlayer Player => (TestPlayer)base.Player;
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override Player CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||||
return new ScoreAccessiblePlayer();
|
return new TestPlayer(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AddCheckSteps()
|
protected override void AddCheckSteps()
|
||||||
{
|
{
|
||||||
AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0);
|
AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0);
|
||||||
AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
|
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
|
||||||
AddStep("rewind", () => track.Seek(-10000));
|
AddStep("seek to break time", () => Player.GameplayClockContainer.Seek(Player.BreakOverlay.Breaks.First().StartTime));
|
||||||
AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
AddUntilStep("wait for seek to complete", () =>
|
||||||
}
|
Player.HUDOverlay.Progress.ReferenceClock.CurrentTime >= Player.BreakOverlay.Breaks.First().StartTime);
|
||||||
|
AddAssert("test keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting);
|
||||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000));
|
||||||
{
|
AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||||
var working = base.CreateWorkingBeatmap(beatmap, storyboard);
|
|
||||||
|
|
||||||
track = (ClockBackedTestWorkingBeatmap.TrackVirtualManual)working.Track;
|
|
||||||
|
|
||||||
return working;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ScoreAccessiblePlayer : TestPlayer
|
|
||||||
{
|
|
||||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
|
||||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
|
||||||
|
|
||||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
|
||||||
|
|
||||||
public ScoreAccessiblePlayer()
|
|
||||||
: base(false, false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ using osu.Game.Rulesets.Difficulty;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
@ -289,7 +290,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
#region HitObject
|
#region HitObject
|
||||||
|
|
||||||
private class TestHitObject : HitObject, IHasEndTime
|
private class TestHitObject : ConvertHitObject, IHasEndTime
|
||||||
{
|
{
|
||||||
public double EndTime { get; set; }
|
public double EndTime { get; set; }
|
||||||
|
|
||||||
|
@ -1,7 +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.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -11,12 +10,8 @@ using osu.Framework.Utils;
|
|||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Rulesets.UI;
|
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osu.Game.Storyboards;
|
using osu.Game.Storyboards;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -24,8 +19,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
public class TestSceneGameplayRewinding : PlayerTestScene
|
public class TestSceneGameplayRewinding : PlayerTestScene
|
||||||
{
|
{
|
||||||
private RulesetExposingPlayer player => (RulesetExposingPlayer)Player;
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private AudioManager audioManager { get; set; }
|
private AudioManager audioManager { get; set; }
|
||||||
|
|
||||||
@ -48,13 +41,13 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
||||||
addSeekStep(3000);
|
addSeekStep(3000);
|
||||||
AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged));
|
AddAssert("all judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged));
|
||||||
AddUntilStep("key counter counted keys", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7));
|
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7));
|
||||||
AddStep("clear results", () => player.AppliedResults.Clear());
|
AddStep("clear results", () => Player.Results.Clear());
|
||||||
addSeekStep(0);
|
addSeekStep(0);
|
||||||
AddAssert("none judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged));
|
AddAssert("none judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged));
|
||||||
AddUntilStep("key counters reset", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
AddUntilStep("key counters reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||||
AddAssert("no results triggered", () => player.AppliedResults.Count == 0);
|
AddAssert("no results triggered", () => Player.Results.Count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSeekStep(double time)
|
private void addSeekStep(double time)
|
||||||
@ -62,13 +55,13 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddStep($"seek to {time}", () => track.Seek(time));
|
AddStep($"seek to {time}", () => track.Seek(time));
|
||||||
|
|
||||||
// Allow a few frames of lenience
|
// Allow a few frames of lenience
|
||||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||||
return new RulesetExposingPlayer();
|
return base.CreatePlayer(ruleset);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||||
@ -89,29 +82,5 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RulesetExposingPlayer : Player
|
|
||||||
{
|
|
||||||
public readonly List<JudgementResult> AppliedResults = new List<JudgementResult>();
|
|
||||||
|
|
||||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
|
||||||
|
|
||||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
|
||||||
|
|
||||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
|
||||||
|
|
||||||
public new DrawableRuleset DrawableRuleset => base.DrawableRuleset;
|
|
||||||
|
|
||||||
public RulesetExposingPlayer()
|
|
||||||
: base(false, false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
ScoreProcessor.NewJudgement += r => AppliedResults.Add(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,17 @@
|
|||||||
// 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 NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Rulesets.Catch.Scoring;
|
using osu.Game.Rulesets.Catch.Scoring;
|
||||||
using osu.Game.Rulesets.Mania.Scoring;
|
using osu.Game.Rulesets.Mania.Scoring;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Scoring;
|
using osu.Game.Rulesets.Osu.Scoring;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.Taiko.Scoring;
|
using osu.Game.Rulesets.Taiko.Scoring;
|
||||||
@ -43,6 +44,22 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddRepeatStep("New max negative", () => newJudgement(-hitWindows.WindowFor(HitResult.Meh)), 20);
|
AddRepeatStep("New max negative", () => newJudgement(-hitWindows.WindowFor(HitResult.Meh)), 20);
|
||||||
AddRepeatStep("New max positive", () => newJudgement(hitWindows.WindowFor(HitResult.Meh)), 20);
|
AddRepeatStep("New max positive", () => newJudgement(hitWindows.WindowFor(HitResult.Meh)), 20);
|
||||||
AddStep("New fixed judgement (50ms)", () => newJudgement(50));
|
AddStep("New fixed judgement (50ms)", () => newJudgement(50));
|
||||||
|
|
||||||
|
AddStep("Judgement barrage", () =>
|
||||||
|
{
|
||||||
|
int runCount = 0;
|
||||||
|
|
||||||
|
ScheduledDelegate del = null;
|
||||||
|
|
||||||
|
del = Scheduler.AddDelayed(() =>
|
||||||
|
{
|
||||||
|
newJudgement(runCount++ / 10f);
|
||||||
|
|
||||||
|
if (runCount == 500)
|
||||||
|
// ReSharper disable once AccessToModifiedClosure
|
||||||
|
del?.Cancel();
|
||||||
|
}, 10, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -47,21 +47,22 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key;
|
Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key;
|
||||||
|
|
||||||
|
void addPressKeyStep()
|
||||||
|
{
|
||||||
AddStep($"Press {testKey} key", () =>
|
AddStep($"Press {testKey} key", () =>
|
||||||
{
|
{
|
||||||
InputManager.PressKey(testKey);
|
InputManager.PressKey(testKey);
|
||||||
InputManager.ReleaseKey(testKey);
|
InputManager.ReleaseKey(testKey);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addPressKeyStep();
|
||||||
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1);
|
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1);
|
||||||
|
addPressKeyStep();
|
||||||
AddStep($"Press {testKey} key", () =>
|
|
||||||
{
|
|
||||||
InputManager.PressKey(testKey);
|
|
||||||
InputManager.ReleaseKey(testKey);
|
|
||||||
});
|
|
||||||
|
|
||||||
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2);
|
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2);
|
||||||
|
AddStep("Disable counting", () => testCounter.IsCounting = false);
|
||||||
|
addPressKeyStep();
|
||||||
|
AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses == 2);
|
||||||
|
|
||||||
Add(kc);
|
Add(kc);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ using osu.Game.Graphics.Containers;
|
|||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
@ -282,14 +281,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
protected override bool AllowFail => true;
|
protected override bool AllowFail => true;
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset) => new PausePlayer();
|
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PausePlayer();
|
||||||
|
|
||||||
protected class PausePlayer : TestPlayer
|
protected class PausePlayer : TestPlayer
|
||||||
{
|
{
|
||||||
public new HealthProcessor HealthProcessor => base.HealthProcessor;
|
|
||||||
|
|
||||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
|
||||||
|
|
||||||
public bool FailOverlayVisible => FailOverlay.State.Value == Visibility.Visible;
|
public bool FailOverlayVisible => FailOverlay.State.Value == Visibility.Visible;
|
||||||
|
|
||||||
public bool PauseOverlayVisible => PauseOverlay.State.Value == Visibility.Visible;
|
public bool PauseOverlayVisible => PauseOverlay.State.Value == Visibility.Visible;
|
||||||
|
@ -9,15 +9,12 @@ using osu.Framework.Testing;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
[HeadlessTest] // we alter unsafe properties on the game host to test inactive window state.
|
[HeadlessTest] // we alter unsafe properties on the game host to test inactive window state.
|
||||||
public class TestScenePauseWhenInactive : PlayerTestScene
|
public class TestScenePauseWhenInactive : PlayerTestScene
|
||||||
{
|
{
|
||||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
|
||||||
|
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||||
{
|
{
|
||||||
var beatmap = (Beatmap)base.CreateBeatmap(ruleset);
|
var beatmap = (Beatmap)base.CreateBeatmap(ruleset);
|
||||||
@ -46,6 +43,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddAssert("time of pause is after gameplay start time", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= Player.DrawableRuleset.GameplayStartTime);
|
AddAssert("time of pause is after gameplay start time", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= Player.DrawableRuleset.GameplayStartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
|
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ using System.Threading.Tasks;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
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.Utils;
|
using osu.Framework.Utils;
|
||||||
@ -307,17 +306,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
|
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestPlayer : Visual.TestPlayer
|
protected class SlowLoadPlayer : TestPlayer
|
||||||
{
|
|
||||||
public new Bindable<IReadOnlyList<Mod>> Mods => base.Mods;
|
|
||||||
|
|
||||||
public TestPlayer(bool allowPause = true, bool showResults = true)
|
|
||||||
: base(allowPause, showResults)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class SlowLoadPlayer : Visual.TestPlayer
|
|
||||||
{
|
{
|
||||||
public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(false);
|
public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(false);
|
||||||
|
|
||||||
|
@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Utils;
|
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Screens.Play.HUD;
|
using osu.Game.Screens.Play.HUD;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -45,32 +42,12 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
};
|
};
|
||||||
Add(accuracyCounter);
|
Add(accuracyCounter);
|
||||||
|
|
||||||
StarCounter stars = new StarCounter
|
|
||||||
{
|
|
||||||
Origin = Anchor.BottomLeft,
|
|
||||||
Anchor = Anchor.BottomLeft,
|
|
||||||
Position = new Vector2(20, -160),
|
|
||||||
CountStars = 5,
|
|
||||||
};
|
|
||||||
Add(stars);
|
|
||||||
|
|
||||||
SpriteText starsLabel = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Origin = Anchor.BottomLeft,
|
|
||||||
Anchor = Anchor.BottomLeft,
|
|
||||||
Position = new Vector2(20, -190),
|
|
||||||
Text = stars.CountStars.ToString("0.00"),
|
|
||||||
};
|
|
||||||
Add(starsLabel);
|
|
||||||
|
|
||||||
AddStep(@"Reset all", delegate
|
AddStep(@"Reset all", delegate
|
||||||
{
|
{
|
||||||
score.Current.Value = 0;
|
score.Current.Value = 0;
|
||||||
comboCounter.Current.Value = 0;
|
comboCounter.Current.Value = 0;
|
||||||
numerator = denominator = 0;
|
numerator = denominator = 0;
|
||||||
accuracyCounter.SetFraction(0, 0);
|
accuracyCounter.SetFraction(0, 0);
|
||||||
stars.CountStars = 0;
|
|
||||||
starsLabel.Text = stars.CountStars.ToString("0.00");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep(@"Hit! :D", delegate
|
AddStep(@"Hit! :D", delegate
|
||||||
@ -88,20 +65,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
denominator++;
|
denominator++;
|
||||||
accuracyCounter.SetFraction(numerator, denominator);
|
accuracyCounter.SetFraction(numerator, denominator);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep(@"Alter stars", delegate
|
|
||||||
{
|
|
||||||
stars.CountStars = RNG.NextSingle() * (stars.StarCount + 1);
|
|
||||||
starsLabel.Text = stars.CountStars.ToString("0.00");
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep(@"Stop counters", delegate
|
|
||||||
{
|
|
||||||
score.StopRolling();
|
|
||||||
comboCounter.StopRolling();
|
|
||||||
accuracyCounter.StopRolling();
|
|
||||||
stars.StopAnimation();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
57
osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestSceneStarCounter : OsuTestScene
|
||||||
|
{
|
||||||
|
public TestSceneStarCounter()
|
||||||
|
{
|
||||||
|
StarCounter stars = new StarCounter
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Current = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
Add(stars);
|
||||||
|
|
||||||
|
SpriteText starsLabel = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Scale = new Vector2(2),
|
||||||
|
Y = 50,
|
||||||
|
Text = stars.Current.ToString("0.00"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Add(starsLabel);
|
||||||
|
|
||||||
|
AddRepeatStep(@"random value", delegate
|
||||||
|
{
|
||||||
|
stars.Current = RNG.NextSingle() * (stars.StarCount + 1);
|
||||||
|
starsLabel.Text = stars.Current.ToString("0.00");
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
AddStep(@"Stop animation", delegate
|
||||||
|
{
|
||||||
|
stars.StopAnimation();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep(@"Reset", delegate
|
||||||
|
{
|
||||||
|
stars.Current = 0;
|
||||||
|
starsLabel.Text = stars.Current.ToString("0.00");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -62,6 +62,17 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
var frameworkConfig = host.Dependencies.Get<FrameworkConfigManager>();
|
var frameworkConfig = host.Dependencies.Get<FrameworkConfigManager>();
|
||||||
frameworkConfig.GetBindable<double>(FrameworkSetting.CursorSensitivity).Disabled = false;
|
frameworkConfig.GetBindable<double>(FrameworkSetting.CursorSensitivity).Disabled = false;
|
||||||
|
|
||||||
|
CreateGame();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
||||||
|
AddUntilStep("Wait for intro", () => Game.ScreenStack.CurrentScreen is IntroScreen);
|
||||||
|
|
||||||
|
ConfirmAtMainMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void CreateGame()
|
||||||
|
{
|
||||||
Game = new TestOsuGame(LocalStorage, API);
|
Game = new TestOsuGame(LocalStorage, API);
|
||||||
Game.SetHost(host);
|
Game.SetHost(host);
|
||||||
|
|
||||||
@ -70,12 +81,6 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
||||||
|
|
||||||
Add(Game);
|
Add(Game);
|
||||||
});
|
|
||||||
|
|
||||||
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
|
||||||
AddUntilStep("Wait for intro", () => Game.ScreenStack.CurrentScreen is IntroScreen);
|
|
||||||
|
|
||||||
ConfirmAtMainMenu();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void PushAndConfirm(Func<Screen> newScreen)
|
protected void PushAndConfirm(Func<Screen> newScreen)
|
||||||
@ -97,12 +102,17 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
|
|
||||||
public new SettingsPanel Settings => base.Settings;
|
public new SettingsPanel Settings => base.Settings;
|
||||||
|
|
||||||
|
public new MusicController MusicController => base.MusicController;
|
||||||
|
|
||||||
public new OsuConfigManager LocalConfig => base.LocalConfig;
|
public new OsuConfigManager LocalConfig => base.LocalConfig;
|
||||||
|
|
||||||
public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;
|
public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;
|
||||||
|
|
||||||
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
|
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
|
||||||
|
|
||||||
|
// if we don't do this, when running under nUnit the version that gets populated is that of nUnit.
|
||||||
|
public override string Version => "test game";
|
||||||
|
|
||||||
protected override Loader CreateLoader() => new TestLoader();
|
protected override Loader CreateLoader() => new TestLoader();
|
||||||
|
|
||||||
public new void PerformFromScreen(Action<IScreen> action, IEnumerable<Type> validScreens = null) => base.PerformFromScreen(action, validScreens);
|
public new void PerformFromScreen(Action<IScreen> action, IEnumerable<Type> validScreens = null) => base.PerformFromScreen(action, validScreens);
|
||||||
|
@ -114,6 +114,22 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
AddAssert("Options overlay was closed", () => Game.Settings.State.Value == Visibility.Hidden);
|
AddAssert("Options overlay was closed", () => Game.Settings.State.Value == Visibility.Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestWaitForNextTrackInMenu()
|
||||||
|
{
|
||||||
|
bool trackCompleted = false;
|
||||||
|
|
||||||
|
AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded);
|
||||||
|
AddStep("Seek close to end", () =>
|
||||||
|
{
|
||||||
|
Game.MusicController.SeekTo(Game.Beatmap.Value.Track.Length - 1000);
|
||||||
|
Game.Beatmap.Value.Track.Completed += () => trackCompleted = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("Track was completed", () => trackCompleted);
|
||||||
|
AddUntilStep("Track was restarted", () => Game.Beatmap.Value.Track.IsRunning);
|
||||||
|
}
|
||||||
|
|
||||||
private void pushEscape() =>
|
private void pushEscape() =>
|
||||||
AddStep("Press escape", () => pressAndRelease(Key.Escape));
|
AddStep("Press escape", () => pressAndRelease(Key.Escape));
|
||||||
|
|
||||||
|
41
osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Navigation
|
||||||
|
{
|
||||||
|
public class TestSettingsMigration : OsuGameTestScene
|
||||||
|
{
|
||||||
|
public override void RecycleLocalStorage()
|
||||||
|
{
|
||||||
|
base.RecycleLocalStorage();
|
||||||
|
|
||||||
|
using (var config = new OsuConfigManager(LocalStorage))
|
||||||
|
{
|
||||||
|
config.Set(OsuSetting.Version, "2020.101.0");
|
||||||
|
config.Set(OsuSetting.DisplayStarsMaximum, 10.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDisplayStarsMigration()
|
||||||
|
{
|
||||||
|
AddAssert("config has migrated value", () => Precision.AlmostEquals(Game.LocalConfig.Get<double>(OsuSetting.DisplayStarsMaximum), 10.1));
|
||||||
|
|
||||||
|
AddStep("set value again", () => Game.LocalConfig.Set<double>(OsuSetting.DisplayStarsMaximum, 10));
|
||||||
|
|
||||||
|
AddStep("force save config", () => Game.LocalConfig.Save());
|
||||||
|
|
||||||
|
AddStep("remove game", () => Remove(Game));
|
||||||
|
|
||||||
|
AddStep("create game again", CreateGame);
|
||||||
|
|
||||||
|
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
||||||
|
|
||||||
|
AddAssert("config did not migrate value", () => Precision.AlmostEquals(Game.LocalConfig.Get<double>(OsuSetting.DisplayStarsMaximum), 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,8 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
@ -30,6 +32,8 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
private readonly BindableBool showDeleted = new BindableBool();
|
private readonly BindableBool showDeleted = new BindableBool();
|
||||||
private readonly Container content;
|
private readonly Container content;
|
||||||
|
|
||||||
|
private TestCommentsPage commentsPage;
|
||||||
|
|
||||||
public TestSceneCommentsPage()
|
public TestSceneCommentsPage()
|
||||||
{
|
{
|
||||||
Add(new FillFlowContainer
|
Add(new FillFlowContainer
|
||||||
@ -57,15 +61,29 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
AddStep("load comments", () => createPage(getCommentBundle()));
|
[Test]
|
||||||
AddStep("load empty comments", () => createPage(getEmptyCommentBundle()));
|
public void TestAppendDuplicatedComment()
|
||||||
|
{
|
||||||
|
AddStep("Create page", () => createPage(getCommentBundle()));
|
||||||
|
AddAssert("Dictionary length is 10", () => commentsPage?.DictionaryLength == 10);
|
||||||
|
AddStep("Append existing comment", () => commentsPage?.AppendComments(getCommentSubBundle()));
|
||||||
|
AddAssert("Dictionary length is 10", () => commentsPage?.DictionaryLength == 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEmptyBundle()
|
||||||
|
{
|
||||||
|
AddStep("Create page", () => createPage(getEmptyCommentBundle()));
|
||||||
|
AddAssert("Dictionary length is 0", () => commentsPage?.DictionaryLength == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createPage(CommentBundle commentBundle)
|
private void createPage(CommentBundle commentBundle)
|
||||||
{
|
{
|
||||||
|
commentsPage = null;
|
||||||
content.Clear();
|
content.Clear();
|
||||||
content.Add(new CommentsPage(commentBundle)
|
content.Add(commentsPage = new TestCommentsPage(commentBundle)
|
||||||
{
|
{
|
||||||
ShowDeleted = { BindTarget = showDeleted }
|
ShowDeleted = { BindTarget = showDeleted }
|
||||||
});
|
});
|
||||||
@ -182,5 +200,33 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private CommentBundle getCommentSubBundle() => new CommentBundle
|
||||||
|
{
|
||||||
|
Comments = new List<Comment>
|
||||||
|
{
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Message = "Simple test comment",
|
||||||
|
LegacyName = "TestUser1",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
VotesCount = 5
|
||||||
|
},
|
||||||
|
},
|
||||||
|
IncludedComments = new List<Comment>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
private class TestCommentsPage : CommentsPage
|
||||||
|
{
|
||||||
|
public TestCommentsPage(CommentBundle commentBundle)
|
||||||
|
: base(commentBundle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void AppendComments([NotNull] CommentBundle bundle) => base.AppendComments(bundle);
|
||||||
|
|
||||||
|
public int DictionaryLength => CommentDictionary.Count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
// 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 NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
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.Game.Rulesets;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -13,13 +15,19 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneUserPanel : OsuTestScene
|
public class TestSceneUserPanel : OsuTestScene
|
||||||
{
|
{
|
||||||
private readonly UserPanel peppy;
|
private readonly Bindable<UserActivity> activity = new Bindable<UserActivity>();
|
||||||
|
|
||||||
public TestSceneUserPanel()
|
private UserPanel peppy;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesetStore { get; set; }
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
UserPanel flyte;
|
UserPanel flyte;
|
||||||
|
|
||||||
Add(new FillFlowContainer
|
Child = new FillFlowContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -44,34 +52,38 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
SupportLevel = 3,
|
SupportLevel = 3,
|
||||||
}) { Width = 300 },
|
}) { Width = 300 },
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
flyte.Status.Value = new UserStatusOnline();
|
flyte.Status.Value = new UserStatusOnline();
|
||||||
peppy.Status.Value = null;
|
peppy.Status.Value = null;
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void UserStatusesTests()
|
|
||||||
{
|
|
||||||
AddStep("online", () => { peppy.Status.Value = new UserStatusOnline(); });
|
|
||||||
AddStep(@"do not disturb", () => { peppy.Status.Value = new UserStatusDoNotDisturb(); });
|
|
||||||
AddStep(@"offline", () => { peppy.Status.Value = new UserStatusOffline(); });
|
|
||||||
AddStep(@"null status", () => { peppy.Status.Value = null; });
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void UserActivitiesTests()
|
|
||||||
{
|
|
||||||
Bindable<UserActivity> activity = new Bindable<UserActivity>();
|
|
||||||
|
|
||||||
peppy.Activity.BindTo(activity);
|
peppy.Activity.BindTo(activity);
|
||||||
|
});
|
||||||
|
|
||||||
AddStep("idle", () => { activity.Value = null; });
|
[Test]
|
||||||
AddStep("spectating", () => { activity.Value = new UserActivity.Spectating(); });
|
public void TestUserStatus()
|
||||||
AddStep("solo", () => { activity.Value = new UserActivity.SoloGame(null, null); });
|
{
|
||||||
AddStep("choosing", () => { activity.Value = new UserActivity.ChoosingBeatmap(); });
|
AddStep("online", () => peppy.Status.Value = new UserStatusOnline());
|
||||||
AddStep("editing", () => { activity.Value = new UserActivity.Editing(null); });
|
AddStep("do not disturb", () => peppy.Status.Value = new UserStatusDoNotDisturb());
|
||||||
AddStep("modding", () => { activity.Value = new UserActivity.Modding(); });
|
AddStep("offline", () => peppy.Status.Value = new UserStatusOffline());
|
||||||
}
|
AddStep("null status", () => peppy.Status.Value = null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestUserActivity()
|
||||||
|
{
|
||||||
|
AddStep("set online status", () => peppy.Status.Value = new UserStatusOnline());
|
||||||
|
|
||||||
|
AddStep("idle", () => activity.Value = null);
|
||||||
|
AddStep("spectating", () => activity.Value = new UserActivity.Spectating());
|
||||||
|
AddStep("solo (osu!)", () => activity.Value = soloGameStatusForRuleset(0));
|
||||||
|
AddStep("solo (osu!taiko)", () => activity.Value = soloGameStatusForRuleset(1));
|
||||||
|
AddStep("solo (osu!catch)", () => activity.Value = soloGameStatusForRuleset(2));
|
||||||
|
AddStep("solo (osu!mania)", () => activity.Value = soloGameStatusForRuleset(3));
|
||||||
|
AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap());
|
||||||
|
AddStep("editing", () => activity.Value = new UserActivity.Editing(null));
|
||||||
|
AddStep("modding", () => activity.Value = new UserActivity.Modding());
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.SoloGame(null, rulesetStore.GetRuleset(rulesetId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Overlays.Comments;
|
using osu.Game.Overlays.Comments;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
@ -18,6 +20,9 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
typeof(VotePill)
|
typeof(VotePill)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||||
|
|
||||||
private VotePill votePill;
|
private VotePill votePill;
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -13,6 +13,7 @@ using osu.Game.Rulesets;
|
|||||||
using osu.Game.Rulesets.Catch;
|
using osu.Game.Rulesets.Catch;
|
||||||
using osu.Game.Rulesets.Mania;
|
using osu.Game.Rulesets.Mania;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Taiko;
|
using osu.Game.Rulesets.Taiko;
|
||||||
@ -194,7 +195,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
public new BufferedWedgeInfo Info => base.Info;
|
public new BufferedWedgeInfo Info => base.Info;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestHitObject : HitObject, IHasPosition
|
private class TestHitObject : ConvertHitObject, IHasPosition
|
||||||
{
|
{
|
||||||
public float X { get; } = 0;
|
public float X { get; } = 0;
|
||||||
public float Y { get; } = 0;
|
public float Y { get; } = 0;
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.Home.Friends;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
|
{
|
||||||
|
public class TestSceneUserListToolbar : OsuTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(UserSortTabControl),
|
||||||
|
typeof(OverlaySortTabControl<>),
|
||||||
|
typeof(OverlayPanelDisplayStyleControl),
|
||||||
|
typeof(UserListToolbar),
|
||||||
|
};
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||||
|
|
||||||
|
public TestSceneUserListToolbar()
|
||||||
|
{
|
||||||
|
UserListToolbar toolbar;
|
||||||
|
OsuSpriteText sort;
|
||||||
|
OsuSpriteText displayStyle;
|
||||||
|
|
||||||
|
Add(toolbar = new UserListToolbar
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 5),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
sort = new OsuSpriteText(),
|
||||||
|
displayStyle = new OsuSpriteText()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
toolbar.SortCriteria.BindValueChanged(criteria => sort.Text = $"Criteria: {criteria.NewValue}", true);
|
||||||
|
toolbar.DisplayStyle.BindValueChanged(style => displayStyle.Text = $"Style: {style.NewValue}", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osu.Game.Tournament.Components;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
using osu.Game.Tournament.Screens.Drawings.Components;
|
||||||
|
using osu.Game.Tournament.Screens.Gameplay.Components;
|
||||||
|
using osu.Game.Tournament.Screens.Ladder.Components;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Tests.Components
|
||||||
|
{
|
||||||
|
public class TestSceneDrawableTournamentTeam : OsuGridTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(DrawableTeamFlag),
|
||||||
|
typeof(DrawableTeamTitle),
|
||||||
|
typeof(DrawableTeamTitleWithHeader),
|
||||||
|
typeof(DrawableMatchTeam),
|
||||||
|
typeof(DrawableTeamWithPlayers),
|
||||||
|
typeof(GroupTeam),
|
||||||
|
typeof(TeamDisplay),
|
||||||
|
};
|
||||||
|
|
||||||
|
public TestSceneDrawableTournamentTeam()
|
||||||
|
: base(4, 3)
|
||||||
|
{
|
||||||
|
var team = new TournamentTeam
|
||||||
|
{
|
||||||
|
FlagName = { Value = "AU" },
|
||||||
|
FullName = { Value = "Australia" },
|
||||||
|
Players =
|
||||||
|
{
|
||||||
|
new User { Username = "ASecretBox" },
|
||||||
|
new User { Username = "Dereban" },
|
||||||
|
new User { Username = "mReKk" },
|
||||||
|
new User { Username = "uyghti" },
|
||||||
|
new User { Username = "Parkes" },
|
||||||
|
new User { Username = "Shiroha" },
|
||||||
|
new User { Username = "Jordan The Bear" },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var match = new TournamentMatch { Team1 = { Value = team } };
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
Cell(i++).AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new TournamentSpriteText { Text = "DrawableTeamFlag" },
|
||||||
|
new DrawableTeamFlag(team)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cell(i++).AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new TournamentSpriteText { Text = "DrawableTeamTitle" },
|
||||||
|
new DrawableTeamTitle(team)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cell(i++).AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new TournamentSpriteText { Text = "DrawableTeamTitleWithHeader" },
|
||||||
|
new DrawableTeamTitleWithHeader(team, TeamColour.Red)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cell(i++).AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new TournamentSpriteText { Text = "DrawableMatchTeam" },
|
||||||
|
new DrawableMatchTeam(team, match, false)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cell(i++).AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new TournamentSpriteText { Text = "TeamWithPlayers" },
|
||||||
|
new DrawableTeamWithPlayers(team, TeamColour.Blue)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cell(i++).AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new TournamentSpriteText { Text = "GroupTeam" },
|
||||||
|
new GroupTeam(team)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cell(i).AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new TournamentSpriteText { Text = "TeamDisplay" },
|
||||||
|
new TeamDisplay(team, TeamColour.Red, new Bindable<int?>(2), 6)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,31 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Tournament.Components;
|
using osu.Game.Tournament.Components;
|
||||||
|
using osu.Game.Tournament.Screens;
|
||||||
using osu.Game.Tournament.Screens.Gameplay;
|
using osu.Game.Tournament.Screens.Gameplay;
|
||||||
|
using osu.Game.Tournament.Screens.Gameplay.Components;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
public class TestSceneGameplayScreen : TournamentTestScene
|
public class TestSceneGameplayScreen : TournamentTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay();
|
private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay { Width = 0.5f };
|
||||||
|
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(TeamScore),
|
||||||
|
typeof(TeamScoreDisplay),
|
||||||
|
typeof(TeamDisplay),
|
||||||
|
typeof(MatchHeader),
|
||||||
|
typeof(MatchScoreDisplay),
|
||||||
|
typeof(BeatmapInfoScreen),
|
||||||
|
typeof(SongBar),
|
||||||
|
};
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Tournament.Components;
|
||||||
using osu.Game.Tournament.Screens.Schedule;
|
using osu.Game.Tournament.Screens.Schedule;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
@ -11,6 +13,7 @@ namespace osu.Game.Tournament.Tests.Screens
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
|
Add(new TourneyVideo("main") { RelativeSizeAxes = Axes.Both });
|
||||||
Add(new ScheduleScreen());
|
Add(new ScheduleScreen());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
using osu.Game.Tournament.Screens.Editors;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
|
{
|
||||||
|
public class TestSceneSeedingEditorScreen : LadderTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private readonly LadderInfo ladder = new LadderInfo();
|
||||||
|
|
||||||
|
public TestSceneSeedingEditorScreen()
|
||||||
|
{
|
||||||
|
var match = TestSceneSeedingScreen.CreateSampleSeededMatch();
|
||||||
|
|
||||||
|
Add(new SeedingEditorScreen(match.Team1.Value)
|
||||||
|
{
|
||||||
|
Width = 0.85f // create room for control panel
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
127
osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
using osu.Game.Tournament.Screens.TeamIntro;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
|
{
|
||||||
|
public class TestSceneSeedingScreen : LadderTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private readonly LadderInfo ladder = new LadderInfo();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
ladder.CurrentMatch.Value = CreateSampleSeededMatch();
|
||||||
|
|
||||||
|
Add(new SeedingScreen
|
||||||
|
{
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
FillAspectRatio = 16 / 9f
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TournamentMatch CreateSampleSeededMatch() => new TournamentMatch
|
||||||
|
{
|
||||||
|
Team1 =
|
||||||
|
{
|
||||||
|
Value = new TournamentTeam
|
||||||
|
{
|
||||||
|
FlagName = { Value = "JP" },
|
||||||
|
FullName = { Value = "Japan" },
|
||||||
|
LastYearPlacing = { Value = 10 },
|
||||||
|
Seed = { Value = "Low" },
|
||||||
|
SeedingResults =
|
||||||
|
{
|
||||||
|
new SeedingResult
|
||||||
|
{
|
||||||
|
Mod = { Value = "NM" },
|
||||||
|
Seed = { Value = 10 },
|
||||||
|
Beatmaps =
|
||||||
|
{
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||||
|
Score = 12345672,
|
||||||
|
Seed = { Value = 24 },
|
||||||
|
},
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||||
|
Score = 1234567,
|
||||||
|
Seed = { Value = 12 },
|
||||||
|
},
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||||
|
Score = 1234567,
|
||||||
|
Seed = { Value = 16 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new SeedingResult
|
||||||
|
{
|
||||||
|
Mod = { Value = "DT" },
|
||||||
|
Seed = { Value = 5 },
|
||||||
|
Beatmaps =
|
||||||
|
{
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||||
|
Score = 234567,
|
||||||
|
Seed = { Value = 3 },
|
||||||
|
},
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||||
|
Score = 234567,
|
||||||
|
Seed = { Value = 6 },
|
||||||
|
},
|
||||||
|
new SeedingBeatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||||
|
Score = 234567,
|
||||||
|
Seed = { Value = 12 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Players =
|
||||||
|
{
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 12 } } },
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 16 } } },
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 20 } } },
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 24 } } },
|
||||||
|
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 30 } } },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Team2 =
|
||||||
|
{
|
||||||
|
Value = new TournamentTeam
|
||||||
|
{
|
||||||
|
FlagName = { Value = "US" },
|
||||||
|
FullName = { Value = "United States" },
|
||||||
|
Players =
|
||||||
|
{
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
new User { Username = "Hello" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Round =
|
||||||
|
{
|
||||||
|
Value = new TournamentRound { Name = { Value = "Quarterfinals" } }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens
|
|||||||
match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA");
|
match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA");
|
||||||
match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN");
|
match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN");
|
||||||
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
|
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
|
||||||
|
match.Completed.Value = true;
|
||||||
ladder.CurrentMatch.Value = match;
|
ladder.CurrentMatch.Value = match;
|
||||||
|
|
||||||
Add(new TeamWinScreen
|
Add(new TeamWinScreen
|
||||||
|
@ -5,7 +5,6 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ namespace osu.Game.Tournament.Components
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = new Color4(54, 54, 54, 255)
|
Colour = new Color4(54, 54, 54, 255)
|
||||||
},
|
},
|
||||||
new OsuSpriteText
|
new TournamentSpriteText
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
|
33
osu.Game.Tournament/Components/DrawableTeamFlag.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Components
|
||||||
|
{
|
||||||
|
public class DrawableTeamFlag : Sprite
|
||||||
|
{
|
||||||
|
private readonly TournamentTeam team;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
private Bindable<string> flag;
|
||||||
|
|
||||||
|
public DrawableTeamFlag(TournamentTeam team)
|
||||||
|
{
|
||||||
|
this.team = team;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TextureStore textures)
|
||||||
|
{
|
||||||
|
if (team == null) return;
|
||||||
|
|
||||||
|
(flag = team.FlagName.GetBoundCopy()).BindValueChanged(acronym => Texture = textures.Get($@"Flags/{team.FlagName}"), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
osu.Game.Tournament/Components/DrawableTeamHeader.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Components
|
||||||
|
{
|
||||||
|
public class DrawableTeamHeader : TournamentSpriteTextWithBackground
|
||||||
|
{
|
||||||
|
public DrawableTeamHeader(TeamColour colour)
|
||||||
|
{
|
||||||
|
Background.Colour = TournamentGame.GetTeamColour(colour);
|
||||||
|
|
||||||
|
Text.Colour = TournamentGame.TEXT_COLOUR;
|
||||||
|
Text.Text = $"Team {colour}".ToUpperInvariant();
|
||||||
|
Text.Scale = new Vector2(0.6f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
osu.Game.Tournament/Components/DrawableTeamTitle.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Components
|
||||||
|
{
|
||||||
|
public class DrawableTeamTitle : TournamentSpriteTextWithBackground
|
||||||
|
{
|
||||||
|
private readonly TournamentTeam team;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
private Bindable<string> acronym;
|
||||||
|
|
||||||
|
public DrawableTeamTitle(TournamentTeam team)
|
||||||
|
{
|
||||||
|
this.team = team;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TextureStore textures)
|
||||||
|
{
|
||||||
|
if (team == null) return;
|
||||||
|
|
||||||
|
(acronym = team.Acronym.GetBoundCopy()).BindValueChanged(acronym => Text.Text = team?.FullName.Value ?? string.Empty, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Components
|
||||||
|
{
|
||||||
|
public class DrawableTeamTitleWithHeader : CompositeDrawable
|
||||||
|
{
|
||||||
|
public DrawableTeamTitleWithHeader(TournamentTeam team, TeamColour colour)
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
InternalChild = new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 10),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new DrawableTeamHeader(colour),
|
||||||
|
new DrawableTeamTitle(team),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Components
|
||||||
|
{
|
||||||
|
public class DrawableTeamWithPlayers : CompositeDrawable
|
||||||
|
{
|
||||||
|
public DrawableTeamWithPlayers(TournamentTeam team, TeamColour colour)
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(30),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new DrawableTeamTitleWithHeader(team, colour),
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Padding = new MarginPadding { Left = 10 },
|
||||||
|
Spacing = new Vector2(30),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
ChildrenEnumerable = team?.Players.Select(createPlayerText).Take(5) ?? Enumerable.Empty<Drawable>()
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
ChildrenEnumerable = team?.Players.Select(createPlayerText).Skip(5) ?? Enumerable.Empty<Drawable>()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
TournamentSpriteText createPlayerText(User p) =>
|
||||||
|
new TournamentSpriteText
|
||||||
|
{
|
||||||
|
Text = p.Username,
|
||||||
|
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.SemiBold),
|
||||||
|
Colour = Color4.White,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Tournament.Models;
|
using osu.Game.Tournament.Models;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Components
|
namespace osu.Game.Tournament.Components
|
||||||
@ -19,27 +18,24 @@ namespace osu.Game.Tournament.Components
|
|||||||
public readonly TournamentTeam Team;
|
public readonly TournamentTeam Team;
|
||||||
|
|
||||||
protected readonly Sprite Flag;
|
protected readonly Sprite Flag;
|
||||||
protected readonly OsuSpriteText AcronymText;
|
protected readonly TournamentSpriteText AcronymText;
|
||||||
|
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
private Bindable<string> acronym;
|
private Bindable<string> acronym;
|
||||||
|
|
||||||
[UsedImplicitly]
|
|
||||||
private Bindable<string> flag;
|
|
||||||
|
|
||||||
protected DrawableTournamentTeam(TournamentTeam team)
|
protected DrawableTournamentTeam(TournamentTeam team)
|
||||||
{
|
{
|
||||||
Team = team;
|
Team = team;
|
||||||
|
|
||||||
Flag = new Sprite
|
Flag = new DrawableTeamFlag(team)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit
|
FillMode = FillMode.Fit
|
||||||
};
|
};
|
||||||
|
|
||||||
AcronymText = new OsuSpriteText
|
AcronymText = new TournamentSpriteText
|
||||||
{
|
{
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Regular),
|
Font = OsuFont.Torus.With(weight: FontWeight.Regular),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +45,6 @@ namespace osu.Game.Tournament.Components
|
|||||||
if (Team == null) return;
|
if (Team == null) return;
|
||||||
|
|
||||||
(acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(acronym => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true);
|
(acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(acronym => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true);
|
||||||
(flag = Team.FlagName.GetBoundCopy()).BindValueChanged(acronym => Flag.Texture = textures.Get($@"Flags/{Team.FlagName}"), true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.Game.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Components
|
||||||
|
{
|
||||||
|
public class DrawableTournamentTitleText : TournamentSpriteText
|
||||||
|
{
|
||||||
|
public DrawableTournamentTitleText()
|
||||||
|
{
|
||||||
|
Text = "osu!taiko world cup 2020";
|
||||||
|
Font = OsuFont.Torus.With(size: 26, weight: FontWeight.SemiBold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|