mirror of
https://github.com/ppy/osu.git
synced 2025-03-04 03:53:21 +08:00
Merge remote-tracking branch 'refs/remotes/ppy/master' into beatmap-listing-expanded
This commit is contained in:
commit
c08e16d97f
8
.github/ISSUE_TEMPLATE/00-mobile-issues.md
vendored
8
.github/ISSUE_TEMPLATE/00-mobile-issues.md
vendored
@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
name: Mobile Report
|
|
||||||
about: ⚠ Due to current development priorities we are not accepting mobile reports at this time (unless you're willing to fix them yourself!)
|
|
||||||
---
|
|
||||||
|
|
||||||
⚠ **PLEASE READ** ⚠: Due to prioritising finishing the client for desktop first we are not accepting reports related to mobile platforms for the time being, unless you're willing to fix them.
|
|
||||||
If you'd like to report a problem or suggest a feature and then work on it, feel free to open an issue and highlight that you'd like to address it yourself in the issue body; mobile pull requests are also welcome.
|
|
||||||
Otherwise, please check back in the future when the focus of development shifts towards mobile!
|
|
5
.github/ISSUE_TEMPLATE/01-bug-issues.md
vendored
5
.github/ISSUE_TEMPLATE/01-bug-issues.md
vendored
@ -9,3 +9,8 @@ about: Issues regarding encountered bugs.
|
|||||||
**osu!lazer version:**
|
**osu!lazer version:**
|
||||||
|
|
||||||
**Logs:**
|
**Logs:**
|
||||||
|
<!--
|
||||||
|
*please attach logs here, which are located at:*
|
||||||
|
- `%AppData%/osu/logs` *(on Windows),*
|
||||||
|
- `~/.local/share/osu/logs` *(on Linux & macOS).*
|
||||||
|
-->
|
||||||
|
5
.github/ISSUE_TEMPLATE/02-crash-issues.md
vendored
5
.github/ISSUE_TEMPLATE/02-crash-issues.md
vendored
@ -9,5 +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:*
|
||||||
|
- `%AppData%/osu/logs` *(on Windows),*
|
||||||
|
- `~/.local/share/osu/logs` *(on Linux & macOS).*
|
||||||
|
-->
|
||||||
|
|
||||||
**Computer Specifications:**
|
**Computer Specifications:**
|
||||||
|
40
.vscode/launch.json
vendored
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"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the
|
|||||||
|
|
||||||
This project is under heavy development, but is in a stable state. Users are encouraged to try it out and keep it installed alongside the stable *osu!* client. It will continue to evolve to the point of eventually replacing the existing stable client as an update.
|
This project is under heavy development, but is in a stable state. Users are encouraged to try it out and keep it installed alongside the stable *osu!* client. It will continue to evolve to the point of eventually replacing the existing stable client as an update.
|
||||||
|
|
||||||
We are accepting bug reports (please report with as much detail as possible). Feature requests are also welcome, but understand that our focus is on completing the game to feature parity before adding new features. A few resources are available as starting points to getting involved and understanding the project:
|
We are accepting bug reports (please report with as much detail as possible and follow the existing issue templates). Feature requests are also welcome, but understand that our focus is on completing the game to feature parity before adding new features. A few resources are available as starting points to getting involved and understanding the project:
|
||||||
|
|
||||||
- Detailed release changelogs are available on the [official osu! site](https://osu.ppy.sh/home/changelog/lazer).
|
- Detailed release changelogs are available on the [official osu! site](https://osu.ppy.sh/home/changelog/lazer).
|
||||||
- You can learn more about our approach to [project management](https://github.com/ppy/osu/wiki/Project-management).
|
- You can learn more about our approach to [project management](https://github.com/ppy/osu/wiki/Project-management).
|
||||||
@ -27,10 +27,9 @@ 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) | [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)
|
||||||
| ------------- | ------------- | ------------- | ------------- |
|
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||||
|
|
||||||
- **Linux** users are recommended to self-compile until we have official deployment in place.
|
|
||||||
- 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.
|
||||||
|
|
||||||
If your platform is not listed above, there is still a chance you can manually build it by following the instructions below.
|
If your platform is not listed above, there is still a chance you can manually build it by following the instructions below.
|
||||||
|
@ -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.219.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.218.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.302.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
|
||||||
<PackageReference Include="DiscordRichPresence" Version="1.0.147" />
|
<PackageReference Include="DiscordRichPresence" Version="1.0.150" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Resources">
|
<ItemGroup Label="Resources">
|
||||||
<EmbeddedResource Include="lazer.ico" />
|
<EmbeddedResource Include="lazer.ico" />
|
||||||
|
@ -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);
|
||||||
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
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.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,10 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
@ -30,6 +33,10 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
AddToggleStep("Hyperdash", t =>
|
AddToggleStep("Hyperdash", t =>
|
||||||
CreatedDrawables.OfType<CatchInputManager>().Select(i => i.Child)
|
CreatedDrawables.OfType<CatchInputManager>().Select(i => i.Child)
|
||||||
.OfType<TestCatcherArea>().ForEach(c => c.ToggleHyperDash(t)));
|
.OfType<TestCatcherArea>().ForEach(c => c.ToggleHyperDash(t)));
|
||||||
|
|
||||||
|
AddRepeatStep("catch fruit", () =>
|
||||||
|
this.ChildrenOfType<CatcherArea>().ForEach(area =>
|
||||||
|
area.MovableCatcher.PlaceOnPlate(new DrawableFruit(new TestSceneFruitObjects.TestCatchFruit(FruitVisualRepresentation.Grape)))), 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createCatcher(float size)
|
private void createCatcher(float size)
|
||||||
@ -58,6 +65,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public new Catcher MovableCatcher => base.MovableCatcher;
|
||||||
|
|
||||||
public void ToggleHyperDash(bool status) => MovableCatcher.SetHyperDashState(status ? 2 : 1);
|
public void ToggleHyperDash(bool status) => MovableCatcher.SetHyperDashState(status ? 2 : 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Catch.UI;
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
@ -6,8 +6,8 @@ using System.Collections.Generic;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
typeof(CatchHitObject),
|
typeof(CatchHitObject),
|
||||||
typeof(Fruit),
|
typeof(Fruit),
|
||||||
|
typeof(FruitPiece),
|
||||||
typeof(Droplet),
|
typeof(Droplet),
|
||||||
typeof(Banana),
|
typeof(Banana),
|
||||||
typeof(BananaShower),
|
typeof(BananaShower),
|
||||||
@ -37,14 +38,59 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
foreach (FruitVisualRepresentation rep in Enum.GetValues(typeof(FruitVisualRepresentation)))
|
foreach (FruitVisualRepresentation rep in Enum.GetValues(typeof(FruitVisualRepresentation)))
|
||||||
AddStep($"show {rep}", () => SetContents(() => createDrawable(rep)));
|
AddStep($"show {rep}", () => SetContents(() => createDrawable(rep)));
|
||||||
|
|
||||||
|
AddStep("show droplet", () => SetContents(createDrawableDroplet));
|
||||||
|
|
||||||
|
AddStep("show tiny droplet", () => SetContents(createDrawableTinyDroplet));
|
||||||
|
|
||||||
|
foreach (FruitVisualRepresentation rep in Enum.GetValues(typeof(FruitVisualRepresentation)))
|
||||||
|
AddStep($"show hyperdash {rep}", () => SetContents(() => createDrawable(rep, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DrawableFruit createDrawable(FruitVisualRepresentation rep)
|
private Drawable createDrawableTinyDroplet()
|
||||||
|
{
|
||||||
|
var droplet = new TinyDroplet
|
||||||
|
{
|
||||||
|
StartTime = Clock.CurrentTime,
|
||||||
|
Scale = 1.5f,
|
||||||
|
};
|
||||||
|
|
||||||
|
return new DrawableTinyDroplet(droplet)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
RelativePositionAxes = Axes.None,
|
||||||
|
Position = Vector2.Zero,
|
||||||
|
Alpha = 1,
|
||||||
|
LifetimeStart = double.NegativeInfinity,
|
||||||
|
LifetimeEnd = double.PositiveInfinity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable createDrawableDroplet()
|
||||||
|
{
|
||||||
|
var droplet = new Droplet
|
||||||
|
{
|
||||||
|
StartTime = Clock.CurrentTime,
|
||||||
|
Scale = 1.5f,
|
||||||
|
};
|
||||||
|
|
||||||
|
return new DrawableDroplet(droplet)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
RelativePositionAxes = Axes.None,
|
||||||
|
Position = Vector2.Zero,
|
||||||
|
Alpha = 1,
|
||||||
|
LifetimeStart = double.NegativeInfinity,
|
||||||
|
LifetimeEnd = double.PositiveInfinity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable createDrawable(FruitVisualRepresentation rep, bool hyperdash = false)
|
||||||
{
|
{
|
||||||
Fruit fruit = new TestCatchFruit(rep)
|
Fruit fruit = new TestCatchFruit(rep)
|
||||||
{
|
{
|
||||||
StartTime = 1000000000000,
|
|
||||||
Scale = 1.5f,
|
Scale = 1.5f,
|
||||||
|
HyperDashTarget = hyperdash ? new Banana() : null
|
||||||
};
|
};
|
||||||
|
|
||||||
return new DrawableFruit(fruit)
|
return new DrawableFruit(fruit)
|
||||||
@ -58,11 +104,12 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestCatchFruit : Fruit
|
public class TestCatchFruit : Fruit
|
||||||
{
|
{
|
||||||
public TestCatchFruit(FruitVisualRepresentation rep)
|
public TestCatchFruit(FruitVisualRepresentation rep)
|
||||||
{
|
{
|
||||||
VisualRepresentation = rep;
|
VisualRepresentation = rep;
|
||||||
|
StartTime = 1000000000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override FruitVisualRepresentation VisualRepresentation { get; }
|
public override FruitVisualRepresentation VisualRepresentation { get; }
|
||||||
|
56
osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs
Normal file
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,8 @@ using osu.Game.Rulesets.Difficulty;
|
|||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using System;
|
using System;
|
||||||
|
using osu.Game.Rulesets.Catch.Skinning;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch
|
namespace osu.Game.Rulesets.Catch
|
||||||
{
|
{
|
||||||
@ -141,6 +143,8 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
||||||
|
|
||||||
|
public override ISkin CreateLegacySkinProvider(ISkinSource source) => new CatchLegacySkinTransformer(source);
|
||||||
|
|
||||||
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new CatchPerformanceCalculator(this, beatmap, score);
|
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new CatchPerformanceCalculator(this, beatmap, score);
|
||||||
|
|
||||||
public int LegacyID => 2;
|
public int LegacyID => 2;
|
||||||
|
@ -5,5 +5,11 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
{
|
{
|
||||||
public enum CatchSkinComponents
|
public enum CatchSkinComponents
|
||||||
{
|
{
|
||||||
|
FruitBananas,
|
||||||
|
FruitApple,
|
||||||
|
FruitGrapes,
|
||||||
|
FruitOrange,
|
||||||
|
FruitPear,
|
||||||
|
Droplet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
{
|
{
|
||||||
public abstract class CatchHitObject : HitObject, IHasXPosition, IHasComboInformation
|
public abstract class CatchHitObject : HitObject, IHasXPosition, IHasComboInformation
|
||||||
{
|
{
|
||||||
public const double OBJECT_RADIUS = 44;
|
public const float OBJECT_RADIUS = 64;
|
||||||
|
|
||||||
private float x;
|
private float x;
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
|
|
||||||
TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
|
TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
|
||||||
|
|
||||||
Scale = 1.0f - 0.7f * (difficulty.CircleSize - 5) / 5;
|
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|
||||||
{
|
|
||||||
public class DrawableBanana : DrawableFruit
|
|
||||||
{
|
|
||||||
public DrawableBanana(Banana h)
|
|
||||||
: base(h)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|
||||||
{
|
|
||||||
public class DrawableDroplet : PalpableCatchHitObject<Droplet>
|
|
||||||
{
|
|
||||||
private Pulp pulp;
|
|
||||||
|
|
||||||
public override bool StaysOnPlate => false;
|
|
||||||
|
|
||||||
public DrawableDroplet(Droplet h)
|
|
||||||
: base(h)
|
|
||||||
{
|
|
||||||
Origin = Anchor.Centre;
|
|
||||||
Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS) / 4;
|
|
||||||
Masking = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
AddInternal(pulp = new Pulp { Size = Size });
|
|
||||||
|
|
||||||
AccentColour.BindValueChanged(colour => { pulp.AccentColour = colour.NewValue; }, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,316 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Utils;
|
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|
||||||
{
|
|
||||||
public class DrawableFruit : PalpableCatchHitObject<Fruit>
|
|
||||||
{
|
|
||||||
private Circle border;
|
|
||||||
|
|
||||||
private const float drawable_radius = (float)CatchHitObject.OBJECT_RADIUS * radius_adjust;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Because we're adding a border around the fruit, we need to scale down some.
|
|
||||||
/// </summary>
|
|
||||||
private const float radius_adjust = 1.1f;
|
|
||||||
|
|
||||||
public DrawableFruit(Fruit h)
|
|
||||||
: base(h)
|
|
||||||
{
|
|
||||||
Origin = Anchor.Centre;
|
|
||||||
|
|
||||||
Size = new Vector2(drawable_radius);
|
|
||||||
Masking = false;
|
|
||||||
|
|
||||||
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
// todo: this should come from the skin.
|
|
||||||
AccentColour.Value = colourForRepresentation(HitObject.VisualRepresentation);
|
|
||||||
|
|
||||||
AddRangeInternal(new[]
|
|
||||||
{
|
|
||||||
createPulp(HitObject.VisualRepresentation),
|
|
||||||
border = new Circle
|
|
||||||
{
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Hollow = !HitObject.HyperDash,
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Radius = 4 * radius_adjust,
|
|
||||||
Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Value.Darken(1).Opacity(0.6f)
|
|
||||||
},
|
|
||||||
Size = new Vector2(Height),
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
BorderColour = Color4.White,
|
|
||||||
BorderThickness = 3f * radius_adjust,
|
|
||||||
Children = new Framework.Graphics.Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
AlwaysPresent = true,
|
|
||||||
Colour = AccentColour.Value,
|
|
||||||
Alpha = 0,
|
|
||||||
RelativeSizeAxes = Axes.Both
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (HitObject.HyperDash)
|
|
||||||
{
|
|
||||||
AddInternal(new Pulp
|
|
||||||
{
|
|
||||||
RelativePositionAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
AccentColour = Color4.Red,
|
|
||||||
Blending = BlendingParameters.Additive,
|
|
||||||
Alpha = 0.5f,
|
|
||||||
Scale = new Vector2(1.333f)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Framework.Graphics.Drawable createPulp(FruitVisualRepresentation representation)
|
|
||||||
{
|
|
||||||
const float large_pulp_3 = 8f * radius_adjust;
|
|
||||||
const float distance_from_centre_3 = 0.15f;
|
|
||||||
|
|
||||||
const float large_pulp_4 = large_pulp_3 * 0.925f;
|
|
||||||
const float distance_from_centre_4 = distance_from_centre_3 / 0.925f;
|
|
||||||
|
|
||||||
const float small_pulp = large_pulp_3 / 2;
|
|
||||||
|
|
||||||
static Vector2 positionAt(float angle, float distance) => new Vector2(
|
|
||||||
distance * MathF.Sin(angle * MathF.PI / 180),
|
|
||||||
distance * MathF.Cos(angle * MathF.PI / 180));
|
|
||||||
|
|
||||||
switch (representation)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return new Container();
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Raspberry:
|
|
||||||
return new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new Framework.Graphics.Drawable[]
|
|
||||||
{
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(small_pulp),
|
|
||||||
Y = -0.34f,
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_4),
|
|
||||||
Position = positionAt(0, distance_from_centre_4),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_4),
|
|
||||||
Position = positionAt(90, distance_from_centre_4),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_4),
|
|
||||||
Position = positionAt(180, distance_from_centre_4),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
Size = new Vector2(large_pulp_4),
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Position = positionAt(270, distance_from_centre_4),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Pineapple:
|
|
||||||
return new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new Framework.Graphics.Drawable[]
|
|
||||||
{
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(small_pulp),
|
|
||||||
Y = -0.3f,
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_4),
|
|
||||||
Position = positionAt(45, distance_from_centre_4),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_4),
|
|
||||||
Position = positionAt(135, distance_from_centre_4),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_4),
|
|
||||||
Position = positionAt(225, distance_from_centre_4),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
Size = new Vector2(large_pulp_4),
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Position = positionAt(315, distance_from_centre_4),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Pear:
|
|
||||||
return new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new Framework.Graphics.Drawable[]
|
|
||||||
{
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(small_pulp),
|
|
||||||
Y = -0.33f,
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_3),
|
|
||||||
Position = positionAt(60, distance_from_centre_3),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_3),
|
|
||||||
Position = positionAt(180, distance_from_centre_3),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
Size = new Vector2(large_pulp_3),
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Position = positionAt(300, distance_from_centre_3),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Grape:
|
|
||||||
return new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new Framework.Graphics.Drawable[]
|
|
||||||
{
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(small_pulp),
|
|
||||||
Y = -0.25f,
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_3),
|
|
||||||
Position = positionAt(0, distance_from_centre_3),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_3),
|
|
||||||
Position = positionAt(120, distance_from_centre_3),
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
Size = new Vector2(large_pulp_3),
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Position = positionAt(240, distance_from_centre_3),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Banana:
|
|
||||||
return new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Children = new Framework.Graphics.Drawable[]
|
|
||||||
{
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(small_pulp),
|
|
||||||
Y = -0.3f
|
|
||||||
},
|
|
||||||
new Pulp
|
|
||||||
{
|
|
||||||
AccentColour = AccentColour.Value,
|
|
||||||
Size = new Vector2(large_pulp_4 * 0.8f, large_pulp_4 * 2.5f),
|
|
||||||
Y = 0.05f,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
border.Alpha = (float)Math.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 colourForRepresentation(FruitVisualRepresentation representation)
|
|
||||||
{
|
|
||||||
switch (representation)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case FruitVisualRepresentation.Pear:
|
|
||||||
return new Color4(17, 136, 170, 255);
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Grape:
|
|
||||||
return new Color4(204, 102, 0, 255);
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Raspberry:
|
|
||||||
return new Color4(121, 9, 13, 255);
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Pineapple:
|
|
||||||
return new Color4(102, 136, 0, 255);
|
|
||||||
|
|
||||||
case FruitVisualRepresentation.Banana:
|
|
||||||
switch (RNG.Next(0, 3))
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return new Color4(255, 240, 0, 255);
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
return new Color4(255, 192, 0, 255);
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return new Color4(214, 221, 28, 255);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
31
osu.Game.Rulesets.Catch/Objects/Drawables/BananaPiece.cs
Normal file
31
osu.Game.Rulesets.Catch/Objects/Drawables/BananaPiece.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 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.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public class BananaPiece : PulpFormation
|
||||||
|
{
|
||||||
|
public BananaPiece()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(SMALL_PULP),
|
||||||
|
Y = -0.3f
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_4 * 0.8f, LARGE_PULP_4 * 2.5f),
|
||||||
|
Y = 0.05f,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs
Normal file
40
osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public class DrawableBanana : DrawableFruit
|
||||||
|
{
|
||||||
|
public DrawableBanana(Banana h)
|
||||||
|
: base(h)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color4? colour;
|
||||||
|
|
||||||
|
protected override Color4 GetComboColour(IReadOnlyList<Color4> comboColours)
|
||||||
|
{
|
||||||
|
// override any external colour changes with banananana
|
||||||
|
return colour ??= getBananaColour();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color4 getBananaColour()
|
||||||
|
{
|
||||||
|
switch (RNG.Next(0, 3))
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
return new Color4(255, 240, 0, 255);
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return new Color4(255, 192, 0, 255);
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return new Color4(214, 221, 28, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableBananaShower : DrawableCatchHitObject<BananaShower>
|
public class DrawableBananaShower : DrawableCatchHitObject<BananaShower>
|
||||||
{
|
{
|
@ -2,24 +2,51 @@
|
|||||||
// 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 osuTK;
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
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.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
{
|
{
|
||||||
public abstract class PalpableCatchHitObject<TObject> : DrawableCatchHitObject<TObject>
|
public abstract class PalpableCatchHitObject<TObject> : DrawableCatchHitObject<TObject>
|
||||||
where TObject : CatchHitObject
|
where TObject : CatchHitObject
|
||||||
{
|
{
|
||||||
public override bool CanBePlated => true;
|
public override bool CanBePlated => true;
|
||||||
|
|
||||||
|
protected Container ScaleContainer { get; private set; }
|
||||||
|
|
||||||
protected PalpableCatchHitObject(TObject hitObject)
|
protected PalpableCatchHitObject(TObject hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
{
|
{
|
||||||
Scale = new Vector2(HitObject.Scale);
|
Origin = Anchor.Centre;
|
||||||
|
Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2);
|
||||||
|
Masking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
AddRangeInternal(new Drawable[]
|
||||||
|
{
|
||||||
|
ScaleContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ScaleContainer.Scale = new Vector2(HitObject.Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Color4 GetComboColour(IReadOnlyList<Color4> comboColours) =>
|
||||||
|
comboColours[(HitObject.IndexInBeatmap + 1) % comboColours.Count];
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class DrawableCatchHitObject<TObject> : DrawableCatchHitObject
|
public abstract class DrawableCatchHitObject<TObject> : DrawableCatchHitObject
|
||||||
@ -41,6 +68,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
|
|
||||||
public virtual bool StaysOnPlate => CanBePlated;
|
public virtual bool StaysOnPlate => CanBePlated;
|
||||||
|
|
||||||
|
public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale;
|
||||||
|
|
||||||
protected DrawableCatchHitObject(CatchHitObject hitObject)
|
protected DrawableCatchHitObject(CatchHitObject hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
{
|
{
|
42
osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs
Normal file
42
osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public class DrawableDroplet : PalpableCatchHitObject<Droplet>
|
||||||
|
{
|
||||||
|
public override bool StaysOnPlate => false;
|
||||||
|
|
||||||
|
public DrawableDroplet(Droplet h)
|
||||||
|
: base(h)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
ScaleContainer.Child = new SkinnableDrawable(new CatchSkinComponent(CatchSkinComponents.Droplet), _ => new Pulp
|
||||||
|
{
|
||||||
|
Size = Size / 4,
|
||||||
|
AccentColour = { BindTarget = AccentColour }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateInitialTransforms()
|
||||||
|
{
|
||||||
|
base.UpdateInitialTransforms();
|
||||||
|
|
||||||
|
// roughly matches osu-stable
|
||||||
|
float startRotation = RNG.NextSingle() * 20;
|
||||||
|
double duration = HitObject.TimePreempt + 2000;
|
||||||
|
|
||||||
|
this.RotateTo(startRotation).RotateTo(startRotation + 720, duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs
Normal file
50
osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public class DrawableFruit : PalpableCatchHitObject<Fruit>
|
||||||
|
{
|
||||||
|
public DrawableFruit(Fruit h)
|
||||||
|
: base(h)
|
||||||
|
{
|
||||||
|
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
ScaleContainer.Child = new SkinnableDrawable(
|
||||||
|
new CatchSkinComponent(getComponent(HitObject.VisualRepresentation)), _ => new FruitPiece());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CatchSkinComponents getComponent(FruitVisualRepresentation hitObjectVisualRepresentation)
|
||||||
|
{
|
||||||
|
switch (hitObjectVisualRepresentation)
|
||||||
|
{
|
||||||
|
case FruitVisualRepresentation.Pear:
|
||||||
|
return CatchSkinComponents.FruitPear;
|
||||||
|
|
||||||
|
case FruitVisualRepresentation.Grape:
|
||||||
|
return CatchSkinComponents.FruitGrapes;
|
||||||
|
|
||||||
|
case FruitVisualRepresentation.Pineapple:
|
||||||
|
return CatchSkinComponents.FruitApple;
|
||||||
|
|
||||||
|
case FruitVisualRepresentation.Raspberry:
|
||||||
|
return CatchSkinComponents.FruitOrange;
|
||||||
|
|
||||||
|
case FruitVisualRepresentation.Banana:
|
||||||
|
return CatchSkinComponents.FruitBananas;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(hitObjectVisualRepresentation), hitObjectVisualRepresentation, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableJuiceStream : DrawableCatchHitObject<JuiceStream>
|
public class DrawableJuiceStream : DrawableCatchHitObject<JuiceStream>
|
||||||
{
|
{
|
||||||
@ -42,10 +42,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
switch (hitObject)
|
switch (hitObject)
|
||||||
{
|
{
|
||||||
case CatchHitObject catchObject:
|
case CatchHitObject catchObject:
|
||||||
return createDrawableRepresentation?.Invoke(catchObject)?.With(o => ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false);
|
return createDrawableRepresentation?.Invoke(catchObject)?.With(o =>
|
||||||
|
((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.CreateNestedHitObject(hitObject);
|
throw new ArgumentException($"{nameof(hitObject)} must be of type {nameof(CatchHitObject)}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,21 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osuTK;
|
using osu.Framework.Allocation;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableTinyDroplet : DrawableDroplet
|
public class DrawableTinyDroplet : DrawableDroplet
|
||||||
{
|
{
|
||||||
public DrawableTinyDroplet(TinyDroplet h)
|
public DrawableTinyDroplet(TinyDroplet h)
|
||||||
: base(h)
|
: base(h)
|
||||||
{
|
{
|
||||||
Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS) / 8;
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
ScaleContainer.Scale /= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
116
osu.Game.Rulesets.Catch/Objects/Drawables/FruitPiece.cs
Normal file
116
osu.Game.Rulesets.Catch/Objects/Drawables/FruitPiece.cs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
internal class FruitPiece : CompositeDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Because we're adding a border around the fruit, we need to scale down some.
|
||||||
|
/// </summary>
|
||||||
|
public const float RADIUS_ADJUST = 1.1f;
|
||||||
|
|
||||||
|
private Circle border;
|
||||||
|
|
||||||
|
private CatchHitObject hitObject;
|
||||||
|
|
||||||
|
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
|
public FruitPiece()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(DrawableHitObject drawableObject)
|
||||||
|
{
|
||||||
|
DrawableCatchHitObject drawableCatchObject = (DrawableCatchHitObject)drawableObject;
|
||||||
|
hitObject = drawableCatchObject.HitObject;
|
||||||
|
|
||||||
|
accentColour.BindTo(drawableCatchObject.AccentColour);
|
||||||
|
|
||||||
|
AddRangeInternal(new[]
|
||||||
|
{
|
||||||
|
getFruitFor(drawableCatchObject.HitObject.VisualRepresentation),
|
||||||
|
border = new Circle
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
BorderColour = Color4.White,
|
||||||
|
BorderThickness = 6f * RADIUS_ADJUST,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0,
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hitObject.HyperDash)
|
||||||
|
{
|
||||||
|
AddInternal(new Circle
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
BorderColour = Color4.Red,
|
||||||
|
BorderThickness = 12f * RADIUS_ADJUST,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0.3f,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Red,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
border.Alpha = (float)Math.Clamp((hitObject.StartTime - Time.Current) / 500, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable getFruitFor(FruitVisualRepresentation representation)
|
||||||
|
{
|
||||||
|
switch (representation)
|
||||||
|
{
|
||||||
|
case FruitVisualRepresentation.Pear:
|
||||||
|
return new PearPiece();
|
||||||
|
|
||||||
|
case FruitVisualRepresentation.Grape:
|
||||||
|
return new GrapePiece();
|
||||||
|
|
||||||
|
case FruitVisualRepresentation.Pineapple:
|
||||||
|
return new PineapplePiece();
|
||||||
|
|
||||||
|
case FruitVisualRepresentation.Banana:
|
||||||
|
return new BananaPiece();
|
||||||
|
|
||||||
|
case FruitVisualRepresentation.Raspberry:
|
||||||
|
return new RaspberryPiece();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
osu.Game.Rulesets.Catch/Objects/Drawables/GrapePiece.cs
Normal file
43
osu.Game.Rulesets.Catch/Objects/Drawables/GrapePiece.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// 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.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public class GrapePiece : PulpFormation
|
||||||
|
{
|
||||||
|
public GrapePiece()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(SMALL_PULP),
|
||||||
|
Y = -0.25f,
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_3),
|
||||||
|
Position = PositionAt(0, DISTANCE_FROM_CENTRE_3),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_3),
|
||||||
|
Position = PositionAt(120, DISTANCE_FROM_CENTRE_3),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
Size = new Vector2(LARGE_PULP_3),
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Position = PositionAt(240, DISTANCE_FROM_CENTRE_3),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
osu.Game.Rulesets.Catch/Objects/Drawables/PearPiece.cs
Normal file
43
osu.Game.Rulesets.Catch/Objects/Drawables/PearPiece.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// 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.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public class PearPiece : PulpFormation
|
||||||
|
{
|
||||||
|
public PearPiece()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(SMALL_PULP),
|
||||||
|
Y = -0.33f,
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_3),
|
||||||
|
Position = PositionAt(60, DISTANCE_FROM_CENTRE_3),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_3),
|
||||||
|
Position = PositionAt(180, DISTANCE_FROM_CENTRE_3),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
Size = new Vector2(LARGE_PULP_3),
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Position = PositionAt(300, DISTANCE_FROM_CENTRE_3),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +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 osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Effects;
|
using osu.Framework.Graphics.Effects;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables.Pieces
|
||||||
{
|
{
|
||||||
public class Pulp : Circle, IHasAccentColour
|
public class Pulp : Circle
|
||||||
{
|
{
|
||||||
public Pulp()
|
public Pulp()
|
||||||
{
|
{
|
||||||
@ -22,32 +22,23 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces
|
|||||||
Colour = Color4.White.Opacity(0.9f);
|
Colour = Color4.White.Opacity(0.9f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color4 accentColour;
|
public readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
public Color4 AccentColour
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
get => accentColour;
|
base.LoadComplete();
|
||||||
set
|
|
||||||
{
|
AccentColour.BindValueChanged(updateAccentColour, true);
|
||||||
accentColour = value;
|
|
||||||
if (IsLoaded) updateAccentColour();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAccentColour()
|
private void updateAccentColour(ValueChangedEvent<Color4> colour)
|
||||||
{
|
{
|
||||||
EdgeEffect = new EdgeEffectParameters
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Radius = Size.X / 2,
|
Radius = Size.X / 2,
|
||||||
Colour = accentColour.Darken(0.2f).Opacity(0.75f)
|
Colour = colour.NewValue.Darken(0.2f).Opacity(0.75f)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
updateAccentColour();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
49
osu.Game.Rulesets.Catch/Objects/Drawables/PineapplePiece.cs
Normal file
49
osu.Game.Rulesets.Catch/Objects/Drawables/PineapplePiece.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public class PineapplePiece : PulpFormation
|
||||||
|
{
|
||||||
|
public PineapplePiece()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(SMALL_PULP),
|
||||||
|
Y = -0.3f,
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_4),
|
||||||
|
Position = PositionAt(45, DISTANCE_FROM_CENTRE_4),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_4),
|
||||||
|
Position = PositionAt(135, DISTANCE_FROM_CENTRE_4),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_4),
|
||||||
|
Position = PositionAt(225, DISTANCE_FROM_CENTRE_4),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
Size = new Vector2(LARGE_PULP_4),
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Position = PositionAt(315, DISTANCE_FROM_CENTRE_4),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
osu.Game.Rulesets.Catch/Objects/Drawables/PulpFormation.cs
Normal file
43
osu.Game.Rulesets.Catch/Objects/Drawables/PulpFormation.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public abstract class PulpFormation : CompositeDrawable
|
||||||
|
{
|
||||||
|
protected readonly IBindable<Color4> AccentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
|
protected const float LARGE_PULP_3 = 16f * FruitPiece.RADIUS_ADJUST;
|
||||||
|
protected const float DISTANCE_FROM_CENTRE_3 = 0.15f;
|
||||||
|
|
||||||
|
protected const float LARGE_PULP_4 = LARGE_PULP_3 * 0.925f;
|
||||||
|
protected const float DISTANCE_FROM_CENTRE_4 = DISTANCE_FROM_CENTRE_3 / 0.925f;
|
||||||
|
|
||||||
|
protected const float SMALL_PULP = LARGE_PULP_3 / 2;
|
||||||
|
|
||||||
|
protected PulpFormation()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Vector2 PositionAt(float angle, float distance) => new Vector2(
|
||||||
|
distance * MathF.Sin(angle * MathF.PI / 180),
|
||||||
|
distance * MathF.Cos(angle * MathF.PI / 180));
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(DrawableHitObject drawableObject)
|
||||||
|
{
|
||||||
|
DrawableCatchHitObject drawableCatchObject = (DrawableCatchHitObject)drawableObject;
|
||||||
|
AccentColour.BindTo(drawableCatchObject.AccentColour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
osu.Game.Rulesets.Catch/Objects/Drawables/RaspberryPiece.cs
Normal file
49
osu.Game.Rulesets.Catch/Objects/Drawables/RaspberryPiece.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||||
|
{
|
||||||
|
public class RaspberryPiece : PulpFormation
|
||||||
|
{
|
||||||
|
public RaspberryPiece()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(SMALL_PULP),
|
||||||
|
Y = -0.34f,
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_4),
|
||||||
|
Position = PositionAt(0, DISTANCE_FROM_CENTRE_4),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_4),
|
||||||
|
Position = PositionAt(90, DISTANCE_FROM_CENTRE_4),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Size = new Vector2(LARGE_PULP_4),
|
||||||
|
Position = PositionAt(180, DISTANCE_FROM_CENTRE_4),
|
||||||
|
},
|
||||||
|
new Pulp
|
||||||
|
{
|
||||||
|
Size = new Vector2(LARGE_PULP_4),
|
||||||
|
AccentColour = { BindTarget = AccentColour },
|
||||||
|
Position = PositionAt(270, DISTANCE_FROM_CENTRE_4),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using Humanizer;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Skinning
|
||||||
|
{
|
||||||
|
public class CatchLegacySkinTransformer : ISkin
|
||||||
|
{
|
||||||
|
private readonly ISkin source;
|
||||||
|
|
||||||
|
public CatchLegacySkinTransformer(ISkinSource source)
|
||||||
|
{
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable GetDrawableComponent(ISkinComponent component)
|
||||||
|
{
|
||||||
|
if (!(component is CatchSkinComponent catchSkinComponent))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
switch (catchSkinComponent.Component)
|
||||||
|
{
|
||||||
|
case CatchSkinComponents.FruitApple:
|
||||||
|
case CatchSkinComponents.FruitBananas:
|
||||||
|
case CatchSkinComponents.FruitOrange:
|
||||||
|
case CatchSkinComponents.FruitGrapes:
|
||||||
|
case CatchSkinComponents.FruitPear:
|
||||||
|
var lookupName = catchSkinComponent.Component.ToString().Kebaberize();
|
||||||
|
if (GetTexture(lookupName) != null)
|
||||||
|
return new LegacyFruitPiece(lookupName);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CatchSkinComponents.Droplet:
|
||||||
|
if (GetTexture("fruit-drop") != null)
|
||||||
|
return new LegacyFruitPiece("fruit-drop") { Scale = new Vector2(0.8f) };
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Texture GetTexture(string componentName) => source.GetTexture(componentName);
|
||||||
|
|
||||||
|
public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample);
|
||||||
|
|
||||||
|
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => source.GetConfig<TLookup, TValue>(lookup);
|
||||||
|
}
|
||||||
|
}
|
79
osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs
Normal file
79
osu.Game.Rulesets.Catch/Skinning/LegacyFruitPiece.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Skinning
|
||||||
|
{
|
||||||
|
internal class LegacyFruitPiece : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly string lookupName;
|
||||||
|
|
||||||
|
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||||
|
private Sprite colouredSprite;
|
||||||
|
|
||||||
|
public LegacyFruitPiece(string lookupName)
|
||||||
|
{
|
||||||
|
this.lookupName = lookupName;
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(DrawableHitObject drawableObject, ISkinSource skin)
|
||||||
|
{
|
||||||
|
DrawableCatchHitObject drawableCatchObject = (DrawableCatchHitObject)drawableObject;
|
||||||
|
|
||||||
|
accentColour.BindTo(drawableCatchObject.AccentColour);
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
colouredSprite = new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture(lookupName),
|
||||||
|
Colour = drawableObject.AccentColour.Value,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
new Sprite
|
||||||
|
{
|
||||||
|
Texture = skin.GetTexture($"{lookupName}-overlay"),
|
||||||
|
Anchor = 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()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
accentColour.BindValueChanged(colour => colouredSprite.Colour = colour.NewValue, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
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.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
@ -4,14 +4,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
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.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Judgements;
|
using osu.Game.Rulesets.Catch.Judgements;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Catch.Replays;
|
using osu.Game.Rulesets.Catch.Replays;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -48,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)
|
||||||
@ -74,11 +79,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
caughtFruit.Anchor = Anchor.TopCentre;
|
caughtFruit.Anchor = Anchor.TopCentre;
|
||||||
caughtFruit.Origin = Anchor.Centre;
|
caughtFruit.Origin = Anchor.Centre;
|
||||||
caughtFruit.Scale *= 0.7f;
|
caughtFruit.Scale *= 0.5f;
|
||||||
caughtFruit.LifetimeStart = caughtFruit.HitObject.StartTime;
|
caughtFruit.LifetimeStart = caughtFruit.HitObject.StartTime;
|
||||||
caughtFruit.LifetimeEnd = double.MaxValue;
|
caughtFruit.LifetimeEnd = double.MaxValue;
|
||||||
|
|
||||||
MovableCatcher.Add(caughtFruit);
|
MovableCatcher.PlaceOnPlate(caughtFruit);
|
||||||
lastPlateableFruit = caughtFruit;
|
lastPlateableFruit = caughtFruit;
|
||||||
|
|
||||||
if (!fruit.StaysOnPlate)
|
if (!fruit.StaysOnPlate)
|
||||||
@ -87,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();
|
||||||
@ -221,9 +226,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// Add a caught fruit to the catcher's stack.
|
/// Add a caught fruit to the catcher's stack.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fruit">The fruit that was caught.</param>
|
/// <param name="fruit">The fruit that was caught.</param>
|
||||||
public void Add(DrawableHitObject fruit)
|
public void PlaceOnPlate(DrawableCatchHitObject fruit)
|
||||||
{
|
{
|
||||||
float ourRadius = fruit.DrawSize.X / 2 * fruit.Scale.X;
|
float ourRadius = fruit.DisplayRadius;
|
||||||
float theirRadius = 0;
|
float theirRadius = 0;
|
||||||
|
|
||||||
const float allowance = 6;
|
const float allowance = 6;
|
||||||
@ -240,6 +245,12 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2);
|
fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2);
|
||||||
|
|
||||||
caughtFruit.Add(fruit);
|
caughtFruit.Add(fruit);
|
||||||
|
|
||||||
|
Add(new HitExplosion(fruit)
|
||||||
|
{
|
||||||
|
X = fruit.X,
|
||||||
|
Scale = new Vector2(fruit.HitObject.Scale)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -465,4 +476,112 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class HitExplosion : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly CircularContainer largeFaint;
|
||||||
|
|
||||||
|
public HitExplosion(DrawableCatchHitObject fruit)
|
||||||
|
{
|
||||||
|
Size = new Vector2(20);
|
||||||
|
Anchor = Anchor.TopCentre;
|
||||||
|
Origin = Anchor.BottomCentre;
|
||||||
|
|
||||||
|
Color4 objectColour = fruit.AccentColour.Value;
|
||||||
|
|
||||||
|
// scale roughly in-line with visual appearance of notes
|
||||||
|
|
||||||
|
const float angle_variangle = 15; // should be less than 45
|
||||||
|
|
||||||
|
const float roundness = 100;
|
||||||
|
|
||||||
|
const float initial_height = 10;
|
||||||
|
|
||||||
|
var colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1);
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
largeFaint = new CircularContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
// we want our size to be very small so the glow dominates it.
|
||||||
|
Size = new Vector2(0.8f),
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = Interpolation.ValueAt(0.1f, objectColour, Color4.White, 0, 1).Opacity(0.3f),
|
||||||
|
Roundness = 160,
|
||||||
|
Radius = 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = Interpolation.ValueAt(0.6f, objectColour, Color4.White, 0, 1),
|
||||||
|
Roundness = 20,
|
||||||
|
Radius = 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
Size = new Vector2(0.01f, initial_height),
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Rotation = RNG.NextSingle(-angle_variangle, angle_variangle),
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = colour,
|
||||||
|
Roundness = roundness,
|
||||||
|
Radius = 40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
Size = new Vector2(0.01f, initial_height),
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Rotation = RNG.NextSingle(-angle_variangle, angle_variangle),
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = colour,
|
||||||
|
Roundness = roundness,
|
||||||
|
Radius = 40,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
const double duration = 400;
|
||||||
|
|
||||||
|
largeFaint
|
||||||
|
.ResizeTo(largeFaint.Size * new Vector2(5, 1), duration, Easing.OutQuint)
|
||||||
|
.FadeOut(duration * 2);
|
||||||
|
|
||||||
|
this.FadeInFromZero(50).Then().FadeOut(duration, Easing.Out);
|
||||||
|
Expire(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ using osu.Game.Configuration;
|
|||||||
using osu.Game.Input.Handlers;
|
using osu.Game.Input.Handlers;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Catch.Replays;
|
using osu.Game.Rulesets.Catch.Replays;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Audio;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Skinning;
|
|
||||||
using osu.Game.Tests.Visual;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Tests
|
|
||||||
{
|
|
||||||
public abstract class SkinnableTestScene : OsuGridTestScene
|
|
||||||
{
|
|
||||||
private Skin defaultSkin;
|
|
||||||
|
|
||||||
protected SkinnableTestScene()
|
|
||||||
: base(1, 2)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(AudioManager audio, SkinManager skinManager)
|
|
||||||
{
|
|
||||||
defaultSkin = skinManager.GetSkin(DefaultLegacySkin.Info);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetContents(Func<Drawable> creationFunction)
|
|
||||||
{
|
|
||||||
Cell(0).Child = createProvider(null, creationFunction);
|
|
||||||
Cell(1).Child = createProvider(defaultSkin, creationFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Drawable createProvider(Skin skin, Func<Drawable> creationFunction)
|
|
||||||
{
|
|
||||||
var mainProvider = new SkinProvidingContainer(skin);
|
|
||||||
|
|
||||||
return mainProvider
|
|
||||||
.WithChild(new SkinProvidingContainer(Ruleset.Value.CreateInstance().CreateLegacySkinProvider(mainProvider))
|
|
||||||
{
|
|
||||||
Child = creationFunction()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
using osu.Game.Rulesets.Mania.UI;
|
using osu.Game.Rulesets.Mania.UI;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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];
|
||||||
|
@ -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);
|
||||||
}
|
|
||||||
|
|
||||||
fp.Expire(true);
|
finalTransformEndTime = fadeOutTime + osuEnd.TimeFadeIn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
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;
|
||||||
@ -214,9 +215,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
public class DefaultSliderBall : CompositeDrawable
|
public class DefaultSliderBall : CompositeDrawable
|
||||||
{
|
{
|
||||||
|
private Box box;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(DrawableHitObject drawableObject, ISkinSource skin)
|
private void load(DrawableHitObject drawableObject, ISkinSource skin)
|
||||||
{
|
{
|
||||||
|
var slider = (DrawableSlider)drawableObject;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
float radius = skin.GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS;
|
float radius = skin.GetConfig<OsuSkinConfiguration, float>(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS;
|
||||||
@ -231,14 +236,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
BorderThickness = 10,
|
BorderThickness = 10,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
||||||
Alpha = 1,
|
Alpha = 1,
|
||||||
Child = new Box
|
Child = box = new Box
|
||||||
{
|
{
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.White,
|
Colour = Color4.White,
|
||||||
Alpha = 0.4f,
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
slider.Tracking.BindValueChanged(trackingChanged, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void trackingChanged(ValueChangedEvent<bool> tracking) =>
|
||||||
|
box.FadeTo(tracking.NewValue ? 0.6f : 0.05f, 200, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ using System.ComponentModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
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;
|
using osu.Game.Storyboards;
|
||||||
|
|
||||||
@ -14,20 +13,22 @@ 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
|
||||||
{
|
{
|
||||||
|
protected new TestPlayer Player => (TestPlayer)base.Player;
|
||||||
|
|
||||||
private ClockBackedTestWorkingBeatmap.TrackVirtualManual track;
|
private ClockBackedTestWorkingBeatmap.TrackVirtualManual track;
|
||||||
|
|
||||||
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("rewind", () => track.Seek(-10000));
|
||||||
AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||||
@ -38,18 +39,5 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
return working;
|
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]
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -62,14 +62,7 @@ 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;
|
||||||
|
|
||||||
Game = new TestOsuGame(LocalStorage, API);
|
CreateGame();
|
||||||
Game.SetHost(host);
|
|
||||||
|
|
||||||
// todo: this can be removed once we can run audio tracks without a device present
|
|
||||||
// see https://github.com/ppy/osu/issues/1302
|
|
||||||
Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
|
||||||
|
|
||||||
Add(Game);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
||||||
@ -78,6 +71,18 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
ConfirmAtMainMenu();
|
ConfirmAtMainMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void CreateGame()
|
||||||
|
{
|
||||||
|
Game = new TestOsuGame(LocalStorage, API);
|
||||||
|
Game.SetHost(host);
|
||||||
|
|
||||||
|
// todo: this can be removed once we can run audio tracks without a device present
|
||||||
|
// see https://github.com/ppy/osu/issues/1302
|
||||||
|
Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
||||||
|
|
||||||
|
Add(Game);
|
||||||
|
}
|
||||||
|
|
||||||
protected void PushAndConfirm(Func<Screen> newScreen)
|
protected void PushAndConfirm(Func<Screen> newScreen)
|
||||||
{
|
{
|
||||||
Screen screen = null;
|
Screen screen = null;
|
||||||
@ -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
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,27 +61,40 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
AddStep("load comments", () => createPage(comment_bundle));
|
[Test]
|
||||||
AddStep("load empty comments", () => createPage(empty_comment_bundle));
|
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 }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly CommentBundle empty_comment_bundle = new CommentBundle
|
private CommentBundle getEmptyCommentBundle() => new CommentBundle
|
||||||
{
|
{
|
||||||
Comments = new List<Comment>(),
|
Comments = new List<Comment>(),
|
||||||
Total = 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly CommentBundle comment_bundle = new CommentBundle
|
private CommentBundle getCommentBundle() => new CommentBundle
|
||||||
{
|
{
|
||||||
Comments = new List<Comment>
|
Comments = new List<Comment>
|
||||||
{
|
{
|
||||||
@ -90,6 +107,33 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
VotesCount = 5
|
VotesCount = 5
|
||||||
},
|
},
|
||||||
new Comment
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 100,
|
||||||
|
Message = "This comment has \"load replies\" button because it has unloaded replies",
|
||||||
|
LegacyName = "TestUser1100",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
VotesCount = 5,
|
||||||
|
RepliesCount = 2,
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 111,
|
||||||
|
Message = "This comment has \"Show More\" button because it has unloaded replies, but some of them are loaded",
|
||||||
|
LegacyName = "TestUser1111",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
VotesCount = 100,
|
||||||
|
RepliesCount = 2,
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
|
{
|
||||||
|
Id = 112,
|
||||||
|
ParentId = 111,
|
||||||
|
Message = "I'm here to make my parent work",
|
||||||
|
LegacyName = "someone",
|
||||||
|
CreatedAt = DateTimeOffset.Now,
|
||||||
|
VotesCount = 2,
|
||||||
|
},
|
||||||
|
new Comment
|
||||||
{
|
{
|
||||||
Id = 2,
|
Id = 2,
|
||||||
Message = "This comment has been deleted :( but visible for admins",
|
Message = "This comment has been deleted :( but visible for admins",
|
||||||
@ -155,8 +199,34 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
Username = "Good_Admin"
|
Username = "Good_Admin"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TopLevelCount = 4,
|
|
||||||
Total = 7
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Overlays.Direct;
|
using osu.Game.Overlays.Direct;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -14,7 +15,8 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
public class TestSceneDirectPanel : OsuTestScene
|
[Cached(typeof(IPreviewTrackOwner))]
|
||||||
|
public class TestSceneDirectPanel : OsuTestScene, IPreviewTrackOwner
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
|
@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online);
|
AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online);
|
||||||
|
|
||||||
AddUntilStep("children are visible", () => onlineView.ViewTarget.IsPresent);
|
AddUntilStep("children are visible", () => onlineView.ViewTarget.IsPresent);
|
||||||
AddUntilStep("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent);
|
AddUntilStep("loading animation is not visible", () => !onlineView.LoadingSpinner.IsPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
AddStep("set status to offline", () => ((DummyAPIAccess)API).State = APIState.Offline);
|
AddStep("set status to offline", () => ((DummyAPIAccess)API).State = APIState.Offline);
|
||||||
|
|
||||||
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
||||||
AddUntilStep("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent);
|
AddUntilStep("loading animation is not visible", () => !onlineView.LoadingSpinner.IsPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
AddStep("set status to connecting", () => ((DummyAPIAccess)API).State = APIState.Connecting);
|
AddStep("set status to connecting", () => ((DummyAPIAccess)API).State = APIState.Connecting);
|
||||||
|
|
||||||
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
||||||
AddUntilStep("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent);
|
AddUntilStep("loading animation is visible", () => onlineView.LoadingSpinner.IsPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -62,12 +62,12 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
AddStep("set status to failing", () => ((DummyAPIAccess)API).State = APIState.Failing);
|
AddStep("set status to failing", () => ((DummyAPIAccess)API).State = APIState.Failing);
|
||||||
|
|
||||||
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent);
|
||||||
AddUntilStep("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent);
|
AddUntilStep("loading animation is visible", () => onlineView.LoadingSpinner.IsPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestOnlineViewContainer : OnlineViewContainer
|
private class TestOnlineViewContainer : OnlineViewContainer
|
||||||
{
|
{
|
||||||
public new LoadingAnimation LoadingAnimation => base.LoadingAnimation;
|
public new LoadingSpinner LoadingSpinner => base.LoadingSpinner;
|
||||||
|
|
||||||
public CompositeDrawable ViewTarget => base.Content;
|
public CompositeDrawable ViewTarget => base.Content;
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ using osu.Game.Overlays.Rankings.Tables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
@ -16,6 +15,7 @@ using osu.Game.Rulesets.Mania;
|
|||||||
using osu.Game.Rulesets.Taiko;
|
using osu.Game.Rulesets.Taiko;
|
||||||
using osu.Game.Rulesets.Catch;
|
using osu.Game.Rulesets.Catch;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
|
||||||
|
|
||||||
private readonly BasicScrollContainer scrollFlow;
|
private readonly BasicScrollContainer scrollFlow;
|
||||||
private readonly DimmedLoadingLayer loading;
|
private readonly LoadingLayer loading;
|
||||||
private CancellationTokenSource cancellationToken;
|
private CancellationTokenSource cancellationToken;
|
||||||
private APIRequest request;
|
private APIRequest request;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Width = 0.8f,
|
Width = 0.8f,
|
||||||
},
|
},
|
||||||
loading = new DimmedLoadingLayer(),
|
loading = new LoadingLayer(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,8 @@ using osu.Game.Rulesets.Mania;
|
|||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Rulesets.Taiko;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Rulesets.Taiko;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private readonly Bindable<User> user = new Bindable<User>();
|
private readonly Bindable<User> user = new Bindable<User>();
|
||||||
private GetUserRequest request;
|
private GetUserRequest request;
|
||||||
private readonly DimmedLoadingLayer loading;
|
private readonly LoadingLayer loading;
|
||||||
|
|
||||||
public TestSceneUserRequest()
|
public TestSceneUserRequest()
|
||||||
{
|
{
|
||||||
@ -40,10 +40,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
{
|
{
|
||||||
User = { BindTarget = user }
|
User = { BindTarget = user }
|
||||||
},
|
},
|
||||||
loading = new DimmedLoadingLayer
|
loading = new LoadingLayer()
|
||||||
{
|
|
||||||
Alpha = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -502,6 +502,72 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
AddAssert("Selected beatmap has not changed", () => songSelect.Carousel.SelectedBeatmap.ID == previousID);
|
AddAssert("Selected beatmap has not changed", () => songSelect.Carousel.SelectedBeatmap.ID == previousID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDifficultyIconSelecting()
|
||||||
|
{
|
||||||
|
addRulesetImportStep(0);
|
||||||
|
createSongSelect();
|
||||||
|
|
||||||
|
DrawableCarouselBeatmapSet set = null;
|
||||||
|
AddStep("Find the DrawableCarouselBeatmapSet", () =>
|
||||||
|
{
|
||||||
|
set = songSelect.Carousel.ChildrenOfType<DrawableCarouselBeatmapSet>().First();
|
||||||
|
});
|
||||||
|
|
||||||
|
DrawableCarouselBeatmapSet.FilterableDifficultyIcon difficultyIcon = null;
|
||||||
|
AddStep("Find an icon", () =>
|
||||||
|
{
|
||||||
|
difficultyIcon = set.ChildrenOfType<DrawableCarouselBeatmapSet.FilterableDifficultyIcon>()
|
||||||
|
.First(icon => getDifficultyIconIndex(set, icon) != getCurrentBeatmapIndex());
|
||||||
|
});
|
||||||
|
AddStep("Click on a difficulty", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(difficultyIcon);
|
||||||
|
|
||||||
|
InputManager.PressButton(MouseButton.Left);
|
||||||
|
InputManager.ReleaseButton(MouseButton.Left);
|
||||||
|
});
|
||||||
|
AddAssert("Selected beatmap correct", () => getCurrentBeatmapIndex() == getDifficultyIconIndex(set, difficultyIcon));
|
||||||
|
|
||||||
|
double? maxBPM = null;
|
||||||
|
AddStep("Filter some difficulties", () => songSelect.Carousel.Filter(new FilterCriteria
|
||||||
|
{
|
||||||
|
BPM = new FilterCriteria.OptionalRange<double>
|
||||||
|
{
|
||||||
|
Min = maxBPM = songSelect.Carousel.SelectedBeatmapSet.MaxBPM,
|
||||||
|
IsLowerInclusive = true
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
DrawableCarouselBeatmapSet.FilterableDifficultyIcon filteredIcon = null;
|
||||||
|
AddStep("Get filtered icon", () =>
|
||||||
|
{
|
||||||
|
var filteredBeatmap = songSelect.Carousel.SelectedBeatmapSet.Beatmaps.Find(b => b.BPM < maxBPM);
|
||||||
|
int filteredBeatmapIndex = getBeatmapIndex(filteredBeatmap.BeatmapSet, filteredBeatmap);
|
||||||
|
filteredIcon = set.ChildrenOfType<DrawableCarouselBeatmapSet.FilterableDifficultyIcon>().ElementAt(filteredBeatmapIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
int? previousID = null;
|
||||||
|
AddStep("Store current ID", () => previousID = songSelect.Carousel.SelectedBeatmap.ID);
|
||||||
|
AddStep("Click on a filtered difficulty", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(filteredIcon);
|
||||||
|
|
||||||
|
InputManager.PressButton(MouseButton.Left);
|
||||||
|
InputManager.ReleaseButton(MouseButton.Left);
|
||||||
|
});
|
||||||
|
AddAssert("Selected beatmap has not changed", () => songSelect.Carousel.SelectedBeatmap.ID == previousID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getBeatmapIndex(BeatmapSetInfo set, BeatmapInfo info) => set.Beatmaps.FindIndex(b => b == info);
|
||||||
|
|
||||||
|
private int getCurrentBeatmapIndex() => getBeatmapIndex(songSelect.Carousel.SelectedBeatmapSet, songSelect.Carousel.SelectedBeatmap);
|
||||||
|
|
||||||
|
private int getDifficultyIconIndex(DrawableCarouselBeatmapSet set, DrawableCarouselBeatmapSet.FilterableDifficultyIcon icon)
|
||||||
|
{
|
||||||
|
return set.ChildrenOfType<DrawableCarouselBeatmapSet.FilterableDifficultyIcon>().ToList().FindIndex(i => i == icon);
|
||||||
|
}
|
||||||
|
|
||||||
private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id));
|
private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id));
|
||||||
|
|
||||||
private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())).Wait();
|
private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())).Wait();
|
||||||
|
157
osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs
Normal file
157
osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.Comments;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
|
{
|
||||||
|
public class TestSceneCommentEditor : ManualInputManagerTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(CommentEditor),
|
||||||
|
typeof(CancellableCommentEditor),
|
||||||
|
};
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||||
|
|
||||||
|
private TestCommentEditor commentEditor;
|
||||||
|
private TestCancellableCommentEditor cancellableCommentEditor;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => Schedule(() =>
|
||||||
|
Add(new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Width = 800,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 20),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
commentEditor = new TestCommentEditor(),
|
||||||
|
cancellableCommentEditor = new TestCancellableCommentEditor()
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCommitViaKeyboard()
|
||||||
|
{
|
||||||
|
AddStep("click on text box", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(commentEditor);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
AddStep("enter text", () => commentEditor.Current.Value = "text");
|
||||||
|
|
||||||
|
AddStep("press Enter", () => press(Key.Enter));
|
||||||
|
|
||||||
|
AddAssert("text committed", () => commentEditor.CommittedText == "text");
|
||||||
|
AddAssert("button is loading", () => commentEditor.IsLoading);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCommitViaKeyboardWhenEmpty()
|
||||||
|
{
|
||||||
|
AddStep("click on text box", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(commentEditor);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("press Enter", () => press(Key.Enter));
|
||||||
|
|
||||||
|
AddAssert("no text committed", () => commentEditor.CommittedText == null);
|
||||||
|
AddAssert("button is not loading", () => !commentEditor.IsLoading);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCommitViaButton()
|
||||||
|
{
|
||||||
|
AddStep("click on text box", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(commentEditor);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
AddStep("enter text", () => commentEditor.Current.Value = "some other text");
|
||||||
|
|
||||||
|
AddStep("click submit", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(commentEditor.ButtonsContainer);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("text committed", () => commentEditor.CommittedText == "some other text");
|
||||||
|
AddAssert("button is loading", () => commentEditor.IsLoading);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCancelAction()
|
||||||
|
{
|
||||||
|
AddStep("click cancel button", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(cancellableCommentEditor.ButtonsContainer);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("cancel action fired", () => cancellableCommentEditor.Cancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void press(Key key)
|
||||||
|
{
|
||||||
|
InputManager.PressKey(key);
|
||||||
|
InputManager.ReleaseKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestCommentEditor : CommentEditor
|
||||||
|
{
|
||||||
|
public new Bindable<string> Current => base.Current;
|
||||||
|
public new FillFlowContainer ButtonsContainer => base.ButtonsContainer;
|
||||||
|
|
||||||
|
public string CommittedText { get; private set; }
|
||||||
|
|
||||||
|
public TestCommentEditor()
|
||||||
|
{
|
||||||
|
OnCommit = onCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onCommit(string value)
|
||||||
|
{
|
||||||
|
CommittedText = value;
|
||||||
|
Scheduler.AddDelayed(() => IsLoading = false, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string FooterText => @"Footer text. And it is pretty long. Cool.";
|
||||||
|
protected override string CommitButtonText => @"Commit";
|
||||||
|
protected override string TextBoxPlaceholder => @"This text box is empty";
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestCancellableCommentEditor : CancellableCommentEditor
|
||||||
|
{
|
||||||
|
public new FillFlowContainer ButtonsContainer => base.ButtonsContainer;
|
||||||
|
protected override string FooterText => @"Wow, another one. Sicc";
|
||||||
|
|
||||||
|
public bool Cancelled { get; private set; }
|
||||||
|
|
||||||
|
public TestCancellableCommentEditor()
|
||||||
|
{
|
||||||
|
OnCancel = () => Cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string CommitButtonText => @"Save";
|
||||||
|
protected override string TextBoxPlaceholder => @"Multiline textboxes soon";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
106
osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs
Normal file
106
osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
|
{
|
||||||
|
public class TestSceneLoadingLayer : OsuTestScene
|
||||||
|
{
|
||||||
|
private Drawable dimContent;
|
||||||
|
private LoadingLayer overlay;
|
||||||
|
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(LoadingSpinner) };
|
||||||
|
|
||||||
|
private Container content;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => Schedule(() =>
|
||||||
|
{
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
content = new Container
|
||||||
|
{
|
||||||
|
Size = new Vector2(300),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Colour = Color4.SlateGray,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
dimContent = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(10),
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(0.9f),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText { Text = "Sample content" },
|
||||||
|
new TriangleButton { Text = "can't puush me", Width = 200, },
|
||||||
|
new TriangleButton { Text = "puush me", Width = 200, Action = () => { } },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
overlay = new LoadingLayer(dimContent),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestShowHide()
|
||||||
|
{
|
||||||
|
AddAssert("not visible", () => !overlay.IsPresent);
|
||||||
|
|
||||||
|
AddStep("show", () => overlay.Show());
|
||||||
|
|
||||||
|
AddUntilStep("wait for content dim", () => dimContent.Colour != Color4.White);
|
||||||
|
|
||||||
|
AddStep("hide", () => overlay.Hide());
|
||||||
|
|
||||||
|
AddUntilStep("wait for content restore", () => dimContent.Colour == Color4.White);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestContentRestoreOnDispose()
|
||||||
|
{
|
||||||
|
AddAssert("not visible", () => !overlay.IsPresent);
|
||||||
|
|
||||||
|
AddStep("show", () => overlay.Show());
|
||||||
|
|
||||||
|
AddUntilStep("wait for content dim", () => dimContent.Colour != Color4.White);
|
||||||
|
|
||||||
|
AddStep("expire", () => overlay.Expire());
|
||||||
|
|
||||||
|
AddUntilStep("wait for content restore", () => dimContent.Colour == Color4.White);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestLargeArea()
|
||||||
|
{
|
||||||
|
AddStep("show", () =>
|
||||||
|
{
|
||||||
|
content.RelativeSizeAxes = Axes.Both;
|
||||||
|
content.Size = new Vector2(1);
|
||||||
|
|
||||||
|
overlay.Show();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("hide", () => overlay.Hide());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,12 +8,12 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Tests.Visual.UserInterface
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
{
|
{
|
||||||
public class TestSceneLoadingAnimation : OsuGridTestScene
|
public class TestSceneLoadingSpinner : OsuGridTestScene
|
||||||
{
|
{
|
||||||
public TestSceneLoadingAnimation()
|
public TestSceneLoadingSpinner()
|
||||||
: base(2, 2)
|
: base(2, 2)
|
||||||
{
|
{
|
||||||
LoadingAnimation loading;
|
LoadingSpinner loading;
|
||||||
|
|
||||||
Cell(0).AddRange(new Drawable[]
|
Cell(0).AddRange(new Drawable[]
|
||||||
{
|
{
|
||||||
@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Colour = Color4.Black,
|
Colour = Color4.Black,
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
},
|
},
|
||||||
loading = new LoadingAnimation()
|
loading = new LoadingSpinner()
|
||||||
});
|
});
|
||||||
|
|
||||||
loading.Show();
|
loading.Show();
|
||||||
@ -34,7 +34,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Colour = Color4.White,
|
Colour = Color4.White,
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
},
|
},
|
||||||
loading = new LoadingAnimation()
|
loading = new LoadingSpinner(true)
|
||||||
});
|
});
|
||||||
|
|
||||||
loading.Show();
|
loading.Show();
|
||||||
@ -46,14 +46,14 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Colour = Color4.Gray,
|
Colour = Color4.Gray,
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
},
|
},
|
||||||
loading = new LoadingAnimation()
|
loading = new LoadingSpinner()
|
||||||
});
|
});
|
||||||
|
|
||||||
loading.Show();
|
loading.Show();
|
||||||
|
|
||||||
Cell(3).AddRange(new Drawable[]
|
Cell(3).AddRange(new Drawable[]
|
||||||
{
|
{
|
||||||
loading = new LoadingAnimation()
|
loading = new LoadingSpinner()
|
||||||
});
|
});
|
||||||
|
|
||||||
Scheduler.AddDelayed(() => loading.ToggleVisibility(), 200, true);
|
Scheduler.AddDelayed(() => loading.ToggleVisibility(), 200, true);
|
@ -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,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
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
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user