mirror of
https://github.com/ppy/osu.git
synced 2024-11-15 23:47:25 +08:00
Merge remote-tracking branch 'refs/remotes/ppy/master'
This commit is contained in:
commit
70a295764c
6
NuGet.config
Normal file
6
NuGet.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="opentk-develop" value="https://www.myget.org/F/opentk-develop" />
|
||||
</packageSources>
|
||||
</configuration>
|
@ -1,3 +1,4 @@
|
||||
# 2017-09-14
|
||||
clone_depth: 1
|
||||
version: '{branch}-{build}'
|
||||
configuration: Debug
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5c22092e590d589927962b8d0173dae5f9b1405c
|
||||
Subproject commit 3f4545aae82650dc87cac7dd5df64e6e47918da1
|
@ -1 +1 @@
|
||||
Subproject commit f6042e1cb37cfad6c879d0e1245f7880c7fcd5f5
|
||||
Subproject commit a4418111f8ed2350a6fd46fe69258884f0757745
|
@ -33,7 +33,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-0.17.1.0" newVersion="0.17.1.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-0.18.1.0" newVersion="0.18.1.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
@ -17,8 +17,8 @@ namespace osu.Desktop.Deploy
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
private const string nuget_path = @"packages\NuGet.CommandLine.3.5.0\tools\NuGet.exe";
|
||||
private const string squirrel_path = @"packages\squirrel.windows.1.5.2\tools\Squirrel.exe";
|
||||
private const string nuget_path = @"packages\NuGet.CommandLine.4.3.0\tools\NuGet.exe";
|
||||
private const string squirrel_path = @"packages\squirrel.windows.1.7.8\tools\Squirrel.exe";
|
||||
private const string msbuild_path = @"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe";
|
||||
|
||||
public static string StagingFolder = ConfigurationManager.AppSettings["StagingFolder"];
|
||||
@ -100,7 +100,7 @@ namespace osu.Desktop.Deploy
|
||||
updateAssemblyInfo(version);
|
||||
|
||||
write("Running build process...");
|
||||
runCommand(msbuild_path, $"/v:quiet /m /t:{TargetName.Replace('.', '_')} /p:OutputPath={stagingPath};Configuration=Release {SolutionName}.sln");
|
||||
runCommand(msbuild_path, $"/v:quiet /m /t:{TargetName.Replace('.', '_')} /p:OutputPath={stagingPath};Targets=\"Clean;Build\";Configuration=Release {SolutionName}.sln");
|
||||
|
||||
write("Creating NuGet deployment package...");
|
||||
runCommand(nuget_path, $"pack {NuSpecName} -Version {version} -Properties Configuration=Deploy -OutputDirectory {stagingPath} -BasePath {stagingPath}");
|
||||
|
@ -9,7 +9,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>osu.Desktop.Deploy</RootNamespace>
|
||||
<AssemblyName>osu.Desktop.Deploy</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
@ -66,22 +66,23 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SharpCompress, Version=0.17.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll</HintPath>
|
||||
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SharpCompress, Version=0.18.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Squirrel, Version=1.7.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\Squirrel.dll</HintPath>
|
||||
<Reference Include="Squirrel, Version=1.7.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
|
@ -6,9 +6,9 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
||||
<packages>
|
||||
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net452" />
|
||||
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
|
||||
<package id="NuGet.CommandLine" version="4.1.0" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="SharpCompress" version="0.17.1" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||
<package id="NuGet.CommandLine" version="4.3.0" targetFramework="net461" developmentDependency="true" />
|
||||
<package id="SharpCompress" version="0.18.1" targetFramework="net461" />
|
||||
<package id="Splat" version="2.0.0" targetFramework="net452" />
|
||||
<package id="squirrel.windows" version="1.7.5" targetFramework="net452" />
|
||||
<package id="squirrel.windows" version="1.7.8" targetFramework="net461" />
|
||||
</packages>
|
25
osu.Desktop.Tests/OpenTK.dll.config
Normal file
25
osu.Desktop.Tests/OpenTK.dll.config
Normal file
@ -0,0 +1,25 @@
|
||||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||
</configuration>
|
@ -1,20 +1,17 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Desktop.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public abstract class OsuTestCase : TestCase
|
||||
{
|
||||
[Test]
|
||||
public override void RunTest()
|
||||
{
|
||||
using (var host = new HeadlessGameHost())
|
||||
using (var host = new HeadlessGameHost(realtime: false))
|
||||
host.Run(new OsuTestCaseTestRunner(this));
|
||||
}
|
||||
|
||||
|
@ -12,50 +12,104 @@ namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
public override string Description => "BeatmapDetails tab of BeatmapDetailArea";
|
||||
|
||||
private readonly BeatmapDetails details;
|
||||
|
||||
public TestCaseBeatmapDetails()
|
||||
{
|
||||
BeatmapDetails details;
|
||||
Add(details = new BeatmapDetails
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(150),
|
||||
Beatmap = new BeatmapInfo
|
||||
});
|
||||
|
||||
AddStep("beatmap all metrics", () => details.Beatmap = new BeatmapInfo
|
||||
{
|
||||
Version = "All Metrics",
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Version = "VisualTest",
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Source = "Some guy",
|
||||
Tags = "beatmap metadata example with a very very long list of tags and not much creativity",
|
||||
},
|
||||
Difficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 7,
|
||||
ApproachRate = 3.5f,
|
||||
OverallDifficulty = 5.7f,
|
||||
DrainRate = 1,
|
||||
},
|
||||
StarDifficulty = 5.3f,
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Ratings = Enumerable.Range(0, 10),
|
||||
Fails = Enumerable.Range(lastRange, 100).Select(i => i % 12 - 6),
|
||||
Retries = Enumerable.Range(lastRange - 3, 100).Select(i => i % 12 - 6),
|
||||
},
|
||||
Source = "osu!lazer",
|
||||
Tags = "this beatmap has all the metrics",
|
||||
},
|
||||
Difficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 7,
|
||||
DrainRate = 1,
|
||||
OverallDifficulty = 5.7f,
|
||||
ApproachRate = 3.5f,
|
||||
},
|
||||
StarDifficulty = 5.3f,
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Ratings = Enumerable.Range(0, 10),
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
|
||||
},
|
||||
});
|
||||
|
||||
AddRepeatStep("fail values", newRetryAndFailValues, 10);
|
||||
}
|
||||
AddStep("beatmap ratings", () => details.Beatmap = new BeatmapInfo
|
||||
{
|
||||
Version = "Only Ratings",
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Source = "osu!lazer",
|
||||
Tags = "this beatmap has ratings metrics but not retries or fails",
|
||||
},
|
||||
Difficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 6,
|
||||
DrainRate = 9,
|
||||
OverallDifficulty = 6,
|
||||
ApproachRate = 6,
|
||||
},
|
||||
StarDifficulty = 4.8f,
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Ratings = Enumerable.Range(0, 10),
|
||||
},
|
||||
});
|
||||
|
||||
private int lastRange = 1;
|
||||
AddStep("beatmap fails retries", () => details.Beatmap = new BeatmapInfo
|
||||
{
|
||||
Version = "Only Retries and Fails",
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Source = "osu!lazer",
|
||||
Tags = "this beatmap has retries and fails but no ratings",
|
||||
},
|
||||
Difficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 3.7f,
|
||||
DrainRate = 6,
|
||||
OverallDifficulty = 6,
|
||||
ApproachRate = 7,
|
||||
},
|
||||
StarDifficulty = 2.91f,
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6),
|
||||
},
|
||||
});
|
||||
|
||||
private void newRetryAndFailValues()
|
||||
{
|
||||
details.Beatmap.Metrics.Fails = Enumerable.Range(lastRange, 100).Select(i => i % 12 - 6);
|
||||
details.Beatmap.Metrics.Retries = Enumerable.Range(lastRange - 3, 100).Select(i => i % 12 - 6);
|
||||
details.Beatmap = details.Beatmap;
|
||||
lastRange += 100;
|
||||
AddStep("beatmap no metrics", () => details.Beatmap = new BeatmapInfo
|
||||
{
|
||||
Version = "No Metrics",
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Source = "osu!lazer",
|
||||
Tags = "this beatmap has no metrics",
|
||||
},
|
||||
Difficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 5,
|
||||
DrainRate = 5,
|
||||
OverallDifficulty = 5.5f,
|
||||
ApproachRate = 6.5f,
|
||||
},
|
||||
StarDifficulty = 1.97f,
|
||||
Metrics = new BeatmapMetrics(),
|
||||
});
|
||||
|
||||
AddStep("null beatmap", () => details.Beatmap = null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,28 +69,28 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
private class MyContextMenuContainer : Container, IHasContextMenu
|
||||
{
|
||||
public ContextMenuItem[] ContextMenuItems => new ContextMenuItem[]
|
||||
public MenuItem[] ContextMenuItems => new MenuItem[]
|
||||
{
|
||||
new OsuContextMenuItem(@"Some option"),
|
||||
new OsuContextMenuItem(@"Highlighted option", MenuItemType.Highlighted),
|
||||
new OsuContextMenuItem(@"Another option"),
|
||||
new OsuContextMenuItem(@"Choose me please"),
|
||||
new OsuContextMenuItem(@"And me too"),
|
||||
new OsuContextMenuItem(@"Trying to fill"),
|
||||
new OsuContextMenuItem(@"Destructive option", MenuItemType.Destructive),
|
||||
new OsuMenuItem(@"Some option"),
|
||||
new OsuMenuItem(@"Highlighted option", MenuItemType.Highlighted),
|
||||
new OsuMenuItem(@"Another option"),
|
||||
new OsuMenuItem(@"Choose me please"),
|
||||
new OsuMenuItem(@"And me too"),
|
||||
new OsuMenuItem(@"Trying to fill"),
|
||||
new OsuMenuItem(@"Destructive option", MenuItemType.Destructive),
|
||||
};
|
||||
}
|
||||
|
||||
private class AnotherContextMenuContainer : Container, IHasContextMenu
|
||||
{
|
||||
public ContextMenuItem[] ContextMenuItems => new ContextMenuItem[]
|
||||
public MenuItem[] ContextMenuItems => new MenuItem[]
|
||||
{
|
||||
new OsuContextMenuItem(@"Simple option"),
|
||||
new OsuContextMenuItem(@"Simple very very long option"),
|
||||
new OsuContextMenuItem(@"Change width", MenuItemType.Highlighted) { Action = () => this.ResizeWidthTo(Width * 2, 100, Easing.OutQuint) },
|
||||
new OsuContextMenuItem(@"Change height", MenuItemType.Highlighted) { Action = () => this.ResizeHeightTo(Height * 2, 100, Easing.OutQuint) },
|
||||
new OsuContextMenuItem(@"Change width back", MenuItemType.Destructive) { Action = () => this.ResizeWidthTo(Width / 2, 100, Easing.OutQuint) },
|
||||
new OsuContextMenuItem(@"Change height back", MenuItemType.Destructive) { Action = () => this.ResizeHeightTo(Height / 2, 100, Easing.OutQuint) },
|
||||
new OsuMenuItem(@"Simple option"),
|
||||
new OsuMenuItem(@"Simple very very long option"),
|
||||
new OsuMenuItem(@"Change width", MenuItemType.Highlighted, () => this.ResizeWidthTo(Width * 2, 100, Easing.OutQuint)),
|
||||
new OsuMenuItem(@"Change height", MenuItemType.Highlighted, () => this.ResizeHeightTo(Height * 2, 100, Easing.OutQuint)),
|
||||
new OsuMenuItem(@"Change width back", MenuItemType.Destructive, () => this.ResizeWidthTo(Width / 2, 100, Easing.OutQuint)),
|
||||
new OsuMenuItem(@"Change height back", MenuItemType.Destructive, () => this.ResizeHeightTo(Height / 2, 100, Easing.OutQuint)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -41,12 +41,14 @@ namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 578332,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"OrVid",
|
||||
Artist = @"An",
|
||||
Author = @"RLC",
|
||||
Source = @"",
|
||||
Tags = @"acuticnotes an-fillnote revid tear tearvid encrpted encryption axi axivid quad her hervid recoll",
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
@ -71,12 +73,14 @@ namespace osu.Desktop.Tests.Visual
|
||||
},
|
||||
new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 599627,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"tiny lamp",
|
||||
Artist = @"fhana",
|
||||
Author = @"Sotarks",
|
||||
Source = @"ぎんぎつね",
|
||||
Tags = @"lantis junichi sato yuxuki waga kevin mitsunaga towana gingitsune opening op full ver version kalibe collab collaboration",
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
@ -101,12 +105,14 @@ namespace osu.Desktop.Tests.Visual
|
||||
},
|
||||
new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 513268,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"At Gwanghwamun",
|
||||
Artist = @"KYUHYUN",
|
||||
Author = @"Cerulean Veyron",
|
||||
Source = @"",
|
||||
Tags = @"soul ballad kh super junior sj suju 슈퍼주니어 kt뮤직 sm엔터테인먼트 s.m.entertainment kt music 1st mini album ep",
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
@ -146,12 +152,14 @@ namespace osu.Desktop.Tests.Visual
|
||||
},
|
||||
new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 586841,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"RHAPSODY OF BLUE SKY",
|
||||
Artist = @"fhana",
|
||||
Author = @"[Kamiya]",
|
||||
Source = @"小林さんちのメイドラゴン",
|
||||
Tags = @"kobayashi san chi no maidragon aozora no opening anime maid dragon oblivion karen dynamix imoutosan pata-mon gxytcgxytc",
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
|
84
osu.Desktop.Tests/Visual/TestCaseEditorMenuBar.cs
Normal file
84
osu.Desktop.Tests/Visual/TestCaseEditorMenuBar.cs
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Edit.Menus;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
public class TestCaseEditorMenuBar : OsuTestCase
|
||||
{
|
||||
public TestCaseEditorMenuBar()
|
||||
{
|
||||
Add(new EditorMenuBar
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Y = 50,
|
||||
Items = new[]
|
||||
{
|
||||
new EditorMenuBarItem("File")
|
||||
{
|
||||
Items = new[]
|
||||
{
|
||||
new EditorMenuItem("Clear All Notes"),
|
||||
new EditorMenuItem("Open Difficulty..."),
|
||||
new EditorMenuItem("Save"),
|
||||
new EditorMenuItem("Create a new Difficulty..."),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Revert to Saved"),
|
||||
new EditorMenuItem("Revert to Saved (Full)"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Test Beatmap"),
|
||||
new EditorMenuItem("Open AiMod"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Upload Beatmap..."),
|
||||
new EditorMenuItem("Export Package"),
|
||||
new EditorMenuItem("Export Map Package"),
|
||||
new EditorMenuItem("Import from..."),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Open Song Folder"),
|
||||
new EditorMenuItem("Open .osu in Notepad"),
|
||||
new EditorMenuItem("Open .osb in Notepad"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Exit"),
|
||||
}
|
||||
},
|
||||
new EditorMenuBarItem("Timing")
|
||||
{
|
||||
Items = new[]
|
||||
{
|
||||
new EditorMenuItem("Time Signature"),
|
||||
new EditorMenuItem("Metronome Clicks"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Add Timing Section"),
|
||||
new EditorMenuItem("Add Inheriting Section"),
|
||||
new EditorMenuItem("Reset Current Section"),
|
||||
new EditorMenuItem("Delete Timing Section"),
|
||||
new EditorMenuItem("Resnap Current Section"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Timing Setup"),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Resnap All Notes", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Move all notes in time...", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Recalculate Slider Lengths", MenuItemType.Destructive),
|
||||
new EditorMenuItem("Delete All Timing Sections", MenuItemType.Destructive),
|
||||
new EditorMenuItemSpacer(),
|
||||
new EditorMenuItem("Set Current Position as Preview Point"),
|
||||
}
|
||||
},
|
||||
new EditorMenuBarItem("Testing")
|
||||
{
|
||||
Items = new[]
|
||||
{
|
||||
new EditorMenuItem("Item 1"),
|
||||
new EditorMenuItem("Item 2"),
|
||||
new EditorMenuItem("Item 3"),
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using OpenTK;
|
||||
@ -110,10 +109,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
h.Depth = depth++;
|
||||
|
||||
if (auto)
|
||||
{
|
||||
h.State = ArmedState.Hit;
|
||||
h.Judgement = new OsuJudgement { Result = HitResult.Hit };
|
||||
}
|
||||
|
||||
playfieldContainer.Add(h);
|
||||
var proxyable = h as IDrawableHitObjectWithProxiedApproach;
|
||||
|
@ -2,12 +2,8 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Screens.Play;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
@ -41,38 +37,5 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
Add(kc);
|
||||
}
|
||||
private class TestSliderBar<T> : SliderBar<T> where T : struct
|
||||
{
|
||||
public Color4 Color
|
||||
{
|
||||
get { return Box.Colour; }
|
||||
set { Box.Colour = value; }
|
||||
}
|
||||
|
||||
public Color4 SelectionColor
|
||||
{
|
||||
get { return SelectionBox.Colour; }
|
||||
set { SelectionBox.Colour = value; }
|
||||
}
|
||||
|
||||
protected readonly Box SelectionBox;
|
||||
protected readonly Box Box;
|
||||
|
||||
public TestSliderBar()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Box = new Box { RelativeSizeAxes = Axes.Both },
|
||||
SelectionBox = new Box { RelativeSizeAxes = Axes.Both }
|
||||
};
|
||||
}
|
||||
|
||||
protected override void UpdateValue(float value)
|
||||
{
|
||||
SelectionBox.ScaleTo(
|
||||
new Vector2(value, 1),
|
||||
300, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Users;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
@ -24,7 +24,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.XH,
|
||||
Accuracy = 100,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -42,7 +42,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.X,
|
||||
Accuracy = 100,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -60,7 +60,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.SH,
|
||||
Accuracy = 100,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -78,7 +78,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.S,
|
||||
Accuracy = 100,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -96,7 +96,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.A,
|
||||
Accuracy = 100,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -114,7 +114,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.B,
|
||||
Accuracy = 98.26,
|
||||
Accuracy = 0.9826,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -132,7 +132,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.C,
|
||||
Accuracy = 96.54,
|
||||
Accuracy = 0.9654,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -150,7 +150,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.F,
|
||||
Accuracy = 60.25,
|
||||
Accuracy = 0.6025,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -168,7 +168,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.F,
|
||||
Accuracy = 51.40,
|
||||
Accuracy = 0.5140,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
@ -186,7 +186,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
new Score
|
||||
{
|
||||
Rank = ScoreRank.F,
|
||||
Accuracy = 42.22,
|
||||
Accuracy = 0.4222,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using OpenTK;
|
||||
@ -40,8 +41,20 @@ namespace osu.Desktop.Tests.Visual
|
||||
RelativeChildSize = new Vector2(1, 10000),
|
||||
Children = new[]
|
||||
{
|
||||
new DrawableNote(new Note { StartTime = 5000 }) { AccentColour = Color4.Red },
|
||||
new DrawableNote(new Note { StartTime = 6000 }) { AccentColour = Color4.Red }
|
||||
new DrawableNote(new Note(), ManiaAction.Key1)
|
||||
{
|
||||
Y = 5000,
|
||||
LifetimeStart = double.MinValue,
|
||||
LifetimeEnd = double.MaxValue,
|
||||
AccentColour = Color4.Red
|
||||
},
|
||||
new DrawableNote(new Note(), ManiaAction.Key1)
|
||||
{
|
||||
Y = 6000,
|
||||
LifetimeStart = double.MinValue,
|
||||
LifetimeEnd = double.MaxValue,
|
||||
AccentColour = Color4.Red
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,11 +75,14 @@ namespace osu.Desktop.Tests.Visual
|
||||
RelativeChildSize = new Vector2(1, 10000),
|
||||
Children = new[]
|
||||
{
|
||||
new DrawableHoldNote(new HoldNote
|
||||
new DrawableHoldNote(new HoldNote(), ManiaAction.Key1)
|
||||
{
|
||||
StartTime = 5000,
|
||||
Duration = 1000
|
||||
}) { AccentColour = Color4.Red }
|
||||
Y = 5000,
|
||||
Height = 1000,
|
||||
LifetimeStart = double.MinValue,
|
||||
LifetimeEnd = double.MaxValue,
|
||||
AccentColour = Color4.Red
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,108 +3,36 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Timing;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Timing;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
internal class TestCaseManiaPlayfield : OsuTestCase
|
||||
{
|
||||
private const double start_time = 500;
|
||||
private const double duration = 500;
|
||||
|
||||
public override string Description => @"Mania playfield";
|
||||
|
||||
protected override double TimePerAction => 200;
|
||||
|
||||
private RulesetInfo maniaRuleset;
|
||||
|
||||
public TestCaseManiaPlayfield()
|
||||
{
|
||||
Action<int, SpecialColumnPosition> createPlayfield = (cols, pos) =>
|
||||
{
|
||||
Clear();
|
||||
Add(new ManiaPlayfield(cols)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
SpecialColumnPosition = pos,
|
||||
Scale = new Vector2(1, -1)
|
||||
});
|
||||
};
|
||||
|
||||
const double start_time = 500;
|
||||
const double duration = 500;
|
||||
|
||||
Func<double, bool, SpeedAdjustmentContainer> createTimingChange = (time, gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time)
|
||||
{
|
||||
TimingPoint = { BeatLength = 1000 }
|
||||
}, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic);
|
||||
|
||||
Action<bool> createPlayfieldWithNotes = gravity =>
|
||||
{
|
||||
Clear();
|
||||
|
||||
var rateAdjustClock = new StopwatchClock(true) { Rate = 1 };
|
||||
|
||||
ManiaPlayfield playField;
|
||||
Add(playField = new ManiaPlayfield(4)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Scale = new Vector2(1, -1),
|
||||
Clock = new FramedClock(rateAdjustClock)
|
||||
});
|
||||
|
||||
if (!gravity)
|
||||
playField.Columns.ForEach(c => c.Add(createTimingChange(0, false)));
|
||||
|
||||
for (double t = start_time; t <= start_time + duration; t += 100)
|
||||
{
|
||||
if (gravity)
|
||||
playField.Columns.ElementAt(0).Add(createTimingChange(t, true));
|
||||
|
||||
playField.Add(new DrawableNote(new Note
|
||||
{
|
||||
StartTime = t,
|
||||
Column = 0
|
||||
}, new Bindable<Key>(Key.D)));
|
||||
|
||||
if (gravity)
|
||||
playField.Columns.ElementAt(3).Add(createTimingChange(t, true));
|
||||
|
||||
playField.Add(new DrawableNote(new Note
|
||||
{
|
||||
StartTime = t,
|
||||
Column = 3
|
||||
}, new Bindable<Key>(Key.K)));
|
||||
}
|
||||
|
||||
if (gravity)
|
||||
playField.Columns.ElementAt(1).Add(createTimingChange(start_time, true));
|
||||
|
||||
playField.Add(new DrawableHoldNote(new HoldNote
|
||||
{
|
||||
StartTime = start_time,
|
||||
Duration = duration,
|
||||
Column = 1
|
||||
}, new Bindable<Key>(Key.F)));
|
||||
|
||||
if (gravity)
|
||||
playField.Columns.ElementAt(2).Add(createTimingChange(start_time, true));
|
||||
|
||||
playField.Add(new DrawableHoldNote(new HoldNote
|
||||
{
|
||||
StartTime = start_time,
|
||||
Duration = duration,
|
||||
Column = 2
|
||||
}, new Bindable<Key>(Key.J)));
|
||||
};
|
||||
var rng = new Random(1337);
|
||||
|
||||
AddStep("1 column", () => createPlayfield(1, SpecialColumnPosition.Normal));
|
||||
AddStep("4 columns", () => createPlayfield(4, SpecialColumnPosition.Normal));
|
||||
@ -114,29 +42,121 @@ namespace osu.Desktop.Tests.Visual
|
||||
AddStep("8 columns", () => createPlayfield(8, SpecialColumnPosition.Normal));
|
||||
AddStep("Left special style", () => createPlayfield(8, SpecialColumnPosition.Left));
|
||||
AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right));
|
||||
AddStep("Reversed", () => createPlayfield(4, SpecialColumnPosition.Normal, true));
|
||||
|
||||
AddStep("Notes with input", () => createPlayfieldWithNotes(false));
|
||||
AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction));
|
||||
|
||||
AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(false, true));
|
||||
AddStep("Notes with gravity", () => createPlayfieldWithNotes(true));
|
||||
AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction));
|
||||
}
|
||||
AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true, true));
|
||||
|
||||
private void triggerKeyDown(Column column)
|
||||
{
|
||||
column.TriggerOnKeyDown(new InputState(), new KeyDownEventArgs
|
||||
AddStep("Hit explosion", () =>
|
||||
{
|
||||
Key = column.Key,
|
||||
Repeat = false
|
||||
var playfield = createPlayfield(4, SpecialColumnPosition.Normal);
|
||||
|
||||
int col = rng.Next(0, 4);
|
||||
|
||||
var note = new DrawableNote(new Note { Column = col }, ManiaAction.Key1)
|
||||
{
|
||||
AccentColour = playfield.Columns.ElementAt(col).AccentColour
|
||||
};
|
||||
|
||||
playfield.OnJudgement(note, new ManiaJudgement { Result = HitResult.Perfect });
|
||||
});
|
||||
}
|
||||
|
||||
private void triggerKeyUp(Column column)
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
column.TriggerOnKeyUp(new InputState(), new KeyUpEventArgs
|
||||
maniaRuleset = rulesets.GetRuleset(3);
|
||||
}
|
||||
|
||||
private SpeedAdjustmentContainer createTimingChange(double time, bool gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time)
|
||||
{
|
||||
TimingPoint = { BeatLength = 1000 }
|
||||
}, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic);
|
||||
|
||||
private ManiaPlayfield createPlayfield(int cols, SpecialColumnPosition specialPos, bool inverted = false)
|
||||
{
|
||||
Clear();
|
||||
|
||||
var inputManager = new ManiaInputManager(maniaRuleset, cols) { RelativeSizeAxes = Axes.Both };
|
||||
Add(inputManager);
|
||||
|
||||
ManiaPlayfield playfield;
|
||||
inputManager.Add(playfield = new ManiaPlayfield(cols)
|
||||
{
|
||||
Key = column.Key
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
SpecialColumnPosition = specialPos
|
||||
});
|
||||
|
||||
playfield.Inverted.Value = inverted;
|
||||
|
||||
return playfield;
|
||||
}
|
||||
|
||||
private void createPlayfieldWithNotes(bool gravity, bool inverted = false)
|
||||
{
|
||||
Clear();
|
||||
|
||||
var rateAdjustClock = new StopwatchClock(true) { Rate = 1 };
|
||||
|
||||
var inputManager = new ManiaInputManager(maniaRuleset, 4) { RelativeSizeAxes = Axes.Both };
|
||||
Add(inputManager);
|
||||
|
||||
ManiaPlayfield playfield;
|
||||
inputManager.Add(playfield = new ManiaPlayfield(4)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Clock = new FramedClock(rateAdjustClock)
|
||||
});
|
||||
|
||||
playfield.Inverted.Value = inverted;
|
||||
|
||||
if (!gravity)
|
||||
playfield.Columns.ForEach(c => c.Add(createTimingChange(0, false)));
|
||||
|
||||
for (double t = start_time; t <= start_time + duration; t += 100)
|
||||
{
|
||||
if (gravity)
|
||||
playfield.Columns.ElementAt(0).Add(createTimingChange(t, true));
|
||||
|
||||
playfield.Add(new DrawableNote(new Note
|
||||
{
|
||||
StartTime = t,
|
||||
Column = 0
|
||||
}, ManiaAction.Key1));
|
||||
|
||||
if (gravity)
|
||||
playfield.Columns.ElementAt(3).Add(createTimingChange(t, true));
|
||||
|
||||
playfield.Add(new DrawableNote(new Note
|
||||
{
|
||||
StartTime = t,
|
||||
Column = 3
|
||||
}, ManiaAction.Key4));
|
||||
}
|
||||
|
||||
if (gravity)
|
||||
playfield.Columns.ElementAt(1).Add(createTimingChange(start_time, true));
|
||||
|
||||
playfield.Add(new DrawableHoldNote(new HoldNote
|
||||
{
|
||||
StartTime = start_time,
|
||||
Duration = duration,
|
||||
Column = 1
|
||||
}, ManiaAction.Key2));
|
||||
|
||||
if (gravity)
|
||||
playfield.Columns.ElementAt(2).Add(createTimingChange(start_time, true));
|
||||
|
||||
playfield.Add(new DrawableHoldNote(new HoldNote
|
||||
{
|
||||
StartTime = start_time,
|
||||
Duration = duration,
|
||||
Column = 2
|
||||
}, ManiaAction.Key3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
backingDatabase.CreateTable<StoreVersion>();
|
||||
|
||||
rulesets = new RulesetStore(backingDatabase);
|
||||
manager = new BeatmapManager(storage, null, backingDatabase, rulesets);
|
||||
manager = new BeatmapManager(storage, null, backingDatabase, rulesets, null);
|
||||
|
||||
for (int i = 0; i < 100; i += 10)
|
||||
manager.Import(createTestBeatmapSet(i));
|
||||
|
@ -1,18 +1,18 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Desktop.Tests.Beatmaps;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
@ -33,55 +33,739 @@ namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
var objects = new List<HitObject>();
|
||||
|
||||
int time = 1500;
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
objects.Add(new HitCircle
|
||||
{
|
||||
StartTime = time,
|
||||
Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : OsuPlayfield.BASE_SIZE.X,
|
||||
i % 4 < 2 ? 0 : OsuPlayfield.BASE_SIZE.Y),
|
||||
NewCombo = i % 4 == 0
|
||||
});
|
||||
|
||||
time += 500;
|
||||
}
|
||||
|
||||
Beatmap b = new Beatmap
|
||||
{
|
||||
HitObjects = objects,
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
Difficulty = new BeatmapDifficulty(),
|
||||
Ruleset = rulesets.Query<RulesetInfo>().First(),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Artist = @"Unknown",
|
||||
Title = @"Sample Beatmap",
|
||||
Author = @"peppy",
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
WorkingBeatmap beatmap = new TestWorkingBeatmap(b);
|
||||
|
||||
Add(new Box
|
||||
{
|
||||
RelativeSizeAxes = Framework.Graphics.Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
});
|
||||
|
||||
Add(Player = CreatePlayer(beatmap));
|
||||
foreach (var r in rulesets.Query<RulesetInfo>())
|
||||
AddStep(r.Name, () => loadPlayerFor(r));
|
||||
|
||||
loadPlayerFor(rulesets.Query<RulesetInfo>().First());
|
||||
}
|
||||
|
||||
protected virtual Player CreatePlayer(WorkingBeatmap beatmap)
|
||||
private void loadPlayerFor(RulesetInfo r)
|
||||
{
|
||||
Beatmap beatmap;
|
||||
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data)))
|
||||
using (var reader = new StreamReader(stream))
|
||||
beatmap = BeatmapDecoder.GetDecoder(reader).Decode(reader);
|
||||
|
||||
beatmap.BeatmapInfo.Ruleset = r;
|
||||
|
||||
var instance = r.CreateInstance();
|
||||
|
||||
WorkingBeatmap working = new TestWorkingBeatmap(beatmap);
|
||||
working.Mods.Value = new[] { instance.GetAllMods().First(m => m is ModNoFail) };
|
||||
|
||||
if (Player != null)
|
||||
Remove(Player);
|
||||
|
||||
Add(Player = CreatePlayer(working, instance));
|
||||
}
|
||||
|
||||
protected virtual Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset)
|
||||
{
|
||||
return new Player
|
||||
{
|
||||
InitialBeatmap = beatmap
|
||||
};
|
||||
}
|
||||
|
||||
private const string test_beatmap_data =
|
||||
@"osu file format v14
|
||||
|
||||
[General]
|
||||
AudioLeadIn: 500
|
||||
PreviewTime: 53498
|
||||
Countdown: 0
|
||||
SampleSet: Soft
|
||||
StackLeniency: 0.7
|
||||
Mode: 0
|
||||
LetterboxInBreaks: 0
|
||||
WidescreenStoryboard: 1
|
||||
|
||||
[Editor]
|
||||
DistanceSpacing: 1.2
|
||||
BeatDivisor: 4
|
||||
GridSize: 4
|
||||
TimelineZoom: 1
|
||||
|
||||
[Metadata]
|
||||
Title:My Love
|
||||
TitleUnicode:My Love
|
||||
Artist:Kuba Oms
|
||||
ArtistUnicode:Kuba Oms
|
||||
Creator:W h i t e
|
||||
Version:Hard
|
||||
Source:ADHD
|
||||
Tags:Monthly Beatmapping Contest Electronic folk pop w_h_i_t_e
|
||||
BeatmapID:397534
|
||||
BeatmapSetID:163112
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:5
|
||||
CircleSize:4
|
||||
OverallDifficulty:6
|
||||
ApproachRate:7
|
||||
SliderMultiplier:1.44
|
||||
SliderTickRate:2
|
||||
|
||||
[Events]
|
||||
//Break Periods
|
||||
2,69870,83770
|
||||
2,152170,158770
|
||||
//Storyboard Layer 0 (Background)
|
||||
//Storyboard Layer 1 (Fail)
|
||||
//Storyboard Layer 2 (Pass)
|
||||
//Storyboard Layer 3 (Foreground)
|
||||
//Storyboard Sound Samples
|
||||
|
||||
[TimingPoints]
|
||||
2170,468.75,4,2,0,40,1,0
|
||||
4045,-100,4,2,0,30,0,0
|
||||
4162,-100,4,2,0,40,0,0
|
||||
5920,-100,4,2,0,30,0,0
|
||||
6037,-100,4,2,0,40,0,0
|
||||
7795,-100,4,2,0,30,0,0
|
||||
7912,-100,4,2,0,40,0,0
|
||||
9670,-100,4,2,0,40,0,0
|
||||
9787,-100,4,2,0,50,0,0
|
||||
11545,-100,4,2,0,40,0,0
|
||||
11662,-100,4,2,0,50,0,0
|
||||
13420,-100,4,2,0,40,0,0
|
||||
13537,-100,4,2,0,50,0,0
|
||||
15295,-100,4,2,0,40,0,0
|
||||
15412,-100,4,2,0,50,0,0
|
||||
17170,-100,4,2,0,40,0,0
|
||||
17287,-100,4,2,0,50,0,0
|
||||
19045,-100,4,2,0,40,0,0
|
||||
19162,-100,4,2,0,50,0,0
|
||||
20920,-100,4,2,0,40,0,0
|
||||
21037,-100,4,2,0,50,0,0
|
||||
22795,-100,4,2,0,40,0,0
|
||||
22912,-100,4,2,0,50,0,0
|
||||
24670,-100,4,2,0,70,0,0
|
||||
37560,-200,4,2,0,30,0,0
|
||||
38263,-200,4,2,0,5,0,0
|
||||
38966,-100,4,2,0,30,0,0
|
||||
39670,-100,4,2,0,70,0,0
|
||||
53732,-100,4,2,0,40,0,0
|
||||
54670,-100,4,2,0,80,0,1
|
||||
55138,-100,4,2,0,60,0,1
|
||||
55255,-100,4,2,0,80,0,1
|
||||
56076,-100,4,2,0,60,0,1
|
||||
56193,-100,4,2,0,80,0,1
|
||||
57013,-100,4,2,0,60,0,1
|
||||
57130,-100,4,2,0,80,0,1
|
||||
57951,-100,4,2,0,60,0,1
|
||||
58068,-100,4,2,0,80,0,1
|
||||
58888,-100,4,2,0,60,0,1
|
||||
59005,-100,4,2,0,80,0,1
|
||||
59826,-100,4,2,0,60,0,1
|
||||
59943,-100,4,2,0,80,0,1
|
||||
60763,-100,4,2,0,60,0,1
|
||||
60880,-100,4,2,0,80,0,1
|
||||
61701,-100,4,2,0,60,0,1
|
||||
61818,-100,4,2,0,80,0,1
|
||||
62638,-100,4,2,0,60,0,1
|
||||
62755,-100,4,2,0,80,0,1
|
||||
63576,-100,4,2,0,60,0,1
|
||||
63693,-100,4,2,0,80,0,1
|
||||
64513,-100,4,2,0,60,0,1
|
||||
64630,-100,4,2,0,80,0,1
|
||||
65451,-100,4,2,0,60,0,1
|
||||
65568,-100,4,2,0,80,0,1
|
||||
66388,-100,4,2,0,60,0,1
|
||||
66505,-100,4,2,0,80,0,1
|
||||
67326,-100,4,2,0,60,0,1
|
||||
67443,-100,4,2,0,80,0,1
|
||||
68263,-100,4,2,0,60,0,1
|
||||
68380,-100,4,2,0,80,0,1
|
||||
69201,-100,4,2,0,60,0,1
|
||||
69318,-100,4,2,0,80,0,1
|
||||
69670,-100,4,2,0,70,0,0
|
||||
84670,-100,4,2,0,70,0,0
|
||||
97560,-200,4,2,0,70,0,0
|
||||
97795,-200,4,2,0,30,0,0
|
||||
98966,-100,4,2,0,30,0,0
|
||||
99670,-100,4,2,0,70,0,0
|
||||
113732,-100,4,2,0,40,0,0
|
||||
114670,-100,4,2,0,80,0,1
|
||||
115138,-100,4,2,0,60,0,1
|
||||
115255,-100,4,2,0,80,0,1
|
||||
116076,-100,4,2,0,60,0,1
|
||||
116193,-100,4,2,0,80,0,1
|
||||
117013,-100,4,2,0,60,0,1
|
||||
117130,-100,4,2,0,80,0,1
|
||||
117951,-100,4,2,0,60,0,1
|
||||
118068,-100,4,2,0,80,0,1
|
||||
118888,-100,4,2,0,60,0,1
|
||||
119005,-100,4,2,0,80,0,1
|
||||
119826,-100,4,2,0,60,0,1
|
||||
119943,-100,4,2,0,80,0,1
|
||||
120763,-100,4,2,0,60,0,1
|
||||
120880,-100,4,2,0,80,0,1
|
||||
121701,-100,4,2,0,60,0,1
|
||||
121818,-100,4,2,0,80,0,1
|
||||
122638,-100,4,2,0,60,0,1
|
||||
122755,-100,4,2,0,80,0,1
|
||||
123576,-100,4,2,0,60,0,1
|
||||
123693,-100,4,2,0,80,0,1
|
||||
124513,-100,4,2,0,60,0,1
|
||||
124630,-100,4,2,0,80,0,1
|
||||
125451,-100,4,2,0,60,0,1
|
||||
125568,-100,4,2,0,80,0,1
|
||||
126388,-100,4,2,0,60,0,1
|
||||
126505,-100,4,2,0,80,0,1
|
||||
127326,-100,4,2,0,60,0,1
|
||||
127443,-100,4,2,0,80,0,1
|
||||
128263,-100,4,2,0,60,0,1
|
||||
128380,-100,4,2,0,80,0,1
|
||||
129201,-100,4,2,0,60,0,1
|
||||
129318,-100,4,2,0,80,0,1
|
||||
129670,-200,4,2,0,40,0,0
|
||||
144670,-133.333333333333,4,2,0,40,0,0
|
||||
159670,-133.333333333333,4,2,0,40,0,0
|
||||
163420,-133.333333333333,4,2,0,45,0,0
|
||||
163888,-125,4,2,0,50,0,0
|
||||
164357,-117.647058823529,4,2,0,55,0,0
|
||||
164826,-111.111111111111,4,2,0,60,0,0
|
||||
165295,-105.263157894737,4,2,0,65,0,0
|
||||
165763,-100,4,2,0,70,0,0
|
||||
166232,-100,4,2,0,40,0,0
|
||||
167170,-100,4,2,0,80,0,1
|
||||
167638,-100,4,2,0,60,0,1
|
||||
167755,-100,4,2,0,80,0,1
|
||||
168576,-100,4,2,0,60,0,1
|
||||
168693,-100,4,2,0,80,0,1
|
||||
169513,-100,4,2,0,60,0,1
|
||||
169630,-100,4,2,0,80,0,1
|
||||
170451,-100,4,2,0,60,0,1
|
||||
170568,-100,4,2,0,80,0,1
|
||||
171388,-100,4,2,0,60,0,1
|
||||
171505,-100,4,2,0,80,0,1
|
||||
172326,-100,4,2,0,60,0,1
|
||||
172443,-100,4,2,0,80,0,1
|
||||
173263,-100,4,2,0,60,0,1
|
||||
173380,-100,4,2,0,80,0,1
|
||||
174201,-100,4,2,0,60,0,1
|
||||
174318,-100,4,2,0,80,0,1
|
||||
175138,-100,4,2,0,60,0,1
|
||||
175255,-100,4,2,0,80,0,1
|
||||
176076,-100,4,2,0,60,0,1
|
||||
176193,-100,4,2,0,80,0,1
|
||||
177013,-100,4,2,0,60,0,1
|
||||
177130,-100,4,2,0,80,0,1
|
||||
177951,-100,4,2,0,60,0,1
|
||||
178068,-100,4,2,0,80,0,1
|
||||
178888,-100,4,2,0,60,0,1
|
||||
179005,-100,4,2,0,80,0,1
|
||||
179826,-100,4,2,0,60,0,1
|
||||
179943,-100,4,2,0,80,0,1
|
||||
180763,-100,4,2,0,60,0,1
|
||||
180880,-100,4,2,0,80,0,1
|
||||
180998,-100,4,2,0,80,0,0
|
||||
181466,-100,4,2,0,60,0,0
|
||||
181584,-100,4,2,0,80,0,0
|
||||
181935,-100,4,2,0,80,0,0
|
||||
182170,-100,4,2,0,80,0,1
|
||||
182638,-100,4,2,0,60,0,1
|
||||
182755,-100,4,2,0,80,0,1
|
||||
183576,-100,4,2,0,60,0,1
|
||||
183693,-100,4,2,0,80,0,1
|
||||
184513,-100,4,2,0,60,0,1
|
||||
184630,-100,4,2,0,80,0,1
|
||||
185451,-100,4,2,0,60,0,1
|
||||
185568,-100,4,2,0,80,0,1
|
||||
186388,-100,4,2,0,60,0,1
|
||||
186505,-100,4,2,0,80,0,1
|
||||
187326,-100,4,2,0,60,0,1
|
||||
187443,-100,4,2,0,80,0,1
|
||||
188263,-100,4,2,0,60,0,1
|
||||
188380,-100,4,2,0,80,0,1
|
||||
189201,-100,4,2,0,60,0,1
|
||||
189318,-100,4,2,0,80,0,1
|
||||
190138,-100,4,2,0,60,0,1
|
||||
190255,-100,4,2,0,80,0,1
|
||||
191076,-100,4,2,0,60,0,1
|
||||
191193,-100,4,2,0,80,0,1
|
||||
192013,-100,4,2,0,60,0,1
|
||||
192130,-100,4,2,0,80,0,1
|
||||
192951,-100,4,2,0,60,0,1
|
||||
193068,-100,4,2,0,80,0,1
|
||||
193888,-100,4,2,0,60,0,1
|
||||
194005,-100,4,2,0,80,0,1
|
||||
194826,-100,4,2,0,60,0,1
|
||||
194943,-100,4,2,0,80,0,1
|
||||
195295,-100,4,2,0,50,0,1
|
||||
195529,-100,4,2,0,52,0,1
|
||||
195646,-100,4,2,0,54,0,1
|
||||
195763,-100,4,2,0,56,0,1
|
||||
195880,-100,4,2,0,58,0,1
|
||||
195998,-100,4,2,0,60,0,1
|
||||
196115,-100,4,2,0,62,0,1
|
||||
196232,-100,4,2,0,64,0,1
|
||||
196349,-100,4,2,0,68,0,1
|
||||
196466,-100,4,2,0,70,0,1
|
||||
196584,-100,4,2,0,72,0,1
|
||||
196701,-100,4,2,0,74,0,1
|
||||
196818,-100,4,2,0,76,0,1
|
||||
196935,-100,4,2,0,78,0,1
|
||||
197052,-100,4,2,0,80,0,1
|
||||
197170,-100,4,2,0,80,0,0
|
||||
197873,-100,4,2,0,60,0,0
|
||||
197990,-100,4,2,0,80,0,0
|
||||
198341,-100,4,2,0,60,0,0
|
||||
199045,-100,4,2,0,80,0,0
|
||||
199279,-100,4,2,0,60,0,0
|
||||
199630,-100,4,2,0,80,0,0
|
||||
200216,-100,4,2,0,60,0,0
|
||||
200334,-100,4,2,0,80,0,0
|
||||
201623,-100,4,2,0,60,0,0
|
||||
201740,-100,4,2,0,80,0,0
|
||||
202326,-100,4,2,0,60,0,0
|
||||
202443,-100,4,2,0,80,0,0
|
||||
203029,-100,4,2,0,60,0,0
|
||||
203498,-100,4,2,0,80,0,0
|
||||
203966,-100,4,2,0,60,0,0
|
||||
204201,-100,4,2,0,80,0,0
|
||||
205373,-100,4,2,0,60,0,0
|
||||
205490,-100,4,2,0,80,0,0
|
||||
205841,-100,4,2,0,60,0,0
|
||||
206076,-100,4,2,0,60,0,0
|
||||
206545,-100,4,2,0,80,0,0
|
||||
206779,-100,4,2,0,60,0,0
|
||||
207130,-100,4,2,0,80,0,0
|
||||
207716,-100,4,2,0,60,0,0
|
||||
207951,-100,4,2,0,80,0,0
|
||||
209123,-100,4,2,0,60,0,0
|
||||
209240,-100,4,2,0,80,0,0
|
||||
209826,-100,4,2,0,60,0,0
|
||||
209943,-100,4,2,0,80,0,0
|
||||
210529,-100,4,2,0,60,0,0
|
||||
210880,-100,4,2,0,80,0,0
|
||||
211232,-100,4,2,0,60,0,0
|
||||
211701,-100,4,2,0,70,0,0
|
||||
212170,-100,4,2,0,80,0,0
|
||||
212873,-100,4,2,0,60,0,0
|
||||
212990,-100,4,2,0,80,0,0
|
||||
213341,-100,4,2,0,60,0,0
|
||||
213576,-100,4,2,0,60,0,0
|
||||
214045,-100,4,2,0,80,0,0
|
||||
214279,-100,4,2,0,60,0,0
|
||||
214630,-100,4,2,0,80,0,0
|
||||
215216,-100,4,2,0,60,0,0
|
||||
215451,-100,4,2,0,80,0,0
|
||||
216623,-100,4,2,0,60,0,0
|
||||
216740,-100,4,2,0,80,0,0
|
||||
217326,-100,4,2,0,60,0,0
|
||||
217443,-100,4,2,0,80,0,0
|
||||
218029,-100,4,2,0,60,0,0
|
||||
218498,-100,4,2,0,80,0,0
|
||||
218732,-100,4,2,0,50,0,0
|
||||
219670,-100,4,2,0,70,0,0
|
||||
220138,-100,4,2,0,65,0,0
|
||||
220373,-100,4,2,0,45,0,0
|
||||
220490,-100,4,2,0,65,0,0
|
||||
220607,-100,4,2,0,60,0,0
|
||||
220841,-100,4,2,0,35,0,0
|
||||
221076,-100,4,2,0,35,0,0
|
||||
221545,-100,4,2,0,50,0,0
|
||||
221779,-100,4,2,0,30,0,0
|
||||
222013,-111.111111111111,4,2,0,25,0,0
|
||||
222130,-111.111111111111,4,2,0,40,0,0
|
||||
222482,-125,4,2,0,40,0,0
|
||||
222716,-125,4,2,0,20,0,0
|
||||
222951,-100,4,2,0,15,0,0
|
||||
223420,-100,4,2,0,30,0,0
|
||||
224357,-100,4,2,0,25,0,0
|
||||
225295,-100,4,2,0,20,0,0
|
||||
226232,-100,4,2,0,15,0,0
|
||||
226701,-100,4,2,0,10,0,0
|
||||
227170,-100,4,2,0,5,0,0
|
||||
|
||||
|
||||
[Colours]
|
||||
Combo1 : 17,254,176
|
||||
Combo2 : 173,255,95
|
||||
Combo3 : 255,88,100
|
||||
Combo4 : 255,94,55
|
||||
|
||||
[HitObjects]
|
||||
320,256,2170,6,0,P|256:284|192:256,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
144,184,2873,1,0,0:0:0:0:
|
||||
108,260,3107,2,0,P|112:296|100:336,1,72
|
||||
28,288,3576,2,0,P|24:252|36:212,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
76,140,4045,6,0,L|220:136,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
292,88,4748,1,0,0:0:0:0:
|
||||
292,88,4982,2,0,P|304:120|300:168,1,72
|
||||
388,168,5451,2,0,P|396:133|416:103,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
472,172,5920,6,0,B|470:200|457:222|457:222|488:256|476:308,1,144,4|0,0:0|0:0,0:0:0:0:
|
||||
396,280,6623,1,0,0:0:0:0:
|
||||
324,328,6857,2,0,P|288:332|252:324,1,72
|
||||
180,280,7326,2,0,L|108:284,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
256,192,7795,12,0,9670,0:0:0:0:
|
||||
428,212,10138,1,0,0:0:0:0:
|
||||
292,320,10607,1,0,0:0:0:0:
|
||||
184,184,11076,2,0,L|112:180,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
24,172,11545,5,6,0:0:0:0:
|
||||
160,280,12013,1,0,0:0:0:0:
|
||||
268,144,12482,1,0,0:0:0:0:
|
||||
132,36,12951,2,0,L|204:32,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
284,60,13420,6,0,P|340:100|344:180,2,144,6|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
268,144,14591,1,0,0:0:0:0:
|
||||
284,228,14826,2,0,P|316:248|364:252,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
436,248,15295,6,0,P|372:272|344:340,1,144,6|2,0:0|0:0,0:0:0:0:
|
||||
168,338,16232,2,0,P|141:273|76:248,1,144,2|2,0:0|0:0,0:0:0:0:
|
||||
4,296,16935,1,0,0:0:0:0:
|
||||
80,336,17170,5,6,0:0:0:0:
|
||||
44,168,17638,1,0,0:0:0:0:
|
||||
212,128,18107,1,0,0:0:0:0:
|
||||
248,296,18576,2,0,P|284:288|320:292,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
400,324,19045,5,6,0:0:0:0:
|
||||
280,200,19513,1,0,0:0:0:0:
|
||||
368,52,19982,1,0,0:0:0:0:
|
||||
488,176,20451,2,0,P|452:168|416:172,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
336,200,20920,6,0,P|284:216|200:192,1,144,6|0,0:0|0:0,0:0:0:0:
|
||||
200,192,21857,2,0,L|204:264,1,72,0|0,0:3|0:0,0:0:0:0:
|
||||
117,244,22326,2,0,L|120:172,1,72,0|0,0:0|0:0,0:0:0:0:
|
||||
40,152,22795,6,0,L|28:296,2,144,6|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
152,24,24201,1,0,0:0:0:0:
|
||||
220,76,24435,1,0,3:0:0:0:
|
||||
304,56,24670,6,0,P|288:120|296:196,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
344,268,25373,1,0,0:0:0:0:
|
||||
416,316,25607,2,0,P|452:312|508:316,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
244,344,26545,6,0,P|176:356|108:328,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
60,256,27248,1,0,0:0:0:0:
|
||||
36,172,27482,2,0,L|40:100,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
188,252,28420,6,0,P|192:184|196:100,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
140,40,29123,1,0,0:0:0:0:
|
||||
140,40,29357,2,0,B|172:16|220:24|220:24|288:36,1,144,0|2,0:0|0:3,0:0:0:0:
|
||||
364,52,30060,1,0,0:0:0:0:
|
||||
308,116,30295,6,0,B|300:168|300:168|328:256,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
340,340,30998,1,0,0:0:0:0:
|
||||
260,308,31232,2,0,L|188:304,1,72,0|2,0:0|0:3,0:0:0:0:
|
||||
100,296,31701,1,2,0:3:0:0:
|
||||
136,374,31935,1,0,0:0:0:0:
|
||||
152,224,32170,6,0,P|160:152|132:88,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
56,48,32873,1,0,0:0:0:0:
|
||||
60,136,33107,2,0,L|56:208,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
224,76,34045,6,0,P|289:104|360:96,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
432,48,34748,1,0,0:0:0:0:
|
||||
440,132,34982,2,0,B|432:156|432:156|436:204,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
448,304,35920,6,0,B|412:315|380:292|380:292|348:269|312:280,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
332,364,36623,1,0,0:0:0:0:
|
||||
247,339,36857,2,0,P|230:308|225:273,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
312,280,37560,6,0,L|316:172,1,108
|
||||
134,35,38966,5,0,0:0:0:0:
|
||||
72,96,39201,2,0,P|119:119|171:111,1,108,0|0,0:0|0:0,0:0:0:0:
|
||||
192,100,39670,6,0,L|200:172,1,72,4|2,0:0|0:0,0:0:0:0:
|
||||
147,240,40138,2,0,P|133:272|132:308,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
216,292,40607,2,0,B|260:308|260:308|356:292,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
356,292,41310,1,2,0:0:0:0:
|
||||
436,327,41545,6,0,P|441:292|435:257,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
364,204,42013,2,0,P|336:144|352:68,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
404,0,42716,1,2,0:0:0:0:
|
||||
440,80,42951,2,0,B|464:84|464:84|512:80,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
351,71,43420,6,0,B|296:68|296:68|268:76|268:76|196:72,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
120,68,44123,1,2,0:0:0:0:
|
||||
160,144,44357,2,0,P|172:180|168:232,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
76,264,44826,2,0,P|76:228|88:194,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
160,144,45295,5,4,0:3:0:0:
|
||||
244,164,45529,1,2,0:0:0:0:
|
||||
268,248,45763,2,0,L|344:252,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
408,156,46232,2,0,L|336:159,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
212,72,46701,2,0,L|288:76,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
400,72,47170,6,0,P|464:96|488:172,1,144,4|0,2:0|1:0,1:0:0:0:
|
||||
476,248,47873,1,2,0:0:0:0:
|
||||
436,324,48107,2,0,L|284:320,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
204,316,48810,1,2,0:0:0:0:
|
||||
127,355,49045,6,0,P|120:321|124:285,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
192,232,49513,2,0,L|335:228,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
412,188,50216,1,2,0:0:0:0:
|
||||
444,108,50451,2,0,P|452:72|448:36,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
368,68,50920,6,0,B|332:79|300:56|300:56|268:33|232:44,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
152,76,51623,1,2,0:0:0:0:
|
||||
76,116,51857,2,0,L|80:268,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
80,260,52560,1,2,0:0:0:0:
|
||||
8,308,52795,6,0,P|34:334|69:346,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
148,312,53263,2,0,P|163:278|162:241,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
156,156,53732,5,0,3:0:0:0:
|
||||
156,156,53966,1,2,0:0:0:0:
|
||||
236,196,54201,2,0,L|312:192,1,72,8|0,0:3|0:0,0:0:0:0:
|
||||
368,256,54670,6,0,P|392:216|352:116,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
288,92,55373,1,0,0:0:0:0:
|
||||
360,40,55607,2,0,L|432:36,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
288,92,56076,2,0,L|216:88,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
132,72,56545,6,0,P|172:88|200:184,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
143,241,57248,1,0,0:0:0:0:
|
||||
65,202,57482,2,0,P|87:174|119:157,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
132,324,57951,2,0,P|98:312|72:288,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
143,241,58420,6,0,L|288:240,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
372,240,59123,1,0,0:0:0:0:
|
||||
330,314,59357,2,0,P|318:350|322:390,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
452,264,59826,2,0,P|453:228|442:194,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
384,128,60295,6,0,B|336:144|336:144|244:128,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
164,160,60998,2,0,P|160:116|168:88,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
244,128,61466,2,0,P|248:172|240:200,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
168,248,61935,1,0,0:0:0:0:
|
||||
120,320,62170,6,0,P|196:328|252:272,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
80,244,63341,1,0,3:0:0:0:
|
||||
100,160,63576,2,0,L|24:156,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
180,128,64045,6,0,P|249:138|304:94,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
226,57,64748,1,0,0:0:0:0:
|
||||
304,94,64982,2,0,L|300:166,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
377,203,65451,2,0,L|388:132,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
468,180,65920,6,0,L|432:328,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
276,252,66857,2,0,P|208:248|140:280,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
84,344,67560,1,0,0:0:0:0:
|
||||
56,260,67795,6,0,L|52:188,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
168,128,68732,2,0,L|172:56,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
244,168,69435,1,0,0:0:0:0:
|
||||
332,164,69670,1,4,0:3:0:0:
|
||||
208,328,84670,6,0,P|224:264|216:188,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
168,116,85373,1,0,0:0:0:0:
|
||||
96,68,85607,2,0,P|60:72|4:68,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
268,40,86545,6,0,P|336:28|404:56,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
452,128,87248,1,0,0:0:0:0:
|
||||
476,212,87482,2,0,L|472:284,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
324,132,88420,6,0,P|320:200|316:284,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
372,344,89123,1,0,0:0:0:0:
|
||||
372,344,89357,2,0,B|340:368|292:360|292:360|224:348,1,144,0|2,0:0|0:3,0:0:0:0:
|
||||
148,332,90060,1,0,0:0:0:0:
|
||||
204,268,90295,6,0,B|212:216|212:216|184:128,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
172,44,90998,1,0,0:0:0:0:
|
||||
252,76,91232,2,0,L|324:80,1,72,0|2,0:0|0:3,0:0:0:0:
|
||||
412,88,91701,1,2,0:3:0:0:
|
||||
377,9,91935,1,0,0:0:0:0:
|
||||
360,160,92170,6,0,P|352:232|380:296,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
456,336,92873,1,0,0:0:0:0:
|
||||
452,248,93107,2,0,L|456:176,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
288,308,94045,6,0,P|223:280|152:288,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
80,336,94748,1,0,0:0:0:0:
|
||||
72,252,94982,2,0,B|80:228|80:228|76:180,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
64,80,95920,6,0,B|100:69|132:92|132:92|164:115|200:104,1,144,4|2,0:3|0:3,0:0:0:0:
|
||||
180,20,96623,1,0,0:0:0:0:
|
||||
265,45,96857,2,0,P|282:76|287:111,2,72,0|0|2,0:0|0:0|0:3,0:0:0:0:
|
||||
200,104,97560,1,0,0:0:0:0:
|
||||
200,104,97677,1,0,0:0:0:0:
|
||||
200,104,97795,6,0,B|196:142|217:166|217:166|176:180|160:220,1,144,4|0,0:3|0:0,0:0:0:0:
|
||||
240,248,98966,5,0,0:0:0:0:
|
||||
202,325,99201,2,0,P|254:333|301:309,1,108,0|0,0:0|0:0,0:0:0:0:
|
||||
315,292,99670,6,0,L|323:220,1,72,4|2,0:0|0:0,0:0:0:0:
|
||||
365,144,100138,2,0,P|379:112|380:76,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
296,92,100607,2,0,B|252:76|252:76|156:92,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
156,92,101310,1,2,0:0:0:0:
|
||||
76,57,101545,6,0,P|71:92|77:127,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
148,180,102013,2,0,P|176:240|160:316,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
108,384,102716,1,2,0:0:0:0:
|
||||
72,304,102951,2,0,B|48:300|48:300|0:304,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
161,313,103420,6,0,B|216:316|216:316|244:308|244:308|316:312,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
392,316,104123,1,2,0:0:0:0:
|
||||
352,240,104357,2,0,P|340:204|344:152,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
436,120,104826,2,0,P|436:156|424:190,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
352,240,105295,5,4,0:3:0:0:
|
||||
268,220,105529,1,2,0:0:0:0:
|
||||
244,136,105763,2,0,L|168:132,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
104,228,106232,2,0,L|176:225,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
300,312,106701,2,0,L|224:308,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
112,312,107170,6,0,P|48:288|24:212,1,144,4|0,2:0|1:0,1:0:0:0:
|
||||
36,136,107873,1,2,0:0:0:0:
|
||||
76,60,108107,2,0,L|228:64,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
308,68,108810,1,2,0:0:0:0:
|
||||
385,29,109045,6,0,P|392:63|388:99,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
320,152,109513,2,0,L|177:156,1,144,0|4,1:0|2:3,1:0:0:0:
|
||||
100,196,110216,1,2,0:0:0:0:
|
||||
68,276,110451,2,0,P|60:312|64:348,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
144,316,110920,6,0,B|180:305|212:328|212:328|244:351|280:340,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
360,308,111623,1,2,0:0:0:0:
|
||||
436,268,111857,2,0,L|432:116,1,144,4|0,2:3|1:0,1:0:0:0:
|
||||
432,124,112560,1,2,0:0:0:0:
|
||||
504,76,112795,6,0,P|478:50|443:38,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
364,72,113263,2,0,P|349:106|350:143,1,72,0|2,1:0|0:0,0:0:0:0:
|
||||
356,228,113732,5,0,3:0:0:0:
|
||||
356,228,113966,1,2,0:0:0:0:
|
||||
276,188,114201,2,0,L|200:192,1,72,8|0,0:3|0:0,0:0:0:0:
|
||||
144,128,114670,6,0,P|120:168|160:268,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
224,292,115373,1,0,0:0:0:0:
|
||||
152,344,115607,2,0,L|80:348,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
224,292,116076,2,0,L|296:296,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
380,312,116545,6,0,P|340:296|312:200,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
369,143,117248,1,0,0:0:0:0:
|
||||
447,182,117482,2,0,P|425:210|393:227,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
380,60,117951,2,0,P|414:72|440:96,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
369,143,118420,6,0,L|224:144,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
140,144,119123,1,0,0:0:0:0:
|
||||
182,70,119357,2,0,P|194:34|190:-6,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
60,120,119826,2,0,P|59:156|70:190,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
128,256,120295,6,0,B|176:240|176:240|268:256,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
348,224,120998,2,0,P|352:268|344:296,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
268,256,121466,2,0,P|264:212|272:184,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
344,136,121935,1,0,0:0:0:0:
|
||||
392,64,122170,6,0,P|316:56|260:112,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
432,140,123341,1,0,3:0:0:0:
|
||||
412,224,123576,2,0,L|488:228,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
332,256,124045,6,0,P|263:246|208:290,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
286,327,124748,1,0,0:0:0:0:
|
||||
208,290,124982,2,0,L|212:218,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
135,181,125451,2,0,L|124:252,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
44,204,125920,6,0,L|80:56,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
236,132,126857,2,0,P|304:136|372:104,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
428,40,127560,1,0,0:0:0:0:
|
||||
456,124,127795,6,0,L|460:196,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
344,256,128732,2,0,L|340:328,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
268,216,129435,1,0,0:0:0:0:
|
||||
180,220,129670,5,4,2:0:0:0:
|
||||
256,40,130373,1,2,0:0:0:0:
|
||||
64,68,131076,1,2,0:0:0:0:
|
||||
92,136,131310,1,0,0:0:0:0:
|
||||
64,204,131545,6,0,L|60:288,1,72
|
||||
31,343,132248,2,0,P|86:345|127:309,1,108
|
||||
332,220,133420,5,2,0:0:0:0:
|
||||
256,40,134123,1,2,0:0:0:0:
|
||||
448,68,134826,1,2,0:0:0:0:
|
||||
420,136,135060,1,0,0:0:0:0:
|
||||
448,204,135295,6,0,L|452:288,1,72,2|0,0:0|0:0,0:0:0:0:
|
||||
480,343,135998,2,0,P|426:345|385:309,1,108
|
||||
256,192,137170,5,2,0:0:0:0:
|
||||
156,360,137873,1,2,0:0:0:0:
|
||||
356,360,138576,2,0,L|352:308,1,36,2|0,0:0|0:0,0:0:0:0:
|
||||
304,268,139045,6,0,P|336:253|372:252,1,72
|
||||
448,260,139748,2,0,L|444:152,1,108
|
||||
256,192,140920,5,2,0:0:0:0:
|
||||
356,24,141623,1,2,0:0:0:0:
|
||||
156,24,142326,2,0,L|160:72,1,36,2|0,0:0|0:0,0:0:0:0:
|
||||
208,116,142795,6,0,P|176:131|140:132,1,72,2|0,0:0|0:0,0:0:0:0:
|
||||
64,124,143498,2,0,L|68:232,1,108
|
||||
68,232,144670,5,4,0:3:0:0:
|
||||
216,320,145138,1,4,0:3:0:0:
|
||||
304,172,145607,1,4,0:3:0:0:
|
||||
156,84,146075,1,4,0:3:0:0:
|
||||
296,320,146545,5,4,0:3:0:0:
|
||||
208,172,147013,1,4,0:3:0:0:
|
||||
356,84,147482,1,4,0:3:0:0:
|
||||
444,232,147950,1,4,0:3:0:0:
|
||||
296,320,148420,6,0,P|252:328|192:296,2,108.000004119873,4|4|4,0:3|0:3|0:3,0:0:0:0:
|
||||
260,248,149591,1,0,0:0:0:0:
|
||||
320,196,149826,2,0,L|316:140,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
120,236,159670,6,0,L|176:232,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
160,152,160138,2,0,L|104:156,1,54.0000020599366,2|0,0:0|0:0,0:0:0:0:
|
||||
240,180,160607,2,0,P|292:188|344:172,1,108.000004119873,4|2,0:3|0:0,3:0:0:0:
|
||||
408,120,161310,1,0,3:0:0:0:
|
||||
424,200,161545,6,0,L|420:256,1,54.0000020599366,4|0,0:3|0:0,0:0:0:0:
|
||||
376,320,162013,2,0,P|396:328|480:304,2,108.000004119873,2|6|2,2:0|0:3|2:0,3:0:0:0:
|
||||
312,268,163185,1,0,0:0:0:0:
|
||||
296,348,163420,6,0,L|240:344,1,54.0000020599366,4|0,3:0|3:0,0:0:0:0:
|
||||
160,320,163888,2,0,L|100:316,1,57.6,4|0,3:0|3:0,0:0:0:0:
|
||||
64,232,164357,6,0,L|128:228,1,61.2000011672974,4|0,3:0|3:0,0:0:0:0:
|
||||
204,200,164825,2,0,L|268:196,1,61.2000011672974,4|0,3:0|3:0,0:0:0:0:
|
||||
232,108,165295,6,0,L|164:104,1,68.399998173523,4|0,3:0|3:0,0:0:0:0:
|
||||
80,84,165763,2,0,L|4:80,1,72,4|0,3:0|3:0,0:0:0:0:
|
||||
324,120,167170,6,0,P|388:128|456:92,1,144,4|2,0:0|1:2,0:0:0:0:
|
||||
496,168,167873,1,0,0:0:0:0:
|
||||
496,168,168107,2,0,P|484:204|488:256,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
408,296,168576,2,0,P|398:261|378:231,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
296,200,169045,6,0,B|228:228|156:204,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
84,156,169748,1,0,0:0:0:0:
|
||||
80,244,169982,2,0,L|76:316,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
170,274,170451,2,0,L|156:204,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
216,140,170920,6,0,L|284:276,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
320,344,171623,1,0,0:0:0:0:
|
||||
372,276,171857,2,0,P|366:240|349:207,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
312,132,172326,2,0,L|276:60,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
208,20,172795,6,0,P|272:36|348:12,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
424,48,173498,2,0,L|412:132,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
484,168,173966,2,0,L|472:252,1,72,0|2,3:0|1:2,0:0:0:0:
|
||||
400,280,174435,1,0,0:0:0:0:
|
||||
346,348,174670,6,0,P|414:363|472:324,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
312,268,175841,1,0,3:0:0:0:
|
||||
256,336,176076,2,0,L|184:332,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
80,244,176545,6,0,B|140:248|140:248|164:244|164:244|223:247,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
312,268,177248,1,0,0:0:0:0:
|
||||
224,247,177482,2,0,P|240:215|272:187,1,72,4|0,0:3|3:0,0:0:0:0:
|
||||
204,131,177951,2,0,P|233:111|275:103,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
240,23,178420,6,0,B|280:15|316:35|316:35|376:71,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
399,236,179357,2,0,B|359:244|323:224|323:224|263:188,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
204,132,180060,1,0,0:0:0:0:
|
||||
184,216,180295,6,0,L|188:288,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
120,156,180998,1,0,0:0:0:0:
|
||||
56,96,181232,2,0,L|60:24,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
36,180,181935,1,0,0:0:0:0:
|
||||
100,240,182170,6,0,P|144:300|116:380,2,144,4|2|4,0:0|1:2|0:3,0:0:0:0:
|
||||
60,316,183341,1,0,0:0:0:0:
|
||||
220,352,183576,2,0,L|308:348,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
396,264,184045,6,0,B|336:268|336:268|312:264|312:264|253:267,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
253,267,184748,1,0,0:0:0:0:
|
||||
268,180,184982,2,0,L|339:177,1,72,4|0,0:3|0:0,0:0:0:0:
|
||||
164,280,185451,2,0,L|92:282,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
52,208,185920,6,0,P|8:268|32:344,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
140,212,187091,1,0,0:0:0:0:
|
||||
92,284,187326,2,0,P|104:316|100:368,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
52,208,187795,6,0,P|48:136|76:72,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
160,52,188498,2,0,P|188:28|220:16,1,72,0|4,0:0|0:3,0:0:0:0:
|
||||
232,100,188966,2,0,P|268:93|301:98,1,72,0|2,0:0|1:2,0:0:0:0:
|
||||
372,152,189435,1,0,0:0:0:0:
|
||||
420,224,189670,6,0,P|428:296|400:360,2,144,4|2|4,0:3|1:2|0:3,0:0:0:0:
|
||||
372,152,190841,1,0,0:0:0:0:
|
||||
392,68,191076,2,0,L|465:64,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
304,92,191545,6,0,P|236:104|168:76,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
108,12,192248,1,0,0:0:0:0:
|
||||
168,76,192482,2,0,L|172:152,1,72,4|0,0:3|0:0,0:0:0:0:
|
||||
80,136,192951,2,0,L|101:204,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
12,220,193420,6,0,B|50:279|50:279|80:300|120:292,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
284,232,194357,2,0,B|320:221|352:244|352:244|384:267|420:256,1,144,4|2,0:3|1:2,0:0:0:0:
|
||||
488,200,195060,1,0,0:0:0:0:
|
||||
507,284,195295,6,0,P|492:315|464:338,1,72,4|0,0:0|0:0,0:0:0:0:
|
||||
380,356,195763,2,0,L|236:352,1,144,0|4,1:0|0:3,0:0:0:0:
|
||||
152,328,196466,1,0,3:0:0:0:
|
||||
64,336,196701,2,0,P|29:325|4:300,1,72,0|0,1:0|0:0,0:0:0:0:
|
||||
76,252,197170,6,0,P|108:188|96:116,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
36,56,197873,1,2,0:0:0:0:
|
||||
120,32,198107,2,0,L|192:28,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
248,152,199045,6,0,P|280:168|304:196,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
336,277,199513,2,0,P|306:296|269:303,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
183,290,199982,2,0,P|180:254|193:219,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
436,252,200920,6,0,P|404:188|416:116,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
476,56,201623,1,2,0:0:0:0:
|
||||
392,32,201857,2,0,L|320:28,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
264,152,202795,6,0,P|232:168|208:196,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
176,277,203263,2,0,P|205:296|242:303,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
329,290,203732,2,0,P|331:254|318:219,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
72,324,204670,6,0,B|60:272|60:272|76:180,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
92,96,205373,1,2,0:0:0:0:
|
||||
8,124,205607,2,0,P|5:88|14:53,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
168,192,206545,6,0,P|200:174|237:173,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
320,160,207013,2,0,P|318:196|301:229,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
272,307,207482,2,0,P|240:287|221:256,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
440,324,208420,6,0,B|452:272|452:272|436:180,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
420,96,209123,1,2,0:0:0:0:
|
||||
504,124,209357,2,0,P|507:88|498:53,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
344,192,210295,6,0,P|311:174|274:173,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
190,156,210763,2,0,P|191:192|208:225,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
288,256,211232,1,4,0:3:0:0:
|
||||
132,332,211701,1,0,1:0:0:0:
|
||||
28,192,212170,6,0,P|16:120|44:56,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
120,16,212873,1,2,0:0:0:0:
|
||||
204,32,213107,2,0,L|304:28,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
192,204,214045,6,0,P|196:240|216:272,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
298,241,214513,2,0,P|327:219|345:186,1,72,6|0,1:2|0:0,0:0:0:0:
|
||||
280,132,214982,2,0,P|246:117|209:118,2,72,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
484,192,215920,6,0,P|496:120|468:56,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
392,16,216623,1,2,0:0:0:0:
|
||||
308,32,216857,2,0,L|208:28,2,72,4|0|2,0:3|0:0|1:2,0:0:0:0:
|
||||
320,204,217795,6,0,P|316:240|296:272,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
213,241,218263,2,0,P|184:219|166:186,1,72,2|0,1:2|0:0,0:0:0:0:
|
||||
232,132,218732,2,0,B|260:112|300:116|300:116|384:128,1,144,4|0,0:3|1:0,0:0:0:0:
|
||||
348,336,219670,6,0,B|320:356|280:352|280:352|196:340,1,144,4|0,0:0|1:0,0:0:0:0:
|
||||
124,328,220373,1,2,0:0:0:0:
|
||||
54,276,220607,2,0,P|41:308|39:345,2,72,4|2|2,0:3|0:0|1:2,0:0:0:0:
|
||||
156,80,221545,6,0,L|251:94,1,72,4|2,0:3|0:0,0:0:0:0:
|
||||
212,169,222013,2,0,L|148:160,1,64.799998022461,2|0,1:2|0:0,0:0:0:0:
|
||||
140,240,222482,2,0,L|216:252,2,57.6,4|2|0,0:3|0:0|1:0,0:0:0:0:
|
||||
256,192,223420,12,0,227170,0:0:0:0:
|
||||
";
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
@ -12,11 +12,10 @@ namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
public override string Description => @"Testing replay playback.";
|
||||
|
||||
protected override Player CreatePlayer(WorkingBeatmap beatmap)
|
||||
protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset)
|
||||
{
|
||||
beatmap.Mods.Value = new Mod[] { new OsuModAutoplay() };
|
||||
|
||||
return base.CreatePlayer(beatmap);
|
||||
beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
|
||||
return base.CreatePlayer(beatmap, ruleset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,23 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using OpenTK;
|
||||
using osu.Desktop.Tests.Beatmaps;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Beatmaps;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Timing;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
@ -22,6 +27,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
/// <summary>
|
||||
/// The most minimal implementation of a playfield with scrolling hit objects.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class TestCaseScrollingPlayfield : OsuTestCase
|
||||
{
|
||||
public TestCaseScrollingPlayfield()
|
||||
@ -58,12 +64,72 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
AddStep("Reverse direction", () =>
|
||||
{
|
||||
horizontalRulesetContainer.Playfield.Reversed.Toggle();
|
||||
verticalRulesetContainer.Playfield.Reversed.Toggle();
|
||||
horizontalRulesetContainer.Playfield.Reverse();
|
||||
verticalRulesetContainer.Playfield.Reverse();
|
||||
});
|
||||
}
|
||||
|
||||
private class TestRulesetContainer : ScrollingRulesetContainer<TestPlayfield, TestHitObject, TestJudgement>
|
||||
[Test]
|
||||
public void TestSpeedAdjustmentOrdering()
|
||||
{
|
||||
var hitObjectContainer = new ScrollingPlayfield.ScrollingHitObjectContainer(Axes.X);
|
||||
|
||||
var speedAdjustments = new[]
|
||||
{
|
||||
new SpeedAdjustmentContainer(new MultiplierControlPoint()),
|
||||
new SpeedAdjustmentContainer(new MultiplierControlPoint(1000)
|
||||
{
|
||||
TimingPoint = new TimingControlPoint { BeatLength = 500 }
|
||||
}),
|
||||
new SpeedAdjustmentContainer(new MultiplierControlPoint(2000)
|
||||
{
|
||||
TimingPoint = new TimingControlPoint { BeatLength = 1000 },
|
||||
DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 2}
|
||||
}),
|
||||
new SpeedAdjustmentContainer(new MultiplierControlPoint(3000)
|
||||
{
|
||||
TimingPoint = new TimingControlPoint { BeatLength = 1000 },
|
||||
DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 1}
|
||||
}),
|
||||
};
|
||||
|
||||
var hitObjects = new[]
|
||||
{
|
||||
new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = -1000 }),
|
||||
new DrawableTestHitObject(Axes.X, new TestHitObject()),
|
||||
new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 1000 }),
|
||||
new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 2000 }),
|
||||
new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 3000 }),
|
||||
new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 4000 }),
|
||||
};
|
||||
|
||||
hitObjects.ForEach(h => hitObjectContainer.Add(h));
|
||||
speedAdjustments.ForEach(hitObjectContainer.AddSpeedAdjustment);
|
||||
|
||||
// The 0th index in hitObjectContainer.SpeedAdjustments is the "default" control point
|
||||
// Check multiplier of the default speed adjustment
|
||||
Assert.AreEqual(1, hitObjectContainer.SpeedAdjustments[0].ControlPoint.Multiplier);
|
||||
Assert.AreEqual(1, speedAdjustments[0].ControlPoint.Multiplier);
|
||||
Assert.AreEqual(2, speedAdjustments[1].ControlPoint.Multiplier);
|
||||
Assert.AreEqual(2, speedAdjustments[2].ControlPoint.Multiplier);
|
||||
Assert.AreEqual(1, speedAdjustments[3].ControlPoint.Multiplier);
|
||||
|
||||
// Check insertion of hit objects
|
||||
Assert.IsTrue(hitObjectContainer.SpeedAdjustments[4].Contains(hitObjects[0]));
|
||||
Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1]));
|
||||
Assert.IsTrue(hitObjectContainer.SpeedAdjustments[2].Contains(hitObjects[2]));
|
||||
Assert.IsTrue(hitObjectContainer.SpeedAdjustments[1].Contains(hitObjects[3]));
|
||||
Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[4]));
|
||||
Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[5]));
|
||||
|
||||
hitObjectContainer.RemoveSpeedAdjustment(hitObjectContainer.SpeedAdjustments[3]);
|
||||
|
||||
// The hit object contained in this speed adjustment should be resorted into the one occuring before it
|
||||
|
||||
Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1]));
|
||||
}
|
||||
|
||||
private class TestRulesetContainer : ScrollingRulesetContainer<TestPlayfield, TestHitObject>
|
||||
{
|
||||
private readonly Axes scrollingAxes;
|
||||
|
||||
@ -77,16 +143,18 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor();
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new PassThroughInputManager();
|
||||
|
||||
protected override BeatmapConverter<TestHitObject> CreateBeatmapConverter() => new TestBeatmapConverter();
|
||||
|
||||
protected override Playfield<TestHitObject, TestJudgement> CreatePlayfield() => new TestPlayfield(scrollingAxes);
|
||||
protected override Playfield CreatePlayfield() => new TestPlayfield(scrollingAxes);
|
||||
|
||||
protected override DrawableHitObject<TestHitObject, TestJudgement> GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(scrollingAxes, h);
|
||||
protected override DrawableHitObject<TestHitObject> GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(scrollingAxes, h);
|
||||
}
|
||||
|
||||
private class TestScoreProcessor : ScoreProcessor<TestHitObject, TestJudgement>
|
||||
private class TestScoreProcessor : ScoreProcessor<TestHitObject>
|
||||
{
|
||||
protected override void OnNewJudgement(TestJudgement judgement)
|
||||
protected override void OnNewJudgement(Judgement judgement)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -101,7 +169,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
}
|
||||
}
|
||||
|
||||
private class DrawableTestHitObject : DrawableScrollingHitObject<TestHitObject, TestJudgement>
|
||||
private class DrawableTestHitObject : DrawableScrollingHitObject<TestHitObject>
|
||||
{
|
||||
public DrawableTestHitObject(Axes scrollingAxes, TestHitObject hitObject)
|
||||
: base(hitObject)
|
||||
@ -117,14 +185,12 @@ namespace osu.Desktop.Tests.Visual
|
||||
});
|
||||
}
|
||||
|
||||
protected override TestJudgement CreateJudgement() => new TestJudgement();
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TestPlayfield : ScrollingPlayfield<TestHitObject, TestJudgement>
|
||||
private class TestPlayfield : ScrollingPlayfield
|
||||
{
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container<Drawable> content;
|
||||
@ -142,17 +208,13 @@ namespace osu.Desktop.Tests.Visual
|
||||
content = new Container { RelativeSizeAxes = Axes.Both }
|
||||
};
|
||||
}
|
||||
|
||||
public void Reverse() => Reversed.Toggle();
|
||||
}
|
||||
|
||||
|
||||
private class TestHitObject : HitObject
|
||||
{
|
||||
}
|
||||
|
||||
private class TestJudgement : Judgement
|
||||
{
|
||||
public override string ResultString { get { throw new NotImplementedException(); } }
|
||||
public override string MaxResultString { get { throw new NotImplementedException(); } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
90
osu.Desktop.Tests/Visual/TestCaseStoryboard.cs
Normal file
90
osu.Desktop.Tests/Visual/TestCaseStoryboard.cs
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Storyboards.Drawables;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
internal class TestCaseStoryboard : OsuTestCase
|
||||
{
|
||||
public override string Description => @"Tests storyboards.";
|
||||
|
||||
private readonly Bindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>();
|
||||
|
||||
private readonly Container<DrawableStoryboard> storyboardContainer;
|
||||
private DrawableStoryboard storyboard;
|
||||
|
||||
public TestCaseStoryboard()
|
||||
{
|
||||
Clock = new FramedClock();
|
||||
|
||||
Add(new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
storyboardContainer = new Container<DrawableStoryboard>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
});
|
||||
Add(new MusicController
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
State = Visibility.Visible,
|
||||
});
|
||||
|
||||
AddStep("Restart", restart);
|
||||
AddToggleStep("Passing", passing => { if (storyboard != null) storyboard.Passing = passing; });
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase game)
|
||||
{
|
||||
beatmapBacking.BindTo(game.Beatmap);
|
||||
beatmapBacking.ValueChanged += beatmapChanged;
|
||||
}
|
||||
|
||||
private void beatmapChanged(WorkingBeatmap working)
|
||||
=> loadStoryboard(working);
|
||||
|
||||
private void restart()
|
||||
{
|
||||
var track = beatmapBacking.Value.Track;
|
||||
|
||||
track.Reset();
|
||||
loadStoryboard(beatmapBacking.Value);
|
||||
track.Start();
|
||||
}
|
||||
|
||||
private void loadStoryboard(WorkingBeatmap working)
|
||||
{
|
||||
if (storyboard != null)
|
||||
storyboardContainer.Remove(storyboard);
|
||||
|
||||
var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true };
|
||||
decoupledClock.ChangeSource(working.Track);
|
||||
storyboardContainer.Clock = decoupledClock;
|
||||
|
||||
storyboardContainer.Add(storyboard = working.Beatmap.Storyboard.CreateDrawable());
|
||||
storyboard.Passing = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,11 @@ using osu.Game.Rulesets.Taiko.UI;
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Desktop.Tests.Beatmaps;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
@ -27,10 +32,11 @@ namespace osu.Desktop.Tests.Visual
|
||||
protected override double TimePerAction => default_duration * 2;
|
||||
|
||||
private readonly Random rng = new Random(1337);
|
||||
private readonly TaikoPlayfield playfield;
|
||||
private readonly Container playfieldContainer;
|
||||
private TaikoRulesetContainer rulesetContainer;
|
||||
private Container playfieldContainer;
|
||||
|
||||
public TestCaseTaikoPlayfield()
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
AddStep("Hit!", () => addHitJudgement(false));
|
||||
AddStep("Kiai hit", () => addHitJudgement(true));
|
||||
@ -51,6 +57,25 @@ namespace osu.Desktop.Tests.Visual
|
||||
AddStep("Height test 5", () => changePlayfieldSize(5));
|
||||
AddStep("Reset height", () => changePlayfieldSize(6));
|
||||
|
||||
var controlPointInfo = new ControlPointInfo();
|
||||
controlPointInfo.TimingPoints.Add(new TimingControlPoint());
|
||||
|
||||
WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject> { new CentreHit() },
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
Difficulty = new BeatmapDifficulty(),
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Artist = @"Unknown",
|
||||
Title = @"Sample Beatmap",
|
||||
Author = @"peppy",
|
||||
},
|
||||
},
|
||||
ControlPointInfo = controlPointInfo
|
||||
});
|
||||
|
||||
var rateAdjustClock = new StopwatchClock(true) { Rate = 1 };
|
||||
|
||||
Add(playfieldContainer = new Container
|
||||
@ -58,12 +83,9 @@ namespace osu.Desktop.Tests.Visual
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = TaikoPlayfield.DEFAULT_HEIGHT,
|
||||
Height = 768,
|
||||
Clock = new FramedClock(rateAdjustClock),
|
||||
Children = new[]
|
||||
{
|
||||
playfield = new TaikoPlayfield()
|
||||
}
|
||||
Children = new[] { rulesetContainer = new TaikoRulesetContainer(rulesets.GetRuleset(1).CreateInstance(), beatmap, true) }
|
||||
});
|
||||
}
|
||||
|
||||
@ -106,7 +128,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
private void addHitJudgement(bool kiai)
|
||||
{
|
||||
TaikoHitResult hitResult = RNG.Next(2) == 0 ? TaikoHitResult.Good : TaikoHitResult.Great;
|
||||
HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great;
|
||||
|
||||
var cpi = new ControlPointInfo();
|
||||
cpi.EffectPoints.Add(new EffectControlPoint
|
||||
@ -117,56 +139,35 @@ namespace osu.Desktop.Tests.Visual
|
||||
Hit hit = new Hit();
|
||||
hit.ApplyDefaults(cpi, new BeatmapDifficulty());
|
||||
|
||||
var h = new DrawableTestHit(hit)
|
||||
{
|
||||
X = RNG.NextSingle(hitResult == TaikoHitResult.Good ? -0.1f : -0.05f, hitResult == TaikoHitResult.Good ? 0.1f : 0.05f),
|
||||
Judgement = new TaikoJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
TaikoResult = hitResult,
|
||||
TimeOffset = 0
|
||||
}
|
||||
};
|
||||
var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) };
|
||||
|
||||
playfield.OnJudgement(h);
|
||||
rulesetContainer.Playfield.OnJudgement(h, new TaikoJudgement { Result = hitResult });
|
||||
|
||||
if (RNG.Next(10) == 0)
|
||||
{
|
||||
h.Judgement.SecondHit = true;
|
||||
playfield.OnJudgement(h);
|
||||
rulesetContainer.Playfield.OnJudgement(h, new TaikoJudgement { Result = hitResult });
|
||||
rulesetContainer.Playfield.OnJudgement(h, new TaikoStrongHitJudgement());
|
||||
}
|
||||
}
|
||||
|
||||
private void addMissJudgement()
|
||||
{
|
||||
playfield.OnJudgement(new DrawableTestHit(new Hit())
|
||||
{
|
||||
Judgement = new TaikoJudgement
|
||||
{
|
||||
Result = HitResult.Miss,
|
||||
TimeOffset = 0
|
||||
}
|
||||
});
|
||||
rulesetContainer.Playfield.OnJudgement(new DrawableTestHit(new Hit()), new TaikoJudgement { Result = HitResult.Miss });
|
||||
}
|
||||
|
||||
private void addBarLine(bool major, double delay = scroll_time)
|
||||
{
|
||||
BarLine bl = new BarLine
|
||||
{
|
||||
StartTime = playfield.Time.Current + delay,
|
||||
ScrollTime = scroll_time
|
||||
};
|
||||
BarLine bl = new BarLine { StartTime = rulesetContainer.Playfield.Time.Current + delay };
|
||||
|
||||
playfield.AddBarLine(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl));
|
||||
rulesetContainer.Playfield.Add(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl));
|
||||
}
|
||||
|
||||
private void addSwell(double duration = default_duration)
|
||||
{
|
||||
playfield.Add(new DrawableSwell(new Swell
|
||||
rulesetContainer.Playfield.Add(new DrawableSwell(new Swell
|
||||
{
|
||||
StartTime = playfield.Time.Current + scroll_time,
|
||||
StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
|
||||
Duration = duration,
|
||||
ScrollTime = scroll_time
|
||||
}));
|
||||
}
|
||||
|
||||
@ -177,54 +178,49 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
var d = new DrumRoll
|
||||
{
|
||||
StartTime = playfield.Time.Current + scroll_time,
|
||||
StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
|
||||
IsStrong = strong,
|
||||
Duration = duration,
|
||||
ScrollTime = scroll_time,
|
||||
};
|
||||
|
||||
playfield.Add(new DrawableDrumRoll(d));
|
||||
rulesetContainer.Playfield.Add(new DrawableDrumRoll(d));
|
||||
}
|
||||
|
||||
private void addCentreHit(bool strong)
|
||||
{
|
||||
Hit h = new Hit
|
||||
{
|
||||
StartTime = playfield.Time.Current + scroll_time,
|
||||
ScrollTime = scroll_time,
|
||||
StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
|
||||
IsStrong = strong
|
||||
};
|
||||
|
||||
if (strong)
|
||||
playfield.Add(new DrawableCentreHitStrong(h));
|
||||
rulesetContainer.Playfield.Add(new DrawableCentreHitStrong(h));
|
||||
else
|
||||
playfield.Add(new DrawableCentreHit(h));
|
||||
rulesetContainer.Playfield.Add(new DrawableCentreHit(h));
|
||||
}
|
||||
|
||||
private void addRimHit(bool strong)
|
||||
{
|
||||
Hit h = new Hit
|
||||
{
|
||||
StartTime = playfield.Time.Current + scroll_time,
|
||||
ScrollTime = scroll_time,
|
||||
StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
|
||||
IsStrong = strong
|
||||
};
|
||||
|
||||
if (strong)
|
||||
playfield.Add(new DrawableRimHitStrong(h));
|
||||
rulesetContainer.Playfield.Add(new DrawableRimHitStrong(h));
|
||||
else
|
||||
playfield.Add(new DrawableRimHit(h));
|
||||
rulesetContainer.Playfield.Add(new DrawableRimHit(h));
|
||||
}
|
||||
|
||||
private class DrawableTestHit : DrawableHitObject<TaikoHitObject, TaikoJudgement>
|
||||
private class DrawableTestHit : DrawableHitObject<TaikoHitObject>
|
||||
{
|
||||
public DrawableTestHit(TaikoHitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
|
@ -33,13 +33,10 @@ namespace osu.Desktop.Tests.Visual
|
||||
Rank = 2148,
|
||||
PP = 4567.89m
|
||||
},
|
||||
AllRankHistories = new User.RankHistories
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
Osu = new User.RankHistory
|
||||
{
|
||||
Mode = @"osu",
|
||||
Data = Enumerable.Range(2345,45).Concat(Enumerable.Range(2109,40)).ToArray()
|
||||
}
|
||||
Mode = @"osu",
|
||||
Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
|
||||
}
|
||||
}, false));
|
||||
AddStep("Show ppy", () => profile.ShowUser(new User
|
||||
|
@ -9,7 +9,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>osu.Desktop.Tests</RootNamespace>
|
||||
<AssemblyName>osu.Desktop.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
@ -35,14 +35,15 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
|
||||
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@ -87,9 +88,11 @@
|
||||
<Compile Include="Visual\TestCaseManiaHitObjects.cs" />
|
||||
<Compile Include="Visual\TestCaseManiaPlayfield.cs" />
|
||||
<Compile Include="Visual\TestCaseMedalOverlay.cs" />
|
||||
<Compile Include="Visual\TestCaseEditorMenuBar.cs" />
|
||||
<Compile Include="Visual\TestCaseMenuButtonSystem.cs" />
|
||||
<Compile Include="Visual\TestCaseMenuOverlays.cs" />
|
||||
<Compile Include="Visual\TestCaseMods.cs" />
|
||||
<Compile Include="Visual\TestCaseStoryboard.cs" />
|
||||
<Compile Include="Visual\TestCaseMusicController.cs" />
|
||||
<Compile Include="Visual\TestCaseNotificationOverlay.cs" />
|
||||
<Compile Include="Visual\TestCaseOnScreenDisplay.cs" />
|
||||
@ -155,6 +158,7 @@
|
||||
<Link>osu.licenseheader</Link>
|
||||
</None>
|
||||
<None Include="app.config" />
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -4,9 +4,9 @@ Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
-->
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
||||
<package id="NUnit" version="3.7.1" targetFramework="net45" />
|
||||
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||
<package id="NUnit" version="3.8.1" targetFramework="net461" />
|
||||
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
||||
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
||||
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
|
||||
|
@ -22,7 +22,7 @@
|
||||
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<TargetZone>LocalIntranet</TargetZone>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
|
@ -1,7 +1,3 @@
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
-->
|
||||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
|
@ -20,16 +20,11 @@ namespace osu.Desktop
|
||||
{
|
||||
internal class OsuGameDesktop : OsuGame
|
||||
{
|
||||
private readonly VersionManager versionManager;
|
||||
private VersionManager versionManager;
|
||||
|
||||
public OsuGameDesktop(string[] args = null)
|
||||
: base(args)
|
||||
{
|
||||
versionManager = new VersionManager
|
||||
{
|
||||
Depth = int.MinValue,
|
||||
State = Visibility.Hidden
|
||||
};
|
||||
}
|
||||
|
||||
public override Storage GetStorageForStableInstall()
|
||||
@ -88,11 +83,15 @@ namespace osu.Desktop
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
LoadComponentAsync(versionManager, Add);
|
||||
LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue });
|
||||
|
||||
ScreenChanged += s =>
|
||||
{
|
||||
if (!versionManager.IsPresent && s is Intro)
|
||||
if (s is Intro && s.ChildScreen == null)
|
||||
{
|
||||
Add(versionManager);
|
||||
versionManager.State = Visibility.Visible;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,6 @@ namespace osu.Desktop
|
||||
public override void SetHost(GameHost host)
|
||||
{
|
||||
base.SetHost(host);
|
||||
|
||||
host.UpdateThread.InactiveHz = host.UpdateThread.ActiveHz;
|
||||
host.DrawThread.InactiveHz = host.DrawThread.ActiveHz;
|
||||
host.InputThread.InactiveHz = host.InputThread.ActiveHz;
|
||||
|
||||
host.Window.CursorState |= CursorState.Hidden;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
@ -19,6 +20,7 @@ using OpenTK.Graphics;
|
||||
using System.Net.Http;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game;
|
||||
using osu.Game.Configuration;
|
||||
|
||||
namespace osu.Desktop.Overlays
|
||||
{
|
||||
@ -26,17 +28,22 @@ namespace osu.Desktop.Overlays
|
||||
{
|
||||
private UpdateManager updateManager;
|
||||
private NotificationOverlay notificationOverlay;
|
||||
private OsuConfigManager config;
|
||||
private OsuGameBase game;
|
||||
|
||||
public override bool HandleInput => false;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game)
|
||||
private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config)
|
||||
{
|
||||
notificationOverlay = notification;
|
||||
this.config = config;
|
||||
this.game = game;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Origin = Anchor.BottomCentre;
|
||||
|
||||
Alpha = 0;
|
||||
|
||||
Children = new Drawable[]
|
||||
@ -91,6 +98,42 @@ namespace osu.Desktop.Overlays
|
||||
checkForUpdateAsync();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
var version = game.Version;
|
||||
var lastVersion = config.Get<string>(OsuSetting.Version);
|
||||
if (game.IsDeployedBuild && version != lastVersion)
|
||||
{
|
||||
config.Set(OsuSetting.Version, version);
|
||||
|
||||
// only show a notification if we've previously saved a version to the config file (ie. not the first run).
|
||||
if (!string.IsNullOrEmpty(lastVersion))
|
||||
Scheduler.AddDelayed(() => notificationOverlay.Post(new UpdateCompleteNotification(version)), 5000);
|
||||
}
|
||||
}
|
||||
|
||||
private class UpdateCompleteNotification : SimpleNotification
|
||||
{
|
||||
public UpdateCompleteNotification(string version)
|
||||
{
|
||||
Text = $"You are now running osu!lazer {version}.\nClick to see what's new!";
|
||||
Icon = FontAwesome.fa_check_square;
|
||||
Activated = delegate
|
||||
{
|
||||
Process.Start($"https://github.com/ppy/osu/releases/tag/v{version}");
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
IconBackgound.Colour = colours.BlueDark;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
15
osu.Desktop/app.config
Normal file
15
osu.Desktop/app.config
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-0.18.1.0" newVersion="0.18.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
@ -22,7 +22,7 @@
|
||||
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<TargetZone>LocalIntranet</TargetZone>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
@ -69,7 +69,8 @@
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>CuttingEdge NoUpdate</DefineConstants>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
@ -104,6 +105,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<StartArguments>--tests</StartArguments>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="DeltaCompressionDotNet, Version=1.1.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
|
||||
@ -136,36 +138,28 @@
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SharpCompress, Version=0.17.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll</HintPath>
|
||||
<Reference Include="SharpCompress, Version=0.18.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Squirrel, Version=1.7.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\Squirrel.dll</HintPath>
|
||||
<Reference Include="Squirrel, Version=1.7.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
@ -173,6 +167,7 @@
|
||||
<None Include="..\osu.licenseheader">
|
||||
<Link>osu.licenseheader</Link>
|
||||
</None>
|
||||
<None Include="app.config" />
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="osu!.res" />
|
||||
<None Include="packages.config" />
|
||||
|
@ -5,10 +5,9 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
||||
-->
|
||||
<packages>
|
||||
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
|
||||
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net45" />
|
||||
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||
<package id="SharpCompress" version="0.17.1" targetFramework="net45" />
|
||||
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||
<package id="SharpCompress" version="0.18.1" targetFramework="net461" />
|
||||
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
||||
<package id="squirrel.windows" version="1.7.5" targetFramework="net45" />
|
||||
<package id="squirrel.windows" version="1.7.8" targetFramework="net461" />
|
||||
</packages>
|
@ -3,11 +3,11 @@
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch
|
||||
{
|
||||
public class CatchInputManager : DatabasedKeyBindingInputManager<CatchAction>
|
||||
public class CatchInputManager : RulesetInputManager<CatchAction>
|
||||
{
|
||||
public CatchInputManager(RulesetInfo ruleset)
|
||||
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
||||
|
@ -1,18 +1,14 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Scoring;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Framework.Input.Bindings;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch
|
||||
@ -23,12 +19,12 @@ namespace osu.Game.Rulesets.Catch
|
||||
|
||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
||||
{
|
||||
new KeyBinding(Key.Z, CatchAction.MoveLeft),
|
||||
new KeyBinding(Key.Left, CatchAction.MoveLeft),
|
||||
new KeyBinding(Key.X, CatchAction.MoveRight),
|
||||
new KeyBinding(Key.Right, CatchAction.MoveRight),
|
||||
new KeyBinding(Key.LShift, CatchAction.Dash),
|
||||
new KeyBinding(Key.RShift, CatchAction.Dash),
|
||||
new KeyBinding(InputKey.Z, CatchAction.MoveLeft),
|
||||
new KeyBinding(InputKey.Left, CatchAction.MoveLeft),
|
||||
new KeyBinding(InputKey.X, CatchAction.MoveRight),
|
||||
new KeyBinding(InputKey.Right, CatchAction.MoveRight),
|
||||
new KeyBinding(InputKey.Shift, CatchAction.Dash),
|
||||
new KeyBinding(InputKey.Shift, CatchAction.Dash),
|
||||
};
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||
@ -95,23 +91,12 @@ namespace osu.Game.Rulesets.Catch
|
||||
}
|
||||
}
|
||||
|
||||
public override Mod GetAutoplayMod() => new ModAutoplay();
|
||||
|
||||
public override string Description => "osu!catch";
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o };
|
||||
|
||||
public override IEnumerable<KeyCounter> CreateGameplayKeys() => new KeyCounter[]
|
||||
{
|
||||
new KeyCounterKeyboard(Key.ShiftLeft),
|
||||
new KeyCounterMouse(MouseButton.Left),
|
||||
new KeyCounterMouse(MouseButton.Right)
|
||||
};
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap);
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor();
|
||||
|
||||
public override int LegacyID => 2;
|
||||
|
||||
public CatchRuleset(RulesetInfo rulesetInfo)
|
||||
|
@ -7,8 +7,6 @@ namespace osu.Game.Rulesets.Catch.Judgements
|
||||
{
|
||||
public class CatchJudgement : Judgement
|
||||
{
|
||||
public override string ResultString => string.Empty;
|
||||
|
||||
public override string MaxResultString => string.Empty;
|
||||
// todo: wangs
|
||||
}
|
||||
}
|
||||
|
@ -9,14 +9,14 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
{
|
||||
public class DrawableFruit : DrawableScrollingHitObject<CatchBaseHit, CatchJudgement>
|
||||
public class DrawableFruit : DrawableScrollingHitObject<CatchBaseHit>
|
||||
{
|
||||
private const float pulp_size = 30;
|
||||
|
||||
@ -98,14 +98,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
};
|
||||
}
|
||||
|
||||
protected override CatchJudgement CreateJudgement() => new CatchJudgement();
|
||||
|
||||
private const float preempt = 1000;
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (Judgement.TimeOffset > 0)
|
||||
Judgement.Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Hit : HitResult.Miss;
|
||||
if (timeOffset > 0)
|
||||
AddJudgement(new Judgement { Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss });
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
|
@ -1,7 +1,3 @@
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
-->
|
||||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
|
@ -1,34 +1,21 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Scoring
|
||||
{
|
||||
internal class CatchScoreProcessor : ScoreProcessor<CatchBaseHit, CatchJudgement>
|
||||
internal class CatchScoreProcessor : ScoreProcessor<CatchBaseHit>
|
||||
{
|
||||
public CatchScoreProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
public CatchScoreProcessor(RulesetContainer<CatchBaseHit, CatchJudgement> rulesetContainer)
|
||||
public CatchScoreProcessor(RulesetContainer<CatchBaseHit> rulesetContainer)
|
||||
: base(rulesetContainer)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
Health.Value = 1;
|
||||
Accuracy.Value = 1;
|
||||
}
|
||||
|
||||
protected override void OnNewJudgement(CatchJudgement judgement)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,17 +2,16 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatchPlayfield : ScrollingPlayfield<CatchBaseHit, CatchJudgement>
|
||||
public class CatchPlayfield : ScrollingPlayfield
|
||||
{
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container<Drawable> content;
|
||||
@ -44,22 +43,23 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
};
|
||||
}
|
||||
|
||||
public override void Add(DrawableHitObject<CatchBaseHit, CatchJudgement> h)
|
||||
public override void Add(DrawableHitObject h)
|
||||
{
|
||||
h.Depth = (float)h.HitObject.StartTime;
|
||||
|
||||
base.Add(h);
|
||||
|
||||
var fruit = (DrawableFruit)h;
|
||||
fruit.CheckPosition = catcherArea.CheckIfWeCanCatch;
|
||||
fruit.OnJudgement += Fruit_OnJudgement;
|
||||
}
|
||||
|
||||
private void Fruit_OnJudgement(DrawableHitObject<CatchBaseHit, CatchJudgement> obj)
|
||||
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
if (obj.Judgement.Result == HitResult.Hit)
|
||||
if (judgement.IsHit)
|
||||
{
|
||||
Vector2 screenPosition = obj.ScreenSpaceDrawQuad.Centre;
|
||||
Remove(obj);
|
||||
catcherArea.Add(obj, screenPosition);
|
||||
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
|
||||
Remove(judgedObject);
|
||||
catcherArea.Add(judgedObject, screenPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ using osu.Framework.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
||||
using osu.Game.Rulesets.Catch.Scoring;
|
||||
@ -15,7 +14,7 @@ using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatchRulesetContainer : ScrollingRulesetContainer<CatchPlayfield, CatchBaseHit, CatchJudgement>
|
||||
public class CatchRulesetContainer : ScrollingRulesetContainer<CatchPlayfield, CatchBaseHit>
|
||||
{
|
||||
public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
@ -26,11 +25,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
protected override BeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter();
|
||||
|
||||
protected override Playfield<CatchBaseHit, CatchJudgement> CreatePlayfield() => new CatchPlayfield();
|
||||
protected override Playfield CreatePlayfield() => new CatchPlayfield();
|
||||
|
||||
public override PassThroughInputManager CreateKeyBindingInputManager() => new CatchInputManager(Ruleset?.RulesetInfo);
|
||||
public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);
|
||||
|
||||
protected override DrawableHitObject<CatchBaseHit, CatchJudgement> GetVisualRepresentation(CatchBaseHit h)
|
||||
protected override DrawableHitObject<CatchBaseHit> GetVisualRepresentation(CatchBaseHit h)
|
||||
{
|
||||
if (h is Fruit)
|
||||
return new DrawableFruit(h);
|
||||
|
@ -10,7 +10,6 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -22,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
private Catcher catcher;
|
||||
|
||||
public void Add(DrawableHitObject<CatchBaseHit, CatchJudgement> fruit, Vector2 screenPosition) => catcher.AddToStack(fruit, screenPosition);
|
||||
public void Add(DrawableHitObject fruit, Vector2 screenPosition) => catcher.AddToStack(fruit, screenPosition);
|
||||
|
||||
public bool CheckIfWeCanCatch(CatchBaseHit obj) => Math.Abs(catcher.Position.X - obj.Position) < catcher.DrawSize.X / DrawSize.X / 2;
|
||||
|
||||
@ -85,7 +84,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
var additive = createCatcherSprite();
|
||||
|
||||
additive.RelativePositionAxes = Axes.Both;
|
||||
additive.BlendingMode = BlendingMode.Additive;
|
||||
additive.Blending = BlendingMode.Additive;
|
||||
additive.Position = Position;
|
||||
additive.Scale = Scale;
|
||||
|
||||
@ -152,7 +151,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime / 1800 * speed, 0, 1);
|
||||
}
|
||||
|
||||
public void AddToStack(DrawableHitObject<CatchBaseHit, CatchJudgement> fruit, Vector2 absolutePosition)
|
||||
public void AddToStack(DrawableHitObject fruit, Vector2 absolutePosition)
|
||||
{
|
||||
fruit.RelativePositionAxes = Axes.None;
|
||||
fruit.Position = new Vector2(ToLocalSpace(absolutePosition).X - DrawSize.X / 2, 0);
|
||||
@ -161,11 +160,10 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
fruit.Origin = Anchor.BottomCentre;
|
||||
fruit.Scale *= 0.7f;
|
||||
fruit.LifetimeEnd = double.MaxValue;
|
||||
fruit.Depth = (float)Time.Current;
|
||||
|
||||
float distance = fruit.DrawSize.X / 2 * fruit.Scale.X;
|
||||
|
||||
while (Children.OfType<DrawableFruit>().Any(f => Vector2.DistanceSquared(f.Position, fruit.Position) < distance * distance))
|
||||
while (Children.OfType<DrawableFruit>().Any(f => Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance))
|
||||
{
|
||||
fruit.X += RNG.Next(-5, 5);
|
||||
fruit.Y -= RNG.Next(0, 5);
|
||||
|
11
osu.Game.Rulesets.Catch/app.config
Normal file
11
osu.Game.Rulesets.Catch/app.config
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
@ -9,7 +9,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>osu.Game.Rulesets.Catch</RootNamespace>
|
||||
<AssemblyName>osu.Game.Rulesets.Catch</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
@ -34,7 +34,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
@ -69,6 +69,7 @@
|
||||
<None Include="..\osu.licenseheader">
|
||||
<Link>osu.licenseheader</Link>
|
||||
</None>
|
||||
<None Include="app.config" />
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
|
@ -1,9 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
-->
|
||||
<packages>
|
||||
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||
</packages>
|
@ -28,12 +28,20 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
private Pattern lastPattern = new Pattern();
|
||||
private FastRandom random;
|
||||
private Beatmap beatmap;
|
||||
private bool isForCurrentRuleset;
|
||||
|
||||
protected override Beatmap<ManiaHitObject> ConvertBeatmap(Beatmap original, bool isForCurrentRuleset)
|
||||
private readonly int availableColumns;
|
||||
private readonly bool isForCurrentRuleset;
|
||||
|
||||
public ManiaBeatmapConverter(bool isForCurrentRuleset, int availableColumns)
|
||||
{
|
||||
this.isForCurrentRuleset = isForCurrentRuleset;
|
||||
if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns));
|
||||
|
||||
this.isForCurrentRuleset = isForCurrentRuleset;
|
||||
this.availableColumns = availableColumns;
|
||||
}
|
||||
|
||||
protected override Beatmap<ManiaHitObject> ConvertBeatmap(Beatmap original)
|
||||
{
|
||||
beatmap = original;
|
||||
|
||||
BeatmapDifficulty difficulty = original.BeatmapInfo.Difficulty;
|
||||
@ -41,7 +49,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate);
|
||||
random = new FastRandom(seed);
|
||||
|
||||
return base.ConvertBeatmap(original, isForCurrentRuleset);
|
||||
return base.ConvertBeatmap(original);
|
||||
}
|
||||
|
||||
protected override IEnumerable<ManiaHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
|
||||
@ -89,7 +97,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// <returns>The hit objects generated.</returns>
|
||||
private IEnumerable<ManiaHitObject> generateSpecific(HitObject original)
|
||||
{
|
||||
var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern);
|
||||
var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, availableColumns, lastPattern);
|
||||
|
||||
Pattern newPattern = generator.Generate();
|
||||
lastPattern = newPattern;
|
||||
@ -113,14 +121,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
Patterns.PatternGenerator conversion = null;
|
||||
|
||||
if (distanceData != null)
|
||||
conversion = new DistanceObjectPatternGenerator(random, original, beatmap, lastPattern);
|
||||
conversion = new DistanceObjectPatternGenerator(random, original, beatmap, availableColumns, lastPattern);
|
||||
else if (endTimeData != null)
|
||||
conversion = new EndTimeObjectPatternGenerator(random, original, beatmap);
|
||||
conversion = new EndTimeObjectPatternGenerator(random, original, beatmap, availableColumns);
|
||||
else if (positionData != null)
|
||||
{
|
||||
computeDensity(original.StartTime);
|
||||
|
||||
conversion = new HitObjectPatternGenerator(random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair);
|
||||
conversion = new HitObjectPatternGenerator(random, original, beatmap, availableColumns, lastPattern, lastTime, lastPosition, density, lastStair);
|
||||
|
||||
recordNote(original.StartTime, positionData.Position);
|
||||
}
|
||||
@ -142,8 +150,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// </summary>
|
||||
private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator
|
||||
{
|
||||
public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern)
|
||||
: base(random, hitObject, beatmap, previousPattern)
|
||||
public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern)
|
||||
: base(random, hitObject, beatmap, availableColumns, previousPattern)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
|
||||
private PatternType convertType;
|
||||
|
||||
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern)
|
||||
: base(random, hitObject, beatmap, previousPattern)
|
||||
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern)
|
||||
: base(random, hitObject, beatmap, availableColumns, previousPattern)
|
||||
{
|
||||
convertType = PatternType.None;
|
||||
if (Beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime).KiaiMode)
|
||||
@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
// The true distance, accounting for any repeats
|
||||
double distance = (distanceData?.Distance ?? 0) * repeatCount;
|
||||
// The velocity of the osu! hit object - calculated as the velocity of a slider
|
||||
double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.Difficulty.SliderMultiplier / (timingPoint.BeatLength * difficultyPoint.SpeedMultiplier);
|
||||
double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.Difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier / timingPoint.BeatLength;
|
||||
// The duration of the osu! hit object
|
||||
double osuDuration = distance / osuVelocity;
|
||||
|
||||
|
@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
{
|
||||
private readonly double endTime;
|
||||
|
||||
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap)
|
||||
: base(random, hitObject, beatmap, new Pattern())
|
||||
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns)
|
||||
: base(random, hitObject, beatmap, availableColumns, new Pattern())
|
||||
{
|
||||
var endtimeData = HitObject as IHasEndTime;
|
||||
|
||||
|
@ -20,9 +20,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
|
||||
private readonly PatternType convertType;
|
||||
|
||||
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair)
|
||||
: base(random, hitObject, beatmap, previousPattern)
|
||||
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair)
|
||||
: base(random, hitObject, beatmap, availableColumns, previousPattern)
|
||||
{
|
||||
if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime));
|
||||
if (density < 0) throw new ArgumentOutOfRangeException(nameof(density));
|
||||
|
||||
StairType = lastStair;
|
||||
|
||||
TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime);
|
||||
|
@ -25,11 +25,15 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
/// </summary>
|
||||
protected readonly FastRandom Random;
|
||||
|
||||
protected PatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern)
|
||||
: base(hitObject, beatmap, previousPattern)
|
||||
protected PatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern)
|
||||
: base(hitObject, beatmap, availableColumns, previousPattern)
|
||||
{
|
||||
Random = random;
|
||||
if (random == null) throw new ArgumentNullException(nameof(random));
|
||||
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
|
||||
if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns));
|
||||
if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern));
|
||||
|
||||
Random = random;
|
||||
RandomStart = AvailableColumns == 8 ? 1 : 0;
|
||||
}
|
||||
|
||||
@ -62,6 +66,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
/// <returns>The amount of notes to be generated.</returns>
|
||||
protected int GetRandomNoteCount(double p2, double p3, double p4 = 0, double p5 = 0, double p6 = 0)
|
||||
{
|
||||
if (p2 < 0 || p2 > 1) throw new ArgumentOutOfRangeException(nameof(p2));
|
||||
if (p3 < 0 || p3 > 1) throw new ArgumentOutOfRangeException(nameof(p3));
|
||||
if (p4 < 0 || p4 > 1) throw new ArgumentOutOfRangeException(nameof(p4));
|
||||
if (p5 < 0 || p5 > 1) throw new ArgumentOutOfRangeException(nameof(p5));
|
||||
if (p6 < 0 || p6 > 1) throw new ArgumentOutOfRangeException(nameof(p6));
|
||||
|
||||
double val = Random.NextDouble();
|
||||
if (val >= 1 - p6)
|
||||
return 6;
|
||||
|
@ -32,13 +32,17 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns
|
||||
/// </summary>
|
||||
protected readonly Beatmap Beatmap;
|
||||
|
||||
protected PatternGenerator(HitObject hitObject, Beatmap beatmap, Pattern previousPattern)
|
||||
protected PatternGenerator(HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern)
|
||||
{
|
||||
PreviousPattern = previousPattern;
|
||||
if (hitObject == null) throw new ArgumentNullException(nameof(hitObject));
|
||||
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
|
||||
if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns));
|
||||
if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern));
|
||||
|
||||
HitObject = hitObject;
|
||||
Beatmap = beatmap;
|
||||
|
||||
AvailableColumns = (int)Math.Round(beatmap.BeatmapInfo.Difficulty.CircleSize);
|
||||
AvailableColumns = availableColumns;
|
||||
PreviousPattern = previousPattern;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
@ -145,18 +146,18 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
||||
/// </summary>
|
||||
/// <param name="hitOffset">The time offset.</param>
|
||||
/// <returns>The hit result, or null if the time offset results in a miss.</returns>
|
||||
public ManiaHitResult? ResultFor(double hitOffset)
|
||||
public HitResult? ResultFor(double hitOffset)
|
||||
{
|
||||
if (hitOffset <= Perfect / 2)
|
||||
return ManiaHitResult.Perfect;
|
||||
return HitResult.Perfect;
|
||||
if (hitOffset <= Great / 2)
|
||||
return ManiaHitResult.Great;
|
||||
return HitResult.Great;
|
||||
if (hitOffset <= Good / 2)
|
||||
return ManiaHitResult.Good;
|
||||
return HitResult.Good;
|
||||
if (hitOffset <= Ok / 2)
|
||||
return ManiaHitResult.Ok;
|
||||
return HitResult.Ok;
|
||||
if (hitOffset <= Bad / 2)
|
||||
return ManiaHitResult.Bad;
|
||||
return HitResult.Meh;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public class HoldNoteTailJudgement : ManiaJudgement
|
||||
@ -10,27 +12,15 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
||||
/// </summary>
|
||||
public bool HasBroken;
|
||||
|
||||
public override int NumericResultForScore(ManiaHitResult result)
|
||||
protected override int NumericResultFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return base.NumericResultForScore(result);
|
||||
case ManiaHitResult.Great:
|
||||
case ManiaHitResult.Perfect:
|
||||
return base.NumericResultForScore(HasBroken ? ManiaHitResult.Good : result);
|
||||
}
|
||||
}
|
||||
|
||||
public override int NumericResultForAccuracy(ManiaHitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return base.NumericResultForAccuracy(result);
|
||||
case ManiaHitResult.Great:
|
||||
case ManiaHitResult.Perfect:
|
||||
return base.NumericResultForAccuracy(HasBroken ? ManiaHitResult.Good : result);
|
||||
return base.NumericResultFor(result);
|
||||
case HitResult.Great:
|
||||
case HitResult.Perfect:
|
||||
return base.NumericResultFor(HasBroken ? HitResult.Good : result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public class HoldNoteTickJudgement : ManiaJudgement
|
||||
{
|
||||
public override bool AffectsCombo => false;
|
||||
|
||||
public override int NumericResultForScore(ManiaHitResult result) => 20;
|
||||
public override int NumericResultForAccuracy(ManiaHitResult result) => 0; // Don't count ticks into accuracy
|
||||
protected override int NumericResultFor(HitResult result) => 20;
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public enum ManiaHitResult
|
||||
{
|
||||
[Description("PERFECT")]
|
||||
Perfect,
|
||||
[Description("GREAT")]
|
||||
Great,
|
||||
[Description("GOOD")]
|
||||
Good,
|
||||
[Description("OK")]
|
||||
Ok,
|
||||
[Description("BAD")]
|
||||
Bad
|
||||
}
|
||||
}
|
@ -8,75 +8,22 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public class ManiaJudgement : Judgement
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum possible hit result.
|
||||
/// </summary>
|
||||
public const ManiaHitResult MAX_HIT_RESULT = ManiaHitResult.Perfect;
|
||||
|
||||
/// <summary>
|
||||
/// The result value for the combo portion of the score.
|
||||
/// </summary>
|
||||
public int ResultValueForScore => Result == HitResult.Miss ? 0 : NumericResultForScore(ManiaResult);
|
||||
|
||||
/// <summary>
|
||||
/// The result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int ResultValueForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(ManiaResult);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum result value for the combo portion of the score.
|
||||
/// </summary>
|
||||
public int MaxResultValueForScore => NumericResultForScore(MAX_HIT_RESULT);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int MaxResultValueForAccuracy => NumericResultForAccuracy(MAX_HIT_RESULT);
|
||||
|
||||
public override string ResultString => string.Empty;
|
||||
|
||||
public override string MaxResultString => string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The hit result.
|
||||
/// </summary>
|
||||
public ManiaHitResult ManiaResult;
|
||||
|
||||
public virtual int NumericResultForScore(ManiaHitResult result)
|
||||
protected override int NumericResultFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case ManiaHitResult.Bad:
|
||||
case HitResult.Meh:
|
||||
return 50;
|
||||
case ManiaHitResult.Ok:
|
||||
case HitResult.Ok:
|
||||
return 100;
|
||||
case ManiaHitResult.Good:
|
||||
case HitResult.Good:
|
||||
return 200;
|
||||
case ManiaHitResult.Great:
|
||||
case ManiaHitResult.Perfect:
|
||||
case HitResult.Great:
|
||||
case HitResult.Perfect:
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int NumericResultForAccuracy(ManiaHitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case ManiaHitResult.Bad:
|
||||
return 50;
|
||||
case ManiaHitResult.Ok:
|
||||
return 100;
|
||||
case ManiaHitResult.Good:
|
||||
return 200;
|
||||
case ManiaHitResult.Great:
|
||||
return 300;
|
||||
case ManiaHitResult.Perfect:
|
||||
return 305;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using osu.Game.Rulesets.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
@ -21,6 +22,6 @@ namespace osu.Game.Rulesets.Mania
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter() => new ManiaBeatmapConverter();
|
||||
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter() => new ManiaBeatmapConverter(true, (int)Math.Max(1, Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
41
osu.Game.Rulesets.Mania/ManiaInputManager.cs
Normal file
41
osu.Game.Rulesets.Mania/ManiaInputManager.cs
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
public class ManiaInputManager : RulesetInputManager<ManiaAction>
|
||||
{
|
||||
public ManiaInputManager(RulesetInfo ruleset, int variant)
|
||||
: base(ruleset, variant, SimultaneousBindingMode.Unique)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public enum ManiaAction
|
||||
{
|
||||
[Description("Special")]
|
||||
Special,
|
||||
[Description("Key 1")]
|
||||
Key1 = 10,
|
||||
[Description("Key 2")]
|
||||
Key2,
|
||||
[Description("Key 3")]
|
||||
Key3,
|
||||
[Description("Key 4")]
|
||||
Key4,
|
||||
[Description("Key 5")]
|
||||
Key5,
|
||||
[Description("Key 6")]
|
||||
Key6,
|
||||
[Description("Key 7")]
|
||||
Key7,
|
||||
[Description("Key 8")]
|
||||
Key8,
|
||||
[Description("Key 9")]
|
||||
Key9
|
||||
}
|
||||
}
|
@ -6,12 +6,10 @@ using osu.Game.Rulesets.Mania.Mods;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Scoring;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
@ -93,7 +91,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ModAutoplay(),
|
||||
new ManiaModAutoplay(),
|
||||
new ModCinema(),
|
||||
},
|
||||
},
|
||||
@ -105,23 +103,55 @@ namespace osu.Game.Rulesets.Mania
|
||||
}
|
||||
}
|
||||
|
||||
public override Mod GetAutoplayMod() => new ModAutoplay();
|
||||
|
||||
public override string Description => "osu!mania";
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o };
|
||||
|
||||
public override IEnumerable<KeyCounter> CreateGameplayKeys() => new KeyCounter[] { /* Todo: Should be keymod specific */ };
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap);
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor();
|
||||
|
||||
public override int LegacyID => 3;
|
||||
|
||||
public ManiaRuleset(RulesetInfo rulesetInfo)
|
||||
: base(rulesetInfo)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<int> AvailableVariants => new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
|
||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0)
|
||||
{
|
||||
var leftKeys = new[]
|
||||
{
|
||||
InputKey.A,
|
||||
InputKey.S,
|
||||
InputKey.D,
|
||||
InputKey.F
|
||||
};
|
||||
|
||||
var rightKeys = new[]
|
||||
{
|
||||
InputKey.J,
|
||||
InputKey.K,
|
||||
InputKey.L,
|
||||
InputKey.Semicolon
|
||||
};
|
||||
|
||||
ManiaAction currentKey = ManiaAction.Key1;
|
||||
|
||||
var bindings = new List<KeyBinding>();
|
||||
|
||||
for (int i = leftKeys.Length - variant / 2; i < leftKeys.Length; i++)
|
||||
bindings.Add(new KeyBinding(leftKeys[i], currentKey++));
|
||||
|
||||
for (int i = 0; i < variant / 2; i++)
|
||||
bindings.Add(new KeyBinding(rightKeys[i], currentKey++));
|
||||
|
||||
if (variant % 2 == 1)
|
||||
bindings.Add(new KeyBinding(InputKey.Space, ManiaAction.Special));
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public override string GetVariantName(int variant) => $"{variant}K";
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,16 @@
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Replays;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@ -68,6 +78,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public class ManiaModFadeIn : Mod
|
||||
{
|
||||
public override string Name => "FadeIn";
|
||||
public override string ShortenedName => "FI";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
|
||||
public override ModType Type => ModType.DifficultyIncrease;
|
||||
public override double ScoreMultiplier => 1;
|
||||
@ -75,15 +86,27 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
|
||||
}
|
||||
|
||||
public class ManiaModRandom : Mod
|
||||
public class ManiaModRandom : Mod, IApplicableMod<ManiaHitObject>
|
||||
{
|
||||
public override string Name => "Random";
|
||||
public override string ShortenedName => "RD";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_dice;
|
||||
public override string Description => @"Shuffle around the notes!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
||||
public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
|
||||
{
|
||||
int availableColumns = ((ManiaRulesetContainer)rulesetContainer).AvailableColumns;
|
||||
|
||||
var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList();
|
||||
|
||||
rulesetContainer.Objects.OfType<ManiaHitObject>().ForEach(h => h.Column = shuffledColumns[h.Column]);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ManiaKeyMod : Mod
|
||||
{
|
||||
public override string ShortenedName => Name;
|
||||
public abstract int KeyCount { get; }
|
||||
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier
|
||||
public override bool Ranked => true;
|
||||
@ -146,8 +169,29 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public class ManiaModKeyCoop : Mod
|
||||
{
|
||||
public override string Name => "KeyCoop";
|
||||
public override string ShortenedName => "2P";
|
||||
public override string Description => @"Double the key amount, double the fun!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => true;
|
||||
}
|
||||
|
||||
public class ManiaModAutoplay : ModAutoplay<ManiaHitObject>
|
||||
{
|
||||
private int availableColumns;
|
||||
|
||||
public override void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
|
||||
{
|
||||
// Todo: This shouldn't be done, we should be getting a ManiaBeatmap which should store AvailableColumns
|
||||
// But this is dependent on a _lot_ of refactoring
|
||||
var maniaRulesetContainer = (ManiaRulesetContainer)rulesetContainer;
|
||||
availableColumns = maniaRulesetContainer.AvailableColumns;
|
||||
|
||||
base.ApplyToRulesetContainer(rulesetContainer);
|
||||
}
|
||||
protected override Score CreateReplayScore(Beatmap<ManiaHitObject> beatmap) => new Score
|
||||
{
|
||||
User = new User { Username = "osu!topus!" },
|
||||
Replay = new ManiaAutoGenerator(beatmap, availableColumns).Generate(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@ -15,6 +16,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public class ManiaModGravity : Mod, IGenerateSpeedAdjustments
|
||||
{
|
||||
public override string Name => "Gravity";
|
||||
public override string ShortenedName => "GR";
|
||||
|
||||
public override double ScoreMultiplier => 0;
|
||||
|
||||
@ -23,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List<SpeedAdjustmentContainer>[] hitObjectTimingChanges, ref List<SpeedAdjustmentContainer> barlineTimingChanges)
|
||||
{
|
||||
// We have to generate one speed adjustment per hit object for gravity
|
||||
foreach (ManiaHitObject obj in rulesetContainer.Objects)
|
||||
foreach (ManiaHitObject obj in rulesetContainer.Objects.OfType<ManiaHitObject>())
|
||||
{
|
||||
MultiplierControlPoint controlPoint = rulesetContainer.CreateControlPointAt(obj.StartTime);
|
||||
// Beat length has too large of an effect for gravity, so we'll force it to a constant value for now
|
||||
|
@ -1,30 +1,32 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Configuration;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Input.Bindings;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="HoldNote"/> hit object.
|
||||
/// </summary>
|
||||
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>
|
||||
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly DrawableNote head;
|
||||
private readonly DrawableNote tail;
|
||||
|
||||
private readonly GlowPiece glowPiece;
|
||||
private readonly BodyPiece bodyPiece;
|
||||
private readonly Container<DrawableHoldNoteTick> tickContainer;
|
||||
private readonly Container fullHeightContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
|
||||
@ -36,21 +38,26 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
/// </summary>
|
||||
private bool hasBroken;
|
||||
|
||||
public DrawableHoldNote(HoldNote hitObject, Bindable<Key> key = null)
|
||||
: base(hitObject, key)
|
||||
public DrawableHoldNote(HoldNote hitObject, ManiaAction action)
|
||||
: base(hitObject, action)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Height = (float)HitObject.Duration;
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
// For now the body piece covers the entire height of the container
|
||||
// whereas possibly in the future we don't want to extend under the head/tail.
|
||||
// This will be fixed when new designs are given or the current design is finalized.
|
||||
// The hit object itself cannot be used for various elements because the tail overshoots it
|
||||
// So a specialized container that is updated to contain the tail height is used
|
||||
fullHeightContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Child = glowPiece = new GlowPiece()
|
||||
},
|
||||
bodyPiece = new BodyPiece
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
tickContainer = new Container<DrawableHoldNoteTick>
|
||||
{
|
||||
@ -58,12 +65,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime),
|
||||
RelativeChildSize = new Vector2(1, (float)HitObject.Duration)
|
||||
},
|
||||
head = new DrawableHeadNote(this, key)
|
||||
head = new DrawableHeadNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
},
|
||||
tail = new DrawableTailNote(this, key)
|
||||
tail = new DrawableTailNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
@ -96,6 +103,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
tickContainer.Children.ForEach(t => t.AccentColour = value);
|
||||
|
||||
glowPiece.AccentColour = value;
|
||||
bodyPiece.AccentColour = value;
|
||||
head.AccentColour = value;
|
||||
tail.AccentColour = value;
|
||||
@ -106,16 +114,26 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
protected override void Update()
|
||||
{
|
||||
// Make sure the keypress happened within the body of the hold note
|
||||
base.Update();
|
||||
|
||||
// Make the body piece not lie under the head note
|
||||
bodyPiece.Y = head.Height;
|
||||
bodyPiece.Height = DrawHeight - head.Height;
|
||||
|
||||
// Make the fullHeightContainer "contain" the height of the tail note, keeping in mind
|
||||
// that the tail note overshoots the height of this hit object
|
||||
fullHeightContainer.Height = DrawHeight + tail.Height;
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
// Make sure the action happened within the body of the hold note
|
||||
if (Time.Current < HitObject.StartTime || Time.Current > HitObject.EndTime)
|
||||
return false;
|
||||
|
||||
if (args.Key != Key)
|
||||
return false;
|
||||
|
||||
if (args.Repeat)
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
// The user has pressed during the body of the hold note, after the head note and its hit windows have passed
|
||||
@ -126,19 +144,19 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args)
|
||||
public bool OnReleased(ManiaAction action)
|
||||
{
|
||||
// Make sure that the user started holding the key during the hold note
|
||||
if (!holdStartTime.HasValue)
|
||||
return false;
|
||||
|
||||
if (args.Key != Key)
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
holdStartTime = null;
|
||||
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (!tail.Judged)
|
||||
if (!tail.AllJudged)
|
||||
hasBroken = true;
|
||||
|
||||
return true;
|
||||
@ -151,26 +169,28 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
private readonly DrawableHoldNote holdNote;
|
||||
|
||||
public DrawableHeadNote(DrawableHoldNote holdNote, Bindable<Key> key = null)
|
||||
: base(holdNote.HitObject.Head, key)
|
||||
public DrawableHeadNote(DrawableHoldNote holdNote, ManiaAction action)
|
||||
: base(holdNote.HitObject.Head, action)
|
||||
{
|
||||
this.holdNote = holdNote;
|
||||
|
||||
RelativePositionAxes = Axes.None;
|
||||
Y = 0;
|
||||
|
||||
// Life time managed by the parent DrawableHoldNote
|
||||
LifetimeStart = double.MinValue;
|
||||
LifetimeEnd = double.MaxValue;
|
||||
|
||||
GlowPiece.Alpha = 0;
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
public override bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (!base.OnKeyDown(state, args))
|
||||
return false;
|
||||
|
||||
// We only want to trigger a holding state from the head if the head has received a judgement
|
||||
if (!Judged)
|
||||
if (!base.OnPressed(action))
|
||||
return false;
|
||||
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (Judgement.Result == HitResult.Miss)
|
||||
if (Judgements.Any(j => j.Result == HitResult.Miss))
|
||||
holdNote.hasBroken = true;
|
||||
|
||||
// The head note also handles early hits before the body, but we want accurate early hits to count as the body being held
|
||||
@ -188,38 +208,58 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
private readonly DrawableHoldNote holdNote;
|
||||
|
||||
public DrawableTailNote(DrawableHoldNote holdNote, Bindable<Key> key = null)
|
||||
: base(holdNote.HitObject.Tail, key)
|
||||
public DrawableTailNote(DrawableHoldNote holdNote, ManiaAction action)
|
||||
: base(holdNote.HitObject.Tail, action)
|
||||
{
|
||||
this.holdNote = holdNote;
|
||||
|
||||
RelativePositionAxes = Axes.None;
|
||||
Y = 0;
|
||||
|
||||
// Life time managed by the parent DrawableHoldNote
|
||||
LifetimeStart = double.MinValue;
|
||||
LifetimeEnd = double.MaxValue;
|
||||
|
||||
GlowPiece.Alpha = 0;
|
||||
}
|
||||
|
||||
protected override ManiaJudgement CreateJudgement() => new HoldNoteTailJudgement();
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
base.CheckJudgement(userTriggered);
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (timeOffset > HitObject.HitWindows.Bad / 2)
|
||||
{
|
||||
AddJudgement(new HoldNoteTailJudgement
|
||||
{
|
||||
Result = HitResult.Miss,
|
||||
HasBroken = holdNote.hasBroken
|
||||
});
|
||||
}
|
||||
|
||||
var tailJudgement = Judgement as HoldNoteTailJudgement;
|
||||
if (tailJudgement == null)
|
||||
return;
|
||||
}
|
||||
|
||||
double offset = Math.Abs(timeOffset);
|
||||
|
||||
if (offset > HitObject.HitWindows.Miss / 2)
|
||||
return;
|
||||
|
||||
tailJudgement.HasBroken = holdNote.hasBroken;
|
||||
AddJudgement(new HoldNoteTailJudgement
|
||||
{
|
||||
Result = HitObject.HitWindows.ResultFor(offset) ?? HitResult.Miss,
|
||||
HasBroken = holdNote.hasBroken
|
||||
});
|
||||
}
|
||||
|
||||
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args)
|
||||
public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down
|
||||
|
||||
public override bool OnReleased(ManiaAction action)
|
||||
{
|
||||
// Make sure that the user started holding the key during the hold note
|
||||
if (!holdNote.holdStartTime.HasValue)
|
||||
return false;
|
||||
|
||||
if (Judgement.Result != HitResult.None)
|
||||
return false;
|
||||
|
||||
if (args.Key != Key)
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
UpdateJudgement(true);
|
||||
@ -227,12 +267,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
// Handled by the hold note, which will set holding = false
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
// Tail doesn't handle key down
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
/// </summary>
|
||||
public Func<double?> HoldStartTime;
|
||||
|
||||
/// <summary>
|
||||
/// References whether the user is currently holding the hold note.
|
||||
/// </summary>
|
||||
public Func<bool> IsHolding;
|
||||
|
||||
private readonly Container glowContainer;
|
||||
|
||||
public DrawableHoldNoteTick(HoldNoteTick hitObject)
|
||||
@ -36,9 +31,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.TopCentre;
|
||||
|
||||
Y = (float)HitObject.StartTime;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Size = new Vector2(1);
|
||||
|
||||
// Life time managed by the parent DrawableHoldNote
|
||||
LifetimeStart = double.MinValue;
|
||||
LifetimeEnd = double.MaxValue;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
glowContainer = new CircularContainer
|
||||
@ -58,9 +59,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Set the default glow
|
||||
AccentColour = Color4.White;
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
@ -80,9 +78,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
protected override ManiaJudgement CreateJudgement() => new HoldNoteTickJudgement();
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
return;
|
||||
@ -93,8 +89,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
if (HoldStartTime?.Invoke() > HitObject.StartTime)
|
||||
return;
|
||||
|
||||
Judgement.ManiaResult = ManiaHitResult.Perfect;
|
||||
Judgement.Result = HitResult.Hit;
|
||||
AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
@ -109,10 +104,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (Judgement.Result != HitResult.None)
|
||||
if (AllJudged)
|
||||
return;
|
||||
|
||||
if (IsHolding?.Invoke() != true)
|
||||
if (HoldStartTime?.Invoke() == null)
|
||||
return;
|
||||
|
||||
UpdateJudgement(true);
|
||||
|
@ -1,31 +1,30 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableManiaHitObject<TObject> : DrawableScrollingHitObject<ManiaHitObject, ManiaJudgement>
|
||||
public abstract class DrawableManiaHitObject<TObject> : DrawableScrollingHitObject<ManiaHitObject>
|
||||
where TObject : ManiaHitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// The key that will trigger input for this hit object.
|
||||
/// </summary>
|
||||
protected Bindable<Key> Key { get; private set; } = new Bindable<Key>();
|
||||
protected ManiaAction Action { get; }
|
||||
|
||||
public new TObject HitObject;
|
||||
|
||||
protected DrawableManiaHitObject(TObject hitObject, Bindable<Key> key = null)
|
||||
protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null)
|
||||
: base(hitObject)
|
||||
{
|
||||
RelativePositionAxes = Axes.Y;
|
||||
HitObject = hitObject;
|
||||
|
||||
if (key != null)
|
||||
Key.BindTo(key);
|
||||
if (action != null)
|
||||
Action = action.Value;
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
@ -38,7 +37,5 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
base.AccentColour = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override ManiaJudgement CreateJudgement() => new ManiaJudgement();
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,8 @@
|
||||
|
||||
using System;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -16,21 +14,33 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="Note"/> hit object.
|
||||
/// </summary>
|
||||
public class DrawableNote : DrawableManiaHitObject<Note>
|
||||
public class DrawableNote : DrawableManiaHitObject<Note>, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
protected readonly GlowPiece GlowPiece;
|
||||
|
||||
private readonly LaneGlowPiece laneGlowPiece;
|
||||
private readonly NotePiece headPiece;
|
||||
|
||||
public DrawableNote(Note hitObject, Bindable<Key> key = null)
|
||||
: base(hitObject, key)
|
||||
public DrawableNote(Note hitObject, ManiaAction action)
|
||||
: base(hitObject, action)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 100;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
Add(headPiece = new NotePiece
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
});
|
||||
laneGlowPiece = new LaneGlowPiece
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
},
|
||||
GlowPiece = new GlowPiece(),
|
||||
headPiece = new NotePiece
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
@ -42,57 +52,41 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
return;
|
||||
base.AccentColour = value;
|
||||
|
||||
laneGlowPiece.AccentColour = value;
|
||||
GlowPiece.AccentColour = value;
|
||||
headPiece.AccentColour = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset > HitObject.HitWindows.Bad / 2)
|
||||
Judgement.Result = HitResult.Miss;
|
||||
if (timeOffset > HitObject.HitWindows.Bad / 2)
|
||||
AddJudgement(new ManiaJudgement { Result = HitResult.Miss });
|
||||
return;
|
||||
}
|
||||
|
||||
double offset = Math.Abs(Judgement.TimeOffset);
|
||||
double offset = Math.Abs(timeOffset);
|
||||
|
||||
if (offset > HitObject.HitWindows.Miss / 2)
|
||||
return;
|
||||
|
||||
ManiaHitResult? tmpResult = HitObject.HitWindows.ResultFor(offset);
|
||||
|
||||
if (tmpResult.HasValue)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.ManiaResult = tmpResult.Value;
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
AddJudgement(new ManiaJudgement { Result = HitObject.HitWindows.ResultFor(offset) ?? HitResult.Miss });
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
switch (State)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
Colour = Color4.Green;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
public virtual bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (Judgement.Result != HitResult.None)
|
||||
return false;
|
||||
|
||||
if (args.Key != Key)
|
||||
return false;
|
||||
|
||||
if (args.Repeat)
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
return UpdateJudgement(true);
|
||||
}
|
||||
|
||||
public virtual bool OnReleased(ManiaAction action) => false;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Caching;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -14,22 +17,61 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
/// </summary>
|
||||
internal class BodyPiece : Container, IHasAccentColour
|
||||
{
|
||||
private readonly Box box;
|
||||
private readonly Container subtractionLayer;
|
||||
|
||||
private readonly Drawable background;
|
||||
private readonly BufferedContainer foreground;
|
||||
private readonly BufferedContainer subtractionContainer;
|
||||
|
||||
public BodyPiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Blending = BlendingMode.Additive;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
box = new Box
|
||||
background = new Box { RelativeSizeAxes = Axes.Both },
|
||||
foreground = new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.3f
|
||||
CacheDrawnFrameBuffer = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box { RelativeSizeAxes = Axes.Both },
|
||||
subtractionContainer = new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// This is needed because we're blending with another object
|
||||
BackgroundColour = Color4.White.Opacity(0),
|
||||
CacheDrawnFrameBuffer = true,
|
||||
// The 'hole' is achieved by subtracting the result of this container with the parent
|
||||
Blending = new BlendingParameters { AlphaEquation = BlendingEquation.ReverseSubtract },
|
||||
Child = subtractionLayer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
// Height computed in Update
|
||||
Width = 1,
|
||||
Masking = true,
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
updateAccentColour();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
{
|
||||
@ -40,8 +82,51 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
box.Colour = accentColour;
|
||||
updateAccentColour();
|
||||
}
|
||||
}
|
||||
|
||||
private Cached subtractionCache = new Cached();
|
||||
|
||||
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()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!subtractionCache.IsValid)
|
||||
{
|
||||
subtractionLayer.Width = 5;
|
||||
subtractionLayer.Height = Math.Max(0, DrawHeight - DrawWidth);
|
||||
subtractionLayer.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Colour = Color4.White,
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = DrawWidth
|
||||
};
|
||||
|
||||
foreground.ForceRedraw();
|
||||
subtractionContainer.ForceRedraw();
|
||||
|
||||
subtractionCache.Validate();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAccentColour()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
foreground.Colour = AccentColour.Opacity(0.4f);
|
||||
background.Colour = AccentColour.Opacity(0.2f);
|
||||
|
||||
subtractionCache.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
public class GlowPiece : CompositeDrawable, IHasAccentColour
|
||||
{
|
||||
private const float glow_alpha = 0.7f;
|
||||
private const float glow_radius = 5;
|
||||
|
||||
public GlowPiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
|
||||
InternalChild = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateGlow();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
updateGlow();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGlow()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = AccentColour.Opacity(glow_alpha),
|
||||
Radius = glow_radius,
|
||||
Hollow = true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
public class LaneGlowPiece : CompositeDrawable, IHasAccentColour
|
||||
{
|
||||
private const float total_height = 100;
|
||||
private const float glow_height = 50;
|
||||
private const float glow_alpha = 0.4f;
|
||||
private const float edge_alpha = 0.3f;
|
||||
|
||||
public LaneGlowPiece()
|
||||
{
|
||||
BypassAutoSizeAxes = Axes.Both;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = total_height;
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Name = "Left edge",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 1,
|
||||
Children = createGradient(edge_alpha)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Right edge",
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 1,
|
||||
Children = createGradient(edge_alpha)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Glow",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = glow_height,
|
||||
Children = createGradient(glow_alpha)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Drawable[] createGradient(float alpha) => new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Name = "Top",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White.Opacity(alpha))
|
||||
},
|
||||
new Box
|
||||
{
|
||||
Name = "Bottom",
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = ColourInfo.GradientVertical(Color4.White.Opacity(alpha), Color4.Transparent)
|
||||
}
|
||||
};
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return Colour; }
|
||||
set { Colour = value; }
|
||||
}
|
||||
}
|
||||
}
|
@ -37,6 +37,17 @@ namespace osu.Game.Rulesets.Mania.Objects
|
||||
}
|
||||
}
|
||||
|
||||
public override int Column
|
||||
{
|
||||
get { return base.Column; }
|
||||
set
|
||||
{
|
||||
base.Column = value;
|
||||
Head.Column = value;
|
||||
Tail.Column = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The head note of the hold.
|
||||
/// </summary>
|
||||
@ -80,7 +91,8 @@ namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
ret.Add(new HoldNoteTick
|
||||
{
|
||||
StartTime = t
|
||||
StartTime = t,
|
||||
Column = Column
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
public abstract class ManiaHitObject : HitObject, IHasColumn
|
||||
{
|
||||
public int Column { get; set; }
|
||||
public virtual int Column { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,3 @@
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
-->
|
||||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
|
133
osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs
Normal file
133
osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs
Normal file
@ -0,0 +1,133 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Replays
|
||||
{
|
||||
internal class ManiaAutoGenerator : AutoGenerator<ManiaHitObject>
|
||||
{
|
||||
private const double release_delay = 20;
|
||||
|
||||
private readonly int availableColumns;
|
||||
|
||||
public ManiaAutoGenerator(Beatmap<ManiaHitObject> beatmap, int availableColumns)
|
||||
: base(beatmap)
|
||||
{
|
||||
this.availableColumns = availableColumns;
|
||||
|
||||
Replay = new Replay { User = new User { Username = @"Autoplay" } };
|
||||
}
|
||||
|
||||
protected Replay Replay;
|
||||
|
||||
public override Replay Generate()
|
||||
{
|
||||
// Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled
|
||||
Replay.Frames.Add(new ReplayFrame(-100000, null, null, ReplayButtonState.None));
|
||||
|
||||
double[] holdEndTimes = new double[availableColumns];
|
||||
for (int i = 0; i < availableColumns; i++)
|
||||
holdEndTimes[i] = double.NegativeInfinity;
|
||||
|
||||
// Notes are handled row-by-row
|
||||
foreach (var objGroup in Beatmap.HitObjects.GroupBy(h => h.StartTime))
|
||||
{
|
||||
double groupTime = objGroup.Key;
|
||||
|
||||
int activeColumns = 0;
|
||||
|
||||
// Get the previously held-down active columns
|
||||
for (int i = 0; i < availableColumns; i++)
|
||||
{
|
||||
if (holdEndTimes[i] > groupTime)
|
||||
activeColumns |= 1 << i;
|
||||
}
|
||||
|
||||
// Add on the group columns, keeping track of the held notes for the next rows
|
||||
foreach (var obj in objGroup)
|
||||
{
|
||||
var holdNote = obj as HoldNote;
|
||||
if (holdNote != null)
|
||||
holdEndTimes[obj.Column] = Math.Max(holdEndTimes[obj.Column], holdNote.EndTime);
|
||||
|
||||
activeColumns |= 1 << obj.Column;
|
||||
}
|
||||
|
||||
Replay.Frames.Add(new ReplayFrame(groupTime, activeColumns, null, ReplayButtonState.None));
|
||||
|
||||
// Add the release frames. We can't do this with the loop above because we need activeColumns to be fully populated
|
||||
foreach (var obj in objGroup.GroupBy(h => (h as IHasEndTime)?.EndTime ?? h.StartTime + release_delay).OrderBy(h => h.Key))
|
||||
{
|
||||
var groupEndTime = obj.Key;
|
||||
|
||||
int activeColumnsAtEnd = 0;
|
||||
for (int i = 0; i < availableColumns; i++)
|
||||
{
|
||||
if (holdEndTimes[i] > groupEndTime)
|
||||
activeColumnsAtEnd |= 1 << i;
|
||||
}
|
||||
|
||||
Replay.Frames.Add(new ReplayFrame(groupEndTime, activeColumnsAtEnd, 0, ReplayButtonState.None));
|
||||
}
|
||||
}
|
||||
|
||||
Replay.Frames = Replay.Frames
|
||||
// Pick the maximum activeColumns for all frames at the same time
|
||||
.GroupBy(f => f.Time)
|
||||
.Select(g => new ReplayFrame(g.First().Time, maxMouseX(g), 0, ReplayButtonState.None))
|
||||
// The addition of release frames above maybe result in unordered frames, but we need them ordered
|
||||
.OrderBy(f => f.Time)
|
||||
.ToList();
|
||||
|
||||
return Replay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the maximum <see cref="ReplayFrame.MouseX"/> by count of bits from a grouping of <see cref="ReplayFrame"/>s.
|
||||
/// </summary>
|
||||
/// <param name="group">The <see cref="ReplayFrame"/> grouping to search.</param>
|
||||
/// <returns>The maximum <see cref="ReplayFrame.MouseX"/> by count of bits.</returns>
|
||||
private float maxMouseX(IGrouping<double, ReplayFrame> group)
|
||||
{
|
||||
int currentCount = -1;
|
||||
int currentMax = 0;
|
||||
|
||||
foreach (var val in group)
|
||||
{
|
||||
int newCount = countBits((int)(val.MouseX ?? 0));
|
||||
if (newCount > currentCount)
|
||||
{
|
||||
currentCount = newCount;
|
||||
currentMax = (int)(val.MouseX ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
return currentMax;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Counts the number of bits set in a value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to count.</param>
|
||||
/// <returns>The number of set bits.</returns>
|
||||
private int countBits(int value)
|
||||
{
|
||||
int count = 0;
|
||||
while (value > 0)
|
||||
{
|
||||
if ((value & 1) > 0)
|
||||
count++;
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Replays
|
||||
{
|
||||
internal class ManiaFramedReplayInputHandler : FramedReplayInputHandler
|
||||
{
|
||||
public ManiaFramedReplayInputHandler(Replay replay)
|
||||
: base(replay)
|
||||
{
|
||||
}
|
||||
|
||||
public override List<InputState> GetPendingStates()
|
||||
{
|
||||
var actions = new List<ManiaAction>();
|
||||
|
||||
int activeColumns = (int)(CurrentFrame.MouseX ?? 0);
|
||||
|
||||
int counter = 0;
|
||||
while (activeColumns > 0)
|
||||
{
|
||||
if ((activeColumns & 1) > 0)
|
||||
actions.Add(ManiaAction.Key1 + counter);
|
||||
counter++;
|
||||
activeColumns >>= 1;
|
||||
}
|
||||
|
||||
return new List<InputState> { new ReplayState<ManiaAction> { PressedActions = actions } };
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -12,34 +12,8 @@ using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Scoring
|
||||
{
|
||||
internal class ManiaScoreProcessor : ScoreProcessor<ManiaHitObject, ManiaJudgement>
|
||||
internal class ManiaScoreProcessor : ScoreProcessor<ManiaHitObject>
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum score achievable.
|
||||
/// Does _not_ include bonus score - for bonus score see <see cref="bonusScore"/>.
|
||||
/// </summary>
|
||||
private const int max_score = 1000000;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of the score attributed to combo.
|
||||
/// </summary>
|
||||
private const double combo_portion_max = max_score * 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of the score attributed to accuracy.
|
||||
/// </summary>
|
||||
private const double accuracy_portion_max = max_score * 0.8;
|
||||
|
||||
/// <summary>
|
||||
/// The factor used to determine relevance of combos.
|
||||
/// </summary>
|
||||
private const double combo_base = 4;
|
||||
|
||||
/// <summary>
|
||||
/// The combo value at which hit objects result in the max score possible.
|
||||
/// </summary>
|
||||
private const int combo_relevance_cap = 400;
|
||||
|
||||
/// <summary>
|
||||
/// The hit HP multiplier at OD = 0.
|
||||
/// </summary>
|
||||
@ -115,52 +89,16 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
/// </summary>
|
||||
private double hpMultiplier = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The cumulative combo portion of the score.
|
||||
/// </summary>
|
||||
private double comboScore => combo_portion_max * comboPortion / maxComboPortion;
|
||||
|
||||
/// <summary>
|
||||
/// The cumulative accuracy portion of the score.
|
||||
/// </summary>
|
||||
private double accuracyScore => accuracy_portion_max * Math.Pow(Accuracy, 4) * totalHits / maxTotalHits;
|
||||
|
||||
/// <summary>
|
||||
/// The cumulative bonus score.
|
||||
/// This is added on top of <see cref="max_score"/>, thus the total score can exceed <see cref="max_score"/>.
|
||||
/// </summary>
|
||||
private double bonusScore;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="comboPortion"/> achieved by a perfect playthrough.
|
||||
/// </summary>
|
||||
private double maxComboPortion;
|
||||
|
||||
/// <summary>
|
||||
/// The portion of the score dedicated to combo.
|
||||
/// </summary>
|
||||
private double comboPortion;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="totalHits"/> achieved by a perfect playthrough.
|
||||
/// </summary>
|
||||
private int maxTotalHits;
|
||||
|
||||
/// <summary>
|
||||
/// The total hits.
|
||||
/// </summary>
|
||||
private int totalHits;
|
||||
|
||||
public ManiaScoreProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
public ManiaScoreProcessor(RulesetContainer<ManiaHitObject, ManiaJudgement> rulesetContainer)
|
||||
public ManiaScoreProcessor(RulesetContainer<ManiaHitObject> rulesetContainer)
|
||||
: base(rulesetContainer)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ComputeTargets(Beatmap<ManiaHitObject> beatmap)
|
||||
protected override void SimulateAutoplay(Beatmap<ManiaHitObject> beatmap)
|
||||
{
|
||||
BeatmapDifficulty difficulty = beatmap.BeatmapInfo.Difficulty;
|
||||
hpMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_min, hp_multiplier_mid, hp_multiplier_max);
|
||||
@ -172,40 +110,18 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
{
|
||||
var holdNote = obj as HoldNote;
|
||||
|
||||
if (obj is Note)
|
||||
{
|
||||
AddJudgement(new ManiaJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
ManiaResult = ManiaHitResult.Perfect
|
||||
});
|
||||
}
|
||||
else if (holdNote != null)
|
||||
if (holdNote != null)
|
||||
{
|
||||
// Head
|
||||
AddJudgement(new ManiaJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
ManiaResult = ManiaJudgement.MAX_HIT_RESULT
|
||||
});
|
||||
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
||||
|
||||
// Ticks
|
||||
int tickCount = holdNote.Ticks.Count();
|
||||
for (int i = 0; i < tickCount; i++)
|
||||
{
|
||||
AddJudgement(new HoldNoteTickJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
ManiaResult = ManiaJudgement.MAX_HIT_RESULT,
|
||||
});
|
||||
}
|
||||
|
||||
AddJudgement(new HoldNoteTailJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
ManiaResult = ManiaJudgement.MAX_HIT_RESULT
|
||||
});
|
||||
AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
|
||||
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
|
||||
if (!HasFailed)
|
||||
@ -214,81 +130,45 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
hpMultiplier *= 1.01;
|
||||
hpMissMultiplier *= 0.98;
|
||||
|
||||
Reset();
|
||||
Reset(false);
|
||||
}
|
||||
|
||||
maxTotalHits = totalHits;
|
||||
maxComboPortion = comboPortion;
|
||||
}
|
||||
|
||||
protected override void OnNewJudgement(ManiaJudgement judgement)
|
||||
protected override void OnNewJudgement(Judgement judgement)
|
||||
{
|
||||
base.OnNewJudgement(judgement);
|
||||
|
||||
bool isTick = judgement is HoldNoteTickJudgement;
|
||||
|
||||
if (!isTick)
|
||||
totalHits++;
|
||||
|
||||
switch (judgement.Result)
|
||||
if (isTick)
|
||||
{
|
||||
case HitResult.Miss:
|
||||
Health.Value += hpMissMultiplier * hp_increase_miss;
|
||||
break;
|
||||
case HitResult.Hit:
|
||||
if (isTick)
|
||||
{
|
||||
Health.Value += hpMultiplier * hp_increase_tick;
|
||||
bonusScore += judgement.ResultValueForScore;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (judgement.ManiaResult)
|
||||
{
|
||||
case ManiaHitResult.Bad:
|
||||
Health.Value += hpMultiplier * hp_increase_bad;
|
||||
break;
|
||||
case ManiaHitResult.Ok:
|
||||
Health.Value += hpMultiplier * hp_increase_ok;
|
||||
break;
|
||||
case ManiaHitResult.Good:
|
||||
Health.Value += hpMultiplier * hp_increase_good;
|
||||
break;
|
||||
case ManiaHitResult.Great:
|
||||
Health.Value += hpMultiplier * hp_increase_great;
|
||||
break;
|
||||
case ManiaHitResult.Perfect:
|
||||
Health.Value += hpMultiplier * hp_increase_perfect;
|
||||
break;
|
||||
}
|
||||
|
||||
// A factor that is applied to make higher combos more relevant
|
||||
double comboRelevance = Math.Min(Math.Max(0.5, Math.Log(Combo.Value, combo_base)), Math.Log(combo_relevance_cap, combo_base));
|
||||
comboPortion += judgement.ResultValueForScore * comboRelevance;
|
||||
}
|
||||
break;
|
||||
if (judgement.IsHit)
|
||||
Health.Value += hpMultiplier * hp_increase_tick;
|
||||
}
|
||||
|
||||
int scoreForAccuracy = 0;
|
||||
int maxScoreForAccuracy = 0;
|
||||
|
||||
foreach (var j in Judgements)
|
||||
else
|
||||
{
|
||||
scoreForAccuracy += j.ResultValueForAccuracy;
|
||||
maxScoreForAccuracy += j.MaxResultValueForAccuracy;
|
||||
switch (judgement.Result)
|
||||
{
|
||||
case HitResult.Miss:
|
||||
Health.Value += hpMissMultiplier * hp_increase_miss;
|
||||
break;
|
||||
case HitResult.Meh:
|
||||
Health.Value += hpMultiplier * hp_increase_bad;
|
||||
break;
|
||||
case HitResult.Ok:
|
||||
Health.Value += hpMultiplier * hp_increase_ok;
|
||||
break;
|
||||
case HitResult.Good:
|
||||
Health.Value += hpMultiplier * hp_increase_good;
|
||||
break;
|
||||
case HitResult.Great:
|
||||
Health.Value += hpMultiplier * hp_increase_great;
|
||||
break;
|
||||
case HitResult.Perfect:
|
||||
Health.Value += hpMultiplier * hp_increase_perfect;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy;
|
||||
TotalScore.Value = comboScore + accuracyScore + bonusScore;
|
||||
}
|
||||
|
||||
protected override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
Health.Value = 1;
|
||||
|
||||
bonusScore = 0;
|
||||
comboPortion = 0;
|
||||
totalHits = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,24 +3,21 @@
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using System;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
public class Column : ScrollingPlayfield<ManiaHitObject, ManiaJudgement>, IHasAccentColour
|
||||
public class Column : ScrollingPlayfield, IHasAccentColour
|
||||
{
|
||||
private const float key_icon_size = 10;
|
||||
private const float key_icon_corner_radius = 3;
|
||||
@ -32,18 +29,21 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
private const float column_width = 45;
|
||||
private const float special_column_width = 70;
|
||||
|
||||
/// <summary>
|
||||
/// The key that will trigger input actions for this column and hit objects contained inside it.
|
||||
/// </summary>
|
||||
public Bindable<Key> Key = new Bindable<Key>();
|
||||
public ManiaAction Action;
|
||||
|
||||
private readonly Box background;
|
||||
private readonly Container hitTargetBar;
|
||||
private readonly Container keyIcon;
|
||||
|
||||
internal readonly Container TopLevelContainer;
|
||||
private readonly Container explosionContainer;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container<Drawable> content;
|
||||
|
||||
private const float opacity_released = 0.1f;
|
||||
private const float opacity_pressed = 0.25f;
|
||||
|
||||
public Column()
|
||||
: base(Axes.Y)
|
||||
{
|
||||
@ -53,9 +53,9 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
Name = "Foreground",
|
||||
Name = "Background",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.2f
|
||||
Alpha = opacity_released
|
||||
},
|
||||
new Container
|
||||
{
|
||||
@ -101,8 +101,13 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
// For column lighting, we need to capture input events before the notes
|
||||
new InputTarget
|
||||
{
|
||||
KeyDown = onKeyDown,
|
||||
KeyUp = onKeyUp
|
||||
Pressed = onPressed,
|
||||
Released = onReleased
|
||||
},
|
||||
explosionContainer = new Container
|
||||
{
|
||||
Name = "Hit explosions",
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -141,8 +146,11 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||
};
|
||||
|
||||
TopLevelContainer.Add(explosionContainer.CreateProxy());
|
||||
}
|
||||
|
||||
public override Axes RelativeSizeAxes => Axes.Y;
|
||||
@ -193,31 +201,38 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
/// Adds a DrawableHitObject to this Playfield.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The DrawableHitObject to add.</param>
|
||||
public override void Add(DrawableHitObject<ManiaHitObject, ManiaJudgement> hitObject)
|
||||
public override void Add(DrawableHitObject hitObject)
|
||||
{
|
||||
hitObject.Depth = (float)hitObject.HitObject.StartTime;
|
||||
|
||||
hitObject.AccentColour = AccentColour;
|
||||
HitObjects.Add(hitObject);
|
||||
}
|
||||
|
||||
private bool onKeyDown(InputState state, KeyDownEventArgs args)
|
||||
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
if (args.Repeat)
|
||||
return false;
|
||||
if (!judgement.IsHit)
|
||||
return;
|
||||
|
||||
if (args.Key == Key)
|
||||
explosionContainer.Add(new HitExplosion(judgedObject));
|
||||
}
|
||||
|
||||
private bool onPressed(ManiaAction action)
|
||||
{
|
||||
if (action == Action)
|
||||
{
|
||||
background.FadeTo(background.Alpha + 0.2f, 50, Easing.OutQuint);
|
||||
background.FadeTo(opacity_pressed, 50, Easing.OutQuint);
|
||||
keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool onKeyUp(InputState state, KeyUpEventArgs args)
|
||||
private bool onReleased(ManiaAction action)
|
||||
{
|
||||
if (args.Key == Key)
|
||||
if (action == Action)
|
||||
{
|
||||
background.FadeTo(0.2f, 800, Easing.OutQuart);
|
||||
background.FadeTo(opacity_released, 800, Easing.OutQuart);
|
||||
keyIcon.ScaleTo(1f, 400, Easing.OutQuart);
|
||||
}
|
||||
|
||||
@ -227,10 +242,10 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
/// <summary>
|
||||
/// This is a simple container which delegates various input events that have to be captured before the notes.
|
||||
/// </summary>
|
||||
private class InputTarget : Container
|
||||
private class InputTarget : Container, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
public Func<InputState, KeyDownEventArgs, bool> KeyDown;
|
||||
public Func<InputState, KeyUpEventArgs, bool> KeyUp;
|
||||
public Func<ManiaAction, bool> Pressed;
|
||||
public Func<ManiaAction, bool> Released;
|
||||
|
||||
public InputTarget()
|
||||
{
|
||||
@ -239,8 +254,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
Alpha = 0;
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => KeyDown?.Invoke(state, args) ?? false;
|
||||
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => KeyUp?.Invoke(state, args) ?? false;
|
||||
public bool OnPressed(ManiaAction action) => Pressed?.Invoke(action) ?? false;
|
||||
public bool OnReleased(ManiaAction action) => Released?.Invoke(action) ?? false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
34
osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs
Normal file
34
osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
internal class DrawableManiaJudgement : DrawableJudgement
|
||||
{
|
||||
public DrawableManiaJudgement(Judgement judgement)
|
||||
: base(judgement)
|
||||
{
|
||||
JudgementText.TextSize = 25;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
this.FadeInFromZero(50, Easing.OutQuint);
|
||||
|
||||
if (Judgement.IsHit)
|
||||
{
|
||||
this.ScaleTo(0.8f);
|
||||
this.ScaleTo(1, 250, Easing.OutElastic);
|
||||
|
||||
this.Delay(50).FadeOut(200).ScaleTo(0.75f, 250);
|
||||
}
|
||||
|
||||
Expire();
|
||||
}
|
||||
}
|
||||
}
|
64
osu.Game.Rulesets.Mania/UI/HitExplosion.cs
Normal file
64
osu.Game.Rulesets.Mania/UI/HitExplosion.cs
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
internal class HitExplosion : CompositeDrawable
|
||||
{
|
||||
private readonly Box inner;
|
||||
|
||||
public HitExplosion(DrawableHitObject judgedObject)
|
||||
{
|
||||
bool isTick = judgedObject is DrawableHoldNoteTick;
|
||||
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Size = new Vector2(isTick ? 0.5f : 1);
|
||||
FillMode = FillMode.Fit;
|
||||
|
||||
Blending = BlendingMode.Additive;
|
||||
|
||||
Color4 accent = isTick ? Color4.White : judgedObject.AccentColour;
|
||||
|
||||
InternalChild = new CircularContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
BorderThickness = 1,
|
||||
BorderColour = accent,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = accent,
|
||||
Radius = 10,
|
||||
Hollow = true
|
||||
},
|
||||
Child = inner = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = accent,
|
||||
Alpha = 1,
|
||||
AlwaysPresent = true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
this.ScaleTo(2f, 600, Easing.OutQuint).FadeOut(500).Expire();
|
||||
inner.FadeOut(250);
|
||||
}
|
||||
}
|
||||
}
|
@ -6,30 +6,24 @@ using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using System;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using OpenTK.Input;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
public class ManiaPlayfield : ScrollingPlayfield<ManiaHitObject, ManiaJudgement>
|
||||
public class ManiaPlayfield : ScrollingPlayfield
|
||||
{
|
||||
public const float HIT_TARGET_POSITION = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Default column keys, expanding outwards from the middle as more column are added.
|
||||
/// E.g. 2 columns use FJ, 4 columns use DFJK, 6 use SDFJKL, etc...
|
||||
/// </summary>
|
||||
private static readonly Key[] default_keys = { Key.A, Key.S, Key.D, Key.F, Key.J, Key.K, Key.L, Key.Semicolon };
|
||||
|
||||
private SpecialColumnPosition specialColumnPosition;
|
||||
/// <summary>
|
||||
/// The style to use for the special column.
|
||||
@ -45,6 +39,11 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this playfield should be inverted. This flips everything inside the playfield.
|
||||
/// </summary>
|
||||
public readonly Bindable<bool> Inverted = new Bindable<bool>(true);
|
||||
|
||||
private readonly FlowContainer<Column> columns;
|
||||
public IEnumerable<Column> Columns => columns.Children;
|
||||
|
||||
@ -54,6 +53,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
private List<Color4> normalColumnColours = new List<Color4>();
|
||||
private Color4 specialColumnColour;
|
||||
|
||||
private readonly Container<DrawableManiaJudgement> judgements;
|
||||
|
||||
private readonly int columnCount;
|
||||
|
||||
public ManiaPlayfield(int columnCount)
|
||||
@ -64,21 +65,23 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
if (columnCount <= 0)
|
||||
throw new ArgumentException("Can't have zero or fewer columns.");
|
||||
|
||||
Inverted.Value = true;
|
||||
|
||||
Container topLevelContainer;
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Name = "Playfield elements",
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Name = "Masked elements",
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Name = "Columns mask",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X,
|
||||
Masking = true,
|
||||
@ -86,6 +89,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Name = "Background",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black
|
||||
},
|
||||
@ -97,39 +101,63 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
Direction = FillDirection.Horizontal,
|
||||
Padding = new MarginPadding { Left = 1, Right = 1 },
|
||||
Spacing = new Vector2(1, 0)
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Barlines mask",
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = HIT_TARGET_POSITION },
|
||||
Children = new[]
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 1366, // Bar lines should only be masked on the vertical axis
|
||||
BypassAutoSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Child = content = new Container
|
||||
{
|
||||
content = new Container
|
||||
{
|
||||
Name = "Bar lines",
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
// Width is set in the Update method
|
||||
}
|
||||
Name = "Bar lines",
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding { Top = HIT_TARGET_POSITION }
|
||||
}
|
||||
}
|
||||
},
|
||||
judgements = new Container<DrawableManiaJudgement>
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Y = HIT_TARGET_POSITION + 150,
|
||||
BypassAutoSizeAxes = Axes.Both
|
||||
},
|
||||
topLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var currentAction = ManiaAction.Key1;
|
||||
for (int i = 0; i < columnCount; i++)
|
||||
{
|
||||
var c = new Column();
|
||||
c.VisibleTimeRange.BindTo(VisibleTimeRange);
|
||||
|
||||
c.IsSpecial = isSpecialColumn(i);
|
||||
c.Action = c.IsSpecial ? ManiaAction.Special : currentAction++;
|
||||
|
||||
topLevelContainer.Add(c.TopLevelContainer.CreateProxy());
|
||||
|
||||
columns.Add(c);
|
||||
AddNested(c);
|
||||
}
|
||||
|
||||
Inverted.ValueChanged += invertedChanged;
|
||||
Inverted.TriggerChange();
|
||||
}
|
||||
|
||||
private void invertedChanged(bool newValue)
|
||||
{
|
||||
Scale = new Vector2(1, newValue ? -1 : 1);
|
||||
judgements.Scale = Scale;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -144,15 +172,11 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
specialColumnColour = colours.BlueDark;
|
||||
|
||||
// Set the special column + colour + key
|
||||
for (int i = 0; i < columnCount; i++)
|
||||
foreach (var column in Columns)
|
||||
{
|
||||
Column column = Columns.ElementAt(i);
|
||||
column.IsSpecial = isSpecialColumn(i);
|
||||
|
||||
if (!column.IsSpecial)
|
||||
continue;
|
||||
|
||||
column.Key.Value = Key.Space;
|
||||
column.AccentColour = specialColumnColour;
|
||||
}
|
||||
|
||||
@ -166,21 +190,19 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
nonSpecialColumns[i].AccentColour = colour;
|
||||
nonSpecialColumns[nonSpecialColumns.Count - 1 - i].AccentColour = colour;
|
||||
}
|
||||
}
|
||||
|
||||
// We'll set the keys for non-special columns in another separate loop because it's not mirrored like the above colours
|
||||
// Todo: This needs to go when we get to bindings and use Button1, ..., ButtonN instead
|
||||
for (int i = 0; i < nonSpecialColumns.Count; i++)
|
||||
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
var maniaObject = (ManiaHitObject)judgedObject.HitObject;
|
||||
columns[maniaObject.Column].OnJudgement(judgedObject, judgement);
|
||||
|
||||
judgements.Clear();
|
||||
judgements.Add(new DrawableManiaJudgement(judgement)
|
||||
{
|
||||
Column column = nonSpecialColumns[i];
|
||||
|
||||
int keyOffset = default_keys.Length / 2 - nonSpecialColumns.Count / 2 + i;
|
||||
if (keyOffset >= 0 && keyOffset < default_keys.Length)
|
||||
column.Key.Value = default_keys[keyOffset];
|
||||
else
|
||||
// There is no default key defined for this column. Let's set this to Unknown for now
|
||||
// however note that this will be gone after bindings are in place
|
||||
column.Key.Value = Key.Unknown;
|
||||
}
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -202,7 +224,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
}
|
||||
}
|
||||
|
||||
public override void Add(DrawableHitObject<ManiaHitObject, ManiaJudgement> h) => Columns.ElementAt(h.HitObject.Column).Add(h);
|
||||
public override void Add(DrawableHitObject h) => Columns.ElementAt(((ManiaHitObject)h.HitObject).Column).Add(h);
|
||||
|
||||
public void Add(DrawableBarLine barline) => HitObjects.Add(barline);
|
||||
|
||||
protected override void Update()
|
||||
|
@ -5,36 +5,37 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Lists;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Replays;
|
||||
using osu.Game.Rulesets.Mania.Scoring;
|
||||
using osu.Game.Rulesets.Mania.Timing;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Timing;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
public class ManiaRulesetContainer : ScrollingRulesetContainer<ManiaPlayfield, ManiaHitObject, ManiaJudgement>
|
||||
public class ManiaRulesetContainer : ScrollingRulesetContainer<ManiaPlayfield, ManiaHitObject>
|
||||
{
|
||||
/// <summary>
|
||||
/// Preferred column count. This will only have an effect during the initialization of the play field.
|
||||
/// The number of columns which the <see cref="ManiaPlayfield"/> should display, and which
|
||||
/// the beatmap converter will attempt to convert beatmaps to use.
|
||||
/// </summary>
|
||||
public int PreferredColumns;
|
||||
public int AvailableColumns { get; private set; }
|
||||
|
||||
public IEnumerable<DrawableBarLine> BarLines;
|
||||
|
||||
@ -75,36 +76,47 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
BarLines.ForEach(Playfield.Add);
|
||||
}
|
||||
|
||||
protected override void ApplyBeatmap()
|
||||
{
|
||||
base.ApplyBeatmap();
|
||||
|
||||
PreferredColumns = (int)Math.Max(1, Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize));
|
||||
}
|
||||
|
||||
protected sealed override Playfield<ManiaHitObject, ManiaJudgement> CreatePlayfield() => new ManiaPlayfield(PreferredColumns)
|
||||
protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(AvailableColumns)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
// Invert by default for now (should be moved to config/skin later)
|
||||
Scale = new Vector2(1, -1)
|
||||
};
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this);
|
||||
|
||||
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter() => new ManiaBeatmapConverter();
|
||||
public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, AvailableColumns);
|
||||
|
||||
protected override DrawableHitObject<ManiaHitObject, ManiaJudgement> GetVisualRepresentation(ManiaHitObject h)
|
||||
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter()
|
||||
{
|
||||
Bindable<Key> key = Playfield.Columns.ElementAt(h.Column).Key;
|
||||
if (IsForCurrentRuleset)
|
||||
AvailableColumns = (int)Math.Max(1, Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.CircleSize));
|
||||
else
|
||||
{
|
||||
float percentSliderOrSpinner = (float)WorkingBeatmap.Beatmap.HitObjects.Count(h => h is IHasEndTime) / WorkingBeatmap.Beatmap.HitObjects.Count;
|
||||
if (percentSliderOrSpinner < 0.2)
|
||||
AvailableColumns = 7;
|
||||
else if (percentSliderOrSpinner < 0.3 || Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.CircleSize) >= 5)
|
||||
AvailableColumns = Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.OverallDifficulty) > 5 ? 7 : 6;
|
||||
else if (percentSliderOrSpinner > 0.6)
|
||||
AvailableColumns = Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.OverallDifficulty) > 4 ? 5 : 4;
|
||||
else
|
||||
AvailableColumns = Math.Max(4, Math.Min((int)Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.OverallDifficulty) + 1, 7));
|
||||
}
|
||||
|
||||
return new ManiaBeatmapConverter(IsForCurrentRuleset, AvailableColumns);
|
||||
}
|
||||
|
||||
protected override DrawableHitObject<ManiaHitObject> GetVisualRepresentation(ManiaHitObject h)
|
||||
{
|
||||
ManiaAction action = Playfield.Columns.ElementAt(h.Column).Action;
|
||||
|
||||
var holdNote = h as HoldNote;
|
||||
if (holdNote != null)
|
||||
return new DrawableHoldNote(holdNote, key);
|
||||
return new DrawableHoldNote(holdNote, action);
|
||||
|
||||
var note = h as Note;
|
||||
if (note != null)
|
||||
return new DrawableNote(note, key);
|
||||
return new DrawableNote(note, action);
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -112,5 +124,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(1, 0.8f);
|
||||
|
||||
protected override SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Basic);
|
||||
|
||||
protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay);
|
||||
}
|
||||
}
|
||||
|
11
osu.Game.Rulesets.Mania/app.config
Normal file
11
osu.Game.Rulesets.Mania/app.config
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
@ -9,7 +9,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>osu.Game.Rulesets.Mania</RootNamespace>
|
||||
<AssemblyName>osu.Game.Rulesets.Mania</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
@ -34,7 +34,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
@ -60,7 +60,6 @@
|
||||
<Compile Include="Judgements\HitWindows.cs" />
|
||||
<Compile Include="Judgements\HoldNoteTailJudgement.cs" />
|
||||
<Compile Include="Judgements\HoldNoteTickJudgement.cs" />
|
||||
<Compile Include="Judgements\ManiaHitResult.cs" />
|
||||
<Compile Include="Judgements\ManiaJudgement.cs" />
|
||||
<Compile Include="ManiaDifficultyCalculator.cs" />
|
||||
<Compile Include="Mods\IGenerateSpeedAdjustments.cs" />
|
||||
@ -70,8 +69,12 @@
|
||||
<Compile Include="Objects\Drawables\DrawableManiaHitObject.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableNote.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\BodyPiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\GlowPiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\LaneGlowPiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\NotePiece.cs" />
|
||||
<Compile Include="Objects\Types\IHasColumn.cs" />
|
||||
<Compile Include="Replays\ManiaAutoGenerator.cs" />
|
||||
<Compile Include="Replays\ManiaFramedReplayInputHandler.cs" />
|
||||
<Compile Include="Scoring\ManiaScoreProcessor.cs" />
|
||||
<Compile Include="Objects\BarLine.cs" />
|
||||
<Compile Include="Objects\HoldNote.cs" />
|
||||
@ -79,9 +82,12 @@
|
||||
<Compile Include="Objects\ManiaHitObject.cs" />
|
||||
<Compile Include="Objects\Note.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ManiaInputManager.cs" />
|
||||
<Compile Include="Timing\GravityScrollingContainer.cs" />
|
||||
<Compile Include="Timing\ScrollingAlgorithm.cs" />
|
||||
<Compile Include="UI\Column.cs" />
|
||||
<Compile Include="UI\DrawableManiaJudgement.cs" />
|
||||
<Compile Include="UI\HitExplosion.cs" />
|
||||
<Compile Include="UI\ManiaRulesetContainer.cs" />
|
||||
<Compile Include="UI\ManiaPlayfield.cs" />
|
||||
<Compile Include="ManiaRuleset.cs" />
|
||||
@ -95,14 +101,6 @@
|
||||
<Project>{C76BF5B3-985E-4D39-95FE-97C9C879B83A}</Project>
|
||||
<Name>osu.Framework</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj">
|
||||
<Project>{C92A607B-1FDD-4954-9F92-03FF547D9080}</Project>
|
||||
<Name>osu.Game.Rulesets.Osu</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj">
|
||||
<Project>{F167E17A-7DE6-4AF5-B920-A5112296C695}</Project>
|
||||
<Name>osu.Game.Rulesets.Taiko</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
||||
<Project>{0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}</Project>
|
||||
<Name>osu.Game</Name>
|
||||
@ -112,6 +110,7 @@
|
||||
<None Include="..\osu.licenseheader">
|
||||
<Link>osu.licenseheader</Link>
|
||||
</None>
|
||||
<None Include="app.config" />
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
|
@ -1,8 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
-->
|
||||
<packages>
|
||||
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||
</packages>
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
@ -64,8 +64,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
//We are no longer within stacking range of the next object.
|
||||
break;
|
||||
|
||||
if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stack_distance ||
|
||||
stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
|
||||
if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance ||
|
||||
stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
|
||||
{
|
||||
stackBaseIndex = n;
|
||||
|
||||
@ -130,14 +130,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
* o <- hitCircle has stack of -1
|
||||
* o <- hitCircle has stack of -2
|
||||
*/
|
||||
if (objectN is Slider && Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||
if (objectN is Slider && Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||
{
|
||||
int offset = objectI.StackHeight - objectN.StackHeight + 1;
|
||||
for (int j = n + 1; j <= i; j++)
|
||||
{
|
||||
//For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
|
||||
OsuHitObject objectJ = beatmap.HitObjects[j];
|
||||
if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stack_distance)
|
||||
if (Vector2Extensions.Distance(objectN.EndPosition, objectJ.Position) < stack_distance)
|
||||
objectJ.StackHeight -= offset;
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
break;
|
||||
}
|
||||
|
||||
if (Vector2.Distance(objectN.Position, objectI.Position) < stack_distance)
|
||||
if (Vector2Extensions.Distance(objectN.Position, objectI.Position) < stack_distance)
|
||||
{
|
||||
//Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out.
|
||||
//NOTE: Sliders with start positions stacking are a special case that is also handled here.
|
||||
@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
//We are no longer within stacking range of the previous object.
|
||||
break;
|
||||
|
||||
if (Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||
if (Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||
{
|
||||
objectN.StackHeight = objectI.StackHeight + 1;
|
||||
objectI = objectN;
|
||||
|
@ -4,49 +4,31 @@
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Judgements
|
||||
{
|
||||
public class OsuJudgement : Judgement
|
||||
{
|
||||
public override HitResult MaxResult => HitResult.Great;
|
||||
|
||||
/// <summary>
|
||||
/// The positional hit offset.
|
||||
/// </summary>
|
||||
public Vector2 PositionOffset;
|
||||
|
||||
/// <summary>
|
||||
/// The score the user achieved.
|
||||
/// </summary>
|
||||
public OsuScoreResult Score;
|
||||
|
||||
/// <summary>
|
||||
/// The score which would be achievable on a perfect hit.
|
||||
/// </summary>
|
||||
public OsuScoreResult MaxScore = OsuScoreResult.Hit300;
|
||||
|
||||
public override string ResultString => Score.GetDescription();
|
||||
|
||||
public override string MaxResultString => MaxScore.GetDescription();
|
||||
|
||||
public int ScoreValue => scoreToInt(Score);
|
||||
|
||||
public int MaxScoreValue => scoreToInt(MaxScore);
|
||||
|
||||
private int scoreToInt(OsuScoreResult result)
|
||||
protected override int NumericResultFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case OsuScoreResult.Hit50:
|
||||
case HitResult.Meh:
|
||||
return 50;
|
||||
case OsuScoreResult.Hit100:
|
||||
case HitResult.Good:
|
||||
return 100;
|
||||
case OsuScoreResult.Hit300:
|
||||
case HitResult.Great:
|
||||
return 300;
|
||||
case OsuScoreResult.SliderTick:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,13 @@ using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
@ -28,10 +33,23 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
}
|
||||
|
||||
public class OsuModHardRock : ModHardRock
|
||||
public class OsuModHardRock : ModHardRock, IApplicableMod<OsuHitObject>
|
||||
{
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToRulesetContainer(RulesetContainer<OsuHitObject> rulesetContainer)
|
||||
{
|
||||
rulesetContainer.Objects.OfType<OsuHitObject>().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Y));
|
||||
rulesetContainer.Objects.OfType<Slider>().ForEach(s =>
|
||||
{
|
||||
var newControlPoints = new List<Vector2>();
|
||||
s.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, OsuPlayfield.BASE_SIZE.Y - c.Y)));
|
||||
|
||||
s.ControlPoints = newControlPoints;
|
||||
s.Curve?.Calculate(); // Recalculate the slider curve
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class OsuModSuddenDeath : ModSuddenDeath
|
||||
@ -78,6 +96,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public class OsuModSpunOut : Mod
|
||||
{
|
||||
public override string Name => "Spun Out";
|
||||
public override string ShortenedName => "SO";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
|
||||
public override string Description => @"Spinners will be automatically completed";
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
@ -88,6 +107,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public class OsuModAutopilot : Mod
|
||||
{
|
||||
public override string Name => "Autopilot";
|
||||
public override string ShortenedName => "AP";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
|
||||
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
||||
public override double ScoreMultiplier => 0;
|
||||
@ -108,6 +128,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public class OsuModTarget : Mod
|
||||
{
|
||||
public override string Name => "Target";
|
||||
public override string ShortenedName => "TP";
|
||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
|
||||
public override string Description => @"";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
new Box
|
||||
{
|
||||
Size = new Vector2(width),
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Alpha = 0.5f,
|
||||
|
@ -7,6 +7,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
@ -38,9 +39,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Colour = AccentColour,
|
||||
Hit = () =>
|
||||
{
|
||||
if (Judgement.Result != HitResult.None) return false;
|
||||
if (AllJudged)
|
||||
return false;
|
||||
|
||||
Judgement.PositionOffset = Vector2.Zero; //todo: set to correct value
|
||||
UpdateJudgement(true);
|
||||
return true;
|
||||
},
|
||||
@ -65,24 +66,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Size = circle.DrawSize;
|
||||
}
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset > HitObject.HitWindowFor(OsuScoreResult.Hit50))
|
||||
Judgement.Result = HitResult.Miss;
|
||||
if (timeOffset > HitObject.HitWindowFor(HitResult.Meh))
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Miss });
|
||||
return;
|
||||
}
|
||||
|
||||
double hitOffset = Math.Abs(Judgement.TimeOffset);
|
||||
|
||||
if (hitOffset < HitObject.HitWindowFor(OsuScoreResult.Hit50))
|
||||
AddJudgement(new OsuJudgement
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.Score = HitObject.ScoreResultForOffset(hitOffset);
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
Result = HitObject.ScoreResultForOffset(Math.Abs(timeOffset)),
|
||||
PositionOffset = Vector2.Zero //todo: set to correct value
|
||||
});
|
||||
}
|
||||
|
||||
protected override void UpdateInitialState()
|
||||
|
@ -3,12 +3,12 @@
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Framework.Graphics;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject, OsuJudgement>
|
||||
public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject>
|
||||
{
|
||||
public const float TIME_PREEMPT = 600;
|
||||
public const float TIME_FADEIN = 400;
|
||||
@ -21,8 +21,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Alpha = 0;
|
||||
}
|
||||
|
||||
protected override OsuJudgement CreateJudgement() => new OsuJudgement { MaxScore = OsuScoreResult.Hit300 };
|
||||
|
||||
protected sealed override void UpdateState(ArmedState state)
|
||||
{
|
||||
FinishTransforms();
|
||||
@ -33,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
UpdatePreemptState();
|
||||
|
||||
using (BeginDelayedSequence(TIME_PREEMPT + Judgement.TimeOffset, true))
|
||||
using (BeginDelayedSequence(TIME_PREEMPT + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true))
|
||||
UpdateCurrentState(state);
|
||||
}
|
||||
}
|
||||
@ -51,6 +49,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
protected virtual void UpdateCurrentState(ArmedState state)
|
||||
{
|
||||
}
|
||||
|
||||
private OsuInputManager osuActionInputManager;
|
||||
internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager);
|
||||
}
|
||||
|
||||
public enum ComboResult
|
||||
@ -62,18 +63,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
[Description(@"Amazing")]
|
||||
Perfect
|
||||
}
|
||||
|
||||
public enum OsuScoreResult
|
||||
{
|
||||
[Description(@"Miss")]
|
||||
Miss,
|
||||
[Description(@"50")]
|
||||
Hit50,
|
||||
[Description(@"100")]
|
||||
Hit100,
|
||||
[Description(@"300")]
|
||||
Hit300,
|
||||
[Description(@"10")]
|
||||
SliderTick
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,10 @@ using osu.Game.Rulesets.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableOsuJudgement : DrawableJudgement<OsuJudgement>
|
||||
public class DrawableOsuJudgement : DrawableJudgement
|
||||
{
|
||||
public DrawableOsuJudgement(OsuJudgement judgement) : base(judgement)
|
||||
public DrawableOsuJudgement(OsuJudgement judgement)
|
||||
: base(judgement)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
@ -64,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Scale = s.Scale,
|
||||
ComboColour = s.ComboColour,
|
||||
Samples = s.Samples,
|
||||
}),
|
||||
})
|
||||
};
|
||||
|
||||
components.Add(body);
|
||||
@ -114,33 +115,31 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0);
|
||||
|
||||
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
|
||||
if (initialCircle.Judgement?.Result != HitResult.Hit)
|
||||
if (!initialCircle.Judgements.Any(j => j.IsHit))
|
||||
initialCircle.Position = slider.Curve.PositionAt(progress);
|
||||
|
||||
foreach (var c in components) c.UpdateProgress(progress, repeat);
|
||||
foreach (var t in ticks.Children) t.Tracking = ball.Tracking;
|
||||
}
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered && Time.Current >= slider.EndTime)
|
||||
{
|
||||
var ticksCount = ticks.Children.Count + 1;
|
||||
var ticksHit = ticks.Children.Count(t => t.Judgement.Result == HitResult.Hit);
|
||||
if (initialCircle.Judgement.Result == HitResult.Hit)
|
||||
var ticksHit = ticks.Children.Count(t => t.Judgements.Any(j => j.IsHit));
|
||||
if (initialCircle.Judgements.Any(j => j.IsHit))
|
||||
ticksHit++;
|
||||
|
||||
var hitFraction = (double)ticksHit / ticksCount;
|
||||
if (hitFraction == 1 && initialCircle.Judgement.Score == OsuScoreResult.Hit300)
|
||||
Judgement.Score = OsuScoreResult.Hit300;
|
||||
else if (hitFraction >= 0.5 && initialCircle.Judgement.Score >= OsuScoreResult.Hit100)
|
||||
Judgement.Score = OsuScoreResult.Hit100;
|
||||
if (hitFraction == 1 && initialCircle.Judgements.Any(j => j.Result == HitResult.Great))
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Great });
|
||||
else if (hitFraction >= 0.5 && initialCircle.Judgements.Any(j => j.Result >= HitResult.Good))
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Good });
|
||||
else if (hitFraction > 0)
|
||||
Judgement.Score = OsuScoreResult.Hit50;
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Meh });
|
||||
else
|
||||
Judgement.Score = OsuScoreResult.Miss;
|
||||
|
||||
Judgement.Result = Judgement.Score != OsuScoreResult.Miss ? HitResult.Hit : HitResult.Miss;
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Miss });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
@ -22,8 +22,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
public override bool RemoveWhenNotAlive => false;
|
||||
|
||||
protected override OsuJudgement CreateJudgement() => new OsuJudgement { MaxScore = OsuScoreResult.SliderTick };
|
||||
|
||||
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
|
||||
{
|
||||
this.sliderTick = sliderTick;
|
||||
@ -49,13 +47,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
};
|
||||
}
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (Judgement.TimeOffset >= 0)
|
||||
{
|
||||
Judgement.Result = Tracking ? HitResult.Hit : HitResult.Miss;
|
||||
Judgement.Score = Tracking ? OsuScoreResult.SliderTick : OsuScoreResult.Miss;
|
||||
}
|
||||
if (timeOffset >= 0)
|
||||
AddJudgement(new OsuJudgement { Result = Tracking ? HitResult.Great : HitResult.Miss });
|
||||
}
|
||||
|
||||
protected override void UpdatePreemptState()
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@ -10,6 +11,7 @@ using OpenTK.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Screens.Ranking;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
@ -106,7 +108,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
public float Progress => MathHelper.Clamp(disc.RotationAbsolute / 360 / spinner.SpinsRequired, 0, 1);
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (Time.Current < HitObject.StartTime) return;
|
||||
|
||||
@ -128,26 +130,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
if (!userTriggered && Time.Current >= spinner.EndTime)
|
||||
{
|
||||
if (Progress >= 1)
|
||||
{
|
||||
Judgement.Score = OsuScoreResult.Hit300;
|
||||
Judgement.Result = HitResult.Hit;
|
||||
}
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Great });
|
||||
else if (Progress > .9)
|
||||
{
|
||||
Judgement.Score = OsuScoreResult.Hit100;
|
||||
Judgement.Result = HitResult.Hit;
|
||||
}
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Good });
|
||||
else if (Progress > .75)
|
||||
{
|
||||
Judgement.Score = OsuScoreResult.Hit50;
|
||||
Judgement.Result = HitResult.Hit;
|
||||
}
|
||||
else
|
||||
{
|
||||
Judgement.Score = OsuScoreResult.Miss;
|
||||
if (Time.Current >= spinner.EndTime)
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Meh });
|
||||
else if (Time.Current >= spinner.EndTime)
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Miss });
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,6 +154,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
glow.Colour = colours.BlueDark;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton);
|
||||
|
||||
base.Update();
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
new TrianglesPiece
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0.5f,
|
||||
}
|
||||
};
|
||||
|
@ -16,14 +16,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
BlendingMode = BlendingMode.Additive;
|
||||
Blending = BlendingMode.Additive;
|
||||
Alpha = 0;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TrianglesPiece
|
||||
{
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.2f,
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
BlendingMode = BlendingMode.Additive;
|
||||
Blending = BlendingMode.Additive;
|
||||
Alpha = 0;
|
||||
|
||||
Children = new Drawable[]
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0.5f
|
||||
}
|
||||
};
|
||||
|
@ -1,10 +1,12 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
@ -37,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
this.slider = slider;
|
||||
Masking = true;
|
||||
AutoSizeAxes = Axes.Both;
|
||||
BlendingMode = BlendingMode.Additive;
|
||||
Blending = BlendingMode.Additive;
|
||||
Origin = Anchor.Centre;
|
||||
BorderThickness = 10;
|
||||
BorderColour = Color4.Orange;
|
||||
@ -96,11 +98,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
return base.OnMouseMove(state);
|
||||
}
|
||||
|
||||
// If the current time is between the start and end of the slider, we should track mouse input regardless of the cursor position.
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => canCurrentlyTrack || base.ReceiveMouseInputAt(screenSpacePos);
|
||||
|
||||
private bool tracking;
|
||||
public bool Tracking
|
||||
{
|
||||
get { return tracking; }
|
||||
set
|
||||
private set
|
||||
{
|
||||
if (value == tracking) return;
|
||||
|
||||
@ -117,8 +122,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// Make sure to use the base version of ReceiveMouseInputAt so that we correctly check the position.
|
||||
if (Time.Current < slider.EndTime)
|
||||
Tracking = canCurrentlyTrack && lastState != null && ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) && lastState.Mouse.HasMainButtonPressed;
|
||||
Tracking = canCurrentlyTrack && lastState != null && base.ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) && ((Parent as DrawableSlider)?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false);
|
||||
}
|
||||
|
||||
public void UpdateProgress(double progress, int repeat)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user