diff --git a/.idea/.idea.osu/.idea/runConfigurations/VisualTests__net461_.xml b/.idea/.idea.osu/.idea/runConfigurations/VisualTests__net461_.xml
new file mode 100644
index 0000000000..cf4bccfe60
--- /dev/null
+++ b/.idea/.idea.osu/.idea/runConfigurations/VisualTests__net461_.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.osu/.idea/runConfigurations/VisualTests__netcoreapp2_0_.xml b/.idea/.idea.osu/.idea/runConfigurations/VisualTests__netcoreapp2_0_.xml
new file mode 100644
index 0000000000..08b4e38667
--- /dev/null
+++ b/.idea/.idea.osu/.idea/runConfigurations/VisualTests__netcoreapp2_0_.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu___net461_.xml b/.idea/.idea.osu/.idea/runConfigurations/osu___net461_.xml
new file mode 100644
index 0000000000..971868a81b
--- /dev/null
+++ b/.idea/.idea.osu/.idea/runConfigurations/osu___net461_.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu___netcoreapp2_0_.xml b/.idea/.idea.osu/.idea/runConfigurations/osu___netcoreapp2_0_.xml
new file mode 100644
index 0000000000..2f5c137631
--- /dev/null
+++ b/.idea/.idea.osu/.idea/runConfigurations/osu___netcoreapp2_0_.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 8c8255db71..624e584f10 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -8,10 +8,7 @@
},
"type": "mono",
"request": "launch",
- "program": "${workspaceRoot}/osu.Desktop/bin/Debug/net461/osu!.exe",
- "args": [
- "--tests"
- ],
+ "program": "${workspaceRoot}/osu.Game.Tests/bin/Debug/net461/osu.Game.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
@@ -25,10 +22,7 @@
},
"type": "mono",
"request": "launch",
- "program": "${workspaceRoot}/osu.Desktop/bin/Release/net461/osu!.exe",
- "args": [
- "--tests"
- ],
+ "program": "${workspaceRoot}/osu.Game.Tests/bin/Debug/net461/osu.Game.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
@@ -69,8 +63,7 @@
"request": "launch",
"program": "dotnet",
"args": [
- "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp2.0/osu!.dll",
- "--tests"
+ "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.0/osu.Game.Tests.dll"
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, dotnet)",
@@ -83,8 +76,7 @@
"request": "launch",
"program": "dotnet",
"args": [
- "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp2.0/osu!.dll",
- "--tests"
+ "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.0/osu.Game.Tests.dll"
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, dotnet)",
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 20af2f68a6..0000000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,3 +0,0 @@
-// Place your settings in this file to overwrite default and user settings.
-{
-}
\ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
index 6388b54db5..4c4b70827f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -22,10 +22,6 @@ build:
project: osu.sln
parallel: true
verbosity: minimal
-test:
- assemblies:
- only:
- - 'osu.Desktop\**\*.dll'
after_build:
- cmd: inspectcode --o="inspectcodereport.xml" --projects:osu.Game* --caches-home="inspectcode" osu.sln > NUL
- cmd: NVika parsereport "inspectcodereport.xml" --treatwarningsaserrors
\ No newline at end of file
diff --git a/osu-framework b/osu-framework
index b59149e1ce..02d7a0fa47 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit b59149e1cebe28675dcd2ebd014e5793d9626c09
+Subproject commit 02d7a0fa4798d197cd08570ee48951edbb7c7860
diff --git a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj
index eab54bd10b..a18db9477a 100644
--- a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj
+++ b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj
@@ -5,10 +5,6 @@
Exe
AnyCPU
true
- ppy Pty Ltd
- ppy Pty Ltd 2007-2017
-
osu.Desktop.Deploy
- osu.Desktop.Deploy
diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs
index 25beb9a7d4..7258610f90 100644
--- a/osu.Desktop/Program.cs
+++ b/osu.Desktop/Program.cs
@@ -44,9 +44,6 @@ namespace osu.Desktop
{
switch (args.FirstOrDefault() ?? string.Empty)
{
- case "--tests":
- host.Run(new OsuTestBrowser());
- break;
default:
host.Run(new OsuGameDesktop(args));
break;
diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj
index 2262bbc515..2ad7b67842 100644
--- a/osu.Desktop/osu.Desktop.csproj
+++ b/osu.Desktop/osu.Desktop.csproj
@@ -5,19 +5,13 @@
WinExe
AnyCPU
true
- ppy Pty Ltd
click the circles. to the beat.
- ppy Pty Ltd 2007-2017
osu!
osu!lazer
osu!lazer
lazer.ico
- $(CONFIGURATIONS);VisualTests
0.0.0.0
0.0.0.0
-
- NU1701
$(DefineConstants);NET_FRAMEWORK
@@ -25,23 +19,18 @@
osu.Desktop.Program
-
- --tests
-
+
-
-
-
diff --git a/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json b/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json
new file mode 100644
index 0000000000..5098b78a42
--- /dev/null
+++ b/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json
@@ -0,0 +1,59 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "VisualTests (Debug, net461)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Catch.Tests.exe",
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Debug, msbuild)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Release, net461)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Catch.Tests.exe",
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release, msbuild)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Debug, netcoreapp2.0)",
+ "type": "coreclr",
+ "request": "launch",
+ "program": "dotnet",
+ "args": [
+ "${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Catch.Tests.dll"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Debug, dotnet)",
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Release, netcoreapp2.0)",
+ "type": "coreclr",
+ "request": "launch",
+ "program": "dotnet",
+ "args": [
+ "${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Catch.Tests.dll"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release, dotnet)",
+ "env": {},
+ "console": "internalConsole"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Catch.Tests/.vscode/tasks.json b/osu.Game.Rulesets.Catch.Tests/.vscode/tasks.json
new file mode 100644
index 0000000000..d21bb8a69a
--- /dev/null
+++ b/osu.Game.Rulesets.Catch.Tests/.vscode/tasks.json
@@ -0,0 +1,87 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Build (Debug, msbuild)",
+ "type": "shell",
+ "command": "msbuild",
+ "args": [
+ "osu.Game.Rulesets.Catch.Tests.csproj",
+ "/p:TargetFramework=net461",
+ "/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=net461",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Build (Debug, dotnet)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "--no-restore",
+ "osu.Game.Rulesets.Catch.Tests.csproj",
+ "/p:TargetFramework=netcoreapp2.0",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Build (Release, dotnet)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "--no-restore",
+ "osu.Game.Rulesets.Catch.Tests.csproj",
+ "/p:TargetFramework=netcoreapp2.0",
+ "/p:Configuration=Release",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Restore (net461)",
+ "type": "shell",
+ "command": "nuget",
+ "args": [
+ "restore"
+ ],
+ "problemMatcher": []
+ },
+ {
+ "label": "Restore (netcoreapp2.0)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "restore"
+ ],
+ "problemMatcher": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Catch/Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs
similarity index 100%
rename from osu.Game.Rulesets.Catch/Tests/CatchBeatmapConversionTest.cs
rename to osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs
diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs
new file mode 100644
index 0000000000..11a22c69f3
--- /dev/null
+++ b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs
@@ -0,0 +1,62 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Collections.Generic;
+using System.Linq;
+using osu.Game.Beatmaps;
+using osu.Game.Rulesets.Catch.Objects;
+using osu.Game.Rulesets.Catch.UI;
+using osu.Game.Rulesets.Objects.Types;
+using osu.Game.Screens.Play;
+using osu.Game.Tests.Visual;
+using OpenTK;
+
+namespace osu.Game.Rulesets.Catch.Tests
+{
+ public class TestCaseAutoJuiceStream : TestCasePlayer
+ {
+ public TestCaseAutoJuiceStream()
+ : base(new CatchRuleset())
+ {
+ }
+
+ protected override Beatmap CreateBeatmap(Ruleset ruleset)
+ {
+ var beatmap = new Beatmap
+ {
+ BeatmapInfo = new BeatmapInfo
+ {
+ BaseDifficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 },
+ Ruleset = ruleset.RulesetInfo
+ }
+ };
+
+ for (int i = 0; i < 100; i++)
+ {
+ float width = (i % 10 + 1) / 20f;
+
+ beatmap.HitObjects.Add(new JuiceStream
+ {
+ X = 0.5f - width / 2,
+ ControlPoints = new List
+ {
+ Vector2.Zero,
+ new Vector2(width * CatchPlayfield.BASE_WIDTH, 0)
+ },
+ CurveType = CurveType.Linear,
+ Distance = width * CatchPlayfield.BASE_WIDTH,
+ StartTime = i * 2000,
+ NewCombo = i % 8 == 0
+ });
+ }
+
+ return beatmap;
+ }
+
+ protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset)
+ {
+ beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
+ return base.CreatePlayer(beatmap, ruleset);
+ }
+ }
+}
diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs
similarity index 100%
rename from osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs
rename to osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs
diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs
similarity index 100%
rename from osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs
rename to osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs
diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs
similarity index 100%
rename from osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs
rename to osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs
diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs
similarity index 100%
rename from osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs
rename to osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs
diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseFruitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs
similarity index 100%
rename from osu.Game.Rulesets.Catch/Tests/TestCaseFruitObjects.cs
rename to osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs
diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseHyperdash.cs
similarity index 100%
rename from osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs
rename to osu.Game.Rulesets.Catch.Tests/TestCaseHyperdash.cs
diff --git a/osu.Game.Rulesets.Catch/Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Catch.Tests/TestCasePerformancePoints.cs
similarity index 100%
rename from osu.Game.Rulesets.Catch/Tests/TestCasePerformancePoints.cs
rename to osu.Game.Rulesets.Catch.Tests/TestCasePerformancePoints.cs
diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
new file mode 100644
index 0000000000..51c6d18f1f
--- /dev/null
+++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj
@@ -0,0 +1,10 @@
+
+
+
+ WinExe
+ netcoreapp2.0;net461
+
+
+
+
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs
index 9479c9d9b0..ed33bf7124 100644
--- a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs
+++ b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs
@@ -8,5 +8,6 @@ namespace osu.Game.Rulesets.Catch.Mods
public class CatchModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.12;
+ public override bool Ranked => true;
}
}
diff --git a/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..fed1013ae1
--- /dev/null
+++ b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Runtime.CompilerServices;
+
+// We publish our internal attributes to other sub-projects of the framework.
+// Note, that we omit visual tests as they are meant to test the framework
+// behavior "in the wild".
+
+[assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests")]
+[assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests.Dynamic")]
diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs
index f1503a14ee..244ab2b508 100644
--- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs
+++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs
@@ -108,6 +108,7 @@ namespace osu.Game.Rulesets.Catch.Replays
case BananaShower.Banana _:
case TinyDroplet _:
case Droplet _:
+ case Fruit _:
moveToNext(nestedObj);
break;
}
diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs
index 39b7ffb387..2b6a7c41f4 100644
--- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs
+++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs
@@ -30,10 +30,10 @@ namespace osu.Game.Rulesets.Catch.UI
Anchor = Anchor.TopCentre;
Origin = Anchor.TopCentre;
- ScaledContent.Anchor = Anchor.BottomLeft;
- ScaledContent.Origin = Anchor.BottomLeft;
+ base.Content.Anchor = Anchor.BottomLeft;
+ base.Content.Origin = Anchor.BottomLeft;
- ScaledContent.AddRange(new Drawable[]
+ base.Content.AddRange(new Drawable[]
{
explodingFruitContainer = new Container
{
@@ -57,7 +57,6 @@ namespace osu.Game.Rulesets.Catch.UI
public override void Add(DrawableHitObject h)
{
- h.Depth = (float)h.HitObject.StartTime;
h.OnJudgement += onJudgement;
base.Add(h);
diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
index aa4d06cf64..883cac67d1 100644
--- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
+++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
@@ -5,25 +5,9 @@
Library
AnyCPU
true
- ppy Pty Ltd
- 1.0.0.0
- ppy Pty Ltd 2007-2017
- osu.Game.Rulesets.Catch
catch the fruit. to the beat.
- osu.Game.Rulesets.Catch
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json b/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json
new file mode 100644
index 0000000000..c71178059b
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json
@@ -0,0 +1,59 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "VisualTests (Debug, net461)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Mania.Tests.exe",
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Debug, msbuild)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Release, net461)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Mania.Tests.exe",
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release, msbuild)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Debug, netcoreapp2.0)",
+ "type": "coreclr",
+ "request": "launch",
+ "program": "dotnet",
+ "args": [
+ "${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Mania.Tests.dll"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Debug, dotnet)",
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Release, netcoreapp2.0)",
+ "type": "coreclr",
+ "request": "launch",
+ "program": "dotnet",
+ "args": [
+ "${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Mania.Tests.dll"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release, dotnet)",
+ "env": {},
+ "console": "internalConsole"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/.vscode/tasks.json b/osu.Game.Rulesets.Mania.Tests/.vscode/tasks.json
new file mode 100644
index 0000000000..781e89598f
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/.vscode/tasks.json
@@ -0,0 +1,87 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Build (Debug, msbuild)",
+ "type": "shell",
+ "command": "msbuild",
+ "args": [
+ "osu.Game.Rulesets.Mania.Tests.csproj",
+ "/p:TargetFramework=net461",
+ "/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=net461",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Build (Debug, dotnet)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "--no-restore",
+ "osu.Game.Rulesets.Mania.Tests.csproj",
+ "/p:TargetFramework=netcoreapp2.0",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Build (Release, dotnet)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "--no-restore",
+ "osu.Game.Rulesets.Mania.Tests.csproj",
+ "/p:TargetFramework=netcoreapp2.0",
+ "/p:Configuration=Release",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Restore (net461)",
+ "type": "shell",
+ "command": "nuget",
+ "args": [
+ "restore"
+ ],
+ "problemMatcher": []
+ },
+ {
+ "label": "Restore (netcoreapp2.0)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "restore"
+ ],
+ "problemMatcher": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania/Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs
similarity index 100%
rename from osu.Game.Rulesets.Mania/Tests/ManiaBeatmapConversionTest.cs
rename to osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs
diff --git a/osu.Game.Rulesets.Mania/Tests/TestCaseAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs
similarity index 100%
rename from osu.Game.Rulesets.Mania/Tests/TestCaseAutoGeneration.cs
rename to osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs
diff --git a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs
similarity index 100%
rename from osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs
rename to osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs
diff --git a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs
similarity index 100%
rename from osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs
rename to osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs
diff --git a/osu.Game.Rulesets.Mania/Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Mania.Tests/TestCasePerformancePoints.cs
similarity index 100%
rename from osu.Game.Rulesets.Mania/Tests/TestCasePerformancePoints.cs
rename to osu.Game.Rulesets.Mania.Tests/TestCasePerformancePoints.cs
diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
new file mode 100644
index 0000000000..187d5e47b9
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
@@ -0,0 +1,10 @@
+
+
+
+ WinExe
+ netcoreapp2.0;net461
+
+
+
+
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..515aeab9df
--- /dev/null
+++ b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Runtime.CompilerServices;
+
+// We publish our internal attributes to other sub-projects of the framework.
+// Note, that we omit visual tests as they are meant to test the framework
+// behavior "in the wild".
+
+[assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests")]
+[assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests.Dynamic")]
diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs
index 21f00c003b..15c9a83b78 100644
--- a/osu.Game.Rulesets.Mania/UI/Column.cs
+++ b/osu.Game.Rulesets.Mania/UI/Column.cs
@@ -205,7 +205,6 @@ namespace osu.Game.Rulesets.Mania.UI
/// The DrawableHitObject to add.
public override void Add(DrawableHitObject hitObject)
{
- hitObject.Depth = (float)hitObject.HitObject.StartTime;
hitObject.AccentColour = AccentColour;
hitObject.OnJudgement += OnJudgement;
@@ -263,21 +262,13 @@ namespace osu.Game.Rulesets.Mania.UI
public bool OnPressed(ManiaAction action)
{
- // Play the sounds of the next hitobject
- if (HitObjects.AliveObjects.Any())
- {
- // If there are alive hitobjects, we can abuse the fact that AliveObjects are sorted by time (see: Add())
- HitObjects.AliveObjects.First().PlaySamples();
- }
- else
- {
- // If not, we do a slow search - we might want to do a BinarySearch here if this becomes problematic
- // We fallback to LastOrDefault() if we're beyond the last note in the map
- var hitObject = HitObjects.Objects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current) ?? HitObjects.Objects.LastOrDefault();
- hitObject?.PlaySamples();
- }
+ if (action != Action)
+ return false;
- return false;
+ var hitObject = HitObjects.Objects.LastOrDefault(h => h.HitObject.StartTime > Time.Current) ?? HitObjects.Objects.FirstOrDefault();
+ hitObject?.PlaySamples();
+
+ return true;
}
public bool OnReleased(ManiaAction action) => false;
diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
index a1f08e9299..a086da0565 100644
--- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
+++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
@@ -5,25 +5,9 @@
Library
AnyCPU
true
- ppy Pty Ltd
- 1.0.0.0
- ppy Pty Ltd 2007-2017
- osu.Game.Rulests.Mania
smash the keys. to the beat.
- osu.Game.Rulests.Mania
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json b/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json
new file mode 100644
index 0000000000..24431eb8de
--- /dev/null
+++ b/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json
@@ -0,0 +1,59 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "VisualTests (Debug, net461)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Osu.Tests.exe",
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Debug, msbuild)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Release, net461)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Osu.Tests.exe",
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release, msbuild)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Debug, netcoreapp2.0)",
+ "type": "coreclr",
+ "request": "launch",
+ "program": "dotnet",
+ "args": [
+ "${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Osu.Tests.dll"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Debug, dotnet)",
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Release, netcoreapp2.0)",
+ "type": "coreclr",
+ "request": "launch",
+ "program": "dotnet",
+ "args": [
+ "${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Osu.Tests.dll"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release, dotnet)",
+ "env": {},
+ "console": "internalConsole"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Osu.Tests/.vscode/tasks.json b/osu.Game.Rulesets.Osu.Tests/.vscode/tasks.json
new file mode 100644
index 0000000000..734e15353b
--- /dev/null
+++ b/osu.Game.Rulesets.Osu.Tests/.vscode/tasks.json
@@ -0,0 +1,87 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Build (Debug, msbuild)",
+ "type": "shell",
+ "command": "msbuild",
+ "args": [
+ "osu.Game.Rulesets.Osu.Tests.csproj",
+ "/p:TargetFramework=net461",
+ "/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=net461",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Build (Debug, dotnet)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "--no-restore",
+ "osu.Game.Rulesets.Osu.Tests.csproj",
+ "/p:TargetFramework=netcoreapp2.0",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Build (Release, dotnet)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "--no-restore",
+ "osu.Game.Rulesets.Osu.Tests.csproj",
+ "/p:TargetFramework=netcoreapp2.0",
+ "/p:Configuration=Release",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Restore (net461)",
+ "type": "shell",
+ "command": "nuget",
+ "args": [
+ "restore"
+ ],
+ "problemMatcher": []
+ },
+ {
+ "label": "Restore (netcoreapp2.0)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "restore"
+ ],
+ "problemMatcher": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Osu/Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/OsuBeatmapConversionTest.cs
rename to osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseEditor.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCaseEditor.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCaseGameplayCursor.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCaseHitCircle.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCaseHitCircleHidden.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Osu.Tests/TestCasePerformancePoints.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCasePerformancePoints.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCasePerformancePoints.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCaseSlider.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCaseSliderHidden.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCaseSpinner.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs
diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs
similarity index 100%
rename from osu.Game.Rulesets.Osu/Tests/TestCaseSpinnerHidden.cs
rename to osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs
diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
new file mode 100644
index 0000000000..b2b524a71c
--- /dev/null
+++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj
@@ -0,0 +1,10 @@
+
+
+
+ WinExe
+ netcoreapp2.0;net461
+
+
+
+
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/HitCircleMask.cs b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/HitCircleMask.cs
index b48dd73bb5..89a7686581 100644
--- a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/HitCircleMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/HitCircleMask.cs
@@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
Size = hitCircle.Size;
Scale = hitCircle.Scale;
+ CornerRadius = Size.X / 2;
+
AddInternal(new RingPiece());
hitCircle.HitObject.PositionChanged += _ => Position = hitCircle.Position;
diff --git a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderCircleMask.cs b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderCircleMask.cs
index 586b516a11..96ff14205e 100644
--- a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderCircleMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderCircleMask.cs
@@ -38,6 +38,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
Scale = slider.HeadCircle.Scale;
AddInternal(new RingPiece());
+
+ Select();
}
[BackgroundDependencyLoader]
@@ -52,5 +54,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
RelativeAnchorPosition = hitObject.RelativeAnchorPosition;
}
+
+ // Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input.
+ public override bool HandleMouseInput => false;
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderMask.cs b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderMask.cs
index 53f02617cd..629bce1847 100644
--- a/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderMask.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Layers/Selection/Overlays/SliderMask.cs
@@ -3,6 +3,7 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
+using osu.Framework.Graphics.Primitives;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Objects;
@@ -59,5 +60,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
}
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => body.ReceiveMouseInputAt(screenSpacePos);
+
+ public override Vector2 SelectionPoint => ToScreenSpace(OriginPosition);
+ public override Quad SelectionQuad => body.PathDrawQuad;
}
}
diff --git a/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs b/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs
index 5f232b1889..46a3d8575f 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs
@@ -8,5 +8,6 @@ namespace osu.Game.Rulesets.Osu.Edit
public class OsuEditPlayfield : OsuPlayfield
{
protected override bool ProxyApproachCircles => false;
+ protected override bool DisplayJudgements => false;
}
}
diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs
index 42fe95356d..a06390a4ea 100644
--- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs
+++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{
public class OsuModAutoplay : ModAutoplay
{
- public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray();
+ public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
protected override Score CreateReplayScore(Beatmap beatmap)
{
diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs
index 74c3585d3d..29bf3e248d 100644
--- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs
+++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs
@@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModHardRock : ModHardRock, IApplicableToHitObject
{
public override double ScoreMultiplier => 1.06;
+ public override bool Ranked => true;
public void ApplyToHitObject(OsuHitObject hitObject)
{
diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs
index f94ee484fc..07128cb8ff 100644
--- a/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs
+++ b/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs
@@ -9,6 +9,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{
public class OsuModNoFail : ModNoFail
{
- public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
+ public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
}
}
diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs
index c9def8c8cf..ed774f0d0a 100644
--- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs
+++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs
@@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModRelax : ModRelax
{
public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things.";
- public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
+ public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
}
}
diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs
index 797e0af0ad..6c15095bfe 100644
--- a/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs
+++ b/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs
@@ -9,6 +9,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{
public class OsuModSuddenDeath : ModSuddenDeath
{
- public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
+ public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index 3872821b96..5373926138 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -10,7 +10,6 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Judgements;
-using osu.Framework.Graphics.Primitives;
using osu.Game.Configuration;
using osu.Game.Rulesets.Scoring;
using OpenTK.Graphics;
@@ -177,8 +176,5 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public Drawable ProxiedLayer => HeadCircle.ApproachCircle;
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => Body.ReceiveMouseInputAt(screenSpacePos);
-
- public override Vector2 SelectionPoint => ToScreenSpace(OriginPosition);
- public override Quad SelectionQuad => Body.PathDrawQuad;
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
index c00c30ced9..f64db6ba9e 100644
--- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
@@ -7,10 +7,11 @@ using osu.Game.Rulesets.Objects;
using OpenTK;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Beatmaps.ControlPoints;
+using osu.Game.Rulesets.Edit.Types;
namespace osu.Game.Rulesets.Osu.Objects
{
- public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition
+ public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasEditablePosition
{
public const double OBJECT_RADIUS = 64;
diff --git a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..ea2c2c6729
--- /dev/null
+++ b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Runtime.CompilerServices;
+
+// We publish our internal attributes to other sub-projects of the framework.
+// Note, that we omit visual tests as they are meant to test the framework
+// behavior "in the wild".
+
+[assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests")]
+[assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests.Dynamic")]
diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs
index 7aa4108428..699cdf75a2 100644
--- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs
+++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs
@@ -92,17 +92,17 @@ namespace osu.Game.Rulesets.Osu.Replays
if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Miss) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50)
{
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
- if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
+ if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Miss), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
}
else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50)
{
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
}
- else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50)
+ else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Good) > endTime + h.HitWindows.HalfWindowFor(HitResult.Good) + 50)
{
- if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
- if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
+ if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new OsuReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Good), new Vector2(prev.StackedEndPosition.X, prev.StackedEndPosition.Y)));
+ if (!(h is Spinner)) AddFrameToReplay(new OsuReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Good), new Vector2(h.StackedPosition.X, h.StackedPosition.Y)));
}
}
diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs
index 0a61b0f199..69154a1d0c 100644
--- a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs
+++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs
@@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Replays
{
new ReplayState
{
- Mouse = new ReplayMouseState(ToScreenSpace(Position ?? Vector2.Zero)),
+ Mouse = new ReplayMouseState(GamefieldToScreenSpace(Position ?? Vector2.Zero)),
PressedActions = CurrentFrame.Actions
}
};
diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
index 98a8096678..9010f66acb 100644
--- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
+++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
@@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Osu.UI
// Todo: This should not be a thing, but is currently required for the editor
// https://github.com/ppy/osu-framework/issues/1283
protected virtual bool ProxyApproachCircles => true;
+ protected virtual bool DisplayJudgements => true;
public static readonly Vector2 BASE_SIZE = new Vector2(512, 384);
@@ -55,8 +56,6 @@ namespace osu.Game.Rulesets.Osu.UI
public override void Add(DrawableHitObject h)
{
- h.Depth = (float)h.HitObject.StartTime;
-
h.OnJudgement += onJudgement;
var c = h as IDrawableHitObjectWithProxiedApproach;
@@ -75,7 +74,7 @@ namespace osu.Game.Rulesets.Osu.UI
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)
{
- if (!judgedObject.DisplayJudgement)
+ if (!judgedObject.DisplayJudgement || !DisplayJudgements)
return;
DrawableOsuJudgement explosion = new DrawableOsuJudgement(judgement, judgedObject)
diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
index a58d3b6795..b0ca314551 100644
--- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
+++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
@@ -5,25 +5,9 @@
Library
AnyCPU
true
- ppy Pty Ltd
- 1.0.0.0
- ppy Pty Ltd 2007-2017
- osu.Game.Rulesets.Osu
click the circles. to the beat.
- osu.Game.Rulesets.Osu
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json b/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json
new file mode 100644
index 0000000000..caa90c32ce
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json
@@ -0,0 +1,59 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "VisualTests (Debug, net461)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Taiko.Tests.exe",
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Debug, msbuild)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Release, net461)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Taiko.Tests.exe",
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release, msbuild)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Debug, netcoreapp2.0)",
+ "type": "coreclr",
+ "request": "launch",
+ "program": "dotnet",
+ "args": [
+ "${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Taiko.Tests.dll"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Debug, dotnet)",
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "VisualTests (Release, netcoreapp2.0)",
+ "type": "coreclr",
+ "request": "launch",
+ "program": "dotnet",
+ "args": [
+ "${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Taiko.Tests.dll"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release, dotnet)",
+ "env": {},
+ "console": "internalConsole"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko.Tests/.vscode/tasks.json b/osu.Game.Rulesets.Taiko.Tests/.vscode/tasks.json
new file mode 100644
index 0000000000..13044e1ccb
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko.Tests/.vscode/tasks.json
@@ -0,0 +1,87 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Build (Debug, msbuild)",
+ "type": "shell",
+ "command": "msbuild",
+ "args": [
+ "osu.Game.Rulesets.Taiko.Tests.csproj",
+ "/p:TargetFramework=net461",
+ "/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=net461",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Build (Debug, dotnet)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "--no-restore",
+ "osu.Game.Rulesets.Taiko.Tests.csproj",
+ "/p:TargetFramework=netcoreapp2.0",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Build (Release, dotnet)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "build",
+ "--no-restore",
+ "osu.Game.Rulesets.Taiko.Tests.csproj",
+ "/p:TargetFramework=netcoreapp2.0",
+ "/p:Configuration=Release",
+ "/p:GenerateFullPaths=true",
+ "/m",
+ "/verbosity:m"
+ ],
+ "group": "build",
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "Restore (net461)",
+ "type": "shell",
+ "command": "nuget",
+ "args": [
+ "restore"
+ ],
+ "problemMatcher": []
+ },
+ {
+ "label": "Restore (netcoreapp2.0)",
+ "type": "shell",
+ "command": "dotnet",
+ "args": [
+ "restore"
+ ],
+ "problemMatcher": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko/Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs
similarity index 100%
rename from osu.Game.Rulesets.Taiko/Tests/TaikoBeatmapConversionTest.cs
rename to osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs
diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs
similarity index 100%
rename from osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs
rename to osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs
diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Taiko.Tests/TestCasePerformancePoints.cs
similarity index 100%
rename from osu.Game.Rulesets.Taiko/Tests/TestCasePerformancePoints.cs
rename to osu.Game.Rulesets.Taiko.Tests/TestCasePerformancePoints.cs
diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs
similarity index 100%
rename from osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs
rename to osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs
diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
new file mode 100644
index 0000000000..df73fa61cb
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj
@@ -0,0 +1,10 @@
+
+
+
+ WinExe
+ netcoreapp2.0;net461
+
+
+
+
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs
index 435a0c1613..ba304c41d8 100644
--- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs
+++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs
@@ -8,5 +8,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
public class TaikoModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.06;
+ public override bool Ranked => true;
}
}
diff --git a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..77218af5e1
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Runtime.CompilerServices;
+
+// We publish our internal attributes to other sub-projects of the framework.
+// Note, that we omit visual tests as they are meant to test the framework
+// behavior "in the wild".
+
+[assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests")]
+[assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests.Dynamic")]
diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
index 75aaceaecb..effb9eb54f 100644
--- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
+++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
@@ -208,8 +208,6 @@ namespace osu.Game.Rulesets.Taiko.UI
public override void Add(DrawableHitObject h)
{
- h.Depth = (float)h.HitObject.StartTime;
-
h.OnJudgement += OnJudgement;
base.Add(h);
diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
index d7794aaafd..002d6a7e8d 100644
--- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
+++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
@@ -5,25 +5,9 @@
Library
AnyCPU
true
- ppy Pty Ltd
- 1.0.0.0
- ppy Pty Ltd 2007-2017
- osu.Game.Rulesets.Taiko
bash the drum. to the beat.
- osu.Game.Rulesets.Taiko
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs
index d9aedb7a5f..6605c61026 100644
--- a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs
+++ b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs
@@ -52,6 +52,7 @@ namespace osu.Game.Tests.Visual
FavouriteCount = 356,
Submitted = new DateTime(2016, 2, 10),
Ranked = new DateTime(2016, 6, 19),
+ Status = BeatmapSetOnlineStatus.Ranked,
BPM = 236,
HasVideo = true,
Covers = new BeatmapSetOnlineCovers
@@ -222,6 +223,7 @@ namespace osu.Game.Tests.Visual
FavouriteCount = 58,
Submitted = new DateTime(2016, 6, 11),
Ranked = new DateTime(2016, 7, 12),
+ Status = BeatmapSetOnlineStatus.Pending,
BPM = 160,
HasVideo = false,
Covers = new BeatmapSetOnlineCovers
diff --git a/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs b/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs
index 20bdd6736c..e3cef06f2f 100644
--- a/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs
+++ b/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs
@@ -2,7 +2,9 @@
// 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.Game.Graphics;
using osu.Game.Graphics.UserInterface;
namespace osu.Game.Tests.Visual
@@ -10,10 +12,12 @@ namespace osu.Game.Tests.Visual
[TestFixture]
public class TestCaseBreadcrumbs : OsuTestCase
{
+ private readonly BreadcrumbControl breadcrumbs;
+
public TestCaseBreadcrumbs()
{
- BreadcrumbControl c;
- Add(c = new BreadcrumbControl
+
+ Add(breadcrumbs = new BreadcrumbControl
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@@ -21,9 +25,15 @@ namespace osu.Game.Tests.Visual
Width = 0.5f,
});
- AddStep(@"first", () => c.Current.Value = BreadcrumbTab.Click);
- AddStep(@"second", () => c.Current.Value = BreadcrumbTab.The);
- AddStep(@"third", () => c.Current.Value = BreadcrumbTab.Circles);
+ AddStep(@"first", () => breadcrumbs.Current.Value = BreadcrumbTab.Click);
+ AddStep(@"second", () => breadcrumbs.Current.Value = BreadcrumbTab.The);
+ AddStep(@"third", () => breadcrumbs.Current.Value = BreadcrumbTab.Circles);
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colours)
+ {
+ breadcrumbs.StripColour = colours.Blue;
}
private enum BreadcrumbTab
diff --git a/osu.Game.Tests/Visual/TestCaseCursors.cs b/osu.Game.Tests/Visual/TestCaseCursors.cs
index 72e699c54b..4f4fdbeb5b 100644
--- a/osu.Game.Tests/Visual/TestCaseCursors.cs
+++ b/osu.Game.Tests/Visual/TestCaseCursors.cs
@@ -9,7 +9,6 @@ using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Framework.MathUtils;
-using osu.Framework.Testing.Input;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.Sprites;
using OpenTK;
@@ -18,88 +17,74 @@ using OpenTK.Graphics;
namespace osu.Game.Tests.Visual
{
[TestFixture]
- public class TestCaseCursors : OsuTestCase
+ public class TestCaseCursors : ManualInputManagerTestCase
{
- private readonly ManualInputManager inputManager;
private readonly CursorOverrideContainer cursorOverrideContainer;
private readonly CustomCursorBox[] cursorBoxes = new CustomCursorBox[6];
public TestCaseCursors()
{
- Child = inputManager = new ManualInputManager
+ Child = cursorOverrideContainer = new CursorOverrideContainer
{
- Child = cursorOverrideContainer = new CursorOverrideContainer
+ RelativeSizeAxes = Axes.Both,
+ Children = new[]
{
- RelativeSizeAxes = Axes.Both,
- Children = new[]
+ // Middle user
+ cursorBoxes[0] = new CustomCursorBox(Color4.Green)
{
- // Middle user
- cursorBoxes[0] = new CustomCursorBox(Color4.Green)
- {
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- RelativeSizeAxes = Axes.Both,
- Size = new Vector2(0.5f),
- },
- // Top-left user
- cursorBoxes[1] = new CustomCursorBox(Color4.Blue)
- {
- RelativeSizeAxes = Axes.Both,
- Size = new Vector2(0.4f)
- },
- // Bottom-right user
- cursorBoxes[2] = new CustomCursorBox(Color4.Red)
- {
- Anchor = Anchor.BottomRight,
- Origin = Anchor.BottomRight,
- RelativeSizeAxes = Axes.Both,
- Size = new Vector2(0.4f)
- },
- // Bottom-left local
- cursorBoxes[3] = new CustomCursorBox(Color4.Magenta, false)
- {
- Anchor = Anchor.BottomLeft,
- Origin = Anchor.BottomLeft,
- RelativeSizeAxes = Axes.Both,
- Size = new Vector2(0.4f)
- },
- // Top-right local
- cursorBoxes[4] = new CustomCursorBox(Color4.Cyan, false)
- {
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- RelativeSizeAxes = Axes.Both,
- Size = new Vector2(0.4f)
- },
- // Left-local
- cursorBoxes[5] = new CustomCursorBox(Color4.Yellow, false)
- {
- Anchor = Anchor.CentreLeft,
- Origin = Anchor.CentreLeft,
- RelativeSizeAxes = Axes.Both,
- Size = new Vector2(0.2f, 1),
- },
- }
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ RelativeSizeAxes = Axes.Both,
+ Size = new Vector2(0.5f),
+ },
+ // Top-left user
+ cursorBoxes[1] = new CustomCursorBox(Color4.Blue)
+ {
+ RelativeSizeAxes = Axes.Both,
+ Size = new Vector2(0.4f)
+ },
+ // Bottom-right user
+ cursorBoxes[2] = new CustomCursorBox(Color4.Red)
+ {
+ Anchor = Anchor.BottomRight,
+ Origin = Anchor.BottomRight,
+ RelativeSizeAxes = Axes.Both,
+ Size = new Vector2(0.4f)
+ },
+ // Bottom-left local
+ cursorBoxes[3] = new CustomCursorBox(Color4.Magenta, false)
+ {
+ Anchor = Anchor.BottomLeft,
+ Origin = Anchor.BottomLeft,
+ RelativeSizeAxes = Axes.Both,
+ Size = new Vector2(0.4f)
+ },
+ // Top-right local
+ cursorBoxes[4] = new CustomCursorBox(Color4.Cyan, false)
+ {
+ Anchor = Anchor.TopRight,
+ Origin = Anchor.TopRight,
+ RelativeSizeAxes = Axes.Both,
+ Size = new Vector2(0.4f)
+ },
+ // Left-local
+ cursorBoxes[5] = new CustomCursorBox(Color4.Yellow, false)
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft,
+ RelativeSizeAxes = Axes.Both,
+ Size = new Vector2(0.2f, 1),
+ },
}
};
- returnUserInput();
-
AddToggleStep("Smooth transitions", b => cursorBoxes.ForEach(box => box.SmoothTransition = b));
testUserCursor();
testLocalCursor();
testUserCursorOverride();
testMultipleLocalCursors();
- returnUserInput();
- }
-
- ///
- /// Returns input back to the user.
- ///
- private void returnUserInput()
- {
- AddStep("Return user input", () => inputManager.UseParentState = true);
+ ReturnUserInput();
}
///
@@ -109,7 +94,7 @@ namespace osu.Game.Tests.Visual
///
private void testUserCursor()
{
- AddStep("Move to green area", () => inputManager.MoveMouseTo(cursorBoxes[0]));
+ AddStep("Move to green area", () => InputManager.MoveMouseTo(cursorBoxes[0]));
AddAssert("Check green cursor visible", () => checkVisible(cursorBoxes[0].Cursor));
AddAssert("Check green cursor at mouse", () => checkAtMouse(cursorBoxes[0].Cursor));
AddStep("Move out", moveOut);
@@ -124,7 +109,7 @@ namespace osu.Game.Tests.Visual
///
private void testLocalCursor()
{
- AddStep("Move to purple area", () => inputManager.MoveMouseTo(cursorBoxes[3]));
+ AddStep("Move to purple area", () => InputManager.MoveMouseTo(cursorBoxes[3]));
AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor));
AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor));
AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor));
@@ -141,7 +126,7 @@ namespace osu.Game.Tests.Visual
///
private void testUserCursorOverride()
{
- AddStep("Move to blue-green boundary", () => inputManager.MoveMouseTo(cursorBoxes[1].ScreenSpaceDrawQuad.BottomRight - new Vector2(10)));
+ AddStep("Move to blue-green boundary", () => InputManager.MoveMouseTo(cursorBoxes[1].ScreenSpaceDrawQuad.BottomRight - new Vector2(10)));
AddAssert("Check blue cursor visible", () => checkVisible(cursorBoxes[1].Cursor));
AddAssert("Check green cursor invisible", () => !checkVisible(cursorBoxes[0].Cursor));
AddAssert("Check blue cursor at mouse", () => checkAtMouse(cursorBoxes[1].Cursor));
@@ -156,7 +141,7 @@ namespace osu.Game.Tests.Visual
///
private void testMultipleLocalCursors()
{
- AddStep("Move to yellow-purple boundary", () => inputManager.MoveMouseTo(cursorBoxes[5].ScreenSpaceDrawQuad.BottomRight - new Vector2(10)));
+ AddStep("Move to yellow-purple boundary", () => InputManager.MoveMouseTo(cursorBoxes[5].ScreenSpaceDrawQuad.BottomRight - new Vector2(10)));
AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor));
AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor));
AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor));
@@ -172,7 +157,7 @@ namespace osu.Game.Tests.Visual
///
private void testUserOverrideWithLocal()
{
- AddStep("Move to yellow-blue boundary", () => inputManager.MoveMouseTo(cursorBoxes[5].ScreenSpaceDrawQuad.TopRight - new Vector2(10)));
+ AddStep("Move to yellow-blue boundary", () => InputManager.MoveMouseTo(cursorBoxes[5].ScreenSpaceDrawQuad.TopRight - new Vector2(10)));
AddAssert("Check blue cursor visible", () => checkVisible(cursorBoxes[1].Cursor));
AddAssert("Check blue cursor at mouse", () => checkAtMouse(cursorBoxes[1].Cursor));
AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor));
@@ -186,7 +171,7 @@ namespace osu.Game.Tests.Visual
/// Moves the cursor to a point not covered by any cursor containers.
///
private void moveOut()
- => inputManager.MoveMouseTo(new Vector2(inputManager.ScreenSpaceDrawQuad.Centre.X, inputManager.ScreenSpaceDrawQuad.TopLeft.Y));
+ => InputManager.MoveMouseTo(new Vector2(InputManager.ScreenSpaceDrawQuad.Centre.X, InputManager.ScreenSpaceDrawQuad.TopLeft.Y));
///
/// Checks if a cursor is visible.
@@ -199,7 +184,7 @@ namespace osu.Game.Tests.Visual
///
/// The cursor to check.
private bool checkAtMouse(CursorContainer cursorContainer)
- => Precision.AlmostEquals(inputManager.CurrentState.Mouse.NativeState.Position, cursorContainer.ToScreenSpace(cursorContainer.ActiveCursor.DrawPosition));
+ => Precision.AlmostEquals(InputManager.CurrentState.Mouse.NativeState.Position, cursorContainer.ToScreenSpace(cursorContainer.ActiveCursor.DrawPosition));
private class CustomCursorBox : Container, IProvideCursor
{
diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs
similarity index 85%
rename from osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs
rename to osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs
index bbbfef477a..72d60d8e01 100644
--- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs
+++ b/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using JetBrains.Annotations;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Timing;
@@ -12,7 +13,6 @@ using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Edit;
-using osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit.Screens.Compose.Layers;
using osu.Game.Tests.Beatmaps;
@@ -20,19 +20,16 @@ using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual
{
[TestFixture]
- public class TestCaseEditorSelectionLayer : OsuTestCase
+ public class TestCaseHitObjectComposer : OsuTestCase
{
public override IReadOnlyList RequiredTypes => new[]
{
- typeof(SelectionLayer),
- typeof(SelectionBox),
+ typeof(MaskSelection),
+ typeof(DragLayer),
typeof(HitObjectComposer),
typeof(OsuHitObjectComposer),
typeof(HitObjectMaskLayer),
- typeof(HitObjectMask),
- typeof(HitCircleMask),
- typeof(SliderMask),
- typeof(SliderCircleMask)
+ typeof(NotNullAttribute)
};
private DependencyContainer dependencies;
diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs
index 745ae9ad9d..0742dd68eb 100644
--- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs
+++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs
@@ -122,7 +122,7 @@ namespace osu.Game.Tests.Visual
Direction = direction;
Padding = new MarginPadding(2);
- ScaledContent.Masking = true;
+ Content.Masking = true;
AddInternal(new Box
{
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index 5b9a1f11e4..2646e953cf 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -1,39 +1,13 @@
-
+
- netstandard2.0
- Library
- AnyCPU
- true
- ppy Pty Ltd
- 1.0.0.0
- ppy Pty Ltd 2007-2017
- osu.Game.Tests
- osu.Game.Tests
-
- NU1701
+ WinExe
+ netcoreapp2.0;net461
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/osu.Game.props b/osu.Game.props
index 07abeb5539..87edafb97f 100644
--- a/osu.Game.props
+++ b/osu.Game.props
@@ -8,4 +8,14 @@
osu.licenseheader
+
+
+
+
+ ppy Pty Ltd
+ ppy Pty Ltd 2007-2018
+
+ NU1701
+
\ No newline at end of file
diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
index be3107c7b9..f7221a6ac3 100644
--- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
+++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
@@ -26,6 +26,11 @@ namespace osu.Game.Beatmaps
///
public DateTimeOffset? LastUpdated { get; set; }
+ ///
+ /// The status of this beatmap set.
+ ///
+ public BeatmapSetOnlineStatus Status { get; set; }
+
///
/// Whether or not this beatmap set has a background video.
///
diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs b/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs
new file mode 100644
index 0000000000..c7f767d3b2
--- /dev/null
+++ b/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs
@@ -0,0 +1,17 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+namespace osu.Game.Beatmaps
+{
+ public enum BeatmapSetOnlineStatus
+ {
+ None = -3,
+ Graveyard = -2,
+ WIP = -1,
+ Pending = 0,
+ Ranked = 1,
+ Approved = 2,
+ Qualified = 3,
+ Loved = 4,
+ }
+}
diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs
new file mode 100644
index 0000000000..8ea7a538f9
--- /dev/null
+++ b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs
@@ -0,0 +1,54 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Game.Graphics.Sprites;
+using OpenTK.Graphics;
+
+namespace osu.Game.Beatmaps.Drawables
+{
+ public class BeatmapSetOnlineStatusPill : CircularContainer
+ {
+ private readonly OsuSpriteText statusText;
+
+ private BeatmapSetOnlineStatus status = BeatmapSetOnlineStatus.None;
+ public BeatmapSetOnlineStatus Status
+ {
+ get { return status; }
+ set
+ {
+ if (value == status) return;
+ status = value;
+
+ statusText.Text = Enum.GetName(typeof(BeatmapSetOnlineStatus), Status)?.ToUpper();
+ }
+ }
+
+ public BeatmapSetOnlineStatusPill(float textSize, MarginPadding textPadding)
+ {
+ AutoSizeAxes = Axes.Both;
+ Masking = true;
+
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = Color4.Black,
+ Alpha = 0.5f,
+ },
+ statusText = new OsuSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Font = @"Exo2.0-Bold",
+ TextSize = textSize,
+ Padding = textPadding,
+ },
+ };
+ }
+ }
+}
diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs
index 9f10485c5f..c07bedc8a6 100644
--- a/osu.Game/Beatmaps/Formats/Decoder.cs
+++ b/osu.Game/Beatmaps/Formats/Decoder.cs
@@ -16,7 +16,7 @@ namespace osu.Game.Beatmaps.Formats
public TOutput Decode(StreamReader primaryStream, params StreamReader[] otherStreams)
{
var output = CreateTemplateObject();
- foreach (StreamReader stream in new[] { primaryStream }.Concat(otherStreams))
+ foreach (StreamReader stream in otherStreams.Prepend(primaryStream))
ParseStreamInto(stream, output);
return output;
}
diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
index 74b7d0272e..52f1a01fcb 100644
--- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
@@ -81,13 +81,13 @@ namespace osu.Game.Beatmaps.Formats
handleDifficulty(line);
return;
case Section.Events:
- handleEvents(line);
+ handleEvent(line);
return;
case Section.TimingPoints:
- handleTimingPoints(line);
+ handleTimingPoint(line);
return;
case Section.HitObjects:
- handleHitObjects(line);
+ handleHitObject(line);
return;
}
@@ -246,7 +246,7 @@ namespace osu.Game.Beatmaps.Formats
}
}
- private void handleEvents(string line)
+ private void handleEvent(string line)
{
string[] split = line.Split(',');
@@ -275,93 +275,99 @@ namespace osu.Game.Beatmaps.Formats
}
}
- private void handleTimingPoints(string line)
+ private void handleTimingPoint(string line)
{
- string[] split = line.Split(',');
-
- double time = getOffsetTime(double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo));
- double beatLength = double.Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo);
- double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1;
-
- TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple;
- if (split.Length >= 3)
- timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)int.Parse(split[2]);
-
- LegacySampleBank sampleSet = defaultSampleBank;
- if (split.Length >= 4)
- sampleSet = (LegacySampleBank)int.Parse(split[3]);
-
- //SampleBank sampleBank = SampleBank.Default;
- //if (split.Length >= 5)
- // sampleBank = (SampleBank)int.Parse(split[4]);
-
- int sampleVolume = defaultSampleVolume;
- if (split.Length >= 6)
- sampleVolume = int.Parse(split[5]);
-
- bool timingChange = true;
- if (split.Length >= 7)
- timingChange = split[6][0] == '1';
-
- bool kiaiMode = false;
- bool omitFirstBarSignature = false;
- if (split.Length >= 8)
+ try
{
- int effectFlags = int.Parse(split[7]);
- kiaiMode = (effectFlags & 1) > 0;
- omitFirstBarSignature = (effectFlags & 8) > 0;
- }
+ string[] split = line.Split(',');
- string stringSampleSet = sampleSet.ToString().ToLower();
- if (stringSampleSet == @"none")
- stringSampleSet = @"normal";
+ double time = getOffsetTime(double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo));
+ double beatLength = double.Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo);
+ double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1;
- DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(time);
- SampleControlPoint samplePoint = beatmap.ControlPointInfo.SamplePointAt(time);
- EffectControlPoint effectPoint = beatmap.ControlPointInfo.EffectPointAt(time);
+ TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple;
+ if (split.Length >= 3)
+ timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)int.Parse(split[2]);
- if (timingChange)
- {
- beatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint
+ LegacySampleBank sampleSet = defaultSampleBank;
+ if (split.Length >= 4)
+ sampleSet = (LegacySampleBank)int.Parse(split[3]);
+
+ //SampleBank sampleBank = SampleBank.Default;
+ //if (split.Length >= 5)
+ // sampleBank = (SampleBank)int.Parse(split[4]);
+
+ int sampleVolume = defaultSampleVolume;
+ if (split.Length >= 6)
+ sampleVolume = int.Parse(split[5]);
+
+ bool timingChange = true;
+ if (split.Length >= 7)
+ timingChange = split[6][0] == '1';
+
+ bool kiaiMode = false;
+ bool omitFirstBarSignature = false;
+ if (split.Length >= 8)
{
- Time = time,
- BeatLength = beatLength,
- TimeSignature = timeSignature
- });
- }
+ int effectFlags = int.Parse(split[7]);
+ kiaiMode = (effectFlags & 1) > 0;
+ omitFirstBarSignature = (effectFlags & 8) > 0;
+ }
- if (speedMultiplier != difficultyPoint.SpeedMultiplier)
- {
- beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == time);
- beatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint
- {
- Time = time,
- SpeedMultiplier = speedMultiplier
- });
- }
+ string stringSampleSet = sampleSet.ToString().ToLower();
+ if (stringSampleSet == @"none")
+ stringSampleSet = @"normal";
- if (stringSampleSet != samplePoint.SampleBank || sampleVolume != samplePoint.SampleVolume)
- {
- beatmap.ControlPointInfo.SamplePoints.Add(new SampleControlPoint
- {
- Time = time,
- SampleBank = stringSampleSet,
- SampleVolume = sampleVolume
- });
- }
+ DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(time);
+ SampleControlPoint samplePoint = beatmap.ControlPointInfo.SamplePointAt(time);
+ EffectControlPoint effectPoint = beatmap.ControlPointInfo.EffectPointAt(time);
- if (kiaiMode != effectPoint.KiaiMode || omitFirstBarSignature != effectPoint.OmitFirstBarLine)
- {
- beatmap.ControlPointInfo.EffectPoints.Add(new EffectControlPoint
+ if (timingChange)
{
- Time = time,
- KiaiMode = kiaiMode,
- OmitFirstBarLine = omitFirstBarSignature
- });
+ beatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint
+ {
+ Time = time,
+ BeatLength = beatLength,
+ TimeSignature = timeSignature
+ });
+ }
+
+ if (speedMultiplier != difficultyPoint.SpeedMultiplier)
+ {
+ beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == time);
+ beatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint
+ {
+ Time = time,
+ SpeedMultiplier = speedMultiplier
+ });
+ }
+
+ if (stringSampleSet != samplePoint.SampleBank || sampleVolume != samplePoint.SampleVolume)
+ {
+ beatmap.ControlPointInfo.SamplePoints.Add(new SampleControlPoint
+ {
+ Time = time,
+ SampleBank = stringSampleSet,
+ SampleVolume = sampleVolume
+ });
+ }
+
+ if (kiaiMode != effectPoint.KiaiMode || omitFirstBarSignature != effectPoint.OmitFirstBarLine)
+ {
+ beatmap.ControlPointInfo.EffectPoints.Add(new EffectControlPoint
+ {
+ Time = time,
+ KiaiMode = kiaiMode,
+ OmitFirstBarLine = omitFirstBarSignature
+ });
+ }
+ }
+ catch (FormatException e)
+ {
}
}
- private void handleHitObjects(string line)
+ private void handleHitObject(string line)
{
// If the ruleset wasn't specified, assume the osu!standard ruleset.
if (parser == null)
diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs
index 5ee0aba9cf..7f30bd715a 100644
--- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs
+++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs
@@ -17,6 +17,8 @@ namespace osu.Game.Graphics.UserInterface
protected override TabItem CreateTabItem(T value) => new BreadcrumbTabItem(value);
+ protected override float StripWidth() => base.StripWidth() - (padding + 8);
+
public BreadcrumbControl()
{
Height = 26;
diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs
index 20385a7dae..8b692f32bc 100644
--- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs
+++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs
@@ -14,22 +14,36 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input;
+using osu.Framework.MathUtils;
using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface
{
public class OsuTabControl : TabControl
{
+ private readonly Box strip;
+
protected override Dropdown CreateDropdown() => new OsuTabDropdown();
protected override TabItem CreateTabItem(T value) => new OsuTabItem(value);
+ protected virtual float StripWidth() => TabContainer.Children.Sum(c => c.IsPresent ? c.DrawWidth + TabContainer.Spacing.X : 0) - TabContainer.Spacing.X;
+ protected virtual float StripHeight() => 1;
+
private static bool isEnumType => typeof(T).IsEnum;
public OsuTabControl()
{
TabContainer.Spacing = new Vector2(10f, 0f);
+ Add(strip = new Box
+ {
+ Anchor = Anchor.BottomLeft,
+ Origin = Anchor.BottomLeft,
+ Height = StripHeight(),
+ Colour = Color4.White.Opacity(0),
+ });
+
if (isEnumType)
foreach (var val in (T[])Enum.GetValues(typeof(T)))
AddItem(val);
@@ -57,6 +71,12 @@ namespace osu.Game.Graphics.UserInterface
}
}
+ public Color4 StripColour
+ {
+ get => strip.Colour;
+ set => strip.Colour = value;
+ }
+
protected override TabFillFlowContainer CreateTabFlow() => new OsuTabFillFlowContainer
{
Direction = FillDirection.Full,
@@ -65,6 +85,15 @@ namespace osu.Game.Graphics.UserInterface
Masking = true
};
+ protected override void UpdateAfterChildren()
+ {
+ base.UpdateAfterChildren();
+
+ // dont bother calculating if the strip is invisible
+ if (strip.Colour.MaxAlpha > 0)
+ strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint);
+ }
+
public class OsuTabItem : TabItem, IHasAccentColour
{
protected readonly SpriteText Text;
diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs
index 97e473a797..9e74a935ea 100644
--- a/osu.Game/Input/Bindings/GlobalActionContainer.cs
+++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs
@@ -45,7 +45,7 @@ namespace osu.Game.Input.Bindings
};
protected override IEnumerable KeyBindingInputQueue =>
- handler == null ? base.KeyBindingInputQueue : new[] { handler }.Concat(base.KeyBindingInputQueue);
+ handler == null ? base.KeyBindingInputQueue : base.KeyBindingInputQueue.Prepend(handler);
}
public enum GlobalAction
diff --git a/osu.Game/Input/Handlers/ReplayInputHandler.cs b/osu.Game/Input/Handlers/ReplayInputHandler.cs
index 8aa3a53cc2..c431af0219 100644
--- a/osu.Game/Input/Handlers/ReplayInputHandler.cs
+++ b/osu.Game/Input/Handlers/ReplayInputHandler.cs
@@ -13,9 +13,9 @@ namespace osu.Game.Input.Handlers
public abstract class ReplayInputHandler : InputHandler
{
///
- /// A function provided to convert replay coordinates from gamefield to screen space.
+ /// A function that converts coordinates from gamefield to screen space.
///
- public Func ToScreenSpace { protected get; set; }
+ public Func GamefieldToScreenSpace { protected get; set; }
///
/// Update the current frame based on an incoming time value.
diff --git a/osu.Game/Online/API/Requests/APIResponseBeatmapSet.cs b/osu.Game/Online/API/Requests/APIResponseBeatmapSet.cs
index 8f011b4df7..28376a1b4f 100644
--- a/osu.Game/Online/API/Requests/APIResponseBeatmapSet.cs
+++ b/osu.Game/Online/API/Requests/APIResponseBeatmapSet.cs
@@ -30,6 +30,9 @@ namespace osu.Game.Online.API.Requests
[JsonProperty(@"video")]
private bool hasVideo { get; set; }
+ [JsonProperty(@"status")]
+ private BeatmapSetOnlineStatus status { get; set; }
+
[JsonProperty(@"submitted_date")]
private DateTimeOffset submitted { get; set; }
@@ -60,6 +63,7 @@ namespace osu.Game.Online.API.Requests
PlayCount = playCount,
FavouriteCount = favouriteCount,
BPM = bpm,
+ Status = status,
HasVideo = hasVideo,
Submitted = submitted,
Ranked = ranked,
diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs
index 3ce0dfee31..b9a35ec1f0 100644
--- a/osu.Game/Overlays/BeatmapSet/Header.cs
+++ b/osu.Game/Overlays/BeatmapSet/Header.cs
@@ -30,6 +30,7 @@ namespace osu.Game.Overlays.BeatmapSet
private readonly FillFlowContainer videoButtons;
private readonly AuthorInfo author;
private readonly Container downloadButtonsContainer;
+ private readonly BeatmapSetOnlineStatusPill onlineStatusPill;
public Details Details;
private BeatmapManager beatmaps;
@@ -50,6 +51,7 @@ namespace osu.Game.Overlays.BeatmapSet
Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = BeatmapSet;
title.Text = BeatmapSet.Metadata.Title;
artist.Text = BeatmapSet.Metadata.Artist;
+ onlineStatusPill.Status = BeatmapSet.OnlineInfo.Status;
downloadButtonsContainer.FadeIn();
noVideoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 0 : 1, transition_duration);
@@ -204,11 +206,23 @@ namespace osu.Game.Overlays.BeatmapSet
},
},
},
- Details = new Details
+ new FillFlowContainer
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
+ AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Right = BeatmapSetOverlay.X_PADDING },
+ Direction = FillDirection.Vertical,
+ Spacing = new Vector2(10),
+ Children = new Drawable[]
+ {
+ onlineStatusPill = new BeatmapSetOnlineStatusPill(14, new MarginPadding { Horizontal = 25, Vertical = 8 })
+ {
+ Anchor = Anchor.TopRight,
+ Origin = Anchor.TopRight,
+ },
+ Details = new Details(),
+ },
},
},
},
diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs
index 2cc51f9e4c..d893c027c7 100644
--- a/osu.Game/Overlays/Direct/DirectGridPanel.cs
+++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs
@@ -11,7 +11,9 @@ using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Framework.Graphics.Shapes;
+using osu.Framework.Input;
using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.Drawables;
namespace osu.Game.Overlays.Direct
{
@@ -20,7 +22,7 @@ namespace osu.Game.Overlays.Direct
private const float horizontal_padding = 10;
private const float vertical_padding = 5;
- private FillFlowContainer bottomPanel;
+ private FillFlowContainer bottomPanel, statusContainer;
private PlayButton playButton;
private Box progressBar;
@@ -199,7 +201,37 @@ namespace osu.Game.Overlays.Direct
Size = new Vector2(30),
Alpha = 0,
},
+ statusContainer = new FillFlowContainer
+ {
+ AutoSizeAxes = Axes.Both,
+ Margin = new MarginPadding { Top = 5, Left = 5 },
+ Spacing = new Vector2(5),
+ },
});
+
+ if (SetInfo.OnlineInfo?.HasVideo ?? false)
+ {
+ statusContainer.Add(new IconPill(FontAwesome.fa_film));
+ }
+
+ statusContainer.Add(new BeatmapSetOnlineStatusPill(12, new MarginPadding { Horizontal = 10, Vertical = 5 })
+ {
+ Status = SetInfo.OnlineInfo?.Status ?? BeatmapSetOnlineStatus.None,
+ });
+ }
+
+ protected override bool OnHover(InputState state)
+ {
+ statusContainer.FadeOut(120, Easing.InOutQuint);
+
+ return base.OnHover(state);
+ }
+
+ protected override void OnHoverLost(InputState state)
+ {
+ base.OnHoverLost(state);
+
+ statusContainer.FadeIn(120, Easing.InOutQuint);
}
}
}
diff --git a/osu.Game/Overlays/Direct/Header.cs b/osu.Game/Overlays/Direct/Header.cs
index 2245f70ed3..252e732614 100644
--- a/osu.Game/Overlays/Direct/Header.cs
+++ b/osu.Game/Overlays/Direct/Header.cs
@@ -13,7 +13,6 @@ namespace osu.Game.Overlays.Direct
public class Header : SearchableListHeader
{
protected override Color4 BackgroundColour => OsuColour.FromHex(@"252f3a");
- protected override float TabStripWidth => 298;
protected override DirectTab DefaultTab => DirectTab.Search;
protected override Drawable CreateHeaderText() => new OsuSpriteText { Text = @"osu!direct", TextSize = 25 };
diff --git a/osu.Game/Overlays/Direct/IconPill.cs b/osu.Game/Overlays/Direct/IconPill.cs
new file mode 100644
index 0000000000..33b67bdf13
--- /dev/null
+++ b/osu.Game/Overlays/Direct/IconPill.cs
@@ -0,0 +1,43 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Game.Graphics;
+using OpenTK;
+using OpenTK.Graphics;
+
+namespace osu.Game.Overlays.Direct
+{
+ public class IconPill : CircularContainer
+ {
+ public IconPill(FontAwesome icon)
+ {
+ AutoSizeAxes = Axes.Both;
+ Masking = true;
+
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = Color4.Black,
+ Alpha = 0.5f,
+ },
+ new Container
+ {
+ AutoSizeAxes = Axes.Both,
+ Margin = new MarginPadding(5),
+ Child = new SpriteIcon
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Icon = icon,
+ Size = new Vector2(12),
+ },
+ },
+ };
+ }
+ }
+}
diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
index 379d25313e..71c346d404 100644
--- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
+++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
@@ -47,7 +47,7 @@ namespace osu.Game.Overlays.KeyBinding
private FillFlowContainer buttons;
- public IEnumerable FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString()));
+ public IEnumerable FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend(text.Text);
public KeyBindingRow(object action, IEnumerable bindings)
{
diff --git a/osu.Game/Overlays/SearchableList/SearchableListHeader.cs b/osu.Game/Overlays/SearchableList/SearchableListHeader.cs
index 0f2650ad40..e053f2f773 100644
--- a/osu.Game/Overlays/SearchableList/SearchableListHeader.cs
+++ b/osu.Game/Overlays/SearchableList/SearchableListHeader.cs
@@ -14,12 +14,9 @@ namespace osu.Game.Overlays.SearchableList
{
public abstract class SearchableListHeader : Container
{
- private readonly Box tabStrip;
-
public readonly HeaderTabControl Tabs;
protected abstract Color4 BackgroundColour { get; }
- protected abstract float TabStripWidth { get; } //can be removed once (if?) TabControl support auto sizing
protected abstract T DefaultTab { get; }
protected abstract Drawable CreateHeaderText();
protected abstract FontAwesome Icon { get; }
@@ -63,13 +60,6 @@ namespace osu.Game.Overlays.SearchableList
CreateHeaderText(),
},
},
- tabStrip = new Box
- {
- Anchor = Anchor.BottomLeft,
- Origin = Anchor.BottomLeft,
- Width = TabStripWidth,
- Height = 1,
- },
Tabs = new HeaderTabControl
{
Anchor = Anchor.BottomLeft,
@@ -87,7 +77,7 @@ namespace osu.Game.Overlays.SearchableList
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
- tabStrip.Colour = colours.Green;
+ Tabs.StripColour = colours.Green;
}
}
}
diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs
index 7bb4b4dde9..89224e1315 100644
--- a/osu.Game/Overlays/Social/Header.cs
+++ b/osu.Game/Overlays/Social/Header.cs
@@ -17,7 +17,6 @@ namespace osu.Game.Overlays.Social
private OsuSpriteText browser;
protected override Color4 BackgroundColour => OsuColour.FromHex(@"38202e");
- protected override float TabStripWidth => 438;
protected override SocialTab DefaultTab => SocialTab.AllPlayers;
protected override FontAwesome Icon => FontAwesome.fa_users;
diff --git a/osu.Game/Properties/AssemblyInfo.cs b/osu.Game/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..9384740308
--- /dev/null
+++ b/osu.Game/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Runtime.CompilerServices;
+
+// We publish our internal attributes to other sub-projects of the framework.
+// Note, that we omit visual tests as they are meant to test the framework
+// behavior "in the wild".
+
+[assembly: InternalsVisibleTo("osu.Game.Tests")]
+[assembly: InternalsVisibleTo("osu.Game.Tests.Dynamic")]
diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs
index c076b53f51..9b33ad2563 100644
--- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs
+++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs
@@ -65,9 +65,6 @@ namespace osu.Game.Rulesets.Edit
return;
}
- HitObjectMaskLayer hitObjectMaskLayer = new HitObjectMaskLayer(this);
- SelectionLayer selectionLayer = new SelectionLayer(rulesetContainer.Playfield);
-
var layerBelowRuleset = new BorderLayer
{
RelativeSizeAxes = Axes.Both,
@@ -75,12 +72,7 @@ namespace osu.Game.Rulesets.Edit
};
var layerAboveRuleset = CreateLayerContainer();
- layerAboveRuleset.Children = new Drawable[]
- {
- selectionLayer, // Below object overlays for input
- hitObjectMaskLayer,
- selectionLayer.CreateProxy() // Proxy above object overlays for selections
- };
+ layerAboveRuleset.Child = new HitObjectMaskLayer(rulesetContainer.Playfield, this);
layerContainers.Add(layerBelowRuleset);
layerContainers.Add(layerAboveRuleset);
@@ -122,16 +114,9 @@ namespace osu.Game.Rulesets.Edit
}
};
- selectionLayer.ObjectSelected += hitObjectMaskLayer.AddOverlay;
- selectionLayer.ObjectDeselected += hitObjectMaskLayer.RemoveOverlay;
- selectionLayer.SelectionCleared += hitObjectMaskLayer.RemoveSelectionOverlay;
- selectionLayer.SelectionFinished += hitObjectMaskLayer.AddSelectionOverlay;
-
toolboxCollection.Items =
- new[] { new RadioButton("Select", () => setCompositionTool(null)) }
- .Concat(
- CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t)))
- )
+ CompositionTools.Select(t => new RadioButton(t.Name, () => setCompositionTool(t)))
+ .Prepend(new RadioButton("Select", () => setCompositionTool(null)))
.ToList();
toolboxCollection.Items[0].Select();
@@ -263,11 +248,10 @@ namespace osu.Game.Rulesets.Edit
public virtual HitObjectMask CreateMaskFor(DrawableHitObject hitObject) => null;
///
- /// Creates a which outlines s
- /// and handles all hitobject movement/pattern adjustments.
+ /// Creates a which outlines s
+ /// and handles hitobject pattern adjustments.
///
- /// The overlays.
- public virtual SelectionBox CreateSelectionOverlay(IReadOnlyList overlays) => new SelectionBox(overlays);
+ public virtual MaskSelection CreateMaskSelection() => new MaskSelection();
///
/// Creates a which provides a layer above or below the .
diff --git a/osu.Game/Rulesets/Edit/HitObjectMask.cs b/osu.Game/Rulesets/Edit/HitObjectMask.cs
index 051b42fec6..9f055ffc5d 100644
--- a/osu.Game/Rulesets/Edit/HitObjectMask.cs
+++ b/osu.Game/Rulesets/Edit/HitObjectMask.cs
@@ -1,21 +1,146 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+using System;
+using osu.Framework;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Primitives;
+using osu.Framework.Input;
using osu.Game.Rulesets.Objects.Drawables;
+using OpenTK;
namespace osu.Game.Rulesets.Edit
{
///
/// A mask placed above a adding editing functionality.
///
- public class HitObjectMask : Container
+ public class HitObjectMask : CompositeDrawable, IStateful
{
+ ///
+ /// Invoked when this has been selected.
+ ///
+ public event Action Selected;
+
+ ///
+ /// Invoked when this has been deselected.
+ ///
+ public event Action Deselected;
+
+ ///
+ /// Invoked when this has requested selection.
+ /// Will fire even if already selected. Does not actually perform selection.
+ ///
+ public event Action SelectionRequested;
+
+ ///
+ /// Invoked when this has requested drag.
+ ///
+ public event Action DragRequested;
+
+ ///
+ /// The which this applies to.
+ ///
public readonly DrawableHitObject HitObject;
+ protected override bool ShouldBeAlive => HitObject.IsAlive && HitObject.IsPresent || State == SelectionState.Selected;
+ public override bool HandleMouseInput => ShouldBeAlive;
+ public override bool RemoveWhenNotAlive => false;
+
public HitObjectMask(DrawableHitObject hitObject)
{
HitObject = hitObject;
+
+ AlwaysPresent = true;
+ Alpha = 0;
}
+
+ private SelectionState state;
+
+ public event Action StateChanged;
+
+ public SelectionState State
+ {
+ get => state;
+ set
+ {
+ if (state == value) return;
+
+ state = value;
+ switch (state)
+ {
+ case SelectionState.Selected:
+ Show();
+ Selected?.Invoke(this);
+ break;
+ case SelectionState.NotSelected:
+ Hide();
+ Deselected?.Invoke(this);
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Selects this , causing it to become visible.
+ ///
+ public void Select() => State = SelectionState.Selected;
+
+ ///
+ /// Deselects this , causing it to become invisible.
+ ///
+ public void Deselect() => State = SelectionState.NotSelected;
+
+ public bool IsSelected => State == SelectionState.Selected;
+
+ private bool selectionRequested;
+
+ protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
+ {
+ selectionRequested = false;
+
+ if (State == SelectionState.NotSelected)
+ {
+ SelectionRequested?.Invoke(this, state);
+ selectionRequested = true;
+ }
+
+ return IsSelected;
+ }
+
+ protected override bool OnClick(InputState state)
+ {
+ if (State == SelectionState.Selected && !selectionRequested)
+ {
+ selectionRequested = true;
+ SelectionRequested?.Invoke(this, state);
+ return true;
+ }
+
+ return base.OnClick(state);
+ }
+
+ protected override bool OnDragStart(InputState state) => true;
+
+ protected override bool OnDrag(InputState state)
+ {
+ DragRequested?.Invoke(this, state);
+ return true;
+ }
+
+ ///
+ /// The screen-space point that causes this to be selected.
+ ///
+ public virtual Vector2 SelectionPoint => ScreenSpaceDrawQuad.Centre;
+
+ ///
+ /// The screen-space quad that outlines this for selections.
+ ///
+ public virtual Quad SelectionQuad => ScreenSpaceDrawQuad;
+ }
+
+ public enum SelectionState
+ {
+ NotSelected,
+ Selected
}
}
diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
index ca203e1cdb..a1a27c0d43 100644
--- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
+++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
@@ -23,6 +23,8 @@ namespace osu.Game.Rulesets.Judgements
{
private const float judgement_size = 80;
+ private OsuColour colours;
+
protected readonly Judgement Judgement;
public readonly DrawableHitObject JudgedObject;
@@ -45,11 +47,13 @@ namespace osu.Game.Rulesets.Judgements
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
+ this.colours = colours;
+
Child = new SkinnableDrawable($"Play/{Judgement.Result}", _ => JudgementText = new OsuSpriteText
{
Text = Judgement.Result.GetDescription().ToUpper(),
Font = @"Venera",
- Colour = Judgement.Result == HitResult.Miss ? colours.Red : Color4.White,
+ Colour = judgementColour(Judgement.Result),
Scale = new Vector2(0.85f, 1),
TextSize = 12
}, restrictSize: false);
@@ -84,5 +88,24 @@ namespace osu.Game.Rulesets.Judgements
Expire(true);
}
+
+ private Color4 judgementColour(HitResult judgement)
+ {
+ switch (judgement)
+ {
+ case HitResult.Perfect:
+ case HitResult.Great:
+ return colours.Blue;
+ case HitResult.Ok:
+ case HitResult.Good:
+ return colours.Green;
+ case HitResult.Meh:
+ return colours.Yellow;
+ case HitResult.Miss:
+ return colours.Red;
+ }
+
+ return Color4.White;
+ }
}
}
diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs
index c998bc123f..c4c0f38faf 100644
--- a/osu.Game/Rulesets/Mods/ModHardRock.cs
+++ b/osu.Game/Rulesets/Mods/ModHardRock.cs
@@ -14,7 +14,6 @@ namespace osu.Game.Rulesets.Mods
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock;
public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Everything just got a bit harder...";
- public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModEasy) };
public void ApplyToDifficulty(BeatmapDifficulty difficulty)
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index 348364a2bf..fdfef14a88 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -6,14 +6,12 @@ using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
-using osu.Framework.Graphics.Primitives;
using osu.Game.Audio;
using osu.Game.Graphics;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
-using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Objects.Drawables
@@ -231,16 +229,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
protected virtual void CheckForJudgements(bool userTriggered, double timeOffset)
{
}
-
- ///
- /// The screen-space point that causes this to be selected in the Editor.
- ///
- public virtual Vector2 SelectionPoint => ScreenSpaceDrawQuad.Centre;
-
- ///
- /// The screen-space quad that outlines this for selections in the Editor.
- ///
- public virtual Quad SelectionQuad => ScreenSpaceDrawQuad;
}
public abstract class DrawableHitObject : DrawableHitObject
diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs
index c26a6cdff0..ecb10dfba2 100644
--- a/osu.Game/Rulesets/UI/HitObjectContainer.cs
+++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
+using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects.Drawables;
@@ -15,5 +16,15 @@ namespace osu.Game.Rulesets.UI
public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject);
public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject);
+
+ protected override int Compare(Drawable x, Drawable y)
+ {
+ if (!(x is DrawableHitObject xObj) || !(y is DrawableHitObject yObj))
+ return base.Compare(x, y);
+
+ // Put earlier hitobjects towards the end of the list, so they handle input first
+ int i = yObj.HitObject.StartTime.CompareTo(xObj.HitObject.StartTime);
+ return i == 0 ? CompareReverseChildID(x, y) : i;
+ }
}
}
diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs
index 2201b6963f..81418fecd4 100644
--- a/osu.Game/Rulesets/UI/RulesetContainer.cs
+++ b/osu.Game/Rulesets/UI/RulesetContainer.cs
@@ -290,7 +290,7 @@ namespace osu.Game.Rulesets.UI
base.SetReplay(replay);
if (ReplayInputManager?.ReplayInputHandler != null)
- ReplayInputManager.ReplayInputHandler.ToScreenSpace = input => Playfield.ScaledContent.ToScreenSpace(input);
+ ReplayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace;
}
///
diff --git a/osu.Game/Rulesets/UI/ScalableContainer.cs b/osu.Game/Rulesets/UI/ScalableContainer.cs
index 9762828e7d..04e6db9578 100644
--- a/osu.Game/Rulesets/UI/ScalableContainer.cs
+++ b/osu.Game/Rulesets/UI/ScalableContainer.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+using System;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using OpenTK;
@@ -12,13 +13,16 @@ namespace osu.Game.Rulesets.UI
///
public class ScalableContainer : Container
{
+ ///
+ /// A function that converts coordinates from gamefield to screen space.
+ ///
+ public Func GamefieldToScreenSpace => scaledContent.GamefieldToScreenSpace;
+
///
/// The scaled content.
///
- public readonly Container ScaledContent;
-
- protected override Container Content => content;
- private readonly Container content;
+ private readonly ScaledContainer scaledContent;
+ protected override Container Content => scaledContent;
///
/// A which can have its internal coordinate system scaled to a specific size.
@@ -31,17 +35,21 @@ namespace osu.Game.Rulesets.UI
///
public ScalableContainer(float? customWidth = null, float? customHeight = null)
{
- AddInternal(ScaledContent = new ScaledContainer
+ AddInternal(scaledContent = new ScaledContainer
{
CustomWidth = customWidth,
CustomHeight = customHeight,
RelativeSizeAxes = Axes.Both,
- Child = content = new Container { RelativeSizeAxes = Axes.Both }
});
}
private class ScaledContainer : Container
{
+ ///
+ /// A function that converts coordinates from gamefield to screen space.
+ ///
+ public Func GamefieldToScreenSpace => content.ToScreenSpace;
+
///
/// The value to scale the width of the content to match.
/// If null, is used.
@@ -54,6 +62,22 @@ namespace osu.Game.Rulesets.UI
///
public float? CustomHeight;
+ private readonly Container content;
+ protected override Container Content => content;
+
+ public ScaledContainer()
+ {
+ AddInternal(content = new Container { RelativeSizeAxes = Axes.Both });
+ }
+
+ protected override void Update()
+ {
+ base.Update();
+
+ content.Scale = sizeScale;
+ content.Size = Vector2.Divide(Vector2.One, sizeScale);
+ }
+
///
/// The scale that is required for the size of the content to match and .
///
@@ -70,17 +94,6 @@ namespace osu.Game.Rulesets.UI
return Vector2.One;
}
}
-
- ///
- /// Scale the content to the required container size by multiplying by .
- ///
- protected override Vector2 DrawScale => sizeScale * base.DrawScale;
-
- protected override void Update()
- {
- base.Update();
- RelativeChildSize = new Vector2(CustomWidth.HasValue ? sizeScale.X : RelativeChildSize.X, CustomHeight.HasValue ? sizeScale.Y : RelativeChildSize.Y);
- }
}
}
}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/DragLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/DragLayer.cs
new file mode 100644
index 0000000000..51bb61b607
--- /dev/null
+++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/DragLayer.cs
@@ -0,0 +1,92 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Primitives;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Input;
+using osu.Game.Rulesets.Edit;
+using OpenTK.Graphics;
+
+namespace osu.Game.Screens.Edit.Screens.Compose.Layers
+{
+ ///
+ /// A layer that handles and displays drag selection for a collection of s.
+ ///
+ public class DragLayer : CompositeDrawable
+ {
+ private readonly Action performSelection;
+
+ ///
+ /// Invoked when the drag selection has finished.
+ ///
+ public event Action DragEnd;
+
+ private Drawable box;
+
+ ///
+ /// Creates a new .
+ ///
+ /// The selectable s.
+ public DragLayer(Action performSelection)
+ {
+ this.performSelection = performSelection;
+
+ RelativeSizeAxes = Axes.Both;
+ AlwaysPresent = true;
+ Alpha = 0;
+ }
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ InternalChild = box = new Container
+ {
+ Masking = true,
+ BorderColour = Color4.White,
+ BorderThickness = MaskSelection.BORDER_RADIUS,
+ Child = new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Alpha = 0.1f
+ }
+ };
+ }
+
+ protected override bool OnDragStart(InputState state)
+ {
+ this.FadeIn(250, Easing.OutQuint);
+ return true;
+ }
+
+ protected override bool OnDrag(InputState state)
+ {
+ var dragPosition = state.Mouse.NativeState.Position;
+ var dragStartPosition = state.Mouse.NativeState.PositionMouseDown ?? dragPosition;
+
+ var dragQuad = new Quad(dragStartPosition.X, dragStartPosition.Y, dragPosition.X - dragStartPosition.X, dragPosition.Y - dragStartPosition.Y);
+
+ // We use AABBFloat instead of RectangleF since it handles negative sizes for us
+ var dragRectangle = dragQuad.AABBFloat;
+
+ var topLeft = ToLocalSpace(dragRectangle.TopLeft);
+ var bottomRight = ToLocalSpace(dragRectangle.BottomRight);
+
+ box.Position = topLeft;
+ box.Size = bottomRight - topLeft;
+
+ performSelection?.Invoke(dragRectangle);
+ return true;
+ }
+
+ protected override bool OnDragEnd(InputState state)
+ {
+ this.FadeOut(250, Easing.OutQuint);
+ DragEnd?.Invoke();
+ return true;
+ }
+ }
+}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs
index 46b09e2c23..423cf0ed29 100644
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs
+++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs
@@ -2,65 +2,92 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Linq;
+using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Input;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects.Drawables;
+using osu.Game.Rulesets.UI;
namespace osu.Game.Screens.Edit.Screens.Compose.Layers
{
public class HitObjectMaskLayer : CompositeDrawable
{
+ private readonly Playfield playfield;
private readonly HitObjectComposer composer;
- private readonly Container overlayContainer;
- public HitObjectMaskLayer(HitObjectComposer composer)
+ private MaskContainer maskContainer;
+
+ public HitObjectMaskLayer(Playfield playfield, HitObjectComposer composer)
{
+ // we need the playfield as HitObjects may not be initialised until its BDL.
+ this.playfield = playfield;
+
this.composer = composer;
+
RelativeSizeAxes = Axes.Both;
+ }
- InternalChild = overlayContainer = new Container { RelativeSizeAxes = Axes.Both };
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ maskContainer = new MaskContainer();
+
+ var maskSelection = composer.CreateMaskSelection();
+
+ maskContainer.MaskSelected += maskSelection.HandleSelected;
+ maskContainer.MaskDeselected += maskSelection.HandleDeselected;
+ maskContainer.MaskSelectionRequested += maskSelection.HandleSelectionRequested;
+ maskContainer.MaskDragRequested += maskSelection.HandleDrag;
+
+ maskSelection.DeselectAll = maskContainer.DeselectAll;
+
+ var dragLayer = new DragLayer(maskContainer.Select);
+ dragLayer.DragEnd += () => maskSelection.UpdateVisibility();
+
+ InternalChildren = new Drawable[]
+ {
+ dragLayer,
+ maskSelection,
+ maskContainer,
+ dragLayer.CreateProxy()
+ };
+
+ foreach (var obj in playfield.HitObjects.Objects)
+ addMask(obj);
+ }
+
+ protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
+ {
+ maskContainer.DeselectAll();
+ return true;
}
///
- /// Adds an overlay for a which adds movement support.
+ /// Adds a mask for a which adds movement support.
///
- /// The to create an overlay for.
- public void AddOverlay(DrawableHitObject hitObject)
+ /// The to create a mask for.
+ private void addMask(DrawableHitObject hitObject)
{
- var overlay = composer.CreateMaskFor(hitObject);
- if (overlay == null)
+ var mask = composer.CreateMaskFor(hitObject);
+ if (mask == null)
return;
- overlayContainer.Add(overlay);
+ maskContainer.Add(mask);
}
///
- /// Removes the overlay for a .
+ /// Removes the mask for a .
///
- /// The to remove the overlay for.
- public void RemoveOverlay(DrawableHitObject hitObject)
+ /// The to remove the mask for.
+ private void removeMask(DrawableHitObject hitObject)
{
- var existing = overlayContainer.FirstOrDefault(h => h.HitObject == hitObject);
- if (existing == null)
+ var mask = maskContainer.FirstOrDefault(h => h.HitObject == hitObject);
+ if (mask == null)
return;
- existing.Hide();
- existing.Expire();
- }
-
- private SelectionBox currentSelectionBox;
-
- public void AddSelectionOverlay()
- {
- if (overlayContainer.Count > 0)
- AddInternal(currentSelectionBox = composer.CreateSelectionOverlay(overlayContainer));
- }
-
- public void RemoveSelectionOverlay()
- {
- currentSelectionBox?.Hide();
- currentSelectionBox?.Expire();
+ maskContainer.Remove(mask);
}
}
}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs
new file mode 100644
index 0000000000..b631628c9e
--- /dev/null
+++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs
@@ -0,0 +1,123 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Input;
+using osu.Game.Rulesets.Edit;
+using RectangleF = osu.Framework.Graphics.Primitives.RectangleF;
+
+namespace osu.Game.Screens.Edit.Screens.Compose.Layers
+{
+ public class MaskContainer : Container
+ {
+ ///
+ /// Invoked when any is selected.
+ ///
+ public event Action MaskSelected;
+
+ ///
+ /// Invoked when any is deselected.
+ ///
+ public event Action MaskDeselected;
+
+ ///
+ /// Invoked when any requests selection.
+ ///
+ public event Action MaskSelectionRequested;
+
+ ///
+ /// Invoked when any requests drag.
+ ///
+ public event Action MaskDragRequested;
+
+ private IEnumerable aliveMasks => AliveInternalChildren.Cast();
+
+ public MaskContainer()
+ {
+ RelativeSizeAxes = Axes.Both;
+ }
+
+ public override void Add(HitObjectMask drawable)
+ {
+ base.Add(drawable);
+
+ drawable.Selected += onMaskSelected;
+ drawable.Deselected += onMaskDeselected;
+ drawable.SelectionRequested += onSelectionRequested;
+ drawable.DragRequested += onDragRequested;
+ }
+
+ public override bool Remove(HitObjectMask drawable)
+ {
+ var result = base.Remove(drawable);
+
+ if (result)
+ {
+ drawable.Selected -= onMaskSelected;
+ drawable.Deselected -= onMaskDeselected;
+ drawable.SelectionRequested -= onSelectionRequested;
+ drawable.DragRequested -= onDragRequested;
+ }
+
+ return result;
+ }
+
+ ///
+ /// Select all masks in a given rectangle selection area.
+ ///
+ /// The rectangle to perform a selection on in screen-space coordinates.
+ public void Select(RectangleF rect)
+ {
+ foreach (var mask in aliveMasks.ToList())
+ {
+ if (mask.IsPresent && rect.Contains(mask.SelectionPoint))
+ mask.Select();
+ else
+ mask.Deselect();
+ }
+ }
+
+ ///
+ /// Deselects all selected s.
+ ///
+ public void DeselectAll() => aliveMasks.ToList().ForEach(m => m.Deselect());
+
+ private void onMaskSelected(HitObjectMask mask)
+ {
+ MaskSelected?.Invoke(mask);
+ ChangeChildDepth(mask, 1);
+ }
+
+ private void onMaskDeselected(HitObjectMask mask)
+ {
+ MaskDeselected?.Invoke(mask);
+ ChangeChildDepth(mask, 0);
+ }
+
+ private void onSelectionRequested(HitObjectMask mask, InputState state) => MaskSelectionRequested?.Invoke(mask, state);
+ private void onDragRequested(HitObjectMask mask, InputState state) => MaskDragRequested?.Invoke(mask, state);
+
+ protected override int Compare(Drawable x, Drawable y)
+ {
+ if (!(x is HitObjectMask xMask) || !(y is HitObjectMask yMask))
+ return base.Compare(x, y);
+ return Compare(xMask, yMask);
+ }
+
+ public int Compare(HitObjectMask x, HitObjectMask y)
+ {
+ // dpeth is used to denote selected status (we always want selected masks to handle input first).
+ int d = x.Depth.CompareTo(y.Depth);
+ if (d != 0)
+ return d;
+
+ // Put earlier hitobjects towards the end of the list, so they handle input first
+ int i = y.HitObject.HitObject.StartTime.CompareTo(x.HitObject.HitObject.StartTime);
+ return i == 0 ? CompareReverseChildID(x, y) : i;
+ }
+ }
+}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs
new file mode 100644
index 0000000000..76b8027b07
--- /dev/null
+++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs
@@ -0,0 +1,164 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using System.Collections.Generic;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Input;
+using osu.Game.Graphics;
+using osu.Game.Rulesets.Edit;
+using osu.Game.Rulesets.Edit.Types;
+using OpenTK;
+
+namespace osu.Game.Screens.Edit.Screens.Compose.Layers
+{
+ ///
+ /// A box which surrounds s and provides interactive handles, context menus etc.
+ ///
+ public class MaskSelection : CompositeDrawable
+ {
+ public const float BORDER_RADIUS = 2;
+
+ private readonly List selectedMasks;
+
+ private Drawable outline;
+
+ public MaskSelection()
+ {
+ selectedMasks = new List();
+
+ RelativeSizeAxes = Axes.Both;
+ AlwaysPresent = true;
+ Alpha = 0;
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colours)
+ {
+ InternalChild = outline = new Container
+ {
+ Masking = true,
+ BorderThickness = BORDER_RADIUS,
+ BorderColour = colours.Yellow,
+ Child = new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ AlwaysPresent = true,
+ Alpha = 0
+ }
+ };
+ }
+
+ #region User Input Handling
+
+ public void HandleDrag(HitObjectMask m, InputState state)
+ {
+ // Todo: Various forms of snapping
+
+ foreach (var mask in selectedMasks)
+ {
+ switch (mask.HitObject.HitObject)
+ {
+ case IHasEditablePosition editablePosition:
+ editablePosition.OffsetPosition(state.Mouse.Delta);
+ break;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Selection Handling
+
+ ///
+ /// Bind an action to deselect all selected masks.
+ ///
+ public Action DeselectAll { private get; set; }
+
+ ///
+ /// Handle a mask becoming selected.
+ ///
+ /// The mask.
+ public void HandleSelected(HitObjectMask mask) => selectedMasks.Add(mask);
+
+ ///
+ /// Handle a mask becoming deselected.
+ ///
+ /// The mask.
+ public void HandleDeselected(HitObjectMask mask)
+ {
+ selectedMasks.Remove(mask);
+
+ // We don't want to update visibility if > 0, since we may be deselecting masks during drag-selection
+ if (selectedMasks.Count == 0)
+ UpdateVisibility();
+ }
+
+ ///
+ /// Handle a mask requesting selection.
+ ///
+ /// The mask.
+ public void HandleSelectionRequested(HitObjectMask mask, InputState state)
+ {
+ if (state.Keyboard.ControlPressed)
+ {
+ if (mask.IsSelected)
+ mask.Deselect();
+ else
+ mask.Select();
+ }
+ else
+ {
+ if (mask.IsSelected)
+ return;
+
+ DeselectAll?.Invoke();
+ mask.Select();
+ }
+
+ UpdateVisibility();
+ }
+
+ #endregion
+
+ ///
+ /// Updates whether this is visible.
+ ///
+ internal void UpdateVisibility()
+ {
+ if (selectedMasks.Count > 0)
+ Show();
+ else
+ Hide();
+ }
+
+ protected override void Update()
+ {
+ base.Update();
+
+ if (selectedMasks.Count == 0)
+ return;
+
+ // Move the rectangle to cover the hitobjects
+ var topLeft = new Vector2(float.MaxValue, float.MaxValue);
+ var bottomRight = new Vector2(float.MinValue, float.MinValue);
+
+ bool hasSelection = false;
+
+ foreach (var mask in selectedMasks)
+ {
+ topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(mask.SelectionQuad.TopLeft));
+ bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(mask.SelectionQuad.BottomRight));
+ }
+
+ topLeft -= new Vector2(5);
+ bottomRight += new Vector2(5);
+
+ outline.Size = bottomRight - topLeft;
+ outline.Position = topLeft;
+ }
+ }
+}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/SelectionBox.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/SelectionBox.cs
deleted file mode 100644
index 0e5d824559..0000000000
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/SelectionBox.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using System.Collections.Generic;
-using System.Linq;
-using osu.Framework.Allocation;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Shapes;
-using osu.Framework.Input;
-using osu.Game.Graphics;
-using osu.Game.Rulesets.Edit;
-using osu.Game.Rulesets.Edit.Types;
-using osu.Game.Rulesets.Objects.Drawables;
-using OpenTK;
-
-namespace osu.Game.Screens.Edit.Screens.Compose.Layers
-{
- ///
- /// A box which surrounds s and provides interactive handles, context menus etc.
- ///
- public class SelectionBox : VisibilityContainer
- {
- private readonly IReadOnlyList overlays;
-
- public const float BORDER_RADIUS = 2;
-
- public SelectionBox(IReadOnlyList overlays)
- {
- this.overlays = overlays;
-
- Masking = true;
- BorderThickness = BORDER_RADIUS;
-
- InternalChild = new Box
- {
- RelativeSizeAxes = Axes.Both,
- AlwaysPresent = true,
- Alpha = 0
- };
-
- State = Visibility.Visible;
- }
-
- [BackgroundDependencyLoader]
- private void load(OsuColour colours)
- {
- BorderColour = colours.Yellow;
- }
-
- protected override void Update()
- {
- base.Update();
-
- // Todo: We might need to optimise this
-
- // Move the rectangle to cover the hitobjects
- var topLeft = new Vector2(float.MaxValue, float.MaxValue);
- var bottomRight = new Vector2(float.MinValue, float.MinValue);
-
- foreach (var obj in overlays)
- {
- topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.HitObject.SelectionQuad.TopLeft));
- bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.HitObject.SelectionQuad.BottomRight));
- }
-
- topLeft -= new Vector2(5);
- bottomRight += new Vector2(5);
-
- Size = bottomRight - topLeft;
- Position = topLeft;
- }
-
- public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => overlays.Any(o => o.ReceiveMouseInputAt(screenSpacePos));
-
- protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true;
-
- protected override bool OnDragStart(InputState state) => true;
-
- protected override bool OnDrag(InputState state)
- {
- // Todo: Various forms of snapping
- foreach (var hitObject in overlays.Select(o => o.HitObject.HitObject))
- {
- switch (hitObject)
- {
- case IHasEditablePosition editablePosition:
- editablePosition.OffsetPosition(state.Mouse.Delta);
- break;
- }
- }
- return true;
- }
-
- protected override bool OnDragEnd(InputState state) => true;
-
- public override bool DisposeOnDeathRemoval => true;
-
- protected override void PopIn() => this.FadeIn();
- protected override void PopOut() => this.FadeOut();
- }
-}
diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/SelectionLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/SelectionLayer.cs
deleted file mode 100644
index ab51385980..0000000000
--- a/osu.Game/Screens/Edit/Screens/Compose/Layers/SelectionLayer.cs
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using osu.Framework.Extensions.IEnumerableExtensions;
-using osu.Framework.Graphics;
-using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Primitives;
-using osu.Framework.Graphics.Shapes;
-using osu.Framework.Input;
-using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.UI;
-using OpenTK;
-using OpenTK.Graphics;
-using RectangleF = osu.Framework.Graphics.Primitives.RectangleF;
-
-namespace osu.Game.Screens.Edit.Screens.Compose.Layers
-{
- public class SelectionLayer : CompositeDrawable
- {
- ///
- /// Invoked when a is selected.
- ///
- public event Action ObjectSelected;
-
- ///
- /// Invoked when a is deselected.
- ///
- public event Action ObjectDeselected;
-
- ///
- /// Invoked when the selection has been cleared.
- ///
- public event Action SelectionCleared;
-
- ///
- /// Invoked when the user has finished selecting all s.
- ///
- public event Action SelectionFinished;
-
- private readonly Playfield playfield;
-
- public SelectionLayer(Playfield playfield)
- {
- this.playfield = playfield;
-
- RelativeSizeAxes = Axes.Both;
- }
-
- private DragBox dragBox;
-
- private readonly HashSet selectedHitObjects = new HashSet();
-
- protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
- {
- DeselectAll();
- return true;
- }
-
- protected override bool OnDragStart(InputState state)
- {
- AddInternal(dragBox = new DragBox());
- return true;
- }
-
- protected override bool OnDrag(InputState state)
- {
- dragBox.Show();
-
- var dragPosition = state.Mouse.NativeState.Position;
- var dragStartPosition = state.Mouse.NativeState.PositionMouseDown ?? dragPosition;
-
- var screenSpaceDragQuad = new Quad(dragStartPosition.X, dragStartPosition.Y, dragPosition.X - dragStartPosition.X, dragPosition.Y - dragStartPosition.Y);
-
- dragBox.SetDragRectangle(screenSpaceDragQuad.AABBFloat);
- selectQuad(screenSpaceDragQuad);
-
- return true;
- }
-
- protected override bool OnDragEnd(InputState state)
- {
- dragBox.Hide();
- dragBox.Expire();
-
- finishSelection();
-
- return true;
- }
-
- protected override bool OnClick(InputState state)
- {
- selectPoint(state.Mouse.NativeState.Position);
- finishSelection();
-
- return true;
- }
-
- ///
- /// Selects a .
- ///
- /// The to select.
- public void Select(DrawableHitObject hitObject)
- {
- if (!select(hitObject))
- return;
-
- clearSelection();
- finishSelection();
- }
-
- ///
- /// Selects a without performing capture updates.
- ///
- /// The to select.
- /// Whether was selected.
- private bool select(DrawableHitObject hitObject)
- {
- if (!selectedHitObjects.Add(hitObject))
- return false;
-
- ObjectSelected?.Invoke(hitObject);
- return true;
- }
-
- ///
- /// Deselects a .
- ///
- /// The to deselect.
- public void Deselect(DrawableHitObject hitObject)
- {
- if (!deselect(hitObject))
- return;
-
- clearSelection();
- finishSelection();
- }
-
- ///
- /// Deselects a without performing capture updates.
- ///
- /// The to deselect.
- /// Whether the was deselected.
- private bool deselect(DrawableHitObject hitObject)
- {
- if (!selectedHitObjects.Remove(hitObject))
- return false;
-
- ObjectDeselected?.Invoke(hitObject);
- return true;
- }
-
- ///
- /// Deselects all selected s.
- ///
- public void DeselectAll()
- {
- selectedHitObjects.ForEach(h => ObjectDeselected?.Invoke(h));
- selectedHitObjects.Clear();
-
- clearSelection();
- }
-
- ///
- /// Selects all hitobjects that are present within the area of a .
- ///
- /// The selection .
- // Todo: If needed we can severely reduce allocations in this method
- private void selectQuad(Quad screenSpaceQuad)
- {
- var expectedSelection = playfield.HitObjects.Objects.Where(h => h.IsAlive && h.IsPresent && screenSpaceQuad.Contains(h.SelectionPoint)).ToList();
-
- var toRemove = selectedHitObjects.Except(expectedSelection).ToList();
- foreach (var obj in toRemove)
- deselect(obj);
-
- expectedSelection.ForEach(h => select(h));
- }
-
- ///
- /// Selects the top-most hitobject that is present under a specific point.
- ///
- /// The to select at.
- private void selectPoint(Vector2 screenSpacePoint)
- {
- var target = playfield.HitObjects.Objects.Reverse().Where(h => h.IsAlive && h.IsPresent).FirstOrDefault(h => h.ReceiveMouseInputAt(screenSpacePoint));
- if (target == null)
- return;
-
- select(target);
- }
-
- private void clearSelection() => SelectionCleared?.Invoke();
-
- private void finishSelection()
- {
- if (selectedHitObjects.Count == 0)
- return;
- SelectionFinished?.Invoke();
- }
-
- ///
- /// A box that represents a drag selection.
- ///
- private class DragBox : VisibilityContainer
- {
- ///
- /// Creates a new .
- ///
- public DragBox()
- {
- Masking = true;
- BorderColour = Color4.White;
- BorderThickness = SelectionBox.BORDER_RADIUS;
-
- Child = new Box
- {
- RelativeSizeAxes = Axes.Both,
- Alpha = 0.1f
- };
- }
-
- public void SetDragRectangle(RectangleF rectangle)
- {
- var topLeft = Parent.ToLocalSpace(rectangle.TopLeft);
- var bottomRight = Parent.ToLocalSpace(rectangle.BottomRight);
-
- Position = topLeft;
- Size = bottomRight - topLeft;
- }
-
- public override bool DisposeOnDeathRemoval => true;
-
- protected override void PopIn() => this.FadeIn(250, Easing.OutQuint);
- protected override void PopOut() => this.FadeOut(250, Easing.OutQuint);
- }
- }
-}
diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs
index b0472f0e0d..93b36e48b9 100644
--- a/osu.Game/Screens/Play/Player.cs
+++ b/osu.Game/Screens/Play/Player.cs
@@ -83,12 +83,19 @@ namespace osu.Game.Screens.Play
private void load(AudioManager audio, APIAccess api, OsuConfigManager config)
{
this.api = api;
+
+ WorkingBeatmap working = Beatmap.Value;
+ if (working is DummyWorkingBeatmap)
+ {
+ Exit();
+ return;
+ }
+
sampleRestart = audio.Sample.Get(@"Gameplay/restart");
mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel);
userAudioOffset = config.GetBindable(OsuSetting.AudioOffset);
- WorkingBeatmap working = Beatmap.Value;
Beatmap beatmap;
try
diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs
index d5a91e1a6b..a3ea3b056b 100644
--- a/osu.Game/Screens/Select/PlaySongSelect.cs
+++ b/osu.Game/Screens/Select/PlaySongSelect.cs
@@ -150,7 +150,7 @@ namespace osu.Game.Screens.Select
var mods = modSelect.SelectedMods.Value;
if (mods.All(m => m.GetType() != autoType))
{
- modSelect.SelectedMods.Value = mods.Concat(new[] { auto });
+ modSelect.SelectedMods.Value = mods.Append(auto);
removeAutoModOnResume = true;
}
}
diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs
index 1b52507688..63d2543bc3 100644
--- a/osu.Game/Skinning/LegacySkin.cs
+++ b/osu.Game/Skinning/LegacySkin.cs
@@ -92,7 +92,7 @@ namespace osu.Game.Skinning
string lastPiece = filename.Split('/').Last();
var file = source.Files.FirstOrDefault(f =>
- string.Equals(hasExtension ? f.Filename : Path.GetFileNameWithoutExtension(f.Filename), lastPiece, StringComparison.InvariantCultureIgnoreCase));
+ string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), lastPiece, StringComparison.InvariantCultureIgnoreCase));
return file?.FileInfo.StoragePath;
}
diff --git a/osu.Desktop/OsuTestBrowser.cs b/osu.Game/Tests/OsuTestBrowser.cs
similarity index 87%
rename from osu.Desktop/OsuTestBrowser.cs
rename to osu.Game/Tests/OsuTestBrowser.cs
index 7aae2604af..6d9b28b5a7 100644
--- a/osu.Desktop/OsuTestBrowser.cs
+++ b/osu.Game/Tests/OsuTestBrowser.cs
@@ -3,12 +3,11 @@
using osu.Framework.Platform;
using osu.Framework.Testing;
-using osu.Game;
using osu.Game.Screens.Backgrounds;
-namespace osu.Desktop
+namespace osu.Game.Tests
{
- internal class OsuTestBrowser : OsuGameBase
+ public class OsuTestBrowser : OsuGameBase
{
protected override void LoadComplete()
{
diff --git a/osu.Game/Tests/TestTestCase.cs b/osu.Game/Tests/TestTestCase.cs
deleted file mode 100644
index 4efd57095e..0000000000
--- a/osu.Game/Tests/TestTestCase.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2007-2018 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using NUnit.Framework;
-using osu.Framework.Testing;
-
-namespace osu.Game.Tests
-{
- [TestFixture]
- internal class TestTestCase : TestCase
- {
- // This TestCase is required for nunit to not throw errors
- // See: https://github.com/nunit/nunit/issues/1118
- }
-}
diff --git a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs
new file mode 100644
index 0000000000..c2595231c9
--- /dev/null
+++ b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs
@@ -0,0 +1,29 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Testing.Input;
+
+namespace osu.Game.Tests.Visual
+{
+ public abstract class ManualInputManagerTestCase : OsuTestCase
+ {
+ protected override Container Content => InputManager;
+ protected readonly ManualInputManager InputManager;
+
+ protected ManualInputManagerTestCase()
+ {
+ base.Content.Add(InputManager = new ManualInputManager());
+ ReturnUserInput();
+ }
+
+ ///
+ /// Returns input back to the user.
+ ///
+ protected void ReturnUserInput()
+ {
+ AddStep("Return user input", () => InputManager.UseParentState = true);
+ }
+ }
+}
diff --git a/osu.Game/Tests/VisualTestRunner.cs b/osu.Game/Tests/VisualTestRunner.cs
new file mode 100644
index 0000000000..d8a4143368
--- /dev/null
+++ b/osu.Game/Tests/VisualTestRunner.cs
@@ -0,0 +1,22 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using osu.Framework;
+using osu.Framework.Platform;
+
+namespace osu.Game.Tests
+{
+ public static class VisualTestRunner
+ {
+ [STAThread]
+ public static int Main(string[] args)
+ {
+ using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true))
+ {
+ host.Run(new OsuTestBrowser());
+ return 0;
+ }
+ }
+ }
+}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index b42d76e331..367c3490d6 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -5,12 +5,6 @@
Library
AnyCPU
true
- ppy Pty Ltd
- 1.0.0.0
- ppy Pty Ltd 2007-2018
- osu.Game
- click the circles. to the beat.
- osu.Game
0
diff --git a/osu.TestProject.props b/osu.TestProject.props
new file mode 100644
index 0000000000..cb841f1940
--- /dev/null
+++ b/osu.TestProject.props
@@ -0,0 +1,29 @@
+
+
+
+ osu.Game.Tests.VisualTestRunner
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ VisualTestRunner.cs
+
+
+
+ false
+
+
\ No newline at end of file
diff --git a/osu.sln b/osu.sln
index 43a7fdf6c3..f017bf9eab 100644
--- a/osu.sln
+++ b/osu.sln
@@ -23,70 +23,74 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Tests", "osu.Game.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Desktop", "osu.Desktop\osu.Desktop.csproj", "{419659FD-72EA-4678-9EB8-B22A746CED70}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Catch.Tests", "osu.Game.Rulesets.Catch.Tests\osu.Game.Rulesets.Catch.Tests.csproj", "{3AD63355-D6B1-4365-8D31-5652C989BEF1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Mania.Tests", "osu.Game.Rulesets.Mania.Tests\osu.Game.Rulesets.Mania.Tests.csproj", "{7E9E9C34-B204-406B-82E2-E01E900699CD}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko.Tests", "osu.Game.Rulesets.Taiko.Tests\osu.Game.Rulesets.Taiko.Tests.csproj", "{B698561F-FB28-46B1-857E-3CA7B92F9D70}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
- VisualTests|Any CPU = VisualTests|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.VisualTests|Any CPU.Build.0 = Debug|Any CPU
{C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Release|Any CPU.Build.0 = Release|Any CPU
- {C76BF5B3-985E-4D39-95FE-97C9C879B83A}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
- {C76BF5B3-985E-4D39-95FE-97C9C879B83A}.VisualTests|Any CPU.Build.0 = Debug|Any CPU
{D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.Build.0 = Release|Any CPU
- {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
- {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.VisualTests|Any CPU.Build.0 = Debug|Any CPU
{C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU
- {C92A607B-1FDD-4954-9F92-03FF547D9080}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
- {C92A607B-1FDD-4954-9F92-03FF547D9080}.VisualTests|Any CPU.Build.0 = Debug|Any CPU
{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU
- {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
- {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.VisualTests|Any CPU.Build.0 = Debug|Any CPU
{F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU
- {F167E17A-7DE6-4AF5-B920-A5112296C695}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
- {F167E17A-7DE6-4AF5-B920-A5112296C695}.VisualTests|Any CPU.Build.0 = Debug|Any CPU
{48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU
- {48F4582B-7687-4621-9CBE-5C24197CB536}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
- {48F4582B-7687-4621-9CBE-5C24197CB536}.VisualTests|Any CPU.Build.0 = Debug|Any CPU
{BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.Build.0 = Release|Any CPU
- {54377672-20B1-40AF-8087-5CF73BF3953A}.VisualTests|Any CPU.ActiveCfg = Release|Any CPU
- {54377672-20B1-40AF-8087-5CF73BF3953A}.VisualTests|Any CPU.Build.0 = Release|Any CPU
{419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|Any CPU.Build.0 = Debug|Any CPU
{419659FD-72EA-4678-9EB8-B22A746CED70}.Release|Any CPU.ActiveCfg = Release|Any CPU
{419659FD-72EA-4678-9EB8-B22A746CED70}.Release|Any CPU.Build.0 = Release|Any CPU
- {419659FD-72EA-4678-9EB8-B22A746CED70}.VisualTests|Any CPU.ActiveCfg = VisualTests|Any CPU
- {419659FD-72EA-4678-9EB8-B22A746CED70}.VisualTests|Any CPU.Build.0 = VisualTests|Any CPU
+ {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE