1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-17 05:52:36 +08:00

Compare commits

..

2244 Commits

646 changed files with 26413 additions and 9664 deletions
+37 -12
View File
@@ -2,35 +2,60 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch VisualTests",
"name": "VisualTests (debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/osu.Desktop.VisualTests/bin/Debug/osu!.exe",
"args": [],
"cwd": "${workspaceRoot}",
"preLaunchTask": "build",
"preLaunchTask": "Build (Debug)",
"runtimeExecutable": null,
"env": {},
"externalConsole": false
"console": "internalConsole"
},
{
"name": "Launch Desktop",
"name": "VisualTests (release)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/osu.Desktop.VisualTests/bin/Release/osu!.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "osu! (debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/osu.Desktop/bin/Debug/osu!.exe",
"args": [],
"cwd": "${workspaceRoot}",
"preLaunchTask": "build",
"preLaunchTask": "Build (Debug)",
"runtimeExecutable": null,
"env": {},
"externalConsole": false
"console": "internalConsole"
},
{
"name": "Attach",
"name": "osu! (release)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "attach",
"address": "localhost",
"port": 55555
"request": "launch",
"program": "${workspaceRoot}/osu.Desktop/bin/Release/osu!.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
}
]
}
+41 -17
View File
@@ -1,26 +1,50 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "0.1.0",
"windows": {
"command": "msbuild"
},
"linux": {
"command": "xbuild"
},
"args": [
// Ask msbuild to generate full paths for file names.
"/property:GenerateFullPaths=true"
],
"taskSelector": "/t:",
"version": "2.0.0",
"problemMatcher": "$msCompile",
"isShellCommand": true,
"command": "msbuild",
"suppressTaskName": true,
"showOutput": "silent",
"args": [
"/property:GenerateFullPaths=true",
"/property:DebugType=portable"
],
"windows": {
"args": [
"/property:GenerateFullPaths=true",
"/property:DebugType=portable",
"/m" //parallel compiling support. doesn't work well with mono atm
]
},
"tasks": [
{
"taskName": "build",
// Show the output window only if unrecognized errors occur.
"showOutput": "silent",
// Use the standard MS compiler pattern to detect errors, warnings and infos
"problemMatcher": "$msCompile"
"taskName": "Build (Debug)",
"isBuildCommand": true
},
{
"taskName": "Build (Release)",
"args": [
"/property:Configuration=Release"
]
},
{
"taskName": "Clean All",
"dependsOn": ["Clean (Debug)", "Clean (Release)"]
},
{
"taskName": "Clean (Debug)",
"args": [
"/target:Clean"
]
},
{
"taskName": "Clean (Release)",
"args": [
"/target:Clean",
"/property:Configuration=Release"
]
}
]
}
+5 -9
View File
@@ -1,10 +1,6 @@
# osu! [![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu)
# osu! [![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) [![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) [![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy)
[osu! on the web](https://osu.ppy.sh) | [dev chat](https://discord.gg/ppy)
Rhythm is just a *click* away. The future of osu! and the beginning of an open era!
Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the beginning of an open era!
# Status
@@ -12,14 +8,14 @@ This is still heavily under development and is not intended for end-user use. Th
# Requirements
- A desktop platform which can compile .NET 4.5.
- Visual Studio or MonoDevelop is recommended.
- A desktop platform which can compile .NET 4.5 (tested on macOS, linux and windows). We recommend using [Visual Studio Code](https://code.visualstudio.com/) (all platforms) or [Visual Studio Community Edition](https://www.visualstudio.com/) (windows only), both of which are free.
- Make sure you initialise and keep submodules up-to-date.
# Contributing
We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention on having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time, to ensure no effort is wasted.
Contributions can be made via pull requests to this repository. We hope to credit and reward larger contributions via a [bounty system](https://goo.gl/nFdoyI). If you're unsure of what you can help with, check out the [list](https://github.com/ppy/osu/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Abounty) of available issues with bounty.
Contributions can be made via pull requests to this repository. We hope to credit and reward larger contributions via a [bounty system](https://www.bountysource.com/teams/ppy). If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu-framework/issues).
Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured; with any libraries we are using; with any processes involved with contributing, *please* bring it up. I welcome all feedback so we can make contributing to this project as pain-free as possible.
+1 -1
View File
@@ -10,7 +10,7 @@ install:
- cmd: git submodule update --init --recursive
- cmd: choco install resharper-clt -y
- cmd: choco install nvika -y
- cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.1/CodeFileSanity.exe
- cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.2.2/CodeFileSanity.exe
before_build:
- cmd: CodeFileSanity.exe
- cmd: nuget restore
+12
View File
@@ -21,4 +21,16 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="DeltaCompressionDotNet.MsDelta" publicKeyToken="46b2138a390abf55" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.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>
@@ -4,7 +4,7 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu.Desktop.Deploy")]
@@ -16,8 +16,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -27,11 +27,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
+4 -4
View File
@@ -22,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -68,9 +69,8 @@
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
<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.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
@@ -120,7 +120,7 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
+1 -1
View File
@@ -6,7 +6,7 @@ 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="9.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
<package id="NuGet.CommandLine" version="3.5.0" targetFramework="net452" developmentDependency="true" />
<package id="Splat" version="2.0.0" targetFramework="net452" />
<package id="squirrel.windows" version="1.5.2" targetFramework="net452" />
-32
View File
@@ -1,32 +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 NUnit.Framework;
using osu.Desktop.VisualTests;
using osu.Framework.Desktop.Platform;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
using osu.Game.Modes.Mania;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Taiko;
namespace osu.Desktop.Tests
{
[TestFixture]
public class BenchmarkTest
{
[Test]
public void TestBenchmark()
{
using (var host = new HeadlessGameHost())
{
Ruleset.Register(new OsuRuleset());
Ruleset.Register(new TaikoRuleset());
Ruleset.Register(new ManiaRuleset());
Ruleset.Register(new CatchRuleset());
host.Run(new Benchmark());
}
}
}
}
+22
View File
@@ -0,0 +1,22 @@
// 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.Desktop.VisualTests;
using osu.Framework.Desktop.Platform;
namespace osu.Desktop.Tests
{
[TestFixture]
public class VisualTests
{
[Test]
public void TestVisualTests()
{
using (var host = new HeadlessGameHost())
{
host.Run(new AutomatedVisualTestGame());
}
}
}
}
+15 -15
View File
@@ -21,6 +21,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -33,18 +34,17 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
<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="nunit.framework, Version=3.6.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="Newtonsoft.Json">
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="SQLiteNetExtensions">
<HintPath>$(SolutionDir)\packages\SQLiteNetExtensions.1.3.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\SQLiteNetExtensions.dll</HintPath>
</Reference>
@@ -56,7 +56,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="BenchmarkTest.cs" />
<Compile Include="VisualTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu-framework\osu.Framework.Desktop\osu.Framework.Desktop.csproj">
@@ -75,21 +75,21 @@
<Project>{69051C69-12AE-4E7D-A3E6-460D2E282312}</Project>
<Name>osu.Desktop.VisualTests</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Catch\osu.Game.Modes.Catch.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
<Project>{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}</Project>
<Name>osu.Game.Modes.Catch</Name>
<Name>osu.Game.Rulesets.Catch</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Mania\osu.Game.Modes.Mania.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj">
<Project>{48F4582B-7687-4621-9CBE-5C24197CB536}</Project>
<Name>osu.Game.Modes.Mania</Name>
<Name>osu.Game.Rulesets.Mania</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj">
<Project>{C92A607B-1FDD-4954-9F92-03FF547D9080}</Project>
<Name>osu.Game.Modes.Osu</Name>
<Name>osu.Game.Rulesets.Osu</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Taiko\osu.Game.Modes.Taiko.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj">
<Project>{F167E17A-7DE6-4AF5-B920-A5112296C695}</Project>
<Name>osu.Game.Modes.Taiko</Name>
<Name>osu.Game.Rulesets.Taiko</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
<Project>{0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}</Project>
+2 -3
View File
@@ -1,12 +1,11 @@
<?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="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="NUnit" version="3.5.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
<package id="NUnit" version="3.6.1" targetFramework="net45" />
<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" />
@@ -0,0 +1,20 @@
// 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.Testing;
using osu.Game;
namespace osu.Desktop.VisualTests
{
public class AutomatedVisualTestGame : OsuGameBase
{
protected override void LoadComplete()
{
base.LoadComplete();
// Have to construct this here, rather than in the constructor, because
// we depend on some dependencies to be loaded within OsuGameBase.load().
Add(new TestRunner(new TestBrowser()));
}
}
}
@@ -10,13 +10,13 @@ namespace osu.Desktop.VisualTests.Beatmaps
public class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
: base(beatmap.BeatmapInfo)
{
this.beatmap = beatmap;
}
private readonly Beatmap beatmap;
protected override Beatmap GetBeatmap() => beatmap;
protected override Texture GetBackground() => null;
protected override Track GetTrack() => null;
-45
View File
@@ -1,45 +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;
using osu.Framework.Allocation;
using osu.Framework.Testing;
using osu.Game;
namespace osu.Desktop.VisualTests
{
public class Benchmark : OsuGameBase
{
private const double time_per_test = 200;
[BackgroundDependencyLoader]
private void load()
{
Host.MaximumDrawHz = int.MaxValue;
Host.MaximumUpdateHz = int.MaxValue;
Host.MaximumInactiveHz = int.MaxValue;
}
protected override void LoadComplete()
{
base.LoadComplete();
TestBrowser f = new TestBrowser();
Add(f);
Console.WriteLine($@"{Time}: Running {f.TestCount} tests for {time_per_test}ms each...");
for (int i = 1; i < f.TestCount; i++)
{
int loadableCase = i;
Scheduler.AddDelayed(delegate
{
f.LoadTest(loadableCase);
Console.WriteLine($@"{Time}: Switching to test #{loadableCase}");
}, loadableCase * time_per_test);
}
Scheduler.AddDelayed(Host.Exit, f.TestCount * time_per_test);
}
}
}
@@ -15,7 +15,7 @@ namespace osu.Desktop.VisualTests.Platform
public TestStorage(string baseName) : base(baseName)
{
}
public override SQLiteConnection GetDatabase(string name)
{
ISQLitePlatform platform;
+1 -11
View File
@@ -4,11 +4,6 @@
using System;
using osu.Framework.Desktop;
using osu.Framework.Platform;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
using osu.Game.Modes.Mania;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Taiko;
namespace osu.Desktop.VisualTests
{
@@ -21,13 +16,8 @@ namespace osu.Desktop.VisualTests
using (GameHost host = Host.GetSuitableHost(@"osu"))
{
Ruleset.Register(new OsuRuleset());
Ruleset.Register(new TaikoRuleset());
Ruleset.Register(new ManiaRuleset());
Ruleset.Register(new CatchRuleset());
if (benchmark)
host.Run(new Benchmark());
host.Run(new AutomatedVisualTestGame());
else
host.Run(new VisualTestGame());
}
@@ -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 osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Screens.Select;
using System.Linq;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseBeatmapDetails : TestCase
{
public override string Description => "BeatmapDetails tab of BeatmapDetailArea";
private BeatmapDetails details;
public override void Reset()
{
base.Reset();
Add(details = new BeatmapDetails
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding(150),
Beatmap = new BeatmapInfo
{
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),
},
},
});
AddRepeatStep("fail values", newRetryAndFailValues, 10);
}
private int lastRange = 1;
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;
}
}
}
@@ -26,7 +26,7 @@ namespace osu.Desktop.VisualTests.Tests
Add(overlay);
AddButton(@"Toggle", overlay.ToggleVisibility);
AddStep(@"Toggle", overlay.ToggleVisibility);
}
}
}
@@ -0,0 +1,39 @@
// 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.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Framework.Graphics;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseBreadcrumbs : TestCase
{
public override string Description => @"breadcrumb > control";
public override void Reset()
{
base.Reset();
BreadcrumbControl<BreadcrumbTab> c;
Add(c = new BreadcrumbControl<BreadcrumbTab>
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Width = 0.5f,
});
AddStep(@"first", () => c.Current.Value = BreadcrumbTab.Click);
AddStep(@"second", () => c.Current.Value = BreadcrumbTab.The);
AddStep(@"third", () => c.Current.Value = BreadcrumbTab.Circles);
}
private enum BreadcrumbTab
{
Click,
The,
Circles,
}
}
}
@@ -3,15 +3,12 @@
using osu.Framework.Testing;
using osu.Framework.Graphics.Containers;
using osu.Framework.Threading;
using osu.Game.Overlays;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseChatDisplay : TestCase
{
private ScheduledDelegate messageRequest;
public override string Description => @"Testing chat api and overlay";
public override void Reset()
@@ -20,7 +20,7 @@ namespace osu.Desktop.VisualTests.Tests
Add(overlay = new DialogOverlay());
AddButton("dialog #1", () => overlay.Push(new PopupDialog
AddStep("dialog #1", () => overlay.Push(new PopupDialog
{
Icon = FontAwesome.fa_trash_o,
HeaderText = @"Confirm deletion of",
@@ -40,7 +40,7 @@ namespace osu.Desktop.VisualTests.Tests
},
}));
AddButton("dialog #2", () => overlay.Push(new PopupDialog
AddStep("dialog #2", () => overlay.Push(new PopupDialog
{
Icon = FontAwesome.fa_gear,
HeaderText = @"What do you want to do with",
@@ -0,0 +1,199 @@
// 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.Allocation;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Overlays;
namespace osu.Desktop.VisualTests.Tests
{
public class TestCaseDirect : TestCase
{
public override string Description => @"osu!direct overlay";
private DirectOverlay direct;
private RulesetDatabase rulesets;
public override void Reset()
{
base.Reset();
Add(direct = new DirectOverlay());
newBeatmaps();
AddStep(@"toggle", direct.ToggleVisibility);
AddStep(@"result counts", () => direct.ResultAmounts = new DirectOverlay.ResultCounts(1, 4, 13));
}
[BackgroundDependencyLoader]
private void load(RulesetDatabase rulesets)
{
this.rulesets = rulesets;
}
private void newBeatmaps()
{
var ruleset = rulesets.GetRuleset(0);
direct.BeatmapSets = new[]
{
new BeatmapSetInfo
{
Metadata = new BeatmapMetadata
{
Title = @"OrVid",
Artist = @"An",
Author = @"RLC",
Source = @"",
},
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 5.35f,
Metadata = new BeatmapMetadata(),
OnlineInfo = new BeatmapOnlineInfo
{
Covers = new[] { @"https://assets.ppy.sh//beatmaps/578332/covers/cover.jpg?1494591390" },
Preview = @"https://b.ppy.sh/preview/578332.mp3",
PlayCount = 97,
FavouriteCount = 72,
},
},
},
},
new BeatmapSetInfo
{
Metadata = new BeatmapMetadata
{
Title = @"tiny lamp",
Artist = @"fhana",
Author = @"Sotarks",
Source = @"ぎんぎつね",
},
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 5.81f,
Metadata = new BeatmapMetadata(),
OnlineInfo = new BeatmapOnlineInfo
{
Covers = new[] { @"https://assets.ppy.sh//beatmaps/599627/covers/cover.jpg?1494539318" },
Preview = @"https//b.ppy.sh/preview/599627.mp3",
PlayCount = 3082,
FavouriteCount = 14,
},
},
},
},
new BeatmapSetInfo
{
Metadata = new BeatmapMetadata
{
Title = @"At Gwanghwamun",
Artist = @"KYUHYUN",
Author = @"Cerulean Veyron",
Source = @"",
},
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 0.9f,
Metadata = new BeatmapMetadata(),
OnlineInfo = new BeatmapOnlineInfo
{
Covers = new[] { @"https://assets.ppy.sh//beatmaps/513268/covers/cover.jpg?1494502863" },
Preview = @"https//b.ppy.sh/preview/513268.mp3",
PlayCount = 2762,
FavouriteCount = 15,
},
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 1.1f,
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 2.02f,
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 3.49f,
},
},
},
new BeatmapSetInfo
{
Metadata = new BeatmapMetadata
{
Title = @"RHAPSODY OF BLUE SKY",
Artist = @"fhana",
Author = @"[Kamiya]",
Source = @"小林さんちのメイドラゴン",
},
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 1.26f,
Metadata = new BeatmapMetadata(),
OnlineInfo = new BeatmapOnlineInfo
{
Covers = new[] { @"https://assets.ppy.sh//beatmaps/586841/covers/cover.jpg?1494052741" },
Preview = @"https//b.ppy.sh/preview/586841.mp3",
PlayCount = 62317,
FavouriteCount = 161,
},
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 2.01f,
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 2.87f,
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 3.76f,
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 3.93f,
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 4.37f,
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 5.13f,
},
new BeatmapInfo
{
Ruleset = ruleset,
StarDifficulty = 5.42f,
},
},
},
};
}
}
}
@@ -0,0 +1,74 @@
// 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.Containers;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Screens.Multiplayer;
using osu.Game.Online.Multiplayer;
using osu.Game.Users;
using osu.Game.Database;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseDrawableRoom : TestCase
{
public override string Description => @"Select your favourite room";
public override void Reset()
{
base.Reset();
DrawableRoom first;
DrawableRoom second;
Add(new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Y,
Width = 500f,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
first = new DrawableRoom(new Room()),
second = new DrawableRoom(new Room()),
}
});
first.Room.Name.Value = @"Great Room Right Here";
first.Room.Host.Value = new User { Username = @"Naeferith", Id = 9492835, Country = new Country { FlagName = @"FR" }};
first.Room.Status.Value = new RoomStatusOpen();
first.Room.Beatmap.Value = new BeatmapMetadata { Title = @"Seiryu", Artist = @"Critical Crystal" };
second.Room.Name.Value = @"Relax It's The Weekend";
second.Room.Host.Value = new User { Username = @"peppy", Id = 2, Country = new Country { FlagName = @"AU" }};
second.Room.Status.Value = new RoomStatusPlaying();
second.Room.Beatmap.Value = new BeatmapMetadata { Title = @"ZAQ", Artist = @"Serendipity" };
AddStep(@"change state", () =>
{
first.Room.Status.Value = new RoomStatusPlaying();
});
AddStep(@"change name", () =>
{
first.Room.Name.Value = @"I Changed Name";
});
AddStep(@"change host", () =>
{
first.Room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } };
});
AddStep(@"change beatmap", () =>
{
first.Room.Beatmap.Value = null;
});
AddStep(@"change state", () =>
{
first.Room.Status.Value = new RoomStatusOpen();
});
}
}
}
@@ -5,7 +5,6 @@ using System.Collections.Generic;
using osu.Framework.Testing;
using osu.Game.Screens.Tournament;
using osu.Game.Screens.Tournament.Teams;
using osu.Game.Users;
namespace osu.Desktop.VisualTests.Tests
{
@@ -25,57 +24,57 @@ namespace osu.Desktop.VisualTests.Tests
private class TestTeamList : ITeamList
{
public IEnumerable<Country> Teams { get; } = new[]
public IEnumerable<DrawingsTeam> Teams { get; } = new[]
{
new Country
new DrawingsTeam
{
FlagName = "GB",
FullName = "United Kingdom",
Acronym = "UK"
},
new Country
new DrawingsTeam
{
FlagName = "FR",
FullName = "France",
Acronym = "FRA"
},
new Country
new DrawingsTeam
{
FlagName = "CN",
FullName = "China",
Acronym = "CHN"
},
new Country
new DrawingsTeam
{
FlagName = "AU",
FullName = "Australia",
Acronym = "AUS"
},
new Country
new DrawingsTeam
{
FlagName = "JP",
FullName = "Japan",
Acronym = "JPN"
},
new Country
new DrawingsTeam
{
FlagName = "RO",
FullName = "Romania",
Acronym = "ROM"
},
new Country
new DrawingsTeam
{
FlagName = "IT",
FullName = "Italy",
Acronym = "PIZZA"
},
new Country
new DrawingsTeam
{
FlagName = "VE",
FullName = "Venezuela",
Acronym = "VNZ"
},
new Country
new DrawingsTeam
{
FlagName = "US",
FullName = "United States of America",
@@ -9,21 +9,31 @@ using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.Taiko.UI;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.Taiko.UI;
using System.Collections.Generic;
using osu.Desktop.VisualTests.Beatmaps;
using osu.Framework.Allocation;
using osu.Game.Beatmaps.ControlPoints;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseGamefield : TestCase
{
private RulesetDatabase rulesets;
public override string Description => @"Showing hitobjects and what not.";
[BackgroundDependencyLoader]
private void load(RulesetDatabase rulesets)
{
this.rulesets = rulesets;
}
public override void Reset()
{
base.Reset();
@@ -36,26 +46,34 @@ namespace osu.Desktop.VisualTests.Tests
objects.Add(new HitCircle
{
StartTime = time,
Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)),
Position = new Vector2(RNG.Next(0, (int)OsuPlayfield.BASE_SIZE.X), RNG.Next(0, (int)OsuPlayfield.BASE_SIZE.Y)),
Scale = RNG.NextSingle(0.5f, 1.0f),
});
time += RNG.Next(50, 500);
}
var controlPointInfo = new ControlPointInfo();
controlPointInfo.TimingPoints.Add(new TimingControlPoint
{
BeatLength = 200
});
WorkingBeatmap beatmap = new TestWorkingBeatmap(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",
}
}
},
},
ControlPointInfo = controlPointInfo
});
Add(new Drawable[]
@@ -67,25 +85,25 @@ namespace osu.Desktop.VisualTests.Tests
Clock = new FramedClock(),
Children = new Drawable[]
{
new OsuHitRenderer(beatmap)
new OsuHitRenderer(beatmap, false)
{
Scale = new Vector2(0.5f),
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft
},
new TaikoHitRenderer(beatmap)
new TaikoHitRenderer(beatmap, false)
{
Scale = new Vector2(0.5f),
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight
},
new CatchHitRenderer(beatmap)
new CatchHitRenderer(beatmap, false)
{
Scale = new Vector2(0.5f),
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft
},
new ManiaHitRenderer(beatmap)
new ManiaHitRenderer(beatmap, false)
{
Scale = new Vector2(0.5f),
Anchor = Anchor.BottomRight,
@@ -0,0 +1,42 @@
// 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.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using System.Linq;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseGraph : TestCase
{
public override string Description => "graph";
private BarGraph graph;
public override void Reset()
{
base.Reset();
Children = new[]
{
graph = new BarGraph
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(0.5f),
},
};
AddStep("values from 1-10", () => graph.Values = Enumerable.Range(1,10).Select(i => (float)i));
AddStep("values from 1-100", () => graph.Values = Enumerable.Range(1, 100).Select(i => (float)i));
AddStep("reversed values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Reverse().Select(i => (float)i));
AddStep("Bottom to top", () => graph.Direction = BarDirection.BottomToTop);
AddStep("Top to bottom", () => graph.Direction = BarDirection.TopToBottom);
AddStep("Left to right", () => graph.Direction = BarDirection.LeftToRight);
AddStep("Right to left", () => graph.Direction = BarDirection.RightToLeft);
}
}
}
@@ -10,11 +10,10 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Judgements;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.Objects.Drawables;
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 System.Collections.Generic;
namespace osu.Desktop.VisualTests.Tests
@@ -62,15 +61,12 @@ namespace osu.Desktop.VisualTests.Tests
add(new DrawableSlider(new Slider
{
StartTime = framedClock.CurrentTime + 600,
CurveObject = new CurvedHitObject
ControlPoints = new List<Vector2>
{
ControlPoints = new List<Vector2>
{
new Vector2(-200, 0),
new Vector2(400, 0),
},
Distance = 400
new Vector2(-200, 0),
new Vector2(400, 0),
},
Distance = 400,
Position = new Vector2(-200, 0),
Velocity = 1,
TickDistance = 100,
@@ -93,21 +89,32 @@ namespace osu.Desktop.VisualTests.Tests
playbackSpeed.TriggerChange();
AddButton(@"circles", () => load(HitObjectType.Circle));
AddButton(@"slider", () => load(HitObjectType.Slider));
AddButton(@"spinner", () => load(HitObjectType.Spinner));
AddStep(@"circles", () => load(HitObjectType.Circle));
AddStep(@"slider", () => load(HitObjectType.Slider));
AddStep(@"spinner", () => load(HitObjectType.Spinner));
AddToggle(@"auto", state => { auto = state; load(mode); });
AddToggleStep(@"auto", state => { auto = state; load(mode); });
ButtonsContainer.Add(new SpriteText { Text = "Playback Speed" });
ButtonsContainer.Add(new BasicSliderBar<double>
BasicSliderBar<double> sliderBar;
Add(new Container
{
Width = 150,
Height = 10,
SelectionColor = Color4.Orange,
Bindable = playbackSpeed
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new SpriteText { Text = "Playback Speed" },
sliderBar = new BasicSliderBar<double>
{
Width = 150,
Height = 10,
SelectionColor = Color4.Orange,
}
}
});
sliderBar.Current.BindTo(playbackSpeed);
framedClock.ProcessFrame();
var clockAdjustContainer = new Container
@@ -122,8 +129,6 @@ namespace osu.Desktop.VisualTests.Tests
};
Add(clockAdjustContainer);
load(mode);
}
private int depth;
@@ -6,6 +6,7 @@ using osu.Framework.Graphics;
using OpenTK.Input;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Configuration;
using osu.Framework.Graphics.Containers;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.MathUtils;
@@ -37,19 +38,33 @@ namespace osu.Desktop.VisualTests.Tests
};
BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 };
bindable.ValueChanged += delegate { kc.FadeTime = bindable.Value; };
AddButton("Add Random", () =>
AddStep("Add Random", () =>
{
Key key = (Key)((int)Key.A + RNG.Next(26));
kc.Add(new KeyCounterKeyboard(key));
});
ButtonsContainer.Add(new SpriteText { Text = "FadeTime" });
ButtonsContainer.Add(new TestSliderBar<int>
TestSliderBar<int> sliderBar;
Add(new Container
{
Width = 150,
Height = 10,
SelectionColor = Color4.Orange,
Bindable = bindable
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new SpriteText { Text = "FadeTime" },
sliderBar =new TestSliderBar<int>
{
Width = 150,
Height = 10,
SelectionColor = Color4.Orange,
}
}
});
sliderBar.Current.BindTo(bindable);
Add(kc);
}
private class TestSliderBar<T> : SliderBar<T> where T : struct
@@ -4,9 +4,9 @@
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Osu.Mods;
using osu.Game.Modes.Scoring;
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;
@@ -218,7 +218,7 @@ namespace osu.Desktop.VisualTests.Tests
Size = new Vector2(550f, 450f),
});
AddButton(@"New Scores", newScores);
AddStep(@"New Scores", newScores);
newScores();
}
}
@@ -0,0 +1,81 @@
// 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.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using OpenTK.Graphics;
using OpenTK;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseManiaHitObjects : TestCase
{
public override void Reset()
{
base.Reset();
Add(new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(10, 0),
// Imagine that the containers containing the drawable notes are the "columns"
Children = new Drawable[]
{
new Container
{
Name = "Normal note column",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Width = 50,
Children = new[]
{
new Container
{
Name = "Timing section",
RelativeSizeAxes = Axes.Both,
RelativeCoordinateSpace = 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 Container
{
Name = "Hold note column",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Width = 50,
Children = new[]
{
new Container
{
Name = "Timing section",
RelativeSizeAxes = Axes.Both,
RelativeCoordinateSpace = new Vector2(1, 10000),
Children = new[]
{
new DrawableHoldNote(new HoldNote
{
StartTime = 5000,
Duration = 1000
}) { AccentColour = Color4.Red }
}
}
}
}
}
});
}
}
}
@@ -0,0 +1,148 @@
// 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.Input;
using osu.Framework.Testing;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Mania.UI;
using System;
using System.Collections.Generic;
using OpenTK;
using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Timing;
using osu.Framework.Configuration;
using OpenTK.Input;
using osu.Framework.Timing;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseManiaPlayfield : TestCase
{
public override string Description => @"Mania playfield";
protected override double TimePerAction => 200;
public override void Reset()
{
base.Reset();
Action<int, SpecialColumnPosition> createPlayfield = (cols, pos) =>
{
Clear();
Add(new ManiaPlayfield(cols, new List<TimingChange>())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
SpecialColumnPosition = pos,
Scale = new Vector2(1, -1)
});
};
Action<int, SpecialColumnPosition> createPlayfieldWithNotes = (cols, pos) =>
{
Clear();
ManiaPlayfield playField;
Add(playField = new ManiaPlayfield(cols, new List<TimingChange> { new TimingChange { BeatLength = 200 } })
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
SpecialColumnPosition = pos,
Scale = new Vector2(1, -1)
});
for (int i = 0; i < cols; i++)
{
playField.Add(new DrawableNote(new Note
{
StartTime = Time.Current + 1000,
Column = i
}));
}
};
Action createPlayfieldWithNotesAcceptingInput = () =>
{
Clear();
var rateAdjustClock = new StopwatchClock(true) { Rate = 0.5 };
ManiaPlayfield playField;
Add(playField = new ManiaPlayfield(4, new List<TimingChange> { new TimingChange { BeatLength = 200 } })
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(1, -1),
Clock = new FramedClock(rateAdjustClock)
});
for (int t = 1000; t <= 2000; t += 100)
{
playField.Add(new DrawableNote(new Note
{
StartTime = t,
Column = 0
}, new Bindable<Key>(Key.D)));
playField.Add(new DrawableNote(new Note
{
StartTime = t,
Column = 3
}, new Bindable<Key>(Key.K)));
}
playField.Add(new DrawableHoldNote(new HoldNote
{
StartTime = 1000,
Duration = 1000,
Column = 1
}, new Bindable<Key>(Key.F)));
playField.Add(new DrawableHoldNote(new HoldNote
{
StartTime = 1000,
Duration = 1000,
Column = 2
}, new Bindable<Key>(Key.J)));
};
AddStep("1 column", () => createPlayfield(1, SpecialColumnPosition.Normal));
AddStep("4 columns", () => createPlayfield(4, SpecialColumnPosition.Normal));
AddStep("Left special style", () => createPlayfield(4, SpecialColumnPosition.Left));
AddStep("Right special style", () => createPlayfield(4, SpecialColumnPosition.Right));
AddStep("5 columns", () => createPlayfield(5, SpecialColumnPosition.Normal));
AddStep("8 columns", () => createPlayfield(8, SpecialColumnPosition.Normal));
AddStep("Left special style", () => createPlayfield(8, SpecialColumnPosition.Left));
AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right));
AddStep("Normal special style", () => createPlayfield(4, SpecialColumnPosition.Normal));
AddStep("Notes", () => createPlayfieldWithNotes(4, SpecialColumnPosition.Normal));
AddWaitStep(10);
AddStep("Left special style", () => createPlayfieldWithNotes(4, SpecialColumnPosition.Left));
AddWaitStep(10);
AddStep("Right special style", () => createPlayfieldWithNotes(4, SpecialColumnPosition.Right));
AddWaitStep(10);
AddStep("Notes with input", () => createPlayfieldWithNotesAcceptingInput());
}
private void triggerKeyDown(Column column)
{
column.TriggerOnKeyDown(new InputState(), new KeyDownEventArgs
{
Key = column.Key,
Repeat = false
});
}
private void triggerKeyUp(Column column)
{
column.TriggerOnKeyUp(new InputState(), new KeyUpEventArgs
{
Key = column.Key
});
}
}
}
@@ -0,0 +1,59 @@
// 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.Containers;
using osu.Framework.Logging;
using osu.Framework.Testing;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseMenuOverlays : TestCase
{
public override string Description => @"Tests pause and fail overlays";
private PauseContainer.PauseOverlay pauseOverlay;
private FailOverlay failOverlay;
private int retryCount;
public override void Reset()
{
base.Reset();
retryCount = 0;
Add(pauseOverlay = new PauseContainer.PauseOverlay
{
OnResume = () => Logger.Log(@"Resume"),
OnRetry = () => Logger.Log(@"Retry"),
OnQuit = () => Logger.Log(@"Quit"),
});
Add(failOverlay = new FailOverlay
{
OnRetry = () => Logger.Log(@"Retry"),
OnQuit = () => Logger.Log(@"Quit"),
});
AddStep(@"Pause", delegate {
if(failOverlay.State == Visibility.Visible)
{
failOverlay.Hide();
}
pauseOverlay.Show();
});
AddStep("Fail", delegate {
if (pauseOverlay.State == Visibility.Visible)
{
pauseOverlay.Hide();
}
failOverlay.Show();
});
AddStep("Add Retry", delegate
{
retryCount++;
pauseOverlay.Retries = retryCount;
failOverlay.Retries = retryCount;
});
}
}
}
@@ -1,35 +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 osu.Framework.Graphics;
using osu.Game.Overlays.Mods;
using osu.Framework.Testing;
using osu.Game.Modes;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseModSelectOverlay : TestCase
{
public override string Description => @"Tests the mod select overlay";
private ModSelectOverlay modSelect;
public override void Reset()
{
base.Reset();
Add(modSelect = new ModSelectOverlay
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
});
AddButton("Toggle", modSelect.ToggleVisibility);
AddButton("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu);
AddButton("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko);
AddButton("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch);
AddButton("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania);
}
}
}
@@ -0,0 +1,57 @@
// 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.Allocation;
using osu.Framework.Graphics;
using osu.Game.Overlays.Mods;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Screens.Play.HUD;
using OpenTK;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseMods : TestCase
{
public override string Description => @"Mod select overlay and in-game display";
private ModSelectOverlay modSelect;
private ModDisplay modDisplay;
private RulesetDatabase rulesets;
[BackgroundDependencyLoader]
private void load(RulesetDatabase rulesets)
{
this.rulesets = rulesets;
}
public override void Reset()
{
base.Reset();
Add(modSelect = new ModSelectOverlay
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
});
Add(modDisplay = new ModDisplay
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Position = new Vector2(0, 25),
});
modDisplay.Current.BindTo(modSelect.SelectedMods);
AddStep("Toggle", modSelect.ToggleVisibility);
foreach (var ruleset in rulesets.AllRulesets)
AddStep(ruleset.CreateInstance().Description, () => modSelect.Ruleset.Value = ruleset);
}
}
}
@@ -30,7 +30,9 @@ namespace osu.Desktop.VisualTests.Tests
Anchor = Anchor.Centre
};
Add(mc);
AddToggle(@"Show", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
AddToggleStep(@"toggle visibility", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
AddStep(@"show", () => mc.State = Visibility.Visible);
}
}
}
@@ -30,13 +30,13 @@ namespace osu.Desktop.VisualTests.Tests
Origin = Anchor.TopRight,
});
AddToggle(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
AddToggleStep(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
AddButton(@"simple #1", sendNotification1);
AddButton(@"simple #2", sendNotification2);
AddButton(@"progress #1", sendProgress1);
AddButton(@"progress #2", sendProgress2);
AddButton(@"barrage", () => sendBarrage());
AddStep(@"simple #1", sendNotification1);
AddStep(@"simple #2", sendNotification2);
AddStep(@"progress #1", sendProgress1);
AddStep(@"progress #2", sendProgress2);
AddStep(@"barrage", () => sendBarrage());
}
private void sendBarrage(int remaining = 100)
@@ -0,0 +1,47 @@
// 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.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Testing;
using osu.Game.Overlays;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseOnScreenDisplay : TestCase
{
private FrameworkConfigManager config;
private Bindable<FrameSync> frameSyncMode;
public override string Description => @"Make it easier to see setting changes";
public override void Reset()
{
base.Reset();
Add(new OnScreenDisplay());
frameSyncMode = config.GetBindable<FrameSync>(FrameworkSetting.FrameSync);
FrameSync initial = frameSyncMode.Value;
AddRepeatStep(@"Change frame limiter", setNextMode, 3);
AddStep(@"Restore frame limiter", () => frameSyncMode.Value = initial);
}
private void setNextMode()
{
var nextMode = frameSyncMode.Value + 1;
if (nextMode > FrameSync.Unlimited)
nextMode = FrameSync.VSync;
frameSyncMode.Value = nextMode;
}
[BackgroundDependencyLoader]
private void load(FrameworkConfigManager config)
{
this.config = config;
}
}
}
@@ -1,38 +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 osu.Framework.Logging;
using osu.Framework.Testing;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCasePauseOverlay : TestCase
{
public override string Description => @"Tests the pause overlay";
private PauseOverlay pauseOverlay;
private int retryCount;
public override void Reset()
{
base.Reset();
Add(pauseOverlay = new PauseOverlay
{
Depth = -1,
OnResume = () => Logger.Log(@"Resume"),
OnRetry = () => Logger.Log(@"Retry"),
OnQuit = () => Logger.Log(@"Quit")
});
AddButton("Pause", pauseOverlay.Show);
AddButton("Add Retry", delegate
{
retryCount++;
pauseOverlay.Retries = retryCount;
});
retryCount = 0;
}
}
}
@@ -6,7 +6,6 @@ using osu.Desktop.VisualTests.Platform;
using osu.Framework.Testing;
using osu.Framework.MathUtils;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Filter;
@@ -14,21 +13,25 @@ namespace osu.Desktop.VisualTests.Tests
{
internal class TestCasePlaySongSelect : TestCase
{
private BeatmapDatabase db, oldDb;
private BeatmapDatabase db;
private TestStorage storage;
private PlaySongSelect songSelect;
public override string Description => @"with fake data";
private RulesetDatabase rulesets;
public override void Reset()
{
base.Reset();
oldDb = Dependencies.Get<BeatmapDatabase>();
if (db == null)
{
storage = new TestStorage(@"TestCasePlaySongSelect");
db = new BeatmapDatabase(storage);
Dependencies.Cache(db, true);
var backingDatabase = storage.GetDatabase(@"client");
rulesets = new RulesetDatabase(storage, backingDatabase);
db = new BeatmapDatabase(storage, backingDatabase, rulesets);
var sets = new List<BeatmapSetInfo>();
@@ -40,22 +43,19 @@ namespace osu.Desktop.VisualTests.Tests
Add(songSelect = new PlaySongSelect());
AddButton(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
AddButton(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
AddButton(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
AddButton(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
AddStep(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
}
protected override void Dispose(bool isDisposing)
{
if (oldDb != null)
{
Dependencies.Cache(oldDb, true);
db = null;
}
//protected override void Dispose(bool isDisposing)
//{
// if (oldDb != null)
// db = null;
base.Dispose(isDisposing);
}
// base.Dispose(isDisposing);
//}
private BeatmapSetInfo createTestBeatmapSet(int i)
{
@@ -77,7 +77,7 @@ namespace osu.Desktop.VisualTests.Tests
new BeatmapInfo
{
OnlineBeatmapID = 1234 + i,
Mode = PlayMode.Osu,
Ruleset = rulesets.Query<RulesetInfo>().First(),
Path = "normal.osu",
Version = "Normal",
Difficulty = new BeatmapDifficulty
@@ -88,7 +88,7 @@ namespace osu.Desktop.VisualTests.Tests
new BeatmapInfo
{
OnlineBeatmapID = 1235 + i,
Mode = PlayMode.Osu,
Ruleset = rulesets.Query<RulesetInfo>().First(),
Path = "hard.osu",
Version = "Hard",
Difficulty = new BeatmapDifficulty
@@ -99,7 +99,7 @@ namespace osu.Desktop.VisualTests.Tests
new BeatmapInfo
{
OnlineBeatmapID = 1236 + i,
Mode = PlayMode.Osu,
Ruleset = rulesets.Query<RulesetInfo>().First(),
Path = "insane.osu",
Version = "Insane",
Difficulty = new BeatmapDifficulty
+11 -11
View File
@@ -9,12 +9,12 @@ using osu.Game.Beatmaps;
using OpenTK;
using osu.Framework.Graphics.Sprites;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Play;
using OpenTK.Graphics;
using osu.Desktop.VisualTests.Beatmaps;
using osu.Game.Rulesets.Osu.UI;
namespace osu.Desktop.VisualTests.Tests
{
@@ -22,12 +22,14 @@ namespace osu.Desktop.VisualTests.Tests
{
protected Player Player;
private BeatmapDatabase db;
private RulesetDatabase rulesets;
public override string Description => @"Showing everything to play the game.";
[BackgroundDependencyLoader]
private void load(BeatmapDatabase db)
private void load(BeatmapDatabase db, RulesetDatabase rulesets)
{
this.rulesets = rulesets;
this.db = db;
}
@@ -37,7 +39,7 @@ namespace osu.Desktop.VisualTests.Tests
WorkingBeatmap beatmap = null;
var beatmapInfo = db.Query<BeatmapInfo>().FirstOrDefault(b => b.Mode == PlayMode.Osu);
var beatmapInfo = db.Query<BeatmapInfo>().FirstOrDefault(b => b.RulesetID == 0);
if (beatmapInfo != null)
beatmap = db.GetWorkingBeatmap(beatmapInfo);
@@ -51,8 +53,8 @@ namespace osu.Desktop.VisualTests.Tests
objects.Add(new HitCircle
{
StartTime = time,
Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512,
i % 4 < 2 ? 0 : 384),
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
});
@@ -65,6 +67,7 @@ namespace osu.Desktop.VisualTests.Tests
BeatmapInfo = new BeatmapInfo
{
Difficulty = new BeatmapDifficulty(),
Ruleset = rulesets.Query<RulesetInfo>().First(),
Metadata = new BeatmapMetadata
{
Artist = @"Unknown",
@@ -83,10 +86,7 @@ namespace osu.Desktop.VisualTests.Tests
Colour = Color4.Black,
});
Add(new PlayerLoader(Player = CreatePlayer(beatmap))
{
Beatmap = beatmap
});
Add(Player = CreatePlayer(beatmap));
}
protected virtual Player CreatePlayer(WorkingBeatmap beatmap)
@@ -1,24 +1,15 @@
// 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.Input.Handlers;
using osu.Game.Beatmaps;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Osu.Mods;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens.Play;
using System;
using System.IO;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseReplay : TestCasePlayer
{
private WorkingBeatmap beatmap;
private InputHandler replay;
private Func<Stream> getReplayStream;
public override string Description => @"Testing replay playback.";
protected override Player CreatePlayer(WorkingBeatmap beatmap)
@@ -0,0 +1,55 @@
// 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.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play;
using osu.Game.Screens.Play.ReplaySettings;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseReplaySettingsOverlay : TestCase
{
public override string Description => @"Settings visible in replay/auto";
private ExampleContainer container;
public override void Reset()
{
base.Reset();
Add(new ReplaySettingsOverlay()
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
});
Add(container = new ExampleContainer());
AddStep(@"Add button", () => container.Add(new OsuButton
{
RelativeSizeAxes = Axes.X,
Text = @"Button",
}));
AddStep(@"Add checkbox", () => container.Add(new ReplayCheckbox
{
LabelText = "Checkbox",
}));
AddStep(@"Add textbox", () => container.Add(new FocusedTextBox
{
RelativeSizeAxes = Axes.X,
Height = 30,
PlaceholderText = "Textbox",
HoldFocus = false,
}));
}
private class ExampleContainer : ReplayGroup
{
protected override string Title => @"example";
}
}
}
@@ -0,0 +1,68 @@
// 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.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Ranking;
using osu.Game.Users;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseResults : TestCase
{
private BeatmapDatabase db;
public override string Description => @"Results after playing.";
[BackgroundDependencyLoader]
private void load(BeatmapDatabase db)
{
this.db = db;
}
private WorkingBeatmap beatmap;
public override void Reset()
{
base.Reset();
if (beatmap == null)
{
var beatmapInfo = db.Query<BeatmapInfo>().FirstOrDefault(b => b.RulesetID == 0);
if (beatmapInfo != null)
beatmap = db.GetWorkingBeatmap(beatmapInfo);
}
base.Reset();
Add(new Results(new Score
{
TotalScore = 2845370,
Accuracy = 0.98,
MaxCombo = 123,
Rank = ScoreRank.A,
Date = DateTimeOffset.Now,
Statistics = new Dictionary<string, dynamic>()
{
{ "300", 50 },
{ "100", 20 },
{ "50", 50 },
{ "x", 1 }
},
User = new User
{
Username = "peppy",
}
})
{
Beatmap = beatmap
});
}
}
}
@@ -3,12 +3,11 @@
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Modes.UI;
using osu.Game.Screens.Play.HUD;
namespace osu.Desktop.VisualTests.Tests
{
@@ -22,8 +21,6 @@ namespace osu.Desktop.VisualTests.Tests
int numerator = 0, denominator = 0;
bool maniaHold = false;
ScoreCounter score = new ScoreCounter(7)
{
Origin = Anchor.TopRight,
@@ -68,7 +65,7 @@ namespace osu.Desktop.VisualTests.Tests
};
Add(starsLabel);
AddButton(@"Reset all", delegate
AddStep(@"Reset all", delegate
{
score.Current.Value = 0;
comboCounter.Current.Value = 0;
@@ -78,7 +75,7 @@ namespace osu.Desktop.VisualTests.Tests
starsLabel.Text = stars.Count.ToString("0.00");
});
AddButton(@"Hit! :D", delegate
AddStep(@"Hit! :D", delegate
{
score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
comboCounter.Increment();
@@ -86,20 +83,20 @@ namespace osu.Desktop.VisualTests.Tests
accuracyCounter.SetFraction(numerator, denominator);
});
AddButton(@"miss...", delegate
AddStep(@"miss...", delegate
{
comboCounter.Current.Value = 0;
denominator++;
accuracyCounter.SetFraction(numerator, denominator);
});
AddButton(@"Alter stars", delegate
AddStep(@"Alter stars", delegate
{
stars.Count = RNG.NextSingle() * (stars.StarCount + 1);
starsLabel.Text = stars.Count.ToString("0.00");
});
AddButton(@"Stop counters", delegate
AddStep(@"Stop counters", delegate
{
score.StopRolling();
comboCounter.StopRolling();
@@ -6,18 +6,18 @@ using osu.Game.Overlays;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseOptions : TestCase
internal class TestCaseSettings : TestCase
{
public override string Description => @"Tests the options overlay";
public override string Description => @"Tests the settings overlay";
private OptionsOverlay options;
private SettingsOverlay settings;
public override void Reset()
{
base.Reset();
Children = new[] { options = new OptionsOverlay() };
options.ToggleVisibility();
Children = new[] { settings = new SettingsOverlay() };
settings.ToggleVisibility();
}
}
}
@@ -0,0 +1,19 @@
// 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.Testing;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseSkipButton : TestCase
{
public override string Description => @"Skip skip skippediskip";
public override void Reset()
{
base.Reset();
Add(new SkipButton(Clock.CurrentTime + 5000));
}
}
}
@@ -0,0 +1,67 @@
// 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.Graphics;
using osu.Framework.MathUtils;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseSongProgress : TestCase
{
public override string Description => @"With fake data";
private SongProgress progress;
private SongProgressGraph graph;
private StopwatchClock clock;
public override void Reset()
{
base.Reset();
clock = new StopwatchClock(true);
Add(progress = new SongProgress
{
RelativeSizeAxes = Axes.X,
AudioClock = new StopwatchClock(true),
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
});
Add(graph = new SongProgressGraph
{
RelativeSizeAxes = Axes.X,
Height = 200,
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft,
});
AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking);
AddWaitStep(5);
AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking);
AddWaitStep(2);
AddRepeatStep("New Values", displayNewValues, 5);
displayNewValues();
}
private void displayNewValues()
{
List<HitObject> objects = new List<HitObject>();
for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000)
objects.Add(new HitObject { StartTime = i });
progress.Objects = objects;
graph.Objects = objects;
progress.AudioClock = clock;
progress.OnSeek = pos => clock.Seek(pos);
}
}
}
@@ -1,8 +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.Framework.Graphics;
using OpenTK;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Testing;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
@@ -36,9 +36,9 @@ namespace osu.Desktop.VisualTests.Tests
filter.PinItem(GroupMode.All);
filter.PinItem(GroupMode.RecentlyPlayed);
filter.ItemChanged += (sender, mode) =>
filter.Current.ValueChanged += newFilter =>
{
text.Text = "Currently Selected: " + mode.ToString();
text.Text = "Currently Selected: " + newFilter.ToString();
};
}
}
@@ -1,16 +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 OpenTK;
using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Testing;
using osu.Game.Graphics;
using osu.Game.Modes.Taiko.Objects;
using osu.Game.Modes.Taiko.Objects.Drawable.Pieces;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
namespace osu.Desktop.VisualTests.Tests
{
@@ -24,181 +20,94 @@ namespace osu.Desktop.VisualTests.Tests
{
base.Reset();
AddToggle("Kiai", b =>
AddToggleStep("Kiai", b =>
{
kiai = !kiai;
Reset();
updateKiaiState();
});
Add(new CentreHitCircle(new CirclePiece()
Add(new CirclePiece
{
KiaiMode = kiai
})
{
Position = new Vector2(100, 100)
});
Add(new CentreHitCircle(new StrongCirclePiece()
{
KiaiMode = kiai
})
{
Position = new Vector2(350, 100)
});
Add(new RimHitCircle(new CirclePiece()
{
KiaiMode = kiai
})
{
Position = new Vector2(100, 300)
});
Add(new RimHitCircle(new StrongCirclePiece()
{
KiaiMode = kiai
})
{
Position = new Vector2(350, 300)
});
Add(new SwellCircle(new CirclePiece()
{
KiaiMode = kiai
})
{
Position = new Vector2(100, 500)
});
Add(new SwellCircle(new StrongCirclePiece()
{
KiaiMode = kiai
})
{
Position = new Vector2(350, 500)
});
Add(new DrumRollCircle(new CirclePiece()
{
KiaiMode = kiai
})
{
Width = 250,
Position = new Vector2(575, 100)
});
Add(new DrumRollCircle(new StrongCirclePiece()
{
KiaiMode = kiai
})
{
Width = 250,
Position = new Vector2(575, 300)
});
}
private class SwellCircle : BaseCircle
{
public SwellCircle(CirclePiece piece)
: base(piece)
{
Piece.Add(new TextAwesome
Position = new Vector2(100, 100),
AccentColour = Color4.DarkRed,
KiaiMode = kiai,
Children = new[]
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
TextSize = SYMBOL_INNER_SIZE,
Icon = FontAwesome.fa_asterisk,
Shadow = false
});
}
new CentreHitSymbolPiece()
}
});
[BackgroundDependencyLoader]
private void load(OsuColour colours)
Add(new CirclePiece(true)
{
Piece.AccentColour = colours.YellowDark;
}
}
private class DrumRollCircle : BaseCircle
{
public DrumRollCircle(CirclePiece piece)
: base(piece)
{
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Piece.AccentColour = colours.YellowDark;
}
}
private class CentreHitCircle : BaseCircle
{
public CentreHitCircle(CirclePiece piece)
: base(piece)
{
Piece.Add(new CircularContainer
Position = new Vector2(350, 100),
AccentColour = Color4.DarkRed,
KiaiMode = kiai,
Children = new[]
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(SYMBOL_INNER_SIZE),
Masking = true,
Children = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both
}
}
});
}
new CentreHitSymbolPiece()
}
});
[BackgroundDependencyLoader]
private void load(OsuColour colours)
Add(new CirclePiece
{
Piece.AccentColour = colours.PinkDarker;
}
Position = new Vector2(100, 300),
AccentColour = Color4.DarkBlue,
KiaiMode = kiai,
Children = new[]
{
new RimHitSymbolPiece()
}
});
Add(new CirclePiece(true)
{
Position = new Vector2(350, 300),
AccentColour = Color4.DarkBlue,
KiaiMode = kiai,
Children = new[]
{
new RimHitSymbolPiece()
}
});
Add(new CirclePiece
{
Position = new Vector2(100, 500),
AccentColour = Color4.Orange,
KiaiMode = kiai,
Children = new[]
{
new SwellSymbolPiece()
}
});
Add(new ElongatedCirclePiece
{
Position = new Vector2(575, 100),
AccentColour = Color4.Orange,
KiaiMode = kiai,
Length = 0.10f,
PlayfieldLengthReference = () => DrawSize.X
});
Add(new ElongatedCirclePiece(true)
{
Position = new Vector2(575, 300),
AccentColour = Color4.Orange,
KiaiMode = kiai,
Length = 0.10f,
PlayfieldLengthReference = () => DrawSize.X
});
}
private class RimHitCircle : BaseCircle
private void updateKiaiState()
{
public RimHitCircle(CirclePiece piece)
: base(piece)
{
Piece.Add(new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(SYMBOL_SIZE),
BorderThickness = SYMBOL_BORDER,
BorderColour = Color4.White,
Masking = true,
Children = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true
}
}
});
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Piece.AccentColour = colours.BlueDarker;
}
foreach (var c in Children.OfType<CirclePiece>())
c.KiaiMode = kiai;
}
private abstract class BaseCircle : Container
{
protected const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f;
protected const float SYMBOL_BORDER = 8;
protected const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER;
protected readonly CirclePiece Piece;
protected BaseCircle(CirclePiece piece)
@@ -1,50 +1,129 @@
// 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.Framework.Graphics.Containers;
using osu.Framework.MathUtils;
using osu.Framework.Testing;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Taiko.Judgements;
using osu.Game.Modes.Taiko.Objects;
using osu.Game.Modes.Taiko.UI;
using osu.Framework.Timing;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.Taiko.UI;
using System;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseTaikoPlayfield : TestCase
{
private const double default_duration = 300;
private const float scroll_time = 1000;
public override string Description => "Taiko playfield";
protected override double TimePerAction => default_duration * 2;
private readonly Random rng = new Random(1337);
private TaikoPlayfield playfield;
private Container playfieldContainer;
public override void Reset()
{
base.Reset();
AddButton("Hit!", addHitJudgement);
AddButton("Miss :(", addMissJudgement);
AddStep("Hit!", addHitJudgement);
AddStep("Miss :(", addMissJudgement);
AddStep("DrumRoll", () => addDrumRoll(false));
AddStep("Strong DrumRoll", () => addDrumRoll(true));
AddStep("Swell", () => addSwell());
AddStep("Centre", () => addCentreHit(false));
AddStep("Strong Centre", () => addCentreHit(true));
AddStep("Rim", () => addRimHit(false));
AddStep("Strong Rim", () => addRimHit(true));
AddStep("Add bar line", () => addBarLine(false));
AddStep("Add major bar line", () => addBarLine(true));
AddStep("Height test 1", () => changePlayfieldSize(1));
AddStep("Height test 2", () => changePlayfieldSize(2));
AddStep("Height test 3", () => changePlayfieldSize(3));
AddStep("Height test 4", () => changePlayfieldSize(4));
AddStep("Height test 5", () => changePlayfieldSize(5));
AddStep("Reset height", () => changePlayfieldSize(6));
Add(playfield = new TaikoPlayfield
var rateAdjustClock = new StopwatchClock(true) { Rate = 1 };
Add(playfieldContainer = new Container
{
Y = 200
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT,
Clock = new FramedClock(rateAdjustClock),
Children = new[]
{
playfield = new TaikoPlayfield()
}
});
}
private void changePlayfieldSize(int step)
{
// Add new hits
switch (step)
{
case 1:
addCentreHit(false);
break;
case 2:
addCentreHit(true);
break;
case 3:
addDrumRoll(false);
break;
case 4:
addDrumRoll(true);
break;
case 5:
addSwell(1000);
playfieldContainer.Delay(scroll_time - 100);
break;
}
// Tween playfield height
switch (step)
{
default:
playfieldContainer.ResizeTo(new Vector2(1, rng.Next(25, 400)), 500);
break;
case 6:
playfieldContainer.ResizeTo(new Vector2(1, TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT), 500);
break;
}
}
private void addHitJudgement()
{
TaikoHitResult hitResult = RNG.Next(2) == 0 ? TaikoHitResult.Good : TaikoHitResult.Great;
playfield.OnJudgement(new DrawableTestHit(new Hit())
var h = new DrawableTestHit(new 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,
ComboAtHit = 1,
SecondHit = RNG.Next(10) == 0
TimeOffset = 0
}
});
};
playfield.OnJudgement(h);
if (RNG.Next(10) == 0)
{
h.Judgement.SecondHit = true;
playfield.OnJudgement(h);
}
}
private void addMissJudgement()
@@ -54,12 +133,76 @@ namespace osu.Desktop.VisualTests.Tests
Judgement = new TaikoJudgement
{
Result = HitResult.Miss,
TimeOffset = 0,
ComboAtHit = 0
TimeOffset = 0
}
});
}
private void addBarLine(bool major, double delay = scroll_time)
{
BarLine bl = new BarLine
{
StartTime = playfield.Time.Current + delay,
ScrollTime = scroll_time
};
playfield.AddBarLine(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl));
}
private void addSwell(double duration = default_duration)
{
playfield.Add(new DrawableSwell(new Swell
{
StartTime = playfield.Time.Current + scroll_time,
Duration = duration,
ScrollTime = scroll_time
}));
}
private void addDrumRoll(bool strong, double duration = default_duration)
{
addBarLine(true);
addBarLine(true, scroll_time + duration);
var d = new DrumRoll
{
StartTime = playfield.Time.Current + scroll_time,
IsStrong = strong,
Duration = duration,
ScrollTime = scroll_time,
};
playfield.Add(new DrawableDrumRoll(d));
}
private void addCentreHit(bool strong)
{
Hit h = new Hit
{
StartTime = playfield.Time.Current + scroll_time,
ScrollTime = scroll_time
};
if (strong)
playfield.Add(new DrawableCentreHitStrong(h));
else
playfield.Add(new DrawableCentreHit(h));
}
private void addRimHit(bool strong)
{
Hit h = new Hit
{
StartTime = playfield.Time.Current + scroll_time,
ScrollTime = scroll_time
};
if (strong)
playfield.Add(new DrawableRimHitStrong(h));
else
playfield.Add(new DrawableRimHit(h));
}
private class DrawableTestHit : DrawableHitObject<TaikoHitObject, TaikoJudgement>
{
public DrawableTestHit(TaikoHitObject hitObject)
@@ -3,20 +3,18 @@
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseTwoLayerButton : TestCase
{
public override string Description => @"Back and skip and what not";
public override string Description => @"Mostly back button";
public override void Reset()
{
base.Reset();
Add(new BackButton());
Add(new SkipButton());
}
}
}
@@ -0,0 +1,57 @@
// 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.Testing;
using osu.Framework.Graphics;
using osu.Game.Users;
using osu.Framework.Graphics.Containers;
using OpenTK;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseUserPanel : TestCase
{
public override string Description => @"Panels for displaying a user's status";
public override void Reset()
{
base.Reset();
UserPanel flyte;
UserPanel peppy;
Add(new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(10f),
Children = new[]
{
flyte = new UserPanel(new User
{
Username = @"flyte",
Id = 3103765,
Country = new Country { FlagName = @"JP" },
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
}) { Width = 300 },
peppy = new UserPanel(new User
{
Username = @"peppy",
Id = 2,
Country = new Country { FlagName = @"AU" },
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg"
}) { Width = 300 },
},
});
flyte.Status.Value = new UserStatusOnline();
peppy.Status.Value = new UserStatusSoloGame();
AddStep(@"spectating", () => { flyte.Status.Value = new UserStatusSpectating(); });
AddStep(@"multiplaying", () => { flyte.Status.Value = new UserStatusMultiplayerGame(); });
AddStep(@"modding", () => { flyte.Status.Value = new UserStatusModding(); });
AddStep(@"offline", () => { flyte.Status.Value = new UserStatusOffline(); });
AddStep(@"null status", () => { flyte.Status.Value = null; });
}
}
}
+2 -2
View File
@@ -14,7 +14,7 @@ namespace osu.Desktop.VisualTests
{
base.LoadComplete();
new BackgroundScreenDefault { Depth = 10 }.LoadAsync(this, AddInternal);
LoadComponentAsync(new BackgroundScreenDefault { Depth = 10 }, AddInternal);
// Have to construct this here, rather than in the constructor, because
// we depend on some dependencies to be loaded within OsuGameBase.load().
@@ -29,7 +29,7 @@ namespace osu.Desktop.VisualTests
host.DrawThread.InactiveHz = host.DrawThread.ActiveHz;
host.InputThread.InactiveHz = host.InputThread.ActiveHz;
host.Window.CursorState = CursorState.Hidden;
host.Window.CursorState |= CursorState.Hidden;
}
}
}
@@ -61,6 +61,7 @@
<RunCodeAnalysis>false</RunCodeAnalysis>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -83,22 +84,20 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1340\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private>
<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="SharpCompress, Version=0.15.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
<HintPath>..\packages\SharpCompress.0.15.1\lib\net45\SharpCompress.dll</HintPath>
<Private>True</Private>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
</Reference>
<Reference Include="SharpCompress, Version=0.15.2.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\SharpCompress.0.15.2\lib\net45\SharpCompress.dll</HintPath>
</Reference>
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="Newtonsoft.Json">
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="SQLiteNetExtensions">
<HintPath>$(SolutionDir)\packages\SQLiteNetExtensions.1.3.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\SQLiteNetExtensions.dll</HintPath>
</Reference>
@@ -162,21 +161,21 @@
<Project>{d9a367c9-4c1a-489f-9b05-a0cea2b53b58}</Project>
<Name>osu.Game.Resources</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj">
<Project>{c92a607b-1fdd-4954-9f92-03ff547d9080}</Project>
<Name>osu.Game.Modes.Osu</Name>
<Name>osu.Game.Rulesets.Osu</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Catch\osu.Game.Modes.Catch.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
<Project>{58f6c80c-1253-4a0e-a465-b8c85ebeadf3}</Project>
<Name>osu.Game.Modes.Catch</Name>
<Name>osu.Game.Rulesets.Catch</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Mania\osu.Game.Modes.Mania.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj">
<Project>{48f4582b-7687-4621-9cbe-5c24197cb536}</Project>
<Name>osu.Game.Modes.Mania</Name>
<Name>osu.Game.Rulesets.Mania</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Taiko\osu.Game.Modes.Taiko.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj">
<Project>{f167e17a-7de6-4af5-b920-a5112296c695}</Project>
<Name>osu.Game.Modes.Taiko</Name>
<Name>osu.Game.Rulesets.Taiko</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
<Project>{0d3fbf8a-7464-4cf7-8c90-3e7886df2d4d}</Project>
@@ -184,19 +183,28 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Benchmark.cs" />
<Compile Include="AutomatedVisualTestGame.cs" />
<Compile Include="Program.cs" />
<Compile Include="Tests\TestCaseChatDisplay.cs" />
<Compile Include="Tests\TestCaseBeatmapDetails.cs" />
<Compile Include="Tests\TestCaseDrawings.cs" />
<Compile Include="Tests\TestCaseGamefield.cs" />
<Compile Include="Tests\TestCaseGraph.cs" />
<Compile Include="Tests\TestCaseManiaHitObjects.cs" />
<Compile Include="Tests\TestCaseManiaPlayfield.cs" />
<Compile Include="Tests\TestCaseMenuOverlays.cs" />
<Compile Include="Tests\TestCaseMusicController.cs" />
<Compile Include="Tests\TestCaseNotificationManager.cs" />
<Compile Include="Tests\TestCaseOnScreenDisplay.cs" />
<Compile Include="Tests\TestCaseReplaySettingsOverlay.cs" />
<Compile Include="Tests\TestCasePlayer.cs" />
<Compile Include="Tests\TestCaseHitObjects.cs" />
<Compile Include="Tests\TestCaseKeyCounter.cs" />
<Compile Include="Tests\TestCaseMenuButtonSystem.cs" />
<Compile Include="Tests\TestCaseReplay.cs" />
<Compile Include="Tests\TestCaseResults.cs" />
<Compile Include="Tests\TestCaseScoreCounter.cs" />
<Compile Include="Tests\TestCaseSkipButton.cs" />
<Compile Include="Tests\TestCaseTabControl.cs" />
<Compile Include="Tests\TestCaseTaikoHitObjects.cs" />
<Compile Include="Tests\TestCaseTaikoPlayfield.cs" />
@@ -205,14 +213,18 @@
<Compile Include="Tests\TestCaseTwoLayerButton.cs" />
<Compile Include="VisualTestGame.cs" />
<Compile Include="Platform\TestStorage.cs" />
<Compile Include="Tests\TestCaseOptions.cs" />
<Compile Include="Tests\TestCasePauseOverlay.cs" />
<Compile Include="Tests\TestCaseModSelectOverlay.cs" />
<Compile Include="Tests\TestCaseSettings.cs" />
<Compile Include="Tests\TestCaseSongProgress.cs" />
<Compile Include="Tests\TestCaseMods.cs" />
<Compile Include="Tests\TestCaseDialogOverlay.cs" />
<Compile Include="Tests\TestCaseBeatmapOptionsOverlay.cs" />
<Compile Include="Tests\TestCaseLeaderboard.cs" />
<Compile Include="Beatmaps\TestWorkingBeatmap.cs" />
<Compile Include="Tests\TestCaseBeatmapDetailArea.cs" />
<Compile Include="Tests\TestCaseDrawableRoom.cs" />
<Compile Include="Tests\TestCaseUserPanel.cs" />
<Compile Include="Tests\TestCaseDirect.cs" />
<Compile Include="Tests\TestCaseBreadcrumbs.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup />
+3 -3
View File
@@ -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="9.0.1" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1340" targetFramework="net45" />
<package id="SharpCompress" version="0.15.1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
<package id="SharpCompress" version="0.15.2" targetFramework="net45" />
<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" />
@@ -3,10 +3,7 @@
using System.IO;
using System.Linq;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.IO;
using osu.Game.Beatmaps;
using osu.Game.Database;
namespace osu.Desktop.Beatmaps.IO
{
@@ -17,21 +14,18 @@ namespace osu.Desktop.Beatmaps.IO
{
public static void Register() => AddReader<LegacyFilesystemReader>((storage, path) => Directory.Exists(path));
private string basePath { get; }
private Beatmap firstMap { get; }
private readonly string basePath;
public LegacyFilesystemReader(string path)
{
basePath = path;
BeatmapFilenames = Directory.GetFiles(basePath, @"*.osu").Select(Path.GetFileName).ToArray();
if (BeatmapFilenames.Length == 0)
throw new FileNotFoundException(@"This directory contains no beatmaps");
StoryboardFilename = Directory.GetFiles(basePath, @"*.osb").Select(Path.GetFileName).FirstOrDefault();
using (var stream = new StreamReader(GetStream(BeatmapFilenames[0])))
{
var decoder = BeatmapDecoder.GetDecoder(stream);
firstMap = decoder.Decode(stream);
}
}
public override Stream GetStream(string name)
@@ -39,14 +33,11 @@ namespace osu.Desktop.Beatmaps.IO
return File.OpenRead(Path.Combine(basePath, name));
}
public override BeatmapMetadata ReadMetadata()
{
return firstMap.BeatmapInfo.Metadata;
}
public override void Dispose()
{
// no-op
}
public override Stream GetUnderlyingStream() => null;
}
}
+2 -2
View File
@@ -29,7 +29,7 @@ namespace osu.Desktop
{
base.LoadComplete();
versionManager.LoadAsync(this);
LoadComponentAsync(versionManager);
ScreenChanged += s =>
{
if (!versionManager.IsAlive && s is Intro)
@@ -43,7 +43,7 @@ namespace osu.Desktop
var desktopWindow = host.Window as DesktopGameWindow;
if (desktopWindow != null)
{
desktopWindow.CursorState = CursorState.Hidden;
desktopWindow.CursorState |= CursorState.Hidden;
desktopWindow.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
desktopWindow.Title = Name;
+7 -2
View File
@@ -189,19 +189,24 @@ namespace osu.Desktop.Overlays
private class UpdateProgressNotification : ProgressNotification
{
private OsuGame game;
protected override Notification CreateCompletionNotification() => new ProgressCompletionNotification()
{
Text = @"Update ready to install. Click to restart!",
Activated = () =>
{
UpdateManager.RestartApp();
UpdateManager.RestartAppWhenExited();
game.GracefullyExit();
return true;
}
};
[BackgroundDependencyLoader]
private void load(OsuColour colours)
private void load(OsuColour colours, OsuGame game)
{
this.game = game;
IconContent.Add(new Drawable[]
{
new Box
-10
View File
@@ -7,11 +7,6 @@ using osu.Desktop.Beatmaps.IO;
using osu.Framework.Desktop;
using osu.Framework.Desktop.Platform;
using osu.Game.IPC;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
using osu.Game.Modes.Mania;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Taiko;
namespace osu.Desktop
{
@@ -41,11 +36,6 @@ namespace osu.Desktop
}
else
{
Ruleset.Register(new OsuRuleset());
Ruleset.Register(new TaikoRuleset());
Ruleset.Register(new ManiaRuleset());
Ruleset.Register(new CatchRuleset());
host.Run(new OsuGameDesktop(args));
}
return 0;
+3 -3
View File
@@ -4,7 +4,7 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu!lazer")]
@@ -16,8 +16,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
+13 -9
View File
@@ -63,6 +63,7 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<Commandlineparameters>
</Commandlineparameters>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -123,7 +124,9 @@
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4" />
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
</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>
@@ -150,6 +153,7 @@
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="OpenTK.dll.config" />
<None Include="osu!.res" />
<None Include="packages.config" />
<None Include="Properties\app.manifest" />
@@ -194,21 +198,21 @@
<Project>{d9a367c9-4c1a-489f-9b05-a0cea2b53b58}</Project>
<Name>osu.Game.Resources</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj">
<Project>{c92a607b-1fdd-4954-9f92-03ff547d9080}</Project>
<Name>osu.Game.Modes.Osu</Name>
<Name>osu.Game.Rulesets.Osu</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Catch\osu.Game.Modes.Catch.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
<Project>{58f6c80c-1253-4a0e-a465-b8c85ebeadf3}</Project>
<Name>osu.Game.Modes.Catch</Name>
<Name>osu.Game.Rulesets.Catch</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Mania\osu.Game.Modes.Mania.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj">
<Project>{48f4582b-7687-4621-9cbe-5c24197cb536}</Project>
<Name>osu.Game.Modes.Mania</Name>
<Name>osu.Game.Rulesets.Mania</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Modes.Taiko\osu.Game.Modes.Taiko.csproj">
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj">
<Project>{f167e17a-7de6-4af5-b920-a5112296c695}</Project>
<Name>osu.Game.Modes.Taiko</Name>
<Name>osu.Game.Rulesets.Taiko</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
<Project>{0d3fbf8a-7464-4cf7-8c90-3e7886df2d4d}</Project>
+1
View File
@@ -7,6 +7,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
<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="2.0.50727.1341" targetFramework="net45" />
<package id="Splat" version="2.0.0" targetFramework="net45" />
<package id="squirrel.windows" version="1.5.2" targetFramework="net45" />
</packages>
@@ -1,20 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Catch.Objects;
using System.Collections.Generic;
namespace osu.Game.Modes.Catch.Beatmaps
{
internal class CatchBeatmapConverter : IBeatmapConverter<CatchBaseHit>
{
public Beatmap<CatchBaseHit> Convert(Beatmap original)
{
return new Beatmap<CatchBaseHit>(original)
{
HitObjects = new List<CatchBaseHit>() // Todo: Convert HitObjects
};
}
}
}
@@ -1,19 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Catch.Objects;
namespace osu.Game.Modes.Catch.Beatmaps
{
internal class CatchBeatmapProcessor : IBeatmapProcessor<CatchBaseHit>
{
public void SetDefaults(CatchBaseHit hitObject, Beatmap<CatchBaseHit> beatmap)
{
}
public void PostProcess(Beatmap<CatchBaseHit> beatmap)
{
}
}
}
@@ -1,20 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Objects;
using System.Collections.Generic;
namespace osu.Game.Modes.Mania.Beatmaps
{
internal class ManiaBeatmapConverter : IBeatmapConverter<ManiaBaseHit>
{
public Beatmap<ManiaBaseHit> Convert(Beatmap original)
{
return new Beatmap<ManiaBaseHit>(original)
{
HitObjects = new List<ManiaBaseHit>() // Todo: Implement
};
}
}
}
@@ -1,19 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Objects;
namespace osu.Game.Modes.Mania.Beatmaps
{
internal class ManiaBeatmapProcessor : IBeatmapProcessor<ManiaBaseHit>
{
public void SetDefaults(ManiaBaseHit hitObject, Beatmap<ManiaBaseHit> beatmap)
{
}
public void PostProcess(Beatmap<ManiaBaseHit> beatmap)
{
}
}
}
@@ -1,14 +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 osu.Game.Modes.Judgements;
namespace osu.Game.Modes.Mania.Judgements
{
public class ManiaJudgement : Judgement
{
public override string ResultString => string.Empty;
public override string MaxResultString => string.Empty;
}
}
@@ -1,36 +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 osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Graphics;
using OpenTK;
namespace osu.Game.Modes.Mania.Objects.Drawable
{
public class DrawableNote : Sprite
{
private readonly ManiaBaseHit note;
public DrawableNote(ManiaBaseHit note)
{
this.note = note;
Origin = Anchor.Centre;
Scale = new Vector2(0.1f);
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
Texture = textures.Get(@"Menu/logo");
const double duration = 0;
Transforms.Add(new TransformPositionY { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f });
Transforms.Add(new TransformAlpha { StartTime = note.StartTime + duration + 200, EndTime = note.StartTime + duration + 400, StartValue = 1, EndValue = 0 });
Expire(true);
}
}
}
@@ -1,12 +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 osu.Game.Modes.Objects;
namespace osu.Game.Modes.Mania.Objects
{
public abstract class ManiaBaseHit : HitObject
{
public int Column;
}
}
@@ -1,26 +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 osu.Game.Modes.Mania.Judgements;
using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Mania.Scoring
{
internal class ManiaScoreProcessor : ScoreProcessor<ManiaBaseHit, ManiaJudgement>
{
public ManiaScoreProcessor()
{
}
public ManiaScoreProcessor(HitRenderer<ManiaBaseHit, ManiaJudgement> hitRenderer)
: base(hitRenderer)
{
}
protected override void OnNewJugement(ManiaJudgement judgement)
{
}
}
}
@@ -1,35 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Beatmaps;
using osu.Game.Modes.Mania.Judgements;
using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.Mania.Scoring;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Mania.UI
{
public class ManiaHitRenderer : HitRenderer<ManiaBaseHit, ManiaJudgement>
{
private readonly int columns;
public ManiaHitRenderer(WorkingBeatmap beatmap, int columns = 5)
: base(beatmap)
{
this.columns = columns;
}
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this);
protected override IBeatmapConverter<ManiaBaseHit> CreateBeatmapConverter() => new ManiaBeatmapConverter();
protected override IBeatmapProcessor<ManiaBaseHit> CreateBeatmapProcessor() => new ManiaBeatmapProcessor();
protected override Playfield<ManiaBaseHit, ManiaJudgement> CreatePlayfield() => new ManiaPlayfield(columns);
protected override DrawableHitObject<ManiaBaseHit, ManiaJudgement> GetVisualRepresentation(ManiaBaseHit h) => null;
}
}
-37
View File
@@ -1,37 +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 osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.UI;
using OpenTK;
using OpenTK.Graphics;
using osu.Game.Modes.Mania.Judgements;
namespace osu.Game.Modes.Mania.UI
{
public class ManiaPlayfield : Playfield<ManiaBaseHit, ManiaJudgement>
{
public ManiaPlayfield(int columns)
{
RelativeSizeAxes = Axes.Both;
Size = new Vector2(columns / 20f, 1f);
Anchor = Anchor.BottomCentre;
Origin = Anchor.BottomCentre;
Add(new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.5f });
for (int i = 0; i < columns; i++)
Add(new Box
{
RelativeSizeAxes = Axes.Y,
Size = new Vector2(2, 1),
RelativePositionAxes = Axes.Both,
Position = new Vector2((float)i / columns, 0),
Alpha = 0.5f,
Colour = Color4.Black
});
}
}
}
@@ -1,32 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Osu.Objects;
namespace osu.Game.Modes.Osu.Beatmaps
{
internal class OsuBeatmapProcessor : IBeatmapProcessor<OsuHitObject>
{
public void PostProcess(Beatmap<OsuHitObject> beatmap)
{
if (beatmap.ComboColors.Count == 0)
return;
int comboIndex = 0;
int colourIndex = 0;
foreach (var obj in beatmap.HitObjects)
{
if (obj.NewCombo)
{
comboIndex = 0;
colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count;
}
obj.ComboIndex = comboIndex++;
obj.ComboColour = beatmap.ComboColors[colourIndex];
}
}
}
}
@@ -1,155 +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;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.MathUtils;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class DrawableSpinner : DrawableOsuHitObject
{
private readonly Spinner spinner;
private readonly SpinnerDisc disc;
private readonly SpinnerBackground background;
private readonly Container circleContainer;
private readonly DrawableHitCircle circle;
public DrawableSpinner(Spinner s) : base(s)
{
AlwaysReceiveInput = true;
Origin = Anchor.Centre;
Position = s.Position;
//take up full playfield.
Size = new Vector2(512);
spinner = s;
Children = new Drawable[]
{
background = new SpinnerBackground
{
Alpha = 0,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
DiscColour = Color4.Black
},
disc = new SpinnerDisc
{
Alpha = 0,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
DiscColour = AccentColour
},
circleContainer = new Container
{
AutoSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new []
{
circle = new DrawableHitCircle(s)
{
Interactive = false,
Position = Vector2.Zero,
Anchor = Anchor.Centre,
}
}
}
};
background.Scale = scaleToCircle;
disc.Scale = scaleToCircle;
}
protected override void CheckJudgement(bool userTriggered)
{
if (Time.Current < HitObject.StartTime) return;
disc.ScaleTo(Interpolation.ValueAt(Math.Sqrt(Progress), scaleToCircle, Vector2.One, 0, 1), 100);
if (Progress >= 1)
disc.Complete = true;
if (!userTriggered && Time.Current >= spinner.EndTime)
{
if (Progress >= 1)
{
Judgement.Score = OsuScoreResult.Hit300;
Judgement.Result = HitResult.Hit;
}
else if (Progress > .9)
{
Judgement.Score = OsuScoreResult.Hit100;
Judgement.Result = HitResult.Hit;
}
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;
}
}
}
private Vector2 scaleToCircle => circle.Scale * circle.DrawWidth / DrawWidth * 0.95f;
private const float spins_per_minute_needed = 100 + 5 * 15; //TODO: read per-map OD and place it on the 5
private float rotationsNeeded => (float)(spins_per_minute_needed * (spinner.EndTime - spinner.StartTime) / 60000f);
public float Progress => MathHelper.Clamp(disc.RotationAbsolute / 360 / rotationsNeeded, 0, 1);
protected override void UpdatePreemptState()
{
base.UpdatePreemptState();
circleContainer.ScaleTo(1, 400, EasingTypes.OutElastic);
background.Delay(TIME_PREEMPT - 500);
background.ScaleTo(scaleToCircle * 1.2f, 400, EasingTypes.OutQuint);
background.FadeIn(200);
background.Delay(400);
background.ScaleTo(1, 250, EasingTypes.OutQuint);
disc.Delay(TIME_PREEMPT - 50);
disc.FadeIn(200);
}
protected override void UpdateState(ArmedState state)
{
base.UpdateState(state);
Delay(spinner.Duration, true);
FadeOut(160);
switch (state)
{
case ArmedState.Hit:
ScaleTo(Scale * 1.2f, 320, EasingTypes.Out);
Expire();
break;
case ArmedState.Miss:
ScaleTo(Scale * 0.8f, 320, EasingTypes.In);
Expire();
break;
}
}
}
}
@@ -1,10 +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
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SpinnerBackground : SpinnerDisc
{
public override bool HandleInput => false;
}
}
@@ -1,208 +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;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Input;
using osu.Game.Graphics;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SpinnerDisc : CircularContainer
{
protected Sprite Disc;
public SRGBColour DiscColour
{
get { return Disc.Colour; }
set { Disc.Colour = value; }
}
private Color4 completeColour;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
completeColour = colours.YellowLight.Opacity(0.8f);
Masking = true;
}
private class SpinnerBorder : Container
{
public SpinnerBorder()
{
Origin = Anchor.Centre;
Anchor = Anchor.Centre;
RelativeSizeAxes = Axes.Both;
layout();
}
private int lastLayoutDotCount;
private void layout()
{
int count = (int)(MathHelper.Pi * ScreenSpaceDrawQuad.Width / 9);
if (count == lastLayoutDotCount) return;
lastLayoutDotCount = count;
while (Children.Count() < count)
{
Add(new CircularContainer
{
Colour = Color4.White,
RelativePositionAxes = Axes.Both,
Masking = true,
Origin = Anchor.Centre,
Size = new Vector2(1 / ScreenSpaceDrawQuad.Width * 2000),
Children = new[]
{
new Box
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
}
}
});
}
var size = new Vector2(1 / ScreenSpaceDrawQuad.Width * 2000);
int i = 0;
foreach (var d in Children)
{
d.Size = size;
d.Position = new Vector2(
0.5f + (float)Math.Sin((float)i / count * 2 * MathHelper.Pi) / 2,
0.5f + (float)Math.Cos((float)i / count * 2 * MathHelper.Pi) / 2
);
i++;
}
}
protected override void Update()
{
base.Update();
layout();
}
}
public SpinnerDisc()
{
AlwaysReceiveInput = true;
RelativeSizeAxes = Axes.Both;
Children = new Drawable[]
{
Disc = new Box
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Alpha = 0.2f,
},
new SpinnerBorder()
};
}
private bool tracking;
public bool Tracking
{
get { return tracking; }
set
{
if (value == tracking) return;
tracking = value;
Disc.FadeTo(tracking ? 0.5f : 0.2f, 100);
}
}
private bool complete;
public bool Complete
{
get { return complete; }
set
{
if (value == complete) return;
complete = value;
Disc.FadeColour(completeColour, 200);
updateCompleteTick();
}
}
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
Tracking = true;
return base.OnMouseDown(state, args);
}
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
{
Tracking = false;
return base.OnMouseUp(state, args);
}
protected override bool OnMouseMove(InputState state)
{
Tracking |= state.Mouse.HasMainButtonPressed;
mousePosition = state.Mouse.Position;
return base.OnMouseMove(state);
}
private Vector2 mousePosition;
private float lastAngle;
private float currentRotation;
public float RotationAbsolute;
private int completeTick;
private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360));
protected override void Update()
{
base.Update();
var thisAngle = -(float)MathHelper.RadiansToDegrees(Math.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2));
if (tracking)
{
if (thisAngle - lastAngle > 180)
lastAngle += 360;
else if (lastAngle - thisAngle > 180)
lastAngle -= 360;
currentRotation += thisAngle - lastAngle;
RotationAbsolute += Math.Abs(thisAngle - lastAngle);
}
lastAngle = thisAngle;
if (Complete && updateCompleteTick())
{
Disc.Flush(flushType: typeof(TransformAlpha));
Disc.FadeTo(0.75f, 30, EasingTypes.OutExpo);
Disc.Delay(30);
Disc.FadeTo(0.5f, 250, EasingTypes.OutQuint);
}
RotateTo(currentRotation, 100, EasingTypes.OutExpo);
}
}
}
-107
View File
@@ -1,107 +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 OpenTK;
using osu.Game.Beatmaps.Samples;
using osu.Game.Beatmaps.Timing;
using osu.Game.Modes.Objects.Types;
using System;
using System.Collections.Generic;
using osu.Game.Modes.Objects;
using osu.Game.Database;
namespace osu.Game.Modes.Osu.Objects
{
public class Slider : OsuHitObject, IHasCurve
{
public IHasCurve CurveObject { get; set; }
public SliderCurve Curve => CurveObject.Curve;
public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity;
public double Duration => EndTime - StartTime;
public override Vector2 EndPosition => PositionAt(1);
public Vector2 PositionAt(double progress) => CurveObject.PositionAt(progress);
public double ProgressAt(double progress) => CurveObject.ProgressAt(progress);
public int RepeatAt(double progress) => CurveObject.RepeatAt(progress);
public List<Vector2> ControlPoints => CurveObject.ControlPoints;
public CurveType CurveType => CurveObject.CurveType;
public double Distance => CurveObject.Distance;
public int RepeatCount => CurveObject.RepeatCount;
private int stackHeight;
public override int StackHeight
{
get { return stackHeight; }
set
{
stackHeight = value;
Curve.Offset = StackOffset;
}
}
public double Velocity;
public double TickDistance;
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{
base.ApplyDefaults(timing, difficulty);
ControlPoint overridePoint;
ControlPoint timingPoint = timing.TimingPointAt(StartTime, out overridePoint);
var velocityAdjustment = overridePoint?.VelocityAdjustment ?? 1;
var baseVelocity = 100 * difficulty.SliderMultiplier / velocityAdjustment;
Velocity = baseVelocity / timingPoint.BeatLength;
TickDistance = baseVelocity / difficulty.SliderTickRate;
}
public IEnumerable<SliderTick> Ticks
{
get
{
if (TickDistance == 0) yield break;
var length = Curve.Distance;
var tickDistance = Math.Min(TickDistance, length);
var repeatDuration = length / Velocity;
var minDistanceFromEnd = Velocity * 0.01;
for (var repeat = 0; repeat < RepeatCount; repeat++)
{
var repeatStartTime = StartTime + repeat * repeatDuration;
var reversed = repeat % 2 == 1;
for (var d = tickDistance; d <= length; d += tickDistance)
{
if (d > length - minDistanceFromEnd)
break;
var distanceProgress = d / length;
var timeProgress = reversed ? 1 - distanceProgress : distanceProgress;
yield return new SliderTick
{
RepeatIndex = repeat,
StartTime = repeatStartTime + timeProgress * repeatDuration,
Position = Curve.PositionAt(distanceProgress),
StackHeight = StackHeight,
Scale = Scale,
ComboColour = ComboColour,
Sample = new HitSampleInfo
{
Type = SampleType.None,
Set = SampleSet.Soft,
},
};
}
}
}
}
}
}
-306
View File
@@ -1,306 +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 OpenTK;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.Objects.Drawables;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using osu.Framework.Graphics;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Osu
{
public class OsuAutoReplay : LegacyReplay
{
private static readonly Vector2 spinner_centre = new Vector2(256, 192);
private const float spin_radius = 50;
private readonly Beatmap<OsuHitObject> beatmap;
public OsuAutoReplay(Beatmap<OsuHitObject> beatmap)
{
this.beatmap = beatmap;
createAutoReplay();
}
private class LegacyReplayFrameComparer : IComparer<LegacyReplayFrame>
{
public int Compare(LegacyReplayFrame f1, LegacyReplayFrame f2)
{
return f1.Time.CompareTo(f2.Time);
}
}
private static readonly IComparer<LegacyReplayFrame> replay_frame_comparer = new LegacyReplayFrameComparer();
private int findInsertionIndex(LegacyReplayFrame frame)
{
int index = Frames.BinarySearch(frame, replay_frame_comparer);
if (index < 0)
{
index = ~index;
}
else
{
// Go to the first index which is actually bigger
while (index < Frames.Count && frame.Time == Frames[index].Time)
{
++index;
}
}
return index;
}
private void addFrameToReplay(LegacyReplayFrame frame) => Frames.Insert(findInsertionIndex(frame), frame);
private static Vector2 circlePosition(double t, double radius) => new Vector2((float)(Math.Cos(t) * radius), (float)(Math.Sin(t) * radius));
private double applyModsToTime(double v) => v;
private double applyModsToRate(double v) => v;
public bool DelayedMovements; // ModManager.CheckActive(Mods.Relax2);
private void createAutoReplay()
{
int buttonIndex = 0;
EasingTypes preferredEasing = DelayedMovements ? EasingTypes.InOutCubic : EasingTypes.Out;
addFrameToReplay(new LegacyReplayFrame(-100000, 256, 500, LegacyButtonState.None));
addFrameToReplay(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1500, 256, 500, LegacyButtonState.None));
addFrameToReplay(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 256, 192, LegacyButtonState.None));
// We are using ApplyModsToRate and not ApplyModsToTime to counteract the speed up / slow down from HalfTime / DoubleTime so that we remain at a constant framerate of 60 fps.
float frameDelay = (float)applyModsToRate(1000.0 / 60.0);
// Already superhuman, but still somewhat realistic
int reactionTime = (int)applyModsToRate(100);
for (int i = 0; i < beatmap.HitObjects.Count; i++)
{
OsuHitObject h = beatmap.HitObjects[i];
//if (h.EndTime < InputManager.ReplayStartTime)
//{
// h.IsHit = true;
// continue;
//}
int endDelay = h is Spinner ? 1 : 0;
if (DelayedMovements && i > 0)
{
OsuHitObject last = beatmap.HitObjects[i - 1];
double endTime = (last as IHasEndTime)?.EndTime ?? last.StartTime;
//Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
{
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, LegacyButtonState.None));
}
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
{
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, LegacyButtonState.None));
}
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
{
if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None));
if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, LegacyButtonState.None));
}
}
Vector2 targetPosition = h.Position;
EasingTypes easing = preferredEasing;
float spinnerDirection = -1;
if (h is Spinner)
{
targetPosition.X = Frames[Frames.Count - 1].MouseX;
targetPosition.Y = Frames[Frames.Count - 1].MouseY;
Vector2 difference = spinner_centre - targetPosition;
float differenceLength = difference.Length;
float newLength = (float)Math.Sqrt(differenceLength * differenceLength - spin_radius * spin_radius);
if (differenceLength > spin_radius)
{
float angle = (float)Math.Asin(spin_radius / differenceLength);
if (angle > 0)
{
spinnerDirection = -1;
}
else
{
spinnerDirection = 1;
}
difference.X = difference.X * (float)Math.Cos(angle) - difference.Y * (float)Math.Sin(angle);
difference.Y = difference.X * (float)Math.Sin(angle) + difference.Y * (float)Math.Cos(angle);
difference.Normalize();
difference *= newLength;
targetPosition += difference;
easing = EasingTypes.In;
}
else if (difference.Length > 0)
{
targetPosition = spinner_centre - difference * (spin_radius / difference.Length);
}
else
{
targetPosition = spinner_centre + new Vector2(0, -spin_radius);
}
}
// Do some nice easing for cursor movements
if (Frames.Count > 0)
{
LegacyReplayFrame lastFrame = Frames[Frames.Count - 1];
// Wait until Auto could "see and react" to the next note.
double waitTime = h.StartTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime);
if (waitTime > lastFrame.Time)
{
lastFrame = new LegacyReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState);
addFrameToReplay(lastFrame);
}
Vector2 lastPosition = new Vector2(lastFrame.MouseX, lastFrame.MouseY);
double timeDifference = applyModsToTime(h.StartTime - lastFrame.Time);
// Only "snap" to hitcircles if they are far enough apart. As the time between hitcircles gets shorter the snapping threshold goes up.
if (timeDifference > 0 && // Sanity checks
((lastPosition - targetPosition).Length > h.Radius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough
timeDifference >= 266)) // ... or the beats are slow enough to tap anyway.
{
// Perform eased movement
for (double time = lastFrame.Time + frameDelay; time < h.StartTime; time += frameDelay)
{
Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPosition, lastFrame.Time, h.StartTime, easing);
addFrameToReplay(new LegacyReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState));
}
buttonIndex = 0;
}
else
{
buttonIndex++;
}
}
LegacyButtonState button = buttonIndex % 2 == 0 ? LegacyButtonState.Left1 : LegacyButtonState.Right1;
double hEndTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
LegacyReplayFrame newFrame = new LegacyReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button);
LegacyReplayFrame endFrame = new LegacyReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, LegacyButtonState.None);
// Decrement because we want the previous frame, not the next one
int index = findInsertionIndex(newFrame) - 1;
// Do we have a previous frame? No need to check for < replay.Count since we decremented!
if (index >= 0)
{
LegacyReplayFrame previousFrame = Frames[index];
var previousButton = previousFrame.ButtonState;
// If a button is already held, then we simply alternate
if (previousButton != LegacyButtonState.None)
{
Debug.Assert(previousButton != (LegacyButtonState.Left1 | LegacyButtonState.Right1));
// Force alternation if we have the same button. Otherwise we can just keep the naturally to us assigned button.
if (previousButton == button)
{
button = (LegacyButtonState.Left1 | LegacyButtonState.Right1) & ~button;
newFrame.SetButtonStates(button);
}
// We always follow the most recent slider / spinner, so remove any other frames that occur while it exists.
int endIndex = findInsertionIndex(endFrame);
if (index < Frames.Count - 1)
Frames.RemoveRange(index + 1, Math.Max(0, endIndex - (index + 1)));
// After alternating we need to keep holding the other button in the future rather than the previous one.
for (int j = index + 1; j < Frames.Count; ++j)
{
// Don't affect frames which stop pressing a button!
if (j < Frames.Count - 1 || Frames[j].ButtonState == previousButton)
Frames[j].SetButtonStates(button);
}
}
}
addFrameToReplay(newFrame);
// We add intermediate frames for spinning / following a slider here.
if (h is Spinner)
{
Spinner s = h as Spinner;
Vector2 difference = targetPosition - spinner_centre;
float radius = difference.Length;
float angle = radius == 0 ? 0 : (float)Math.Atan2(difference.Y, difference.X);
double t;
for (double j = h.StartTime + frameDelay; j < s.EndTime; j += frameDelay)
{
t = applyModsToTime(j - h.StartTime) * spinnerDirection;
Vector2 pos = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
addFrameToReplay(new LegacyReplayFrame((int)j, pos.X, pos.Y, button));
}
t = applyModsToTime(s.EndTime - h.StartTime) * spinnerDirection;
Vector2 endPosition = spinner_centre + circlePosition(t / 20 + angle, spin_radius);
addFrameToReplay(new LegacyReplayFrame(s.EndTime, endPosition.X, endPosition.Y, button));
endFrame.MouseX = endPosition.X;
endFrame.MouseY = endPosition.Y;
}
else if (h is Slider)
{
Slider s = h as Slider;
for (double j = frameDelay; j < s.Duration; j += frameDelay)
{
Vector2 pos = s.PositionAt(j / s.Duration);
addFrameToReplay(new LegacyReplayFrame(h.StartTime + j, pos.X, pos.Y, button));
}
addFrameToReplay(new LegacyReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button));
}
// We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed!
if (Frames[Frames.Count - 1].Time <= endFrame.Time)
addFrameToReplay(endFrame);
}
//Player.currentScore.Replay = InputManager.ReplayScore.Replay;
//Player.currentScore.PlayerName = "osu!";
}
}
}
@@ -1,61 +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 osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Judgements;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Osu.Scoring
{
internal class OsuScoreProcessor : ScoreProcessor<OsuHitObject, OsuJudgement>
{
public OsuScoreProcessor()
{
}
public OsuScoreProcessor(HitRenderer<OsuHitObject, OsuJudgement> hitRenderer)
: base(hitRenderer)
{
}
protected override void Reset()
{
base.Reset();
Health.Value = 1;
Accuracy.Value = 1;
}
protected override void OnNewJugement(OsuJudgement judgement)
{
if (judgement != null)
{
switch (judgement.Result)
{
case HitResult.Hit:
Combo.Value++;
Health.Value += 0.1f;
break;
case HitResult.Miss:
Combo.Value = 0;
Health.Value -= 0.2f;
break;
}
}
int score = 0;
int maxScore = 0;
foreach (var j in Judgements)
{
score += j.ScoreValue;
maxScore += j.MaxScoreValue;
}
TotalScore.Value = score;
Accuracy.Value = (double)score / maxScore;
}
}
}
@@ -1,82 +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 osu.Game.Beatmaps;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Beatmaps.Samples;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Types;
using osu.Game.Modes.Taiko.Objects;
using System.Collections.Generic;
using System.Linq;
namespace osu.Game.Modes.Taiko.Beatmaps
{
internal class TaikoBeatmapConverter : IBeatmapConverter<TaikoHitObject>
{
private const float legacy_velocity_scale = 1.4f;
private const float bash_convert_factor = 1.65f;
public Beatmap<TaikoHitObject> Convert(Beatmap original)
{
if (original is LegacyBeatmap)
original.TimingInfo.ControlPoints.ForEach(c => c.VelocityAdjustment /= legacy_velocity_scale);
return new Beatmap<TaikoHitObject>(original)
{
HitObjects = convertHitObjects(original.HitObjects)
};
}
private List<TaikoHitObject> convertHitObjects(List<HitObject> hitObjects)
{
return hitObjects.Select(convertHitObject).ToList();
}
private TaikoHitObject convertHitObject(HitObject original)
{
// Check if this HitObject is already a TaikoHitObject, and return it if so
TaikoHitObject originalTaiko = original as TaikoHitObject;
if (originalTaiko != null)
return originalTaiko;
IHasDistance distanceData = original as IHasDistance;
IHasRepeats repeatsData = original as IHasRepeats;
IHasEndTime endTimeData = original as IHasEndTime;
bool strong = ((original.Sample?.Type ?? SampleType.None) & SampleType.Finish) > 0;
if (distanceData != null)
{
return new DrumRoll
{
StartTime = original.StartTime,
Sample = original.Sample,
IsStrong = strong,
Distance = distanceData.Distance * (repeatsData?.RepeatCount ?? 1)
};
}
if (endTimeData != null)
{
// We compute the end time manually to add in the Bash convert factor
return new Swell
{
StartTime = original.StartTime,
Sample = original.Sample,
IsStrong = strong,
EndTime = original.StartTime + endTimeData.Duration * bash_convert_factor
};
}
return new Hit
{
StartTime = original.StartTime,
Sample = original.Sample,
IsStrong = strong
};
}
}
}
@@ -1,19 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Taiko.Objects;
namespace osu.Game.Modes.Taiko.Beatmaps
{
internal class TaikoBeatmapProcessor : IBeatmapProcessor<TaikoHitObject>
{
public void SetDefaults(TaikoHitObject hitObject, Beatmap<TaikoHitObject> beatmap)
{
}
public void PostProcess(Beatmap<TaikoHitObject> beatmap)
{
}
}
}
@@ -1,57 +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 osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Taiko.Judgements;
using System.Linq;
namespace osu.Game.Modes.Taiko.Objects.Drawable
{
public class DrawableDrumRoll : DrawableTaikoHitObject
{
private readonly DrumRoll drumRoll;
public DrawableDrumRoll(DrumRoll drumRoll)
: base(drumRoll)
{
this.drumRoll = drumRoll;
int tickIndex = 0;
foreach (var tick in drumRoll.Ticks)
{
var newTick = new DrawableDrumRollTick(tick)
{
Depth = tickIndex,
X = (float)((tick.StartTime - HitObject.StartTime) / drumRoll.Duration)
};
AddNested(newTick);
tickIndex++;
}
}
protected override void UpdateState(ArmedState state)
{
}
protected override void CheckJudgement(bool userTriggered)
{
if (userTriggered)
return;
if (Judgement.TimeOffset < 0)
return;
int countHit = NestedHitObjects.Count(o => o.Judgement.Result == HitResult.Hit);
if (countHit > drumRoll.RequiredGoodHits)
{
Judgement.Result = HitResult.Hit;
Judgement.TaikoResult = countHit >= drumRoll.RequiredGreatHits ? TaikoHitResult.Great : TaikoHitResult.Good;
}
else
Judgement.Result = HitResult.Miss;
}
}
}
@@ -1,67 +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 OpenTK.Input;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Taiko.Judgements;
using System;
using System.Collections.Generic;
namespace osu.Game.Modes.Taiko.Objects.Drawable
{
public abstract class DrawableHit : DrawableTaikoHitObject
{
/// <summary>
/// A list of keys which can result in hits for this HitObject.
/// </summary>
protected abstract List<Key> HitKeys { get; }
private readonly Hit hit;
/// <summary>
/// Whether the last key pressed is a valid hit key.
/// </summary>
private bool validKeyPressed;
protected DrawableHit(Hit hit)
: base(hit)
{
this.hit = hit;
}
protected override void CheckJudgement(bool userTriggered)
{
if (!userTriggered)
{
if (Judgement.TimeOffset > hit.HitWindowGood)
Judgement.Result = HitResult.Miss;
return;
}
double hitOffset = Math.Abs(Judgement.TimeOffset);
if (hitOffset > hit.HitWindowMiss)
return;
if (!validKeyPressed)
Judgement.Result = HitResult.Miss;
else if (hitOffset < hit.HitWindowGood)
{
Judgement.Result = HitResult.Hit;
Judgement.TaikoResult = hitOffset < hit.HitWindowGreat ? TaikoHitResult.Great : TaikoHitResult.Good;
}
else
Judgement.Result = HitResult.Miss;
}
protected override bool HandleKeyPress(Key key)
{
if (Judgement.Result.HasValue)
return false;
validKeyPressed = HitKeys.Contains(key);
return UpdateJudgement(true);
}
}
}
@@ -1,75 +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 OpenTK.Input;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Taiko.Judgements;
using System;
namespace osu.Game.Modes.Taiko.Objects.Drawable
{
public class DrawableSwell : DrawableTaikoHitObject
{
/// <summary>
/// The amount of times the user has hit this swell.
/// </summary>
private int userHits;
private readonly Swell swell;
public DrawableSwell(Swell swell)
: base(swell)
{
this.swell = swell;
}
protected override void CheckJudgement(bool userTriggered)
{
if (userTriggered)
{
if (Time.Current < HitObject.StartTime)
return;
userHits++;
if (userHits == swell.RequiredHits)
{
Judgement.Result = HitResult.Hit;
Judgement.TaikoResult = TaikoHitResult.Great;
}
}
else
{
if (Judgement.TimeOffset < 0)
return;
if (userHits > swell.RequiredHits / 2)
{
Judgement.Result = HitResult.Hit;
Judgement.TaikoResult = TaikoHitResult.Good;
}
else
Judgement.Result = HitResult.Miss;
}
}
protected override void UpdateState(ArmedState state)
{
}
protected override void UpdateScrollPosition(double time)
{
base.UpdateScrollPosition(Math.Min(time, HitObject.StartTime));
}
protected override bool HandleKeyPress(Key key)
{
if (Judgement.Result.HasValue)
return false;
UpdateJudgement(true);
return true;
}
}
}
@@ -1,160 +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 osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics.Backgrounds;
using OpenTK.Graphics;
using System;
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
{
/// <summary>
/// A circle piece which is used uniformly through osu!taiko to visualise hitobjects.
/// <para>
/// The body of this piece will overshoot its parent by <see cref="CirclePiece.Height"/> to form
/// a rounded (_[-Width-]_) figure such that a regular "circle" is the result of a parent with Width = 0.
/// </para>
/// </summary>
public class CirclePiece : Container
{
public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f;
public const float SYMBOL_BORDER = 8;
public const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER;
private Color4 accentColour;
/// <summary>
/// The colour of the inner circle and outer glows.
/// </summary>
public Color4 AccentColour
{
get { return accentColour; }
set
{
accentColour = value;
innerBackground.Colour = AccentColour;
triangles.ColourLight = AccentColour;
triangles.ColourDark = AccentColour.Darken(0.1f);
resetEdgeEffects();
}
}
private bool kiaiMode;
/// <summary>
/// Whether Kiai mode effects are enabled for this circle piece.
/// </summary>
public bool KiaiMode
{
get { return kiaiMode; }
set
{
kiaiMode = value;
resetEdgeEffects();
}
}
public override Anchor Origin
{
get { return Anchor.CentreLeft; }
set { throw new InvalidOperationException($"{nameof(CirclePiece)} must always use CentreLeft origin."); }
}
protected override Container<Framework.Graphics.Drawable> Content => SymbolContainer;
protected readonly Container SymbolContainer;
private readonly Container innerLayer;
private readonly Container innerCircleContainer;
private readonly Box innerBackground;
private readonly Triangles triangles;
public CirclePiece()
{
RelativeSizeAxes = Axes.X;
Height = TaikoHitObject.CIRCLE_RADIUS * 2;
// The "inner layer" is the body of the CirclePiece that overshoots it by Height/2 px on both sides
AddInternal(innerLayer = new Container
{
Name = "Inner Layer",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Children = new Framework.Graphics.Drawable[]
{
innerCircleContainer = new CircularContainer
{
Name = "Inner Circle",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Masking = true,
Children = new Framework.Graphics.Drawable[]
{
innerBackground = new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
},
triangles = new Triangles
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
}
}
},
new CircularContainer
{
Name = "Ring",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
BorderThickness = 8,
BorderColour = Color4.White,
Masking = true,
Children = new[]
{
new Box
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true
}
}
},
SymbolContainer = new Container
{
Name = "Symbol",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
}
});
}
protected override void Update()
{
// Add the overshoot to compensate for corner radius
innerLayer.Width = DrawWidth + DrawHeight;
}
private void resetEdgeEffects()
{
innerCircleContainer.EdgeEffect = new EdgeEffect
{
Type = EdgeEffectType.Glow,
Colour = AccentColour,
Radius = KiaiMode ? 50 : 8
};
}
}
}
@@ -1,25 +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 OpenTK;
namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces
{
/// <summary>
/// A type of circle piece which is drawn at a higher scale to represent a "strong" piece.
/// </summary>
public class StrongCirclePiece : CirclePiece
{
/// <summary>
/// The amount to scale up the base circle to show it as a "strong" piece.
/// </summary>
private const float strong_scale = 1.5f;
public StrongCirclePiece()
{
SymbolContainer.Scale = new Vector2(strong_scale);
}
public override Vector2 Size => new Vector2(base.Size.X, base.Size.Y * strong_scale);
}
}
-30
View File
@@ -1,30 +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;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Taiko.Objects
{
public class Swell : TaikoHitObject, IHasEndTime
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
/// <summary>
/// The number of hits required to complete the swell successfully.
/// </summary>
public int RequiredHits { get; protected set; }
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{
base.ApplyDefaults(timing, difficulty);
double spinnerRotationRatio = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
RequiredHits = (int)Math.Max(1, Duration / 1000f * spinnerRotationRatio);
}
}
}
@@ -1,46 +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 osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using osu.Game.Modes.Objects;
namespace osu.Game.Modes.Taiko.Objects
{
public abstract class TaikoHitObject : HitObject
{
/// <summary>
/// HitCircle radius.
/// </summary>
public const float CIRCLE_RADIUS = 64;
/// <summary>
/// The time to scroll in the HitObject.
/// </summary>
public double PreEmpt;
/// <summary>
/// Whether this HitObject is a "strong" type.
/// Strong hit objects give more points for hitting the hit object with both keys.
/// </summary>
public bool IsStrong;
/// <summary>
/// Whether this HitObject is in Kiai time.
/// </summary>
public bool Kiai { get; protected set; }
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{
base.ApplyDefaults(timing, difficulty);
PreEmpt = 600 / (timing.SliderVelocityAt(StartTime) * difficulty.SliderMultiplier) * 1000;
ControlPoint overridePoint;
Kiai = timing.TimingPointAt(StartTime, out overridePoint).KiaiMode;
if (overridePoint != null)
Kiai |= overridePoint.KiaiMode;
}
}
}
@@ -1,24 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Taiko.Beatmaps;
using osu.Game.Modes.Taiko.Objects;
using System.Collections.Generic;
namespace osu.Game.Modes.Taiko
{
public class TaikoDifficultyCalculator : DifficultyCalculator<TaikoHitObject>
{
public TaikoDifficultyCalculator(Beatmap beatmap) : base(beatmap)
{
}
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
{
return 0;
}
protected override IBeatmapConverter<TaikoHitObject> CreateBeatmapConverter() => new TaikoBeatmapConverter();
}
}
@@ -1,32 +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 osu.Game.Beatmaps;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.Taiko.Beatmaps;
using osu.Game.Modes.Taiko.Judgements;
using osu.Game.Modes.Taiko.Objects;
using osu.Game.Modes.Taiko.Scoring;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Taiko.UI
{
public class TaikoHitRenderer : HitRenderer<TaikoHitObject, TaikoJudgement>
{
public TaikoHitRenderer(WorkingBeatmap beatmap)
: base(beatmap)
{
}
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);
protected override IBeatmapConverter<TaikoHitObject> CreateBeatmapConverter() => new TaikoBeatmapConverter();
protected override IBeatmapProcessor<TaikoHitObject> CreateBeatmapProcessor() => new TaikoBeatmapProcessor();
protected override Playfield<TaikoHitObject, TaikoJudgement> CreatePlayfield() => new TaikoPlayfield();
protected override DrawableHitObject<TaikoHitObject, TaikoJudgement> GetVisualRepresentation(TaikoHitObject h) => null;
}
}
-198
View File
@@ -1,198 +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 osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Modes.Taiko.Objects;
using osu.Game.Modes.UI;
using OpenTK;
using OpenTK.Graphics;
using osu.Game.Modes.Taiko.Judgements;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics.Primitives;
namespace osu.Game.Modes.Taiko.UI
{
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgement>
{
/// <summary>
/// The default play field height.
/// </summary>
public const float PLAYFIELD_BASE_HEIGHT = 242;
/// <summary>
/// The play field height scale.
/// This also uniformly scales the notes to match the new playfield height.
/// </summary>
public const float PLAYFIELD_SCALE = 0.65f;
/// <summary>
/// The play field height after scaling.
/// </summary>
public static float PlayfieldHeight => PLAYFIELD_BASE_HEIGHT * PLAYFIELD_SCALE;
/// <summary>
/// The offset from <see cref="left_area_size"/> which the center of the hit target lies at.
/// </summary>
private const float hit_target_offset = 80;
/// <summary>
/// The size of the left area of the playfield. This area contains the input drum.
/// </summary>
private const float left_area_size = 240;
protected override Container<Drawable> Content => hitObjectContainer;
private readonly Container<HitExplosion> hitExplosionContainer;
//private Container<DrawableBarLine> barLineContainer;
private readonly Container<DrawableTaikoJudgement> judgementContainer;
private readonly Container hitObjectContainer;
//private Container topLevelHitContainer;
private readonly Container leftBackgroundContainer;
private readonly Container rightBackgroundContainer;
private readonly Box leftBackground;
private readonly Box rightBackground;
public TaikoPlayfield()
{
RelativeSizeAxes = Axes.X;
Height = PlayfieldHeight;
AddInternal(new Drawable[]
{
rightBackgroundContainer = new Container
{
RelativeSizeAxes = Axes.Both,
BorderThickness = 2,
Masking = true,
EdgeEffect = new EdgeEffect
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Black.Opacity(0.2f),
Radius = 5,
},
Children = new Drawable[]
{
rightBackground = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.6f
},
}
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = left_area_size },
Children = new Drawable[]
{
new Container
{
Padding = new MarginPadding { Left = hit_target_offset },
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
hitExplosionContainer = new Container<HitExplosion>
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre,
Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2),
Scale = new Vector2(PLAYFIELD_SCALE),
BlendingMode = BlendingMode.Additive
},
//barLineContainer = new Container<DrawableBarLine>
//{
// RelativeSizeAxes = Axes.Both,
//},
new HitTarget
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre,
},
hitObjectContainer = new Container
{
RelativeSizeAxes = Axes.Both,
},
judgementContainer = new Container<DrawableTaikoJudgement>
{
RelativeSizeAxes = Axes.Both,
BlendingMode = BlendingMode.Additive
},
},
},
}
},
leftBackgroundContainer = new Container
{
Size = new Vector2(left_area_size, PlayfieldHeight),
BorderThickness = 1,
Children = new Drawable[]
{
leftBackground = new Box
{
RelativeSizeAxes = Axes.Both,
},
new InputDrum
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativePositionAxes = Axes.X,
Position = new Vector2(0.10f, 0),
Scale = new Vector2(0.9f)
},
new Box
{
Anchor = Anchor.TopRight,
RelativeSizeAxes = Axes.Y,
Width = 10,
ColourInfo = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)),
},
}
},
//topLevelHitContainer = new Container
//{
// RelativeSizeAxes = Axes.Both,
//}
});
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
leftBackgroundContainer.BorderColour = colours.Gray0;
leftBackground.Colour = colours.Gray1;
rightBackgroundContainer.BorderColour = colours.Gray1;
rightBackground.Colour = colours.Gray0;
}
public override void Add(DrawableHitObject<TaikoHitObject, TaikoJudgement> h)
{
h.Depth = (float)h.HitObject.StartTime;
h.Scale = new Vector2(PLAYFIELD_SCALE);
base.Add(h);
}
public override void OnJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> judgedObject)
{
bool wasHit = judgedObject.Judgement.Result == HitResult.Hit;
if (wasHit)
hitExplosionContainer.Add(new HitExplosion(judgedObject.Judgement));
judgementContainer.Add(new DrawableTaikoJudgement(judgedObject.Judgement)
{
Anchor = wasHit ? Anchor.TopLeft : Anchor.CentreLeft,
Origin = wasHit ? Anchor.BottomCentre : Anchor.Centre,
RelativePositionAxes = Axes.X,
X = wasHit ? judgedObject.Position.X : 0,
});
}
}
}
@@ -0,0 +1,23 @@
// 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.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using System.Collections.Generic;
using System;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Beatmaps;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Catch.Beatmaps
{
internal class CatchBeatmapConverter : BeatmapConverter<CatchBaseHit>
{
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) };
protected override IEnumerable<CatchBaseHit> ConvertHitObject(HitObject original, Beatmap beatmap)
{
yield return null;
}
}
}
@@ -2,11 +2,12 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Catch.Beatmaps;
using osu.Game.Modes.Catch.Objects;
using osu.Game.Rulesets.Beatmaps;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using System.Collections.Generic;
namespace osu.Game.Modes.Catch
namespace osu.Game.Rulesets.Catch
{
public class CatchDifficultyCalculator : DifficultyCalculator<CatchBaseHit>
{
@@ -19,6 +20,6 @@ namespace osu.Game.Modes.Catch
return 0;
}
protected override IBeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter();
protected override BeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter();
}
}
@@ -4,20 +4,20 @@
using OpenTK.Input;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Modes.Catch.Mods;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Mods;
using osu.Game.Modes.UI;
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.Game.Modes.Catch.Scoring;
using osu.Game.Modes.Scoring;
using osu.Game.Rulesets.Catch.Scoring;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Modes.Catch
namespace osu.Game.Rulesets.Catch
{
public class CatchRuleset : Ruleset
{
public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap) => new CatchHitRenderer(beatmap);
public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchHitRenderer(beatmap, isForCurrentRuleset);
public override IEnumerable<Mod> GetModsFor(ModType type)
{
@@ -28,7 +28,14 @@ namespace osu.Game.Modes.Catch
{
new CatchModEasy(),
new CatchModNoFail(),
new CatchModHalfTime(),
new MultiMod
{
Mods = new Mod[]
{
new CatchModHalfTime(),
new CatchModDaycore(),
},
},
};
case ModType.DifficultyIncrease:
@@ -76,8 +83,6 @@ namespace osu.Game.Modes.Catch
}
}
protected override PlayMode PlayMode => PlayMode.Catch;
public override string Description => "osu!catch";
public override FontAwesome Icon => FontAwesome.fa_osu_fruits_o;
@@ -92,5 +97,7 @@ namespace osu.Game.Modes.Catch
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap);
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor();
public override int LegacyID => 2;
}
}
@@ -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 osu.Game.Modes.Judgements;
using osu.Game.Rulesets.Judgements;
namespace osu.Game.Modes.Catch.Judgements
namespace osu.Game.Rulesets.Catch.Judgements
{
public class CatchJudgement : Judgement
{
@@ -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 osu.Game.Modes.Mods;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Modes.Catch.Mods
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModNoFail : ModNoFail
{
@@ -32,6 +32,11 @@ namespace osu.Game.Modes.Catch.Mods
}
public class CatchModDaycore : ModDaycore
{
public override double ScoreMultiplier => 0.5;
}
public class CatchModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.06;

Some files were not shown because too many files have changed in this diff Show More