1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 14:32:55 +08:00

Merge branch 'master' into mania-mask-container

This commit is contained in:
Dean Herbert 2018-08-02 20:41:27 +09:00 committed by GitHub
commit 6ee06602b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 694 additions and 629 deletions

View File

@ -24,7 +24,7 @@ Clone the repository including submodules
Build and run Build and run
- Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included) - Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included)
- From command line using `dotnet run --project osu.Desktop --framework netcoreapp2.1` - From command line using `dotnet run --project osu.Desktop`
If you run into issues building you may need to restore nuget packages (commonly via `dotnet restore`). Visual Studio Code users must run `Restore` task from debug tab before attempt to build. If you run into issues building you may need to restore nuget packages (commonly via `dotnet restore`). Visual Studio Code users must run `Restore` task from debug tab before attempt to build.

View File

@ -9,12 +9,10 @@ install:
- cmd: git submodule update --init --recursive --depth=5 - cmd: git submodule update --init --recursive --depth=5
- cmd: choco install resharper-clt -y - cmd: choco install resharper-clt -y
- cmd: choco install nvika -y - cmd: choco install nvika -y
- cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.2.5/CodeFileSanity.exe - cmd: dotnet tool install CodeFileSanity --version 0.0.16 --global
before_build: before_build:
- cmd: CodeFileSanity.exe - cmd: CodeFileSanity
- cmd: nuget restore -verbosity quiet - cmd: nuget restore -verbosity quiet
environment:
TargetFramework: net471
build: build:
project: osu.sln project: osu.sln
parallel: true parallel: true

View File

@ -16,17 +16,15 @@ build_script:
- cd osu-deploy - cd osu-deploy
- nuget restore -verbosity quiet - nuget restore -verbosity quiet
- msbuild osu.Desktop.Deploy.csproj - msbuild osu.Desktop.Deploy.csproj
- cmd: ..\appveyor-tools\secure-file -decrypt ..\fdc6f19b04.enc -secret %decode_secret% -out bin\Debug\net471\osu.Desktop.Deploy.exe.config - cmd: ..\appveyor-tools\secure-file -decrypt ..\fdc6f19b04.enc -secret %decode_secret% -out bin\Debug\netcoreapp2.1\osu.Desktop.Deploy.dll.config
- cd bin\Debug\net471\ - dotnet bin/Debug/netcoreapp2.1/osu.Desktop.Deploy.dll %code_signing_password% %APPVEYOR_REPO_TAG_NAME%
- osu.Desktop.Deploy.exe %code_signing_password% %APPVEYOR_REPO_TAG_NAME%
environment: environment:
TargetFramework: net471
decode_secret: decode_secret:
secure: i67IC2xj6DjjxmA6Oj2jing3+MwzLkq6CbGsjfZ7rdY= secure: i67IC2xj6DjjxmA6Oj2jing3+MwzLkq6CbGsjfZ7rdY=
code_signing_password: code_signing_password:
secure: 34tLNqvjmmZEi97MLKfrnQ== secure: 34tLNqvjmmZEi97MLKfrnQ==
artifacts: artifacts:
- path: 'Releases\*' - path: 'osu-deploy/releases/*'
deploy: deploy:
- provider: Environment - provider: Environment
name: github name: github

View File

@ -13,6 +13,7 @@ using osu.Game;
using OpenTK.Input; using OpenTK.Input;
using Microsoft.Win32; using Microsoft.Win32;
using osu.Desktop.Updater; using osu.Desktop.Updater;
using osu.Framework;
using osu.Framework.Platform.Windows; using osu.Framework.Platform.Windows;
namespace osu.Desktop namespace osu.Desktop
@ -51,11 +52,10 @@ namespace osu.Desktop
v.State = Visibility.Visible; v.State = Visibility.Visible;
}); });
#if NET_FRAMEWORK if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows)
Add(new SquirrelUpdateManager()); Add(new SquirrelUpdateManager());
#else else
Add(new SimpleUpdateManager()); Add(new SimpleUpdateManager());
#endif
} }
} }

View File

@ -8,10 +8,6 @@ using osu.Framework;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.IPC; using osu.Game.IPC;
#if NET_FRAMEWORK
using System.Runtime;
#endif
namespace osu.Desktop namespace osu.Desktop
{ {
public static class Program public static class Program
@ -19,8 +15,6 @@ namespace osu.Desktop
[STAThread] [STAThread]
public static int Main(string[] args) public static int Main(string[] args)
{ {
useMultiCoreJit();
// Back up the cwd before DesktopGameHost changes it // Back up the cwd before DesktopGameHost changes it
var cwd = Environment.CurrentDirectory; var cwd = Environment.CurrentDirectory;
@ -51,14 +45,5 @@ namespace osu.Desktop
return 0; return 0;
} }
} }
private static void useMultiCoreJit()
{
#if NET_FRAMEWORK
var directory = Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Profiles"));
ProfileOptimization.SetProfileRoot(directory.FullName);
ProfileOptimization.StartProfile("Startup.Profile");
#endif
}
} }
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
#if NET_FRAMEWORK
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -162,4 +161,3 @@ namespace osu.Desktop.Updater
} }
} }
} }
#endif

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.Game.props" /> <Import Project="..\osu.Game.props" />
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<TargetFrameworks>net471;netcoreapp2.1</TargetFrameworks> <TargetFramework>netcoreapp2.1</TargetFramework>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -13,9 +13,6 @@
<Version>0.0.0</Version> <Version>0.0.0</Version>
<FileVersion>0.0.0</FileVersion> <FileVersion>0.0.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Defines">
<DefineConstants Condition="'$(TargetFramework)' == 'net471'">$(DefineConstants);NET_FRAMEWORK</DefineConstants>
</PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject>osu.Desktop.Program</StartupObject> <StartupObject>osu.Desktop.Program</StartupObject>
</PropertyGroup> </PropertyGroup>
@ -29,9 +26,10 @@
<PackageReference Include="Microsoft.Win32.Registry" Version="4.5.0" /> <PackageReference Include="Microsoft.Win32.Registry" Version="4.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="System.IO.Packaging" Version="4.5.0" />
<PackageReference Include="ppy.squirrel.windows" Version="1.8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.1" />
<PackageReference Include="squirrel.windows" Version="1.8.0" Condition="'$(TargetFramework)' == 'net471'" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Resources"> <ItemGroup Label="Resources">
<EmbeddedResource Include="lazer.ico" /> <EmbeddedResource Include="lazer.ico" />

View File

@ -3,7 +3,7 @@
<metadata> <metadata>
<id>osulazer</id> <id>osulazer</id>
<version>0.0.0</version> <version>0.0.0</version>
<title>osulazer</title> <title>osu!lazer</title>
<authors>ppy Pty Ltd</authors> <authors>ppy Pty Ltd</authors>
<owners>Dean Herbert</owners> <owners>Dean Herbert</owners>
<projectUrl>https://osu.ppy.sh/</projectUrl> <projectUrl>https://osu.ppy.sh/</projectUrl>

View File

@ -2,35 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net471)", "name": "VisualTests (Debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Catch.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Release, net471)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Catch.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Debug, netcoreapp2.1)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -38,12 +10,12 @@
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Catch.Tests.dll" "${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Catch.Tests.dll"
], ],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, dotnet)", "preLaunchTask": "Build (Debug)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, netcoreapp2.1)", "name": "VisualTests (Release)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -51,7 +23,7 @@
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Catch.Tests.dll" "${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Catch.Tests.dll"
], ],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, dotnet)", "preLaunchTask": "Build (Release)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
} }

View File

@ -4,43 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build (Debug, msbuild)", "label": "Build (Debug)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Catch.Tests.csproj",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release, msbuild)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Catch.Tests.csproj",
"/p:Configuration=Release",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Debug, dotnet)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Catch.Tests.csproj", "osu.Game.Rulesets.Catch.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -49,14 +19,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Build (Release, dotnet)", "label": "Build (Release)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Catch.Tests.csproj", "osu.Game.Rulesets.Catch.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
@ -66,16 +35,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net471)", "label": "Restore",
"type": "shell",
"command": "nuget",
"args": [
"restore"
],
"problemMatcher": []
},
{
"label": "Restore (netcoreapp2.1)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [

View File

@ -1,8 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks> <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />

View File

@ -52,6 +52,9 @@ namespace osu.Game.Rulesets.Catch.UI
{ {
void runAfterLoaded(Action action) void runAfterLoaded(Action action)
{ {
if (lastPlateableFruit == null)
return;
// this is required to make this run after the last caught fruit runs UpdateState at least once. // this is required to make this run after the last caught fruit runs UpdateState at least once.
// TODO: find a better alternative // TODO: find a better alternative
if (lastPlateableFruit.IsLoaded) if (lastPlateableFruit.IsLoaded)

View File

@ -2,35 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net471)", "name": "VisualTests (Debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Mania.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Release, net471)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Mania.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Debug, netcoreapp2.1)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -38,12 +10,12 @@
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Mania.Tests.dll" "${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Mania.Tests.dll"
], ],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, dotnet)", "preLaunchTask": "Build (Debug)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, netcoreapp2.1)", "name": "VisualTests (Release)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -51,7 +23,7 @@
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Mania.Tests.dll" "${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Mania.Tests.dll"
], ],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, dotnet)", "preLaunchTask": "Build (Release)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
} }

View File

@ -4,43 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build (Debug, msbuild)", "label": "Build (Debug)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Mania.Tests.csproj",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release, msbuild)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Mania.Tests.csproj",
"/p:Configuration=Release",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Debug, dotnet)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Mania.Tests.csproj", "osu.Game.Rulesets.Mania.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -49,14 +19,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Build (Release, dotnet)", "label": "Build (Release)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Mania.Tests.csproj", "osu.Game.Rulesets.Mania.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
@ -66,16 +35,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net471)", "label": "Restore",
"type": "shell",
"command": "nuget",
"args": [
"restore"
],
"problemMatcher": []
},
{
"label": "Restore (netcoreapp2.1)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [

View File

@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Mania.Tests
return new ScrollingTestContainer(direction) return new ScrollingTestContainer(direction)
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Child = new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") Child = new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLowerInvariant()}")
{ {
Child = new DrawableNote(note) { AccentColour = Color4.OrangeRed } Child = new DrawableNote(note) { AccentColour = Color4.OrangeRed }
} }
@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Tests
return new ScrollingTestContainer(direction) return new ScrollingTestContainer(direction)
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Child = new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") Child = new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLowerInvariant()}")
{ {
Child = new DrawableHoldNote(note) Child = new DrawableHoldNote(note)
{ {

View File

@ -1,8 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks> <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />

View File

@ -2,35 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net471)", "name": "VisualTests (Debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Osu.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Release, net471)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Osu.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Debug, netcoreapp2.1)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -38,12 +10,12 @@
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Osu.Tests.dll" "${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Osu.Tests.dll"
], ],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, dotnet)", "preLaunchTask": "Build (Debug)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, netcoreapp2.1)", "name": "VisualTests (Release)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -51,7 +23,7 @@
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Osu.Tests.dll" "${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Osu.Tests.dll"
], ],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, dotnet)", "preLaunchTask": "Build (Release)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
} }

View File

@ -4,43 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build (Debug, msbuild)", "label": "Build (Debug)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Osu.Tests.csproj",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release, msbuild)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Osu.Tests.csproj",
"/p:Configuration=Release",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Debug, dotnet)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Osu.Tests.csproj", "osu.Game.Rulesets.Osu.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -49,14 +19,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Build (Release, dotnet)", "label": "Build (Release)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Osu.Tests.csproj", "osu.Game.Rulesets.Osu.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
@ -66,16 +35,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net471)", "label": "Restore",
"type": "shell",
"command": "nuget",
"args": [
"restore"
],
"problemMatcher": []
},
{
"label": "Restore (netcoreapp2.1)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [

View File

@ -1,8 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks> <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />

View File

@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
{ {
@ -20,27 +21,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
Masking = true; Child = new SkinnableDrawable("Play/osu/followpoint", _ => new Container
AutoSizeAxes = Axes.Both; {
CornerRadius = width / 2; Masking = true,
AutoSizeAxes = Axes.Both,
CornerRadius = width / 2,
EdgeEffect = new EdgeEffectParameters EdgeEffect = new EdgeEffectParameters
{ {
Type = EdgeEffectType.Glow, Type = EdgeEffectType.Glow,
Colour = Color4.White.Opacity(0.2f), Colour = Color4.White.Opacity(0.2f),
Radius = 4, Radius = 4,
}; },
Child = new Box
Children = new Drawable[]
{
new Box
{ {
Size = new Vector2(width), Size = new Vector2(width),
Blending = BlendingMode.Additive, Blending = BlendingMode.Additive,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Alpha = 0.5f, Alpha = 0.5f,
}, }
}; }, restrictSize: false);
} }
} }
} }

View File

@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
Vector2 distanceVector = endPosition - startPosition; Vector2 distanceVector = endPosition - startPosition;
int distance = (int)distanceVector.Length; int distance = (int)distanceVector.Length;
float rotation = (float)Math.Atan2(distanceVector.Y, distanceVector.X); float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI));
double duration = endTime - startTime; double duration = endTime - startTime;
for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance) for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance)

View File

@ -1,11 +1,13 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.ComponentModel; using System.ComponentModel;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using System.Linq; using System.Linq;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning; using osu.Game.Skinning;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -32,7 +34,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
UpdatePreemptState(); UpdatePreemptState();
using (BeginDelayedSequence(HitObject.TimePreempt + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true)) var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), Judgements.FirstOrDefault()?.TimeOffset ?? 0);
using (BeginDelayedSequence(HitObject.TimePreempt + judgementOffset, true))
UpdateCurrentState(state); UpdateCurrentState(state);
} }
} }

View File

@ -10,6 +10,7 @@ using OpenTK;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -33,11 +34,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new SpriteIcon new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Icon = FontAwesome.fa_chevron_right Icon = FontAwesome.fa_chevron_right
} }, restrictSize: false)
}; };
} }
@ -74,6 +75,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
} }
} }
private bool hasRotation;
public void UpdateSnakingPosition(Vector2 start, Vector2 end) public void UpdateSnakingPosition(Vector2 start, Vector2 end)
{ {
bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0; bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0;
@ -87,15 +90,33 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
int searchStart = isRepeatAtEnd ? curve.Count - 1 : 0; int searchStart = isRepeatAtEnd ? curve.Count - 1 : 0;
int direction = isRepeatAtEnd ? -1 : 1; int direction = isRepeatAtEnd ? -1 : 1;
Vector2 aimRotationVector = Vector2.Zero;
// find the next vector2 in the curve which is not equal to our current position to infer a rotation. // find the next vector2 in the curve which is not equal to our current position to infer a rotation.
for (int i = searchStart; i >= 0 && i < curve.Count; i += direction) for (int i = searchStart; i >= 0 && i < curve.Count; i += direction)
{ {
if (Precision.AlmostEquals(curve[i], Position)) if (Precision.AlmostEquals(curve[i], Position))
continue; continue;
Rotation = MathHelper.RadiansToDegrees((float)Math.Atan2(curve[i].Y - Position.Y, curve[i].X - Position.X)); aimRotationVector = curve[i];
break; break;
} }
float aimRotation = MathHelper.RadiansToDegrees((float)Math.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X));
while (Math.Abs(aimRotation - Rotation) > 180)
aimRotation += aimRotation < Rotation ? 360 : -360;
if (!hasRotation)
{
Rotation = aimRotation;
hasRotation = true;
}
else
{
// If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly).
Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint);
}
} }
} }
} }

View File

@ -8,6 +8,8 @@ using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -22,23 +24,27 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
{ {
Size = new Vector2(16) * sliderTick.Scale; Size = new Vector2(16) * sliderTick.Scale;
Masking = true;
CornerRadius = Size.X / 2;
Origin = Anchor.Centre; Origin = Anchor.Centre;
BorderThickness = 2;
BorderColour = Color4.White;
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new Box new SkinnableDrawable("Play/osu/sliderscorepoint", _ => new Container
{
Masking = true,
RelativeSizeAxes = Axes.Both,
Origin = Anchor.Centre,
CornerRadius = Size.X / 2,
BorderThickness = 2,
BorderColour = Color4.White,
Child = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = AccentColour, Colour = AccentColour,
Alpha = 0.3f, Alpha = 0.3f,
} }
}, restrictSize: false)
}; };
} }

View File

@ -10,6 +10,7 @@ using osu.Framework.Input.States;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
@ -18,6 +19,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
private const float width = 128; private const float width = 128;
private Color4 accentColour = Color4.Black; private Color4 accentColour = Color4.Black;
/// <summary> /// <summary>
/// The colour that is used for the slider ball. /// The colour that is used for the slider ball.
/// </summary> /// </summary>
@ -27,14 +29,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
set set
{ {
accentColour = value; accentColour = value;
if (ball != null) if (drawableBall != null)
ball.Colour = value; drawableBall.Colour = value;
} }
} }
private readonly Slider slider; private readonly Slider slider;
public readonly Box FollowCircle; public readonly Drawable FollowCircle;
private readonly Box ball; private Drawable drawableBall;
public SliderBall(Slider slider) public SliderBall(Slider slider)
{ {
@ -43,19 +45,30 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
Blending = BlendingMode.Additive; Blending = BlendingMode.Additive;
Origin = Anchor.Centre; Origin = Anchor.Centre;
BorderThickness = 10;
BorderColour = Color4.Orange;
Children = new Drawable[] Children = new[]
{ {
FollowCircle = new Box FollowCircle = new Container
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Colour = Color4.Orange,
Width = width, Width = width,
Height = width, Height = width,
Alpha = 0, Alpha = 0,
Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new CircularContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderThickness = 5,
BorderColour = Color4.Orange,
Blending = BlendingMode.Additive,
Child = new Box
{
Colour = Color4.Orange,
RelativeSizeAxes = Axes.Both,
Alpha = 0.2f,
}
}),
}, },
new CircularContainer new CircularContainer
{ {
@ -63,18 +76,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Alpha = 1,
Child = new Container
{
Width = width,
Height = width,
// TODO: support skin filename animation (sliderb0, sliderb1...)
Child = new SkinnableDrawable("Play/osu/sliderb", _ => new CircularContainer
{
Masking = true,
RelativeSizeAxes = Axes.Both,
BorderThickness = 10, BorderThickness = 10,
BorderColour = Color4.White, BorderColour = Color4.White,
Alpha = 1, Alpha = 1,
Children = new[] Child = drawableBall = new Box
{
ball = new Box
{ {
Colour = AccentColour, Colour = AccentColour,
RelativeSizeAxes = Axes.Both,
Alpha = 0.4f, Alpha = 0.4f,
Width = width, }
Height = width, }),
},
} }
} }
}; };
@ -111,6 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
} }
private bool tracking; private bool tracking;
public bool Tracking public bool Tracking
{ {
get { return tracking; } get { return tracking; }
@ -120,8 +142,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
return; return;
tracking = value; tracking = value;
FollowCircle.ScaleTo(tracking ? 2.8f : 1, 300, Easing.OutQuint); FollowCircle.ScaleTo(tracking ? 2f : 1, 300, Easing.OutQuint);
FollowCircle.FadeTo(tracking ? 0.2f : 0, 300, Easing.OutQuint); FollowCircle.FadeTo(tracking ? 1f : 0, 300, Easing.OutQuint);
} }
} }

View File

@ -16,6 +16,9 @@ namespace osu.Game.Rulesets.Osu.Objects
{ {
base.ApplyDefaultsToSelf(controlPointInfo, difficulty); base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
// Out preempt should be one span early to give the user ample warning.
TimePreempt += SpanDuration;
// We want to show the first RepeatPoint as the TimePreempt dictates but on short (and possibly fast) sliders // We want to show the first RepeatPoint as the TimePreempt dictates but on short (and possibly fast) sliders
// we may need to cut down this time on following RepeatPoints to only show up to two RepeatPoints at any given time. // we may need to cut down this time on following RepeatPoints to only show up to two RepeatPoints at any given time.
if (RepeatIndex > 0) if (RepeatIndex > 0)

View File

@ -2,35 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net471)", "name": "VisualTests (Debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Taiko.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Release, net471)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Taiko.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Debug, netcoreapp2.1)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -38,12 +10,12 @@
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Taiko.Tests.dll" "${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Taiko.Tests.dll"
], ],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, dotnet)", "preLaunchTask": "Build (Debug)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, netcoreapp2.1)", "name": "VisualTests (Release)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -51,7 +23,7 @@
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Taiko.Tests.dll" "${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Taiko.Tests.dll"
], ],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, dotnet)", "preLaunchTask": "Build (Release)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
} }

View File

@ -4,43 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build (Debug, msbuild)", "label": "Build (Debug)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release, msbuild)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:Configuration=Release",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Debug, dotnet)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Taiko.Tests.csproj", "osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -49,14 +19,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Build (Release, dotnet)", "label": "Build (Release)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Taiko.Tests.csproj", "osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
@ -66,16 +35,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net471)", "label": "Restore",
"type": "shell",
"command": "nuget",
"args": [
"restore"
],
"problemMatcher": []
},
{
"label": "Restore (netcoreapp2.1)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [

View File

@ -1,8 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks> <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />

View File

@ -530,7 +530,7 @@ namespace osu.Game.Tests.Visual
{ {
public new List<DrawableCarouselItem> Items => base.Items; public new List<DrawableCarouselItem> Items => base.Items;
public bool PendingFilterTask => FilterTask != null; public bool PendingFilterTask => PendingFilter != null;
} }
} }
} }

View File

@ -0,0 +1,41 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Screens.Edit.Screens.Setup.Components.LabelledComponents;
using System;
using System.Collections.Generic;
namespace osu.Game.Tests.Visual
{
[TestFixture]
public class TestCaseLabelledTextBox : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(LabelledTextBox),
};
[BackgroundDependencyLoader]
private void load()
{
Child = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Padding = new MarginPadding { Left = 150, Right = 150 },
Child = new LabelledTextBox
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
LabelText = "Testing text",
PlaceholderText = "This is definitely working as intended",
}
};
}
}
}

View File

@ -54,14 +54,25 @@ namespace osu.Game.Tests.Visual
public new BeatmapCarousel Carousel => base.Carousel; public new BeatmapCarousel Carousel => base.Carousel;
} }
private TestSongSelect songSelect;
protected override void Dispose(bool isDisposing)
{
factory.ResetDatabase();
base.Dispose(isDisposing);
}
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
TestSongSelect songSelect = null;
factory = new DatabaseContextFactory(LocalStorage); factory = new DatabaseContextFactory(LocalStorage);
factory.ResetDatabase(); factory.ResetDatabase();
using (var usage = factory.Get())
usage.Migrate();
factory.ResetDatabase();
using (var usage = factory.Get()) using (var usage = factory.Get())
usage.Migrate(); usage.Migrate();
@ -71,42 +82,35 @@ namespace osu.Game.Tests.Visual
DefaultBeatmap = defaultBeatmap = Beatmap.Default DefaultBeatmap = defaultBeatmap = Beatmap.Default
}); });
void loadNewSongSelect(bool deleteMaps = false) => AddStep("reload song select", () =>
{
if (deleteMaps)
{
manager.Delete(manager.GetAllUsableBeatmapSets());
Beatmap.SetDefault(); Beatmap.SetDefault();
} }
if (songSelect != null) [SetUp]
public virtual void SetUp()
{ {
Remove(songSelect); manager?.Delete(manager.GetAllUsableBeatmapSets());
songSelect.Dispose(); Child = songSelect = new TestSongSelect();
} }
Add(songSelect = new TestSongSelect()); [Test]
}); public void TestDummy()
{
loadNewSongSelect(true);
AddWaitStep(3);
AddAssert("dummy selected", () => songSelect.CurrentBeatmap == defaultBeatmap); AddAssert("dummy selected", () => songSelect.CurrentBeatmap == defaultBeatmap);
AddAssert("dummy shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap == defaultBeatmap); AddAssert("dummy shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap == defaultBeatmap);
AddStep("import test maps", () => addManyTestMaps();
{
for (int i = 0; i < 100; i += 10)
manager.Import(createTestBeatmapSet(i));
});
AddWaitStep(3); AddWaitStep(3);
AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap); AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap);
}
loadNewSongSelect(); [Test]
public void TestSorting()
{
addManyTestMaps();
AddWaitStep(3); AddWaitStep(3);
AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap); AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap);
AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; }); AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
@ -115,55 +119,84 @@ namespace osu.Game.Tests.Visual
AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; }); AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
} }
private BeatmapSetInfo createTestBeatmapSet(int i) [Test]
[Ignore("needs fixing")]
public void ImportUnderDifferentRuleset()
{ {
return new BeatmapSetInfo changeRuleset(2);
importForRuleset(0);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection");
}
[Test]
public void ImportUnderCurrentRuleset()
{ {
OnlineBeatmapSetID = 1234 + i, changeRuleset(2);
Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), importForRuleset(2);
Metadata = new BeatmapMetadata importForRuleset(1);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap.RulesetID == 2, "has selection");
changeRuleset(1);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap.RulesetID == 1, "has selection");
changeRuleset(0);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection");
}
private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())));
private static int importId;
private int getImportId() => ++importId;
private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id));
private void addManyTestMaps()
{ {
// Create random metadata, then we can check if sorting works based on these AddStep("import test maps", () =>
Artist = "MONACA " + RNG.Next(0, 9),
Title = "Black Song " + RNG.Next(0, 9),
AuthorString = "Some Guy " + RNG.Next(0, 9),
},
Beatmaps = new List<BeatmapInfo>(new[]
{ {
new BeatmapInfo var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
for (int i = 0; i < 100; i += 10)
manager.Import(createTestBeatmapSet(i, usableRulesets));
});
}
private BeatmapSetInfo createTestBeatmapSet(int setId, RulesetInfo[] rulesets)
{ {
OnlineBeatmapID = 1234 + i, int j = 0;
Ruleset = rulesets.AvailableRulesets.First(), RulesetInfo getRuleset() => rulesets[j++ % rulesets.Length];
var beatmaps = new List<BeatmapInfo>();
for (int i = 0; i < 6; i++)
{
int beatmapId = setId * 10 + i;
beatmaps.Add(new BeatmapInfo
{
Ruleset = getRuleset(),
OnlineBeatmapID = beatmapId,
Path = "normal.osu", Path = "normal.osu",
Version = "Normal", Version = $"{beatmapId}",
BaseDifficulty = new BeatmapDifficulty BaseDifficulty = new BeatmapDifficulty
{ {
OverallDifficulty = 3.5f, OverallDifficulty = 3.5f,
} }
}, });
new BeatmapInfo
{
OnlineBeatmapID = 1235 + i,
Ruleset = rulesets.AvailableRulesets.First(),
Path = "hard.osu",
Version = "Hard",
BaseDifficulty = new BeatmapDifficulty
{
OverallDifficulty = 5,
} }
},
new BeatmapInfo return new BeatmapSetInfo
{ {
OnlineBeatmapID = 1236 + i, OnlineBeatmapSetID = setId,
Ruleset = rulesets.AvailableRulesets.First(), Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(),
Path = "insane.osu", Metadata = new BeatmapMetadata
Version = "Insane",
BaseDifficulty = new BeatmapDifficulty
{ {
OverallDifficulty = 7, // Create random metadata, then we can check if sorting works based on these
} Artist = "Some Artist " + RNG.Next(0, 9),
Title = $"Some Song (set id {setId})",
AuthorString = "Some Guy " + RNG.Next(0, 9),
}, },
}), Beatmaps = beatmaps
}; };
} }
} }

View File

@ -54,11 +54,11 @@ namespace osu.Game.Tests.Visual
breadcrumbs.Current.TriggerChange(); breadcrumbs.Current.TriggerChange();
assertCurrent(); waitForCurrent();
pushNext(); pushNext();
assertCurrent(); waitForCurrent();
pushNext(); pushNext();
assertCurrent(); waitForCurrent();
AddStep(@"make start current", () => AddStep(@"make start current", () =>
{ {
@ -66,8 +66,9 @@ namespace osu.Game.Tests.Visual
currentScreen = startScreen; currentScreen = startScreen;
}); });
assertCurrent(); waitForCurrent();
pushNext(); pushNext();
waitForCurrent();
AddAssert(@"only 2 items", () => breadcrumbs.Items.Count() == 2); AddAssert(@"only 2 items", () => breadcrumbs.Items.Count() == 2);
AddStep(@"exit current", () => changedScreen.Exit()); AddStep(@"exit current", () => changedScreen.Exit());
AddAssert(@"current screen is first", () => startScreen == changedScreen); AddAssert(@"current screen is first", () => startScreen == changedScreen);
@ -80,7 +81,7 @@ namespace osu.Game.Tests.Visual
} }
private void pushNext() => AddStep(@"push next screen", () => currentScreen = ((TestScreen)currentScreen).PushNext()); private void pushNext() => AddStep(@"push next screen", () => currentScreen = ((TestScreen)currentScreen).PushNext());
private void assertCurrent() => AddAssert(@"changedScreen correct", () => currentScreen == changedScreen); private void waitForCurrent() => AddUntilStep(() => currentScreen.IsCurrentScreen, "current screen");
private abstract class TestScreen : OsuScreen private abstract class TestScreen : OsuScreen
{ {

View File

@ -1,8 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks> <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />

View File

@ -23,7 +23,7 @@ namespace osu.Game.Beatmaps.Drawables
if (value == status) return; if (value == status) return;
status = value; status = value;
statusText.Text = Enum.GetName(typeof(BeatmapSetOnlineStatus), Status)?.ToUpper(); statusText.Text = Enum.GetName(typeof(BeatmapSetOnlineStatus), Status)?.ToUpperInvariant();
} }
} }

View File

@ -312,7 +312,7 @@ namespace osu.Game.Beatmaps.Formats
omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine); omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine);
} }
string stringSampleSet = sampleSet.ToString().ToLower(); string stringSampleSet = sampleSet.ToString().ToLowerInvariant();
if (stringSampleSet == @"none") if (stringSampleSet == @"none")
stringSampleSet = @"normal"; stringSampleSet = @"normal";

View File

@ -134,6 +134,8 @@ namespace osu.Game.Beatmaps
return converted; return converted;
} }
public override string ToString() => BeatmapInfo.ToString();
public bool BackgroundLoaded => background.IsResultAvailable; public bool BackgroundLoaded => background.IsResultAvailable;
public Texture Background => background.Value.Result; public Texture Background => background.Value.Result;
public async Task<Texture> GetBackgroundAsync() => await background.Value; public async Task<Texture> GetBackgroundAsync() => await background.Value;

View File

@ -5,6 +5,7 @@ using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Platform; using osu.Framework.Platform;
namespace osu.Game.Database namespace osu.Game.Database
@ -115,7 +116,11 @@ namespace osu.Game.Database
} }
} }
private void recycleThreadContexts() => threadContexts = new ThreadLocal<OsuDbContext>(CreateContext); private void recycleThreadContexts()
{
threadContexts?.Values.ForEach(c => c.Dispose());
threadContexts = new ThreadLocal<OsuDbContext>(CreateContext, true);
}
protected virtual OsuDbContext CreateContext() => new OsuDbContext(storage.GetDatabaseConnectionString(database_name)) protected virtual OsuDbContext CreateContext() => new OsuDbContext(storage.GetDatabaseConnectionString(database_name))
{ {
@ -127,8 +132,6 @@ namespace osu.Game.Database
lock (writeLock) lock (writeLock)
{ {
recycleThreadContexts(); recycleThreadContexts();
GC.Collect();
GC.WaitForPendingFinalizers();
storage.DeleteDatabase(database_name); storage.DeleteDatabase(database_name);
} }
} }

View File

@ -134,7 +134,7 @@ namespace osu.Game.Graphics
private string getFileName() private string getFileName()
{ {
var dt = DateTime.Now; var dt = DateTime.Now;
var fileExt = screenshotFormat.ToString().ToLower(); var fileExt = screenshotFormat.ToString().ToLowerInvariant();
var withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}"; var withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}";
if (!storage.Exists(withoutIndex)) if (!storage.Exists(withoutIndex))

View File

@ -37,7 +37,7 @@ namespace osu.Game.Graphics.UserInterface
{ {
TabContainer.Spacing = new Vector2(10f, 0f); TabContainer.Spacing = new Vector2(10f, 0f);
Add(strip = new Box AddInternal(strip = new Box
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,

View File

@ -20,7 +20,7 @@ namespace osu.Game.Online.API.Requests
} }
// ReSharper disable once ImpureMethodCallOnReadonlyValueField // ReSharper disable once ImpureMethodCallOnReadonlyValueField
protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLower()}?offset={offset}"; protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLowerInvariant()}?offset={offset}";
} }
public enum ScoreType public enum ScoreType

View File

@ -23,7 +23,7 @@ namespace osu.Game.Online.API.Requests
req.Method = HttpMethod.POST; req.Method = HttpMethod.POST;
req.AddParameter(@"target_type", message.TargetType.GetDescription()); req.AddParameter(@"target_type", message.TargetType.GetDescription());
req.AddParameter(@"target_id", message.TargetId.ToString()); req.AddParameter(@"target_id", message.TargetId.ToString());
req.AddParameter(@"is_action", message.IsAction.ToString().ToLower()); req.AddParameter(@"is_action", message.IsAction.ToString().ToLowerInvariant());
req.AddParameter(@"message", message.Content); req.AddParameter(@"message", message.Content);
return req; return req;

View File

@ -29,7 +29,7 @@ namespace osu.Game.Online.API.Requests
} }
// ReSharper disable once ImpureMethodCallOnReadonlyValueField // ReSharper disable once ImpureMethodCallOnReadonlyValueField
protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={(int)searchCategory}&sort={sortCriteria.ToString().ToLower()}_{directionString}"; protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={(int)searchCategory}&sort={sortCriteria.ToString().ToLowerInvariant()}_{directionString}";
} }
public enum BeatmapSearchCategory public enum BeatmapSearchCategory

View File

@ -197,7 +197,13 @@ namespace osu.Game
return; return;
} }
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); var databasedSet = BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID);
// Use first beatmap available for current ruleset, else switch ruleset.
var first = databasedSet.Beatmaps.FirstOrDefault(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First();
ruleset.Value = first.Ruleset;
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first);
} }
switch (currentScreen) switch (currentScreen)
@ -580,10 +586,10 @@ namespace osu.Game
// we only want to apply these restrictions when we are inside a screen stack. // we only want to apply these restrictions when we are inside a screen stack.
// the use case for not applying is in visual/unit tests. // the use case for not applying is in visual/unit tests.
bool applyRestrictions = !currentScreen?.AllowBeatmapRulesetChange ?? false; bool applyBeatmapRulesetRestrictions = !currentScreen?.AllowBeatmapRulesetChange ?? false;
ruleset.Disabled = applyRestrictions; ruleset.Disabled = applyBeatmapRulesetRestrictions;
Beatmap.Disabled = applyRestrictions; Beatmap.Disabled = applyBeatmapRulesetRestrictions;
mainContent.Padding = new MarginPadding { Top = ToolbarOffset }; mainContent.Padding = new MarginPadding { Top = ToolbarOffset };

View File

@ -224,7 +224,7 @@ namespace osu.Game
// todo: we probably want a better (non-destructive) migrations/recovery process at a later point than this. // todo: we probably want a better (non-destructive) migrations/recovery process at a later point than this.
contextFactory.ResetDatabase(); contextFactory.ResetDatabase();
Logger.Log("Database purged successfully.", LoggingTarget.Database, LogLevel.Important); Logger.Log("Database purged successfully.", LoggingTarget.Database);
// only run once more, then hard bail. // only run once more, then hard bail.
using (var db = contextFactory.GetForWrite(false)) using (var db = contextFactory.GetForWrite(false))

View File

@ -1,18 +1,28 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables; using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.API;
using osu.Game.Users;
using OpenTK; using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Overlays.BeatmapSet.Buttons namespace osu.Game.Overlays.BeatmapSet.Buttons
{ {
public class DownloadButton : HeaderButton public class DownloadButton : HeaderButton, IHasTooltip
{ {
public string TooltipText => Enabled ? null : "You gotta be an osu!supporter to download for now 'yo";
private readonly IBindable<User> localUser = new Bindable<User>();
public DownloadButton(BeatmapSetInfo set, bool noVideo = false) public DownloadButton(BeatmapSetInfo set, bool noVideo = false)
{ {
Width = 120; Width = 120;
@ -86,5 +96,17 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
} }
}; };
} }
[BackgroundDependencyLoader]
private void load(APIAccess api)
{
localUser.BindTo(api.LocalUser);
localUser.BindValueChanged(userChanged, true);
Enabled.BindValueChanged(enabledChanged, true);
}
private void userChanged(User user) => Enabled.Value = user.IsSupporter;
private void enabledChanged(bool enabled) => this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint);
} }
} }

View File

@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Chat
public string Header public string Header
{ {
get { return header.Text; } get { return header.Text; }
set { header.Text = value.ToUpper(); } set { header.Text = value.ToUpperInvariant(); }
} }
public IEnumerable<Channel> Channels public IEnumerable<Channel> Channels

View File

@ -14,6 +14,7 @@ namespace osu.Game.Overlays.Direct
{ {
public class DownloadButton : OsuAnimatedButton public class DownloadButton : OsuAnimatedButton
{ {
private readonly BeatmapSetInfo beatmapSet;
private readonly SpriteIcon icon; private readonly SpriteIcon icon;
private readonly SpriteIcon checkmark; private readonly SpriteIcon checkmark;
private readonly BeatmapSetDownloader downloader; private readonly BeatmapSetDownloader downloader;
@ -21,11 +22,13 @@ namespace osu.Game.Overlays.Direct
private OsuColour colours; private OsuColour colours;
public DownloadButton(BeatmapSetInfo set, bool noVideo = false) public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false)
{ {
this.beatmapSet = beatmapSet;
AddRange(new Drawable[] AddRange(new Drawable[]
{ {
downloader = new BeatmapSetDownloader(set, noVideo), downloader = new BeatmapSetDownloader(beatmapSet, noVideo),
background = new Box background = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -47,26 +50,6 @@ namespace osu.Game.Overlays.Direct
Icon = FontAwesome.fa_check, Icon = FontAwesome.fa_check,
} }
}); });
Action = () =>
{
if (downloader.DownloadState == BeatmapSetDownloader.DownloadStatus.Downloading)
{
// todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged.
Content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
}
else if (downloader.DownloadState == BeatmapSetDownloader.DownloadStatus.Downloaded)
{
// TODO: Jump to song select with this set when the capability is implemented
}
else
{
downloader.Download();
}
};
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -77,9 +60,29 @@ namespace osu.Game.Overlays.Direct
} }
[BackgroundDependencyLoader(permitNulls: true)] [BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuColour colours) private void load(OsuColour colours, OsuGame game)
{ {
this.colours = colours; this.colours = colours;
Action = () =>
{
switch (downloader.DownloadState.Value)
{
case BeatmapSetDownloader.DownloadStatus.Downloading:
// todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged.
Content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
break;
case BeatmapSetDownloader.DownloadStatus.Downloaded:
game.PresentBeatmap(beatmapSet);
break;
default:
downloader.Download();
break;
}
};
} }
private void updateState(BeatmapSetDownloader.DownloadStatus state) private void updateState(BeatmapSetDownloader.DownloadStatus state)

View File

@ -62,7 +62,7 @@ namespace osu.Game.Overlays.MedalSplash
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Text = "Medal Unlocked".ToUpper(), Text = "Medal Unlocked".ToUpperInvariant(),
TextSize = 24, TextSize = 24,
Font = @"Exo2.0-Light", Font = @"Exo2.0-Light",
Alpha = 0f, Alpha = 0f,

View File

@ -183,7 +183,7 @@ namespace osu.Game.Overlays
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
Height = progress_height, Height = progress_height,
FillColour = colours.Yellow, FillColour = colours.Yellow,
OnSeek = progress => current?.Track.Seek(progress) OnSeek = attemptSeek
} }
}, },
}, },
@ -198,6 +198,12 @@ namespace osu.Game.Overlays
playlist.StateChanged += s => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); playlist.StateChanged += s => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint);
} }
private void attemptSeek(double progress)
{
if (!beatmap.Disabled)
current?.Track.Seek(progress);
}
private void playlistOrderChanged(BeatmapSetInfo beatmapSetInfo, int index) private void playlistOrderChanged(BeatmapSetInfo beatmapSetInfo, int index)
{ {
beatmapSets.Remove(beatmapSetInfo); beatmapSets.Remove(beatmapSetInfo);
@ -219,6 +225,7 @@ namespace osu.Game.Overlays
if (disabled) if (disabled)
playlist.Hide(); playlist.Hide();
playButton.Enabled.Value = !disabled;
prevButton.Enabled.Value = !disabled; prevButton.Enabled.Value = !disabled;
nextButton.Enabled.Value = !disabled; nextButton.Enabled.Value = !disabled;
playlistButton.Enabled.Value = !disabled; playlistButton.Enabled.Value = !disabled;

View File

@ -55,7 +55,7 @@ namespace osu.Game.Overlays.Notifications
set set
{ {
title = value; title = value;
if (titleText != null) titleText.Text = title.ToUpper(); if (titleText != null) titleText.Text = title.ToUpperInvariant();
} }
} }
@ -101,7 +101,7 @@ namespace osu.Game.Overlays.Notifications
{ {
titleText = new OsuSpriteText titleText = new OsuSpriteText
{ {
Text = title.ToUpper(), Text = title.ToUpperInvariant(),
Font = @"Exo2.0-Black", Font = @"Exo2.0-Black",
}, },
countText = new OsuSpriteText countText = new OsuSpriteText
@ -154,7 +154,7 @@ namespace osu.Game.Overlays.Notifications
public string Text public string Text
{ {
get { return text.Text; } get { return text.Text; }
set { text.Text = value.ToUpper(); } set { text.Text = value.ToUpperInvariant(); }
} }
} }

View File

@ -176,9 +176,9 @@ namespace osu.Game.Overlays
{ {
Schedule(() => Schedule(() =>
{ {
textLine1.Text = description.Name.ToUpper(); textLine1.Text = description.Name.ToUpperInvariant();
textLine2.Text = description.Value; textLine2.Text = description.Value;
textLine3.Text = description.Shortcut.ToUpper(); textLine3.Text = description.Shortcut.ToUpperInvariant();
if (string.IsNullOrEmpty(textLine3.Text)) if (string.IsNullOrEmpty(textLine3.Text))
textLine3.Text = "NO KEY BOUND"; textLine3.Text = "NO KEY BOUND";

View File

@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Settings
{ {
new OsuSpriteText new OsuSpriteText
{ {
Text = Header.ToUpper(), Text = Header.ToUpperInvariant(),
Margin = new MarginPadding { Bottom = 10, Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }, Margin = new MarginPadding { Bottom = 10, Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS },
Font = @"Exo2.0-Black", Font = @"Exo2.0-Black",
}, },

View File

@ -195,7 +195,7 @@ namespace osu.Game.Overlays
TabContainer.AutoSizeAxes |= Axes.X; TabContainer.AutoSizeAxes |= Axes.X;
TabContainer.Anchor |= Anchor.x1; TabContainer.Anchor |= Anchor.x1;
TabContainer.Origin |= Anchor.x1; TabContainer.Origin |= Anchor.x1;
Add(bottom = new Box AddInternal(bottom = new Box
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 1, Height = 1,

View File

@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Judgements
Child = new SkinnableDrawable($"Play/{Judgement.Result}", _ => JudgementText = new OsuSpriteText Child = new SkinnableDrawable($"Play/{Judgement.Result}", _ => JudgementText = new OsuSpriteText
{ {
Text = Judgement.Result.GetDescription().ToUpper(), Text = Judgement.Result.GetDescription().ToUpperInvariant(),
Font = @"Venera", Font = @"Venera",
Colour = judgementColour(Judgement.Result), Colour = judgementColour(Judgement.Result),
Scale = new Vector2(0.85f, 1), Scale = new Vector2(0.85f, 1),

View File

@ -197,10 +197,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
var bank = (LegacyBeatmapDecoder.LegacySampleBank)int.Parse(split[0]); var bank = (LegacyBeatmapDecoder.LegacySampleBank)int.Parse(split[0]);
var addbank = (LegacyBeatmapDecoder.LegacySampleBank)int.Parse(split[1]); var addbank = (LegacyBeatmapDecoder.LegacySampleBank)int.Parse(split[1]);
string stringBank = bank.ToString().ToLower(); string stringBank = bank.ToString().ToLowerInvariant();
if (stringBank == @"none") if (stringBank == @"none")
stringBank = null; stringBank = null;
string stringAddBank = addbank.ToString().ToLower(); string stringAddBank = addbank.ToString().ToLowerInvariant();
if (stringAddBank == @"none") if (stringAddBank == @"none")
stringAddBank = null; stringAddBank = null;

View File

@ -25,5 +25,7 @@ namespace osu.Game.Rulesets
public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this); public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this);
public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo;
public override string ToString() => $"{Name} ({ShortName}) ID: {ID}";
} }
} }

View File

@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit.Menus
TabContainer.AutoSizeAxes = Axes.X; TabContainer.AutoSizeAxes = Axes.X;
TabContainer.Padding = new MarginPadding(); TabContainer.Padding = new MarginPadding();
Add(new Box AddInternal(new Box
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,

View File

@ -0,0 +1,137 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Screens.Edit.Screens.Setup.Components.LabelledComponents
{
public class LabelledTextBox : CompositeDrawable
{
private const float label_container_width = 150;
private const float corner_radius = 15;
private const float default_height = 40;
private const float default_label_left_padding = 15;
private const float default_label_top_padding = 12;
private const float default_label_text_size = 16;
public event TextBox.OnCommitHandler OnCommit;
public bool ReadOnly
{
get => textBox.ReadOnly;
set => textBox.ReadOnly = value;
}
public string LabelText
{
get => label.Text;
set => label.Text = value;
}
public float LabelTextSize
{
get => label.TextSize;
set => label.TextSize = value;
}
public string PlaceholderText
{
get => textBox.PlaceholderText;
set => textBox.PlaceholderText = value;
}
public string Text
{
get => textBox.Text;
set => textBox.Text = value;
}
public Color4 LabelTextColour
{
get => label.Colour;
set => label.Colour = value;
}
public Color4 BackgroundColour
{
get => content.Colour;
set => content.Colour = value;
}
private readonly OsuTextBox textBox;
private readonly Container content;
private readonly OsuSpriteText label;
public LabelledTextBox()
{
RelativeSizeAxes = Axes.X;
Height = default_height;
CornerRadius = corner_radius;
Masking = true;
InternalChild = new Container
{
RelativeSizeAxes = Axes.Both,
CornerRadius = corner_radius,
Masking = true,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.FromHex("1c2125"),
},
new GridContainer
{
RelativeSizeAxes = Axes.X,
Height = default_height,
Content = new[]
{
new Drawable[]
{
label = new OsuSpriteText
{
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft,
Padding = new MarginPadding { Left = default_label_left_padding, Top = default_label_top_padding },
Colour = Color4.White,
TextSize = default_label_text_size,
Font = @"Exo2.0-Bold",
},
textBox = new OsuTextBox
{
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft,
RelativeSizeAxes = Axes.Both,
Height = 1,
CornerRadius = corner_radius,
},
},
},
ColumnDimensions = new[]
{
new Dimension(GridSizeMode.Absolute, label_container_width),
new Dimension()
}
}
}
};
textBox.OnCommit += OnCommit;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
textBox.BorderColour = colours.Blue;
}
}
}

View File

@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi
}, },
}; };
breadcrumbs.Current.ValueChanged += s => screenType.Text = ((MultiplayerScreen)s).Type.ToLower(); breadcrumbs.Current.ValueChanged += s => screenType.Text = ((MultiplayerScreen)s).Type.ToLowerInvariant();
breadcrumbs.Current.TriggerChange(); breadcrumbs.Current.TriggerChange();
} }

View File

@ -28,7 +28,7 @@ namespace osu.Game.Screens.Play.Break
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Text = "current progress".ToUpper(), Text = "current progress".ToUpperInvariant(),
TextSize = 15, TextSize = 15,
Font = "Exo2.0-Black", Font = "Exo2.0-Black",
}, },

View File

@ -139,7 +139,7 @@ namespace osu.Game.Screens.Play
adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
adjustableClock.Seek(AllowLeadIn adjustableClock.Seek(AllowLeadIn
? Math.Min(RulesetContainer.GameplayStartTime, beatmap.HitObjects.First().StartTime - beatmap.BeatmapInfo.AudioLeadIn) ? Math.Min(0, RulesetContainer.GameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn)
: RulesetContainer.GameplayStartTime); : RulesetContainer.GameplayStartTime);
adjustableClock.ProcessFrame(); adjustableClock.ProcessFrame();
@ -278,6 +278,8 @@ namespace osu.Game.Screens.Play
ScoreProcessor.PopulateScore(score); ScoreProcessor.PopulateScore(score);
score.User = RulesetContainer.Replay?.User ?? api.LocalUser.Value; score.User = RulesetContainer.Replay?.User ?? api.LocalUser.Value;
Push(new Results(score)); Push(new Results(score));
onCompletionEvent = null;
}); });
} }
} }
@ -340,6 +342,13 @@ namespace osu.Game.Screens.Play
protected override bool OnExiting(Screen next) protected override bool OnExiting(Screen next)
{ {
if (onCompletionEvent != null)
{
// Proceed to result screen if beatmap already finished playing
onCompletionEvent.RunTask();
return true;
}
if ((!AllowPause || HasFailed || !ValidForResume || pauseContainer?.IsPaused != false || RulesetContainer?.HasReplayLoaded != false) && (!pauseContainer?.IsResuming ?? true)) if ((!AllowPause || HasFailed || !ValidForResume || pauseContainer?.IsPaused != false || RulesetContainer?.HasReplayLoaded != false) && (!pauseContainer?.IsResuming ?? true))
{ {
// In the case of replays, we may have changed the playback rate. // In the case of replays, we may have changed the playback rate.

View File

@ -6,8 +6,6 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.EventArgs;
using osu.Framework.Input.States;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Framework.Threading; using osu.Framework.Threading;
@ -123,23 +121,9 @@ namespace osu.Game.Screens.Play
logo.Delay(resuming ? 0 : 500).MoveToOffset(new Vector2(0, -0.24f), 500, Easing.InOutExpo); logo.Delay(resuming ? 0 : 500).MoveToOffset(new Vector2(0, -0.24f), 500, Easing.InOutExpo);
} }
private bool weHandledMouseDown;
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
weHandledMouseDown = true;
return base.OnMouseDown(state, args);
}
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
{
weHandledMouseDown = false;
return base.OnMouseUp(state, args);
}
private ScheduledDelegate pushDebounce; private ScheduledDelegate pushDebounce;
private bool readyForPush => player.LoadState == LoadState.Ready && IsHovered && (!GetContainingInputManager().CurrentState.Mouse.HasAnyButtonPressed || weHandledMouseDown); private bool readyForPush => player.LoadState == LoadState.Ready && IsHovered && GetContainingInputManager()?.DraggedDrawable == null;
private void pushWhenLoaded() private void pushWhenLoaded()
{ {

View File

@ -94,7 +94,7 @@ namespace osu.Game.Screens.Play.PlayerSettings
{ {
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Text = Title.ToUpper(), Text = Title.ToUpperInvariant(),
TextSize = 17, TextSize = 17,
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
Margin = new MarginPadding { Left = 10 }, Margin = new MarginPadding { Left = 10 },

View File

@ -4,6 +4,8 @@
using System; using System;
using osu.Framework; using osu.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Threading; using osu.Framework.Threading;
@ -214,17 +216,21 @@ namespace osu.Game.Screens.Play
private Box background; private Box background;
private AspectContainer aspect; private AspectContainer aspect;
private SampleChannel sampleConfirm;
public Button() public Button()
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours, AudioManager audio)
{ {
colourNormal = colours.Yellow; colourNormal = colours.Yellow;
colourHover = colours.YellowDark; colourHover = colours.YellowDark;
sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection");
Children = new Drawable[] Children = new Drawable[]
{ {
background = new Box background = new Box
@ -311,6 +317,8 @@ namespace osu.Game.Screens.Play
if (!Enabled) if (!Enabled)
return false; return false;
sampleConfirm.Play();
box.FlashColour(Color4.White, 500, Easing.OutQuint); box.FlashColour(Color4.White, 500, Easing.OutQuint);
aspect.ScaleTo(1.2f, 2000, Easing.OutQuint); aspect.ScaleTo(1.2f, 2000, Easing.OutQuint);

View File

@ -330,13 +330,13 @@ namespace osu.Game.Screens.Select
private FilterCriteria activeCriteria = new FilterCriteria(); private FilterCriteria activeCriteria = new FilterCriteria();
protected ScheduledDelegate FilterTask; protected ScheduledDelegate PendingFilter;
public bool AllowSelection = true; public bool AllowSelection = true;
public void FlushPendingFilterOperations() public void FlushPendingFilterOperations()
{ {
if (FilterTask?.Completed == false) if (PendingFilter?.Completed == false)
{ {
applyActiveCriteria(false, false); applyActiveCriteria(false, false);
Update(); Update();
@ -357,18 +357,18 @@ namespace osu.Game.Screens.Select
void perform() void perform()
{ {
FilterTask = null; PendingFilter = null;
root.Filter(activeCriteria); root.Filter(activeCriteria);
itemsCache.Invalidate(); itemsCache.Invalidate();
if (scroll) scrollPositionCache.Invalidate(); if (scroll) scrollPositionCache.Invalidate();
} }
FilterTask?.Cancel(); PendingFilter?.Cancel();
FilterTask = null; PendingFilter = null;
if (debounce) if (debounce)
FilterTask = Scheduler.AddDelayed(perform, 250); PendingFilter = Scheduler.AddDelayed(perform, 250);
else else
perform(); perform();
} }

View File

@ -79,8 +79,13 @@ namespace osu.Game.Screens.Select.Carousel
public override void Filter(FilterCriteria criteria) public override void Filter(FilterCriteria criteria)
{ {
base.Filter(criteria); base.Filter(criteria);
InternalChildren.Sort((x, y) => x.CompareTo(criteria, y));
InternalChildren.ForEach(c => c.Filter(criteria)); var children = new List<CarouselItem>(InternalChildren);
children.Sort((x, y) => x.CompareTo(criteria, y));
children.ForEach(c => c.Filter(criteria));
InternalChildren = children;
} }
protected virtual void ChildItemStateChanged(CarouselItem item, CarouselItemState value) protected virtual void ChildItemStateChanged(CarouselItem item, CarouselItemState value)

View File

@ -182,7 +182,7 @@ namespace osu.Game.Screens.Select
showConverted.ValueChanged += val => updateCriteria(); showConverted.ValueChanged += val => updateCriteria();
ruleset.BindTo(parentRuleset); ruleset.BindTo(parentRuleset);
ruleset.BindValueChanged(val => updateCriteria(), true); ruleset.BindValueChanged(_ => updateCriteria(), true);
} }
private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria());

View File

@ -12,6 +12,7 @@ using osu.Framework.Audio.Track;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using osu.Framework.Input.EventArgs; using osu.Framework.Input.EventArgs;
using osu.Framework.Input.States; using osu.Framework.Input.States;
using osu.Framework.Screens; using osu.Framework.Screens;
@ -199,10 +200,6 @@ namespace osu.Game.Screens.Select
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours)
{ {
// manual binding to parent ruleset to allow for delayed load in the incoming direction.
base.Ruleset.ValueChanged += r => updateSelectedBeatmap(beatmapNoDebounce);
Ruleset.ValueChanged += r => base.Ruleset.Value = r;
if (Footer != null) if (Footer != null)
{ {
Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2); Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2);
@ -225,15 +222,6 @@ namespace osu.Game.Screens.Select
sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand"); sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand");
Carousel.BeatmapSets = this.beatmaps.GetAllUsableBeatmapSetsEnumerable(); Carousel.BeatmapSets = this.beatmaps.GetAllUsableBeatmapSetsEnumerable();
Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true);
Beatmap.BindValueChanged(workingBeatmapChanged);
}
protected override void LoadComplete()
{
base.LoadComplete();
base.Ruleset.ValueChanged += r => updateSelectedBeatmap(beatmapNoDebounce);
} }
public void Edit(BeatmapInfo beatmap) public void Edit(BeatmapInfo beatmap)
@ -296,61 +284,88 @@ namespace osu.Game.Screens.Select
private BeatmapInfo beatmapNoDebounce; private BeatmapInfo beatmapNoDebounce;
private RulesetInfo rulesetNoDebounce; private RulesetInfo rulesetNoDebounce;
private void updateSelectedBeatmap(BeatmapInfo beatmap)
{
if (beatmap?.Equals(beatmapNoDebounce) == true)
return;
beatmapNoDebounce = beatmap;
performUpdateSelected();
}
private void updateSelectedRuleset(RulesetInfo ruleset)
{
if (ruleset?.Equals(rulesetNoDebounce) == true)
return;
rulesetNoDebounce = ruleset;
performUpdateSelected();
}
/// <summary> /// <summary>
/// selection has been changed as the result of a user interaction. /// selection has been changed as the result of a user interaction.
/// </summary> /// </summary>
private void updateSelectedBeatmap(BeatmapInfo beatmap) private void performUpdateSelected()
{ {
var ruleset = base.Ruleset.Value; var beatmap = beatmapNoDebounce;
var ruleset = rulesetNoDebounce;
void performLoad() void run()
{ {
Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}");
WorkingBeatmap working = Beatmap.Value; WorkingBeatmap working = Beatmap.Value;
bool preview = false; bool preview = false;
if (ruleset?.Equals(Ruleset.Value) == false)
{
Logger.Log($"ruleset changed from \"{Ruleset.Value}\" to \"{ruleset}\"");
Ruleset.Value = ruleset;
// force a filter before attempting to change the beatmap.
// we may still be in the wrong ruleset as there is a debounce delay on ruleset changes.
Carousel.Filter(null, false);
// Filtering only completes after the carousel runs Update.
// If we also have a pending beatmap change we should delay it one frame.
selectionChangedDebounce = Schedule(run);
return;
}
// We may be arriving here due to another component changing the bindable Beatmap. // We may be arriving here due to another component changing the bindable Beatmap.
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again. // In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
if (beatmap?.Equals(Beatmap.Value.BeatmapInfo) != true) if (!Equals(beatmap, Beatmap.Value.BeatmapInfo))
{ {
Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\"");
preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID; preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID;
working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value); working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value);
}
if (beatmap != null)
working.Mods.Value = Enumerable.Empty<Mod>();
Beatmap.Value = working;
Ruleset.Value = ruleset;
ensurePlayingSelected(preview);
UpdateBeatmap(Beatmap.Value);
}
if (beatmap?.Equals(beatmapNoDebounce) == true && ruleset?.Equals(rulesetNoDebounce) == true)
return;
selectionChangedDebounce?.Cancel();
beatmapNoDebounce = beatmap;
rulesetNoDebounce = ruleset;
if (beatmap == null)
performLoad();
else
{ {
if (beatmap.BeatmapSetInfoID == beatmapNoDebounce?.BeatmapSetInfoID) if (beatmap.BeatmapSetInfoID == beatmapNoDebounce?.BeatmapSetInfoID)
sampleChangeDifficulty.Play(); sampleChangeDifficulty.Play();
else else
sampleChangeBeatmap.Play(); sampleChangeBeatmap.Play();
if (beatmap == Beatmap.Value.BeatmapInfo)
performLoad();
else
selectionChangedDebounce = Scheduler.AddDelayed(performLoad, 200);
} }
} }
working.Mods.Value = Enumerable.Empty<Mod>();
Beatmap.Value = working;
ensurePlayingSelected(preview);
UpdateBeatmap(Beatmap.Value);
}
selectionChangedDebounce?.Cancel();
if (beatmap == null)
run();
else
selectionChangedDebounce = Scheduler.AddDelayed(run, 200);
}
private void triggerRandom() private void triggerRandom()
{ {
if (GetContainingInputManager().CurrentState.Keyboard.ShiftPressed) if (GetContainingInputManager().CurrentState.Keyboard.ShiftPressed)
@ -464,6 +479,8 @@ namespace osu.Game.Screens.Select
/// <param name="beatmap">The working beatmap.</param> /// <param name="beatmap">The working beatmap.</param>
protected virtual void UpdateBeatmap(WorkingBeatmap beatmap) protected virtual void UpdateBeatmap(WorkingBeatmap beatmap)
{ {
Logger.Log($"working beatmap updated to {beatmap}");
if (Background is BackgroundScreenBeatmap backgroundModeBeatmap) if (Background is BackgroundScreenBeatmap backgroundModeBeatmap)
{ {
backgroundModeBeatmap.Beatmap = beatmap; backgroundModeBeatmap.Beatmap = beatmap;
@ -495,6 +512,17 @@ namespace osu.Game.Screens.Select
private void carouselBeatmapsLoaded() private void carouselBeatmapsLoaded()
{ {
if (rulesetNoDebounce == null)
{
// manual binding to parent ruleset to allow for delayed load in the incoming direction.
rulesetNoDebounce = Ruleset.Value = base.Ruleset.Value;
base.Ruleset.ValueChanged += updateSelectedRuleset;
Ruleset.ValueChanged += r => base.Ruleset.Value = r;
Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true);
Beatmap.BindValueChanged(workingBeatmapChanged);
}
if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false
&& Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false)) && Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false))
return; return;
@ -503,7 +531,7 @@ namespace osu.Game.Screens.Select
{ {
// in the case random selection failed, we want to trigger selectionChanged // in the case random selection failed, we want to trigger selectionChanged
// to show the dummy beatmap (we have nothing else to display). // to show the dummy beatmap (we have nothing else to display).
updateSelectedBeatmap(null); performUpdateSelected();
} }
} }

View File

@ -323,7 +323,7 @@ namespace osu.Game.Screens.Tournament
if (string.IsNullOrEmpty(line)) if (string.IsNullOrEmpty(line))
continue; continue;
if (line.ToUpper().StartsWith("GROUP")) if (line.ToUpperInvariant().StartsWith("GROUP"))
continue; continue;
// ReSharper disable once AccessToModifiedClosure // ReSharper disable once AccessToModifiedClosure

View File

@ -51,7 +51,7 @@ namespace osu.Game.Screens.Tournament
Position = new Vector2(0, 7f), Position = new Vector2(0, 7f),
Text = $"GROUP {name.ToUpper()}", Text = $"GROUP {name.ToUpperInvariant()}",
TextSize = 8f, TextSize = 8f,
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
Colour = new Color4(255, 204, 34, 255), Colour = new Color4(255, 204, 34, 255),
@ -161,7 +161,7 @@ namespace osu.Game.Screens.Tournament
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Text = team.Acronym.ToUpper(), Text = team.Acronym.ToUpperInvariant(),
TextSize = 10f, TextSize = 10f,
Font = @"Exo2.0-Bold" Font = @"Exo2.0-Bold"
} }

View File

@ -62,8 +62,17 @@ namespace osu.Game.Tests.Visual
} }
if (localStorage.IsValueCreated) if (localStorage.IsValueCreated)
{
try
{
localStorage.Value.DeleteDirectory("."); localStorage.Value.DeleteDirectory(".");
} }
catch
{
// we don't really care if this fails; it will just leave folders lying around from test runs.
}
}
}
protected override ITestCaseTestRunner CreateRunner() => new OsuTestCaseTestRunner(); protected override ITestCaseTestRunner CreateRunner() => new OsuTestCaseTestRunner();

View File

@ -18,8 +18,8 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="ppy.osu.Framework" Version="2018.721.0" /> <PackageReference Include="ppy.osu.Framework" Version="2018.801.1" />
<PackageReference Include="SharpCompress" Version="0.17.1" /> <PackageReference Include="SharpCompress" Version="0.22.0" />
<PackageReference Include="NUnit" Version="3.10.1" /> <PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
</ItemGroup> </ItemGroup>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>osulazer</id>
<version>0.0.0</version>
<title>osulazer</title>
<authors>ppy Pty Ltd</authors>
<owners>Dean Herbert</owners>
<projectUrl>https://osu.ppy.sh/</projectUrl>
<iconUrl>https://puu.sh/tYyXZ/9a01a5d1b0.ico</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>click the circles. to the beat.</description>
<summary>click the circles.</summary>
<releaseNotes>testing</releaseNotes>
<copyright>Copyright ppy Pty Ltd 2007-2018</copyright>
<language>en-AU</language>
</metadata>
<files>
<file src="*.exe" target="lib\net45\" exclude="**vshost**"/>
<file src="*.dll" target="lib\net45\"/>
<file src="*.config" target="lib\net45\"/>
<file src="x86\*.dll" target="lib\net45\x86\"/>
<file src="x64\*.dll" target="lib\net45\x64\"/>
</files>
</package>

View File

@ -13,9 +13,6 @@
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" />
<PackageReference Include="DeepEqual" Version="1.6.0" /> <PackageReference Include="DeepEqual" Version="1.6.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\osu.Game\Tests\VisualTestRunner.cs"> <Compile Include="..\osu.Game\Tests\VisualTestRunner.cs">