1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-15 05:02:33 +08:00

Compare commits

...

1966 Commits

516 changed files with 23778 additions and 6664 deletions
+18
View File
@@ -7,3 +7,21 @@ insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
#Roslyn naming styles
#PascalCase for public and protected members
dotnet_naming_style.pascalcase.capitalization = pascal_case
dotnet_naming_symbols.public_members.applicable_accessibilities = public,internal,protected,protected_internal
dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event,delegate
dotnet_naming_rule.public_members_pascalcase.severity = suggestion
dotnet_naming_rule.public_members_pascalcase.symbols = public_members
dotnet_naming_rule.public_members_pascalcase.style = pascalcase
#camelCase for private members
dotnet_naming_style.camelcase.capitalization = camel_case
dotnet_naming_symbols.private_members.applicable_accessibilities = private
dotnet_naming_symbols.private_members.applicable_kinds = property,method,field,event,delegate
dotnet_naming_rule.private_members_camelcase.severity = suggestion
dotnet_naming_rule.private_members_camelcase.symbols = private_members
dotnet_naming_rule.private_members_camelcase.style = camelcase
+3 -2
View File
@@ -11,7 +11,7 @@
*.userprefs
# Build results
[Dd]ebug/
bin/[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
@@ -255,4 +255,5 @@ paket-files/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
*.pyc
Staging/
+2 -2
View File
@@ -11,7 +11,7 @@
"preLaunchTask": "build",
"runtimeExecutable": null,
"env": {},
"externalConsole": false
"console": "internalConsole"
},
{
"name": "Launch Desktop",
@@ -23,7 +23,7 @@
"preLaunchTask": "build",
"runtimeExecutable": null,
"env": {},
"externalConsole": false
"console": "internalConsole"
},
{
"name": "Attach",
+11 -13
View File
@@ -2,25 +2,23 @@
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "0.1.0",
"windows": {
"command": "msbuild"
},
"linux": {
"command": "xbuild"
},
"args": [
// Ask msbuild to generate full paths for file names.
"/property:GenerateFullPaths=true"
],
"taskSelector": "/t:",
"showOutput": "silent",
"tasks": [
{
"taskName": "build",
// Show the output window only if unrecognized errors occur.
"isShellCommand": true,
"showOutput": "silent",
"command": "xbuild",
"windows": {
"command": "msbuild"
},
"args": [
// Ask msbuild to generate full paths for file names.
"/property:GenerateFullPaths=true"
],
// Use the standard MS compiler pattern to detect errors, warnings and infos
"problemMatcher": "$msCompile"
"problemMatcher": "$msCompile",
"isBuildCommand": true
}
]
}
+2 -4
View File
@@ -1,6 +1,4 @@
The MIT License
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.
+23
View File
@@ -0,0 +1,23 @@
clone_depth: 1
version: '{branch}-{build}'
configuration: Debug
cache:
- C:\ProgramData\chocolatey\bin -> appveyor.yml
- C:\ProgramData\chocolatey\lib -> appveyor.yml
- inspectcode -> appveyor.yml
- packages -> **\packages.config
install:
- cmd: git submodule update --init --recursive
- cmd: choco install resharper-clt -y
- cmd: choco install nvika -y
- cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.2.2/CodeFileSanity.exe
before_build:
- cmd: CodeFileSanity.exe
- cmd: nuget restore
build:
project: osu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: inspectcode /o="inspectcodereport.xml" /caches-home="inspectcode" osu.sln
- cmd: NVika parsereport "inspectcodereport.xml"
+36
View File
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<appSettings>
<add key="StagingFolder" value="Staging" />
<add key="ReleasesFolder" value="Releases" />
<add key="GitHubAccessToken" value="" />
<add key="GitHubUsername" value="ppy" />
<add key="GitHubRepoName" value="osu" />
<add key="ProjectName" value="osu.Desktop" />
<add key="NuSpecName" value="osu.Desktop\osu.nuspec" />
<add key="SolutionName" value="osu" />
<add key="TargetName" value="Client\osu.Desktop" />
<add key="PackageName" value="osulazer" />
<add key="IconName" value="lazer.ico" />
<add key="CodeSigningCertificate" value="" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="DeltaCompressionDotNet.MsDelta" publicKeyToken="46b2138a390abf55" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -3,17 +3,14 @@
using Newtonsoft.Json;
namespace osu.Game.Online
namespace osu.Desktop.Deploy
{
public class User
public class GitHubObject
{
[JsonProperty(@"username")]
public string Name;
[JsonProperty(@"id")]
public int Id;
[JsonProperty(@"colour")]
public string Colour;
[JsonProperty(@"name")]
public string Name;
}
}
}
+28
View File
@@ -0,0 +1,28 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
namespace osu.Desktop.Deploy
{
public class GitHubRelease
{
[JsonProperty(@"id")]
public int Id;
[JsonProperty(@"tag_name")]
public string TagName => $"v{Name}";
[JsonProperty(@"name")]
public string Name;
[JsonProperty(@"draft")]
public bool Draft;
[JsonProperty(@"prerelease")]
public bool PreRelease;
[JsonProperty(@"upload_url")]
public string UploadUrl;
}
}
+428
View File
@@ -0,0 +1,428 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using Newtonsoft.Json;
using osu.Framework.IO.Network;
using FileWebRequest = osu.Framework.IO.Network.FileWebRequest;
using WebRequest = osu.Framework.IO.Network.WebRequest;
namespace osu.Desktop.Deploy
{
internal static class Program
{
private const string nuget_path = @"packages\NuGet.CommandLine.3.5.0\tools\NuGet.exe";
private const string squirrel_path = @"packages\squirrel.windows.1.5.2\tools\Squirrel.exe";
private const string msbuild_path = @"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe";
public static string StagingFolder = ConfigurationManager.AppSettings["StagingFolder"];
public static string ReleasesFolder = ConfigurationManager.AppSettings["ReleasesFolder"];
public static string GitHubAccessToken = ConfigurationManager.AppSettings["GitHubAccessToken"];
public static string GitHubUsername = ConfigurationManager.AppSettings["GitHubUsername"];
public static string GitHubRepoName = ConfigurationManager.AppSettings["GitHubRepoName"];
public static string SolutionName = ConfigurationManager.AppSettings["SolutionName"];
public static string ProjectName = ConfigurationManager.AppSettings["ProjectName"];
public static string NuSpecName = ConfigurationManager.AppSettings["NuSpecName"];
public static string TargetName = ConfigurationManager.AppSettings["TargetName"];
public static string PackageName = ConfigurationManager.AppSettings["PackageName"];
public static string IconName = ConfigurationManager.AppSettings["IconName"];
public static string CodeSigningCertificate = ConfigurationManager.AppSettings["CodeSigningCertificate"];
public static string GitHubApiEndpoint => $"https://api.github.com/repos/{GitHubUsername}/{GitHubRepoName}/releases";
public static string GitHubReleasePage => $"https://github.com/{GitHubUsername}/{GitHubRepoName}/releases";
/// <summary>
/// How many previous build deltas we want to keep when publishing.
/// </summary>
private const int keep_delta_count = 3;
private static string codeSigningCmd => string.IsNullOrEmpty(codeSigningPassword) ? "" : $"-n \"/a /f {codeSigningCertPath} /p {codeSigningPassword} /t http://timestamp.comodoca.com/authenticode\"";
private static string homeDir => Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
private static string codeSigningCertPath => Path.Combine(homeDir, CodeSigningCertificate);
private static string solutionPath => Environment.CurrentDirectory;
private static string stagingPath => Path.Combine(solutionPath, StagingFolder);
private static string iconPath => Path.Combine(solutionPath, ProjectName, IconName);
private static string nupkgFilename(string ver) => $"{PackageName}.{ver}.nupkg";
private static string nupkgDistroFilename(string ver) => $"{PackageName}-{ver}-full.nupkg";
private static readonly Stopwatch sw = new Stopwatch();
private static string codeSigningPassword;
public static void Main(string[] args)
{
displayHeader();
findSolutionPath();
if (!Directory.Exists(ReleasesFolder))
{
write("WARNING: No release directory found. Make sure you want this!", ConsoleColor.Yellow);
Directory.CreateDirectory(ReleasesFolder);
}
checkGitHubReleases();
refreshDirectory(StagingFolder);
//increment build number until we have a unique one.
string verBase = DateTime.Now.ToString("yyyy.Mdd.");
int increment = 0;
while (Directory.GetFiles(ReleasesFolder, $"*{verBase}{increment}*").Any())
increment++;
string version = $"{verBase}{increment}";
Console.ForegroundColor = ConsoleColor.White;
Console.Write($"Ready to deploy {version}: ");
Console.ReadLine();
sw.Start();
if (!string.IsNullOrEmpty(CodeSigningCertificate))
{
Console.Write("Enter code signing password: ");
codeSigningPassword = readLineMasked();
}
write("Restoring NuGet packages...");
runCommand(nuget_path, "restore " + solutionPath);
write("Updating AssemblyInfo...");
updateAssemblyInfo(version);
write("Running build process...");
runCommand(msbuild_path, $"/v:quiet /m /t:{TargetName.Replace('.', '_')} /p:OutputPath={stagingPath};Configuration=Release {SolutionName}.sln");
write("Creating NuGet deployment package...");
runCommand(nuget_path, $"pack {NuSpecName} -Version {version} -Properties Configuration=Deploy -OutputDirectory {stagingPath} -BasePath {stagingPath}");
//prune once before checking for files so we can avoid erroring on files which aren't even needed for this build.
pruneReleases();
checkReleaseFiles();
write("Running squirrel build...");
runCommand(squirrel_path, $"--releasify {stagingPath}\\{nupkgFilename(version)} --setupIcon {iconPath} --icon {iconPath} {codeSigningCmd} --no-msi");
//prune again to clean up before upload.
pruneReleases();
//rename setup to install.
File.Copy(Path.Combine(ReleasesFolder, "Setup.exe"), Path.Combine(ReleasesFolder, "install.exe"), true);
File.Delete(Path.Combine(ReleasesFolder, "Setup.exe"));
uploadBuild(version);
//reset assemblyinfo.
updateAssemblyInfo("0.0.0");
write("Done!", ConsoleColor.White);
Console.ReadLine();
}
private static void displayHeader()
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine();
Console.WriteLine(" Please note that OSU! and PPY are registered trademarks and as such covered by trademark law.");
Console.WriteLine(" Do not distribute builds of this project publicly that make use of these.");
Console.ResetColor();
Console.WriteLine();
}
/// <summary>
/// Ensure we have all the files in the release directory which are expected to be there.
/// This should have been accounted for in earlier steps, and just serves as a verification step.
/// </summary>
private static void checkReleaseFiles()
{
var releaseLines = getReleaseLines();
//ensure we have all files necessary
foreach (var l in releaseLines)
if (!File.Exists(Path.Combine(ReleasesFolder, l.Filename)))
error($"Local file missing {l.Filename}");
}
private static IEnumerable<ReleaseLine> getReleaseLines() => File.ReadAllLines(Path.Combine(ReleasesFolder, "RELEASES")).Select(l => new ReleaseLine(l));
private static void pruneReleases()
{
write("Pruning RELEASES...");
var releaseLines = getReleaseLines().ToList();
var fulls = releaseLines.Where(l => l.Filename.Contains("-full")).Reverse().Skip(1);
//remove any FULL releases (except most recent)
foreach (var l in fulls)
{
write($"- Removing old release {l.Filename}", ConsoleColor.Yellow);
File.Delete(Path.Combine(ReleasesFolder, l.Filename));
releaseLines.Remove(l);
}
//remove excess deltas
var deltas = releaseLines.Where(l => l.Filename.Contains("-delta")).ToArray();
if (deltas.Length > keep_delta_count)
{
foreach (var l in deltas.Take(deltas.Length - keep_delta_count))
{
write($"- Removing old delta {l.Filename}", ConsoleColor.Yellow);
File.Delete(Path.Combine(ReleasesFolder, l.Filename));
releaseLines.Remove(l);
}
}
var lines = new List<string>();
releaseLines.ForEach(l => lines.Add(l.ToString()));
File.WriteAllLines(Path.Combine(ReleasesFolder, "RELEASES"), lines);
}
private static void uploadBuild(string version)
{
if (string.IsNullOrEmpty(GitHubAccessToken) || string.IsNullOrEmpty(codeSigningCertPath))
return;
write("Publishing to GitHub...");
write($"- Creating release {version}...", ConsoleColor.Yellow);
var req = new JsonWebRequest<GitHubRelease>($"{GitHubApiEndpoint}")
{
Method = HttpMethod.POST,
};
req.AddRaw(JsonConvert.SerializeObject(new GitHubRelease
{
Name = version,
Draft = true,
PreRelease = true
}));
req.AuthenticatedBlockingPerform();
var assetUploadUrl = req.ResponseObject.UploadUrl.Replace("{?name,label}", "?name={0}");
foreach (var a in Directory.GetFiles(ReleasesFolder).Reverse()) //reverse to upload RELEASES first.
{
write($"- Adding asset {a}...", ConsoleColor.Yellow);
var upload = new WebRequest(assetUploadUrl, Path.GetFileName(a))
{
Method = HttpMethod.POST,
Timeout = 240000,
ContentType = "application/octet-stream",
};
upload.AddRaw(File.ReadAllBytes(a));
upload.AuthenticatedBlockingPerform();
}
openGitHubReleasePage();
}
private static void openGitHubReleasePage() => Process.Start(GitHubReleasePage);
private static void checkGitHubReleases()
{
write("Checking GitHub releases...");
var req = new JsonWebRequest<List<GitHubRelease>>($"{GitHubApiEndpoint}");
req.AuthenticatedBlockingPerform();
var lastRelease = req.ResponseObject.FirstOrDefault();
if (lastRelease == null)
return;
if (lastRelease.Draft)
{
openGitHubReleasePage();
error("There's a pending draft release! You probably don't want to push a build with this present.");
}
//there's a previous release for this project.
var assetReq = new JsonWebRequest<List<GitHubObject>>($"{GitHubApiEndpoint}/{lastRelease.Id}/assets");
assetReq.AuthenticatedBlockingPerform();
var assets = assetReq.ResponseObject;
//make sure our RELEASES file is the same as the last build on the server.
var releaseAsset = assets.FirstOrDefault(a => a.Name == "RELEASES");
//if we don't have a RELEASES asset then the previous release likely wasn't a Squirrel one.
if (releaseAsset == null) return;
write($"Last GitHub release was {lastRelease.Name}.");
bool requireDownload = false;
if (!File.Exists(Path.Combine(ReleasesFolder, nupkgDistroFilename(lastRelease.Name))))
{
write("Last version's package not found locally.", ConsoleColor.Red);
requireDownload = true;
}
else
{
var lastReleases = new RawFileWebRequest($"{GitHubApiEndpoint}/assets/{releaseAsset.Id}");
lastReleases.AuthenticatedBlockingPerform();
if (File.ReadAllText(Path.Combine(ReleasesFolder, "RELEASES")) != lastReleases.ResponseString)
{
write("Server's RELEASES differed from ours.", ConsoleColor.Red);
requireDownload = true;
}
}
if (!requireDownload) return;
write("Refreshing local releases directory...");
refreshDirectory(ReleasesFolder);
foreach (var a in assets)
{
if (a.Name.EndsWith(".exe")) continue;
write($"- Downloading {a.Name}...", ConsoleColor.Yellow);
new FileWebRequest(Path.Combine(ReleasesFolder, a.Name), $"{GitHubApiEndpoint}/assets/{a.Id}").AuthenticatedBlockingPerform();
}
}
private static void refreshDirectory(string directory)
{
if (Directory.Exists(directory))
Directory.Delete(directory, true);
Directory.CreateDirectory(directory);
}
private static void updateAssemblyInfo(string version)
{
string file = Path.Combine(ProjectName, "Properties", "AssemblyInfo.cs");
var l1 = File.ReadAllLines(file);
List<string> l2 = new List<string>();
foreach (var l in l1)
{
if (l.StartsWith("[assembly: AssemblyVersion("))
l2.Add($"[assembly: AssemblyVersion(\"{version}\")]");
else if (l.StartsWith("[assembly: AssemblyFileVersion("))
l2.Add($"[assembly: AssemblyFileVersion(\"{version}\")]");
else
l2.Add(l);
}
File.WriteAllLines(file, l2);
}
/// <summary>
/// Find the base path of the active solution (git checkout location)
/// </summary>
private static void findSolutionPath()
{
string path = Path.GetDirectoryName(Environment.CommandLine.Replace("\"", "").Trim());
if (string.IsNullOrEmpty(path))
path = Environment.CurrentDirectory;
while (!File.Exists(Path.Combine(path, $"{SolutionName}.sln")))
path = path.Remove(path.LastIndexOf('\\'));
path += "\\";
Environment.CurrentDirectory = path;
}
private static bool runCommand(string command, string args)
{
var psi = new ProcessStartInfo(command, args)
{
WorkingDirectory = solutionPath,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden
};
Process p = Process.Start(psi);
if (p == null) return false;
string output = p.StandardOutput.ReadToEnd();
output += p.StandardError.ReadToEnd();
if (p.ExitCode == 0) return true;
write(output);
error($"Command {command} {args} failed!");
return false;
}
private static string readLineMasked()
{
var fg = Console.ForegroundColor;
Console.ForegroundColor = Console.BackgroundColor;
var ret = Console.ReadLine();
Console.ForegroundColor = fg;
return ret;
}
private static void error(string message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"FATAL ERROR: {message}");
Console.ReadLine();
Environment.Exit(-1);
}
private static void write(string message, ConsoleColor col = ConsoleColor.Gray)
{
if (sw.ElapsedMilliseconds > 0)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(sw.ElapsedMilliseconds.ToString().PadRight(8));
}
Console.ForegroundColor = col;
Console.WriteLine(message);
}
public static void AuthenticatedBlockingPerform(this WebRequest r)
{
r.AddHeader("Authorization", $"token {GitHubAccessToken}");
r.BlockingPerform();
}
}
internal class RawFileWebRequest : WebRequest
{
public RawFileWebRequest(string url) : base(url)
{
}
protected override HttpWebRequest CreateWebRequest(string requestString = null)
{
var req = base.CreateWebRequest(requestString);
req.Accept = "application/octet-stream";
return req;
}
}
internal class ReleaseLine
{
public string Hash;
public string Filename;
public int Filesize;
public ReleaseLine(string line)
{
var split = line.Split(' ');
Hash = split[0];
Filename = split[1];
Filesize = int.Parse(split[2]);
}
public override string ToString() => $"{Hash} {Filename} {Filesize}";
}
}
@@ -0,0 +1,38 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu.Desktop.Deploy")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("osu.Desktop.Deploy")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("baea2f74-0315-4667-84e0-acac0b4bf785")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BAEA2F74-0315-4667-84E0-ACAC0B4BF785}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>osu.Desktop.Deploy</RootNamespace>
<AssemblyName>osu.Desktop.Deploy</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>osu.Desktop.Deploy.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="DeltaCompressionDotNet, Version=1.1.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="DeltaCompressionDotNet.MsDelta, Version=1.1.0.0, Culture=neutral, PublicKeyToken=46b2138a390abf55, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.MsDelta.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="DeltaCompressionDotNet.PatchApi, Version=1.1.0.0, Culture=neutral, PublicKeyToken=3e8888ee913ed789, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Squirrel, Version=1.5.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\Squirrel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="GitHubObject.cs" />
<Compile Include="GitHubRelease.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="App.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu-framework\osu.Framework.Desktop\osu.Framework.Desktop.csproj">
<Project>{65dc628f-a640-4111-ab35-3a5652bc1e17}</Project>
<Name>osu.Framework.Desktop</Name>
</ProjectReference>
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
<Project>{C76BF5B3-985E-4D39-95FE-97C9C879B83A}</Project>
<Name>osu.Framework</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net452" />
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net452" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
<package id="NuGet.CommandLine" version="3.5.0" targetFramework="net452" developmentDependency="true" />
<package id="Splat" version="2.0.0" targetFramework="net452" />
<package id="squirrel.windows" version="1.5.2" targetFramework="net452" />
</packages>
@@ -13,10 +13,10 @@ using osu.Game.Modes.Taiko;
namespace osu.Desktop.Tests
{
[TestFixture]
public class BenchmarkTest
public class VisualTests
{
[Test]
public void TestBenchmark()
public void TestVisualTests()
{
using (var host = new HeadlessGameHost())
{
@@ -25,8 +25,7 @@ namespace osu.Desktop.Tests
Ruleset.Register(new ManiaRuleset());
Ruleset.Register(new CatchRuleset());
host.Add(new Benchmark());
host.Run();
host.Run(new AutomatedVisualTestGame());
}
}
}
-11
View File
@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+14 -11
View File
@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,21 +29,21 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=3.6.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="Newtonsoft.Json">
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="SQLiteNetExtensions">
<HintPath>$(SolutionDir)\packages\SQLiteNetExtensions.1.3.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\SQLiteNetExtensions.dll</HintPath>
</Reference>
@@ -52,12 +53,9 @@
<Reference Include="SQLite.Net.Platform.Generic">
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.1.1\lib\net40\SQLite.Net.Platform.Generic.dll</HintPath>
</Reference>
<Reference Include="OpenTK">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="BenchmarkTest.cs" />
<Compile Include="VisualTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu-framework\osu.Framework.Desktop\osu.Framework.Desktop.csproj">
@@ -98,12 +96,17 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
+6 -2
View File
@@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="NUnit" version="3.5.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
<package id="NUnit" version="3.6.1" targetFramework="net45" />
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
@@ -0,0 +1,20 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Testing;
using osu.Game;
namespace osu.Desktop.VisualTests
{
public class AutomatedVisualTestGame : OsuGameBase
{
protected override void LoadComplete()
{
base.LoadComplete();
// Have to construct this here, rather than in the constructor, because
// we depend on some dependencies to be loaded within OsuGameBase.load().
Add(new TestRunner(new TestBrowser()));
}
}
}
@@ -0,0 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
namespace osu.Desktop.VisualTests.Beatmaps
{
public class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
{
this.beatmap = beatmap;
}
private readonly Beatmap beatmap;
protected override Beatmap GetBeatmap() => beatmap;
protected override Texture GetBackground() => null;
protected override Track GetTrack() => null;
}
}
-56
View File
@@ -1,56 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Desktop.Platform;
using osu.Framework.GameModes.Testing;
using osu.Game;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
using osu.Game.Modes.Mania;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Taiko;
namespace osu.Desktop.VisualTests
{
public class Benchmark : OsuGameBase
{
private double timePerTest = 200;
[BackgroundDependencyLoader]
private void load(BaseGame game)
{
Host.MaximumDrawHz = int.MaxValue;
Host.MaximumUpdateHz = int.MaxValue;
Host.MaximumInactiveHz = int.MaxValue;
}
protected override void LoadComplete()
{
base.LoadComplete();
TestBrowser f = new TestBrowser();
Add(f);
Console.WriteLine($@"{Time}: Running {f.TestCount} tests for {timePerTest}ms each...");
for (int i = 1; i < f.TestCount; i++)
{
int loadableCase = i;
Scheduler.AddDelayed(delegate
{
f.LoadTest(loadableCase);
Console.WriteLine($@"{Time}: Switching to test #{loadableCase}");
}, loadableCase * timePerTest);
}
Scheduler.AddDelayed(Host.Exit, f.TestCount * timePerTest);
}
}
}
+1 -2
View File
@@ -1,8 +1,7 @@
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
@@ -15,7 +15,7 @@ namespace osu.Desktop.VisualTests.Platform
public TestStorage(string baseName) : base(baseName)
{
}
public override SQLiteConnection GetDatabase(string name)
{
ISQLitePlatform platform;
@@ -23,7 +23,7 @@ namespace osu.Desktop.VisualTests.Platform
platform = new SQLitePlatformWin32();
else
platform = new SQLitePlatformGeneric();
return new SQLiteConnection(platform, $@":memory:");
return new SQLiteConnection(platform, @":memory:");
}
}
}
+3 -5
View File
@@ -3,7 +3,6 @@
using System;
using osu.Framework.Desktop;
using osu.Framework.Desktop.Platform;
using osu.Framework.Platform;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
@@ -20,7 +19,7 @@ namespace osu.Desktop.VisualTests
{
bool benchmark = args.Length > 0 && args[0] == @"-benchmark";
using (BasicGameHost host = Host.GetSuitableHost(@"osu"))
using (GameHost host = Host.GetSuitableHost(@"osu"))
{
Ruleset.Register(new OsuRuleset());
Ruleset.Register(new TaikoRuleset());
@@ -28,10 +27,9 @@ namespace osu.Desktop.VisualTests
Ruleset.Register(new CatchRuleset());
if (benchmark)
host.Add(new Benchmark());
host.Run(new AutomatedVisualTestGame());
else
host.Add(new VisualTestGame());
host.Run();
host.Run(new VisualTestGame());
}
}
}
@@ -0,0 +1,27 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Screens.Select;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseBeatmapDetailArea : TestCase
{
public override string Description => @"Beatmap details in song select";
public override void Reset()
{
base.Reset();
Add(new BeatmapDetailArea
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(550f, 450f),
});
}
}
}
@@ -0,0 +1,65 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Screens.Select;
using System.Linq;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseBeatmapDetails : TestCase
{
public override string Description => "BeatmapDetails tab of BeatmapDetailArea";
private BeatmapDetails details;
public override void Reset()
{
base.Reset();
Add(details = new BeatmapDetails
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding(150),
Beatmap = new BeatmapInfo
{
Version = "VisualTest",
Metadata = new BeatmapMetadata
{
Source = "Some guy",
Tags = "beatmap metadata example with a very very long list of tags and not much creativity",
},
Difficulty = new BeatmapDifficulty
{
CircleSize = 7,
ApproachRate = 3.5f,
OverallDifficulty = 5.7f,
DrainRate = 1,
},
StarDifficulty = 5.3f,
Metrics = new BeatmapMetrics
{
Ratings = Enumerable.Range(0,10),
Fails = Enumerable.Range(lastRange, 100).Select(i => i % 12 - 6),
Retries = Enumerable.Range(lastRange - 3, 100).Select(i => i % 12 - 6),
},
},
});
AddRepeatStep("fail values", newRetryAndFailValues, 10);
}
private int lastRange = 1;
private void newRetryAndFailValues()
{
details.Beatmap.Metrics.Fails = Enumerable.Range(lastRange, 100).Select(i => i % 12 - 6);
details.Beatmap.Metrics.Retries = Enumerable.Range(lastRange - 3, 100).Select(i => i % 12 - 6);
details.Beatmap = details.Beatmap;
lastRange += 100;
}
}
}
@@ -0,0 +1,32 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Graphics;
using OpenTK.Input;
using osu.Framework.Testing;
using osu.Game.Graphics;
using osu.Game.Screens.Select.Options;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseBeatmapOptionsOverlay : TestCase
{
public override string Description => @"Beatmap options in song select";
public override void Reset()
{
base.Reset();
var overlay = new BeatmapOptionsOverlay();
overlay.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, Color4.Purple, null, Key.Number1);
overlay.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, Color4.Purple, null, Key.Number2);
overlay.AddButton(@"Edit", @"Beatmap", FontAwesome.fa_pencil, Color4.Yellow, null, Key.Number3);
overlay.AddButton(@"Delete", @"Beatmap", FontAwesome.fa_trash, Color4.Pink, null, Key.Number4, float.MaxValue);
Add(overlay);
AddStep(@"Toggle", overlay.ToggleVisibility);
}
}
}
@@ -1,143 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Framework;
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Threading;
using osu.Game;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.Chat;
using OpenTK;
using osu.Framework.Allocation;
using osu.Game.Online.Chat.Drawables;
using osu.Game.Overlays;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseChatDisplay : TestCase
internal class TestCaseChatDisplay : TestCase
{
private ScheduledDelegate messageRequest;
public override string Name => @"Chat";
public override string Description => @"Testing API polling";
FlowContainer flow;
private Scheduler scheduler = new Scheduler();
private APIAccess api;
private ChannelDisplay channelDisplay;
[BackgroundDependencyLoader]
private void load(APIAccess api)
{
this.api = api;
}
public override string Description => @"Testing chat api and overlay";
public override void Reset()
{
base.Reset();
if (api.State != APIState.Online)
api.OnStateChange += delegate { initializeChannels(); };
else
initializeChannels();
}
protected override void Update()
{
scheduler.Update();
base.Update();
}
private long? lastMessageId;
List<Channel> careChannels;
private void initializeChannels()
{
careChannels = new List<Channel>();
if (api.State != APIState.Online)
return;
Add(flow = new FlowContainer
Add(new ChatOverlay
{
RelativeSizeAxes = Axes.Both,
Direction = FlowDirection.VerticalOnly
State = Visibility.Visible
});
SpriteText loading;
Add(loading = new SpriteText
{
Text = @"Loading available channels...",
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
TextSize = 40,
});
messageRequest?.Cancel();
ListChannelsRequest req = new ListChannelsRequest();
req.Success += delegate (List<Channel> channels)
{
Scheduler.Add(delegate
{
loading.FadeOut(100);
});
addChannel(channels.Find(c => c.Name == @"#osu"));
addChannel(channels.Find(c => c.Name == @"#lobby"));
addChannel(channels.Find(c => c.Name == @"#english"));
messageRequest = scheduler.AddDelayed(() => FetchNewMessages(api), 1000, true);
};
api.Queue(req);
}
private void addChannel(Channel channel)
{
flow.Add(channelDisplay = new ChannelDisplay(channel)
{
Size = new Vector2(1, 0.3f)
});
careChannels.Add(channel);
}
GetMessagesRequest fetchReq;
public void FetchNewMessages(APIAccess api)
{
if (fetchReq != null) return;
fetchReq = new GetMessagesRequest(careChannels, lastMessageId);
fetchReq.Success += delegate (List<Message> messages)
{
foreach (Message m in messages)
{
careChannels.Find(c => c.Id == m.ChannelId).AddNewMessages(m);
}
lastMessageId = messages.LastOrDefault()?.Id ?? lastMessageId;
Debug.Write("success!");
fetchReq = null;
};
fetchReq.Failure += delegate
{
Debug.Write("failure!");
fetchReq = null;
};
api.Queue(fetchReq);
}
}
}
@@ -0,0 +1,78 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Testing;
using osu.Game.Graphics;
using osu.Game.Overlays;
using osu.Game.Overlays.Dialog;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseDialogOverlay : TestCase
{
public override string Description => @"Display dialogs";
private DialogOverlay overlay;
public override void Reset()
{
base.Reset();
Add(overlay = new DialogOverlay());
AddStep("dialog #1", () => overlay.Push(new PopupDialog
{
Icon = FontAwesome.fa_trash_o,
HeaderText = @"Confirm deletion of",
BodyText = @"Ayase Rie - Yuima-ru*World TVver.",
Buttons = new PopupDialogButton[]
{
new PopupDialogOkButton
{
Text = @"I never want to see this again.",
Action = () => System.Console.WriteLine(@"OK"),
},
new PopupDialogCancelButton
{
Text = @"Firetruck, I still want quick ranks!",
Action = () => System.Console.WriteLine(@"Cancel"),
},
},
}));
AddStep("dialog #2", () => overlay.Push(new PopupDialog
{
Icon = FontAwesome.fa_gear,
HeaderText = @"What do you want to do with",
BodyText = "Camellia as \"Bang Riot\" - Blastix Riotz",
Buttons = new PopupDialogButton[]
{
new PopupDialogOkButton
{
Text = @"Manage collections",
},
new PopupDialogOkButton
{
Text = @"Delete...",
},
new PopupDialogOkButton
{
Text = @"Remove from unplayed",
},
new PopupDialogOkButton
{
Text = @"Clear local scores",
},
new PopupDialogOkButton
{
Text = @"Edit",
},
new PopupDialogCancelButton
{
Text = @"Cancel",
},
},
}));
}
}
}
@@ -0,0 +1,87 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Framework.Testing;
using osu.Game.Screens.Tournament;
using osu.Game.Screens.Tournament.Teams;
using osu.Game.Users;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseDrawings : TestCase
{
public override string Description => "Tournament drawings";
public override void Reset()
{
base.Reset();
Add(new Drawings
{
TeamList = new TestTeamList(),
});
}
private class TestTeamList : ITeamList
{
public IEnumerable<Country> Teams { get; } = new[]
{
new Country
{
FlagName = "GB",
FullName = "United Kingdom",
Acronym = "UK"
},
new Country
{
FlagName = "FR",
FullName = "France",
Acronym = "FRA"
},
new Country
{
FlagName = "CN",
FullName = "China",
Acronym = "CHN"
},
new Country
{
FlagName = "AU",
FullName = "Australia",
Acronym = "AUS"
},
new Country
{
FlagName = "JP",
FullName = "Japan",
Acronym = "JPN"
},
new Country
{
FlagName = "RO",
FullName = "Romania",
Acronym = "ROM"
},
new Country
{
FlagName = "IT",
FullName = "Italy",
Acronym = "PIZZA"
},
new Country
{
FlagName = "VE",
FullName = "Venezuela",
Acronym = "VNZ"
},
new Country
{
FlagName = "US",
FullName = "United States of America",
Acronym = "USA"
},
};
}
}
}
@@ -1,45 +1,39 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Framework.GameModes.Testing;
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.MathUtils;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Modes.Catch;
using osu.Game.Database;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Mania;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.Taiko;
using osu.Game.Modes.Taiko.UI;
using OpenTK;
using System.Collections.Generic;
using osu.Desktop.VisualTests.Beatmaps;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseGamefield : TestCase
internal class TestCaseGamefield : TestCase
{
public override string Name => @"Gamefield";
public override string Description => @"Showing hitobjects and what not.";
public override void Reset()
{
base.Reset();
//ensure we are at offset 0
Clock = new FramedClock();
List<HitObject> objects = new List<HitObject>();
int time = 500;
for (int i = 0; i < 100; i++)
{
objects.Add(new HitCircle()
objects.Add(new HitCircle
{
StartTime = time,
Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)),
@@ -49,40 +43,55 @@ namespace osu.Desktop.VisualTests.Tests
time += RNG.Next(50, 500);
}
Beatmap beatmap = new Beatmap
WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap
{
HitObjects = objects
};
HitObjects = objects,
BeatmapInfo = new BeatmapInfo
{
Difficulty = new BeatmapDifficulty(),
Metadata = new BeatmapMetadata
{
Artist = @"Unknown",
Title = @"Sample Beatmap",
Author = @"peppy",
}
}
});
Add(new Drawable[]
{
new OsuHitRenderer
new Container
{
Beatmap = beatmap,
Scale = new Vector2(0.5f),
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft
},
new TaikoHitRenderer
{
Beatmap = beatmap,
Scale = new Vector2(0.5f),
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight
},
new CatchHitRenderer
{
Beatmap = beatmap,
Scale = new Vector2(0.5f),
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft
},
new ManiaHitRenderer
{
Beatmap = beatmap,
Scale = new Vector2(0.5f),
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight
RelativeSizeAxes = Axes.Both,
//ensure we are at offset 0
Clock = new FramedClock(),
Children = new Drawable[]
{
new OsuHitRenderer(beatmap)
{
Scale = new Vector2(0.5f),
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft
},
new TaikoHitRenderer(beatmap)
{
Scale = new Vector2(0.5f),
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight
},
new CatchHitRenderer(beatmap)
{
Scale = new Vector2(0.5f),
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft
},
new ManiaHitRenderer(beatmap)
{
Scale = new Vector2(0.5f),
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight
}
}
}
});
}
@@ -0,0 +1,42 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using System.Linq;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseGraph : TestCase
{
public override string Description => "graph";
private BarGraph graph;
public override void Reset()
{
base.Reset();
Children = new[]
{
graph = new BarGraph
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(0.5f),
},
};
AddStep("values from 1-10", () => graph.Values = Enumerable.Range(1,10).Select(i => (float)i));
AddStep("values from 1-100", () => graph.Values = Enumerable.Range(1, 100).Select(i => (float)i));
AddStep("reversed values from 1-10", () => graph.Values = Enumerable.Range(1, 10).Reverse().Select(i => (float)i));
AddStep("Bottom to top", () => graph.Direction = BarDirection.BottomToTop);
AddStep("Top to bottom", () => graph.Direction = BarDirection.TopToBottom);
AddStep("Left to right", () => graph.Direction = BarDirection.LeftToRight);
AddStep("Right to left", () => graph.Direction = BarDirection.RightToLeft);
}
}
}
@@ -1,63 +1,166 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework;
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics;
using osu.Framework.Timing;
using OpenTK;
using osu.Framework.Allocation;
using OpenTK.Graphics;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Judgements;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.Objects.Drawables;
using osu.Framework.Graphics.Containers;
using osu.Game.Modes;
using System.Collections.Generic;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseHitObjects : TestCase
internal class TestCaseHitObjects : TestCase
{
public override string Name => @"Hit Objects";
private readonly FramedClock framedClock;
private bool auto;
public TestCaseHitObjects()
{
var swClock = new StopwatchClock(true) { Rate = 0.2f };
Clock = new FramedClock(swClock);
var rateAdjustClock = new StopwatchClock(true);
framedClock = new FramedClock(rateAdjustClock);
playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; };
}
private HitObjectType mode = HitObjectType.Slider;
private readonly BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 };
private Container playfieldContainer;
private Container approachContainer;
private void load(HitObjectType mode)
{
this.mode = mode;
switch (mode)
{
case HitObjectType.Circle:
const int count = 10;
for (int i = 0; i < count; i++)
{
var h = new HitCircle
{
StartTime = framedClock.CurrentTime + 600 + i * 80,
Position = new Vector2((i - count / 2) * 14),
};
add(new DrawableHitCircle(h));
}
break;
case HitObjectType.Slider:
add(new DrawableSlider(new Slider
{
StartTime = framedClock.CurrentTime + 600,
CurveObject = new CurvedHitObject
{
ControlPoints = new List<Vector2>
{
new Vector2(-200, 0),
new Vector2(400, 0),
},
Distance = 400
},
Position = new Vector2(-200, 0),
Velocity = 1,
TickDistance = 100,
}));
break;
case HitObjectType.Spinner:
add(new DrawableSpinner(new Spinner
{
StartTime = framedClock.CurrentTime + 600,
EndTime = framedClock.CurrentTime + 1600,
Position = new Vector2(0, 0),
}));
break;
}
}
public override void Reset()
{
base.Reset();
Clock.ProcessFrame();
playbackSpeed.TriggerChange();
Container approachContainer = new Container { Depth = float.MinValue, };
AddStep(@"circles", () => load(HitObjectType.Circle));
AddStep(@"slider", () => load(HitObjectType.Slider));
AddStep(@"spinner", () => load(HitObjectType.Spinner));
Add(approachContainer);
AddToggleStep(@"auto", state => { auto = state; load(mode); });
const int count = 10;
for (int i = 0; i < count; i++)
BasicSliderBar<double> sliderBar;
Add(new Container
{
var h = new HitCircle
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
StartTime = Clock.CurrentTime + 600 + i * 80,
Position = new Vector2((i - count / 2) * 14),
};
new SpriteText { Text = "Playback Speed" },
sliderBar = new BasicSliderBar<double>
{
Width = 150,
Height = 10,
SelectionColor = Color4.Orange,
}
}
});
DrawableHitCircle d = new DrawableHitCircle(h)
sliderBar.Current.BindTo(playbackSpeed);
framedClock.ProcessFrame();
var clockAdjustContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Clock = framedClock,
Children = new[]
{
Anchor = Anchor.Centre,
Depth = i,
State = ArmedState.Hit,
Judgement = new OsuJudgementInfo { Result = HitResult.Hit }
};
playfieldContainer = new Container { RelativeSizeAxes = Axes.Both },
approachContainer = new Container { RelativeSizeAxes = Axes.Both }
}
};
Add(clockAdjustContainer);
approachContainer.Add(d.ApproachCircle.CreateProxy());
Add(d);
load(mode);
}
private int depth;
private void add(DrawableOsuHitObject h)
{
h.Anchor = Anchor.Centre;
h.Depth = depth++;
if (auto)
{
h.State = ArmedState.Hit;
h.Judgement = new OsuJudgement { Result = HitResult.Hit };
}
playfieldContainer.Add(h);
var proxyable = h as IDrawableHitObjectWithProxiedApproach;
if (proxyable != null)
approachContainer.Add(proxyable.ProxiedLayer.CreateProxy());
}
private enum HitObjectType
{
Circle,
Slider,
Spinner
}
}
}
@@ -1,26 +1,22 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.GameModes.Testing;
using osu.Framework.Testing;
using osu.Framework.Graphics;
using osu.Game.Graphics.UserInterface;
using OpenTK.Input;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Configuration;
using osu.Framework.Graphics.Containers;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.MathUtils;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseKeyCounter : TestCase
internal class TestCaseKeyCounter : TestCase
{
public override string Name => @"KeyCounter";
public override string Description => @"Tests key counter";
public override void Reset()
@@ -34,27 +30,41 @@ namespace osu.Desktop.VisualTests.Tests
IsCounting = true,
Children = new KeyCounter[]
{
new KeyCounterKeyboard(@"Z", Key.Z),
new KeyCounterKeyboard(@"X", Key.X),
new KeyCounterMouse(@"M1", MouseButton.Left),
new KeyCounterMouse(@"M2", MouseButton.Right),
new KeyCounterKeyboard(Key.Z),
new KeyCounterKeyboard(Key.X),
new KeyCounterMouse(MouseButton.Left),
new KeyCounterMouse(MouseButton.Right),
},
};
BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 };
bindable.ValueChanged += delegate { kc.FadeTime = bindable.Value; };
AddButton("Add Random", () =>
AddStep("Add Random", () =>
{
Key key = (Key)((int)Key.A + RNG.Next(26));
kc.Add(new KeyCounterKeyboard(key.ToString(), key));
kc.Add(new KeyCounterKeyboard(key));
});
ButtonsContainer.Add(new SpriteText { Text = "FadeTime" });
ButtonsContainer.Add(new TestSliderBar<int>
TestSliderBar<int> sliderBar;
Add(new Container
{
Width = 150,
Height = 10,
SelectionColor = Color4.Orange,
Bindable = bindable
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new SpriteText { Text = "FadeTime" },
sliderBar =new TestSliderBar<int>
{
Width = 150,
Height = 10,
SelectionColor = Color4.Orange,
}
}
});
sliderBar.Current.BindTo(bindable);
Add(kc);
}
private class TestSliderBar<T> : SliderBar<T> where T : struct
@@ -0,0 +1,225 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Osu.Mods;
using osu.Game.Modes.Scoring;
using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Users;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseLeaderboard : TestCase
{
public override string Description => @"From song select";
private Leaderboard leaderboard;
private void newScores()
{
var scores = new[]
{
new Score
{
Rank = ScoreRank.XH,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 6602580,
Username = @"waaiiru",
Country = new Country
{
FullName = @"Spain",
FlagName = @"ES",
},
},
},
new Score
{
Rank = ScoreRank.X,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 4608074,
Username = @"Skycries",
Country = new Country
{
FullName = @"Brazil",
FlagName = @"BR",
},
},
},
new Score
{
Rank = ScoreRank.SH,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 1014222,
Username = @"eLy",
Country = new Country
{
FullName = @"Japan",
FlagName = @"JP",
},
},
},
new Score
{
Rank = ScoreRank.S,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 1541390,
Username = @"Toukai",
Country = new Country
{
FullName = @"Canada",
FlagName = @"CA",
},
},
},
new Score
{
Rank = ScoreRank.A,
Accuracy = 100,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 2243452,
Username = @"Satoruu",
Country = new Country
{
FullName = @"Venezuela",
FlagName = @"VE",
},
},
},
new Score
{
Rank = ScoreRank.B,
Accuracy = 98.26,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 2705430,
Username = @"Mooha",
Country = new Country
{
FullName = @"France",
FlagName = @"FR",
},
},
},
new Score
{
Rank = ScoreRank.C,
Accuracy = 96.54,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 7151382,
Username = @"Mayuri Hana",
Country = new Country
{
FullName = @"Thailand",
FlagName = @"TH",
},
},
},
new Score
{
Rank = ScoreRank.F,
Accuracy = 60.25,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 2051389,
Username = @"FunOrange",
Country = new Country
{
FullName = @"Canada",
FlagName = @"CA",
},
},
},
new Score
{
Rank = ScoreRank.F,
Accuracy = 51.40,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 6169483,
Username = @"-Hebel-",
Country = new Country
{
FullName = @"Mexico",
FlagName = @"MX",
},
},
},
new Score
{
Rank = ScoreRank.F,
Accuracy = 42.22,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
User = new User
{
Id = 6702666,
Username = @"prhtnsm",
Country = new Country
{
FullName = @"Germany",
FlagName = @"DE",
},
},
},
};
leaderboard.Scores = scores;
}
public override void Reset()
{
base.Reset();
Add(leaderboard = new Leaderboard
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(550f, 450f),
});
AddStep(@"New Scores", newScores);
newScores();
}
}
}
@@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.GameModes.Testing;
using osu.Framework.Testing;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Sprites;
using osu.Game.Screens.Menu;
@@ -9,9 +9,8 @@ using OpenTK.Graphics;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseMenuButtonSystem : TestCase
internal class TestCaseMenuButtonSystem : TestCase
{
public override string Name => @"ButtonSystem";
public override string Description => @"Main menu button system";
public override void Reset()
@@ -0,0 +1,59 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using osu.Framework.Testing;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseMenuOverlays : TestCase
{
public override string Description => @"Tests pause and fail overlays";
private PauseOverlay pauseOverlay;
private FailOverlay failOverlay;
private int retryCount;
public override void Reset()
{
base.Reset();
retryCount = 0;
Add(pauseOverlay = new PauseOverlay
{
OnResume = () => Logger.Log(@"Resume"),
OnRetry = () => Logger.Log(@"Retry"),
OnQuit = () => Logger.Log(@"Quit"),
});
Add(failOverlay = new FailOverlay
{
OnRetry = () => Logger.Log(@"Retry"),
OnQuit = () => Logger.Log(@"Quit"),
});
AddStep(@"Pause", delegate {
if(failOverlay.State == Visibility.Visible)
{
failOverlay.Hide();
}
pauseOverlay.Show();
});
AddStep("Fail", delegate {
if (pauseOverlay.State == Visibility.Visible)
{
pauseOverlay.Hide();
}
failOverlay.Show();
});
AddStep("Add Retry", delegate
{
retryCount++;
pauseOverlay.Retries = retryCount;
failOverlay.Retries = retryCount;
});
}
}
}
@@ -0,0 +1,35 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Game.Overlays.Mods;
using osu.Framework.Testing;
using osu.Game.Modes;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseModSelectOverlay : TestCase
{
public override string Description => @"Tests the mod select overlay";
private ModSelectOverlay modSelect;
public override void Reset()
{
base.Reset();
Add(modSelect = new ModSelectOverlay
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
});
AddStep("Toggle", modSelect.ToggleVisibility);
AddStep("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu);
AddStep("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko);
AddStep("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch);
AddStep("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania);
}
}
}
@@ -1,16 +1,16 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.GameModes.Testing;
using osu.Framework.Testing;
using osu.Framework.Graphics;
using osu.Framework.Timing;
using osu.Game.Overlays;
using osu.Framework.Graphics.Containers;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseMusicController : TestCase
internal class TestCaseMusicController : TestCase
{
public override string Name => @"Music Controller";
public override string Description => @"Tests music controller ui.";
private MusicController mc;
@@ -30,7 +30,9 @@ namespace osu.Desktop.VisualTests.Tests
Anchor = Anchor.Centre
};
Add(mc);
AddToggle(@"Show", mc.ToggleVisibility);
AddToggleStep(@"toggle visibility", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
AddStep(@"show", () => mc.State = Visibility.Visible);
}
}
}
@@ -3,22 +3,20 @@
using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Framework.GameModes.Testing;
using osu.Framework.Testing;
using osu.Framework.MathUtils;
using osu.Framework.Timing;
using osu.Game.Overlays;
using System.Linq;
using osu.Game.Overlays.Notifications;
using osu.Game.Screens.Backgrounds;
using osu.Framework.Graphics.Containers;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseNotificationManager : TestCase
internal class TestCaseNotificationManager : TestCase
{
public override string Name => @"Notification Manager";
public override string Description => @"I handle notifications";
NotificationManager manager;
private NotificationManager manager;
public override void Reset()
{
@@ -26,21 +24,19 @@ namespace osu.Desktop.VisualTests.Tests
progressingNotifications.Clear();
AddInternal(new BackgroundModeDefault() { Depth = 10 });
Content.Add(manager = new NotificationManager
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
});
AddToggle(@"show", manager.ToggleVisibility);
AddToggleStep(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
AddButton(@"simple #1", sendNotification1);
AddButton(@"simple #2", sendNotification2);
AddButton(@"progress #1", sendProgress1);
AddButton(@"progress #2", sendProgress2);
AddButton(@"barrage", () => sendBarrage());
AddStep(@"simple #1", sendNotification1);
AddStep(@"simple #2", sendNotification2);
AddStep(@"progress #1", sendProgress1);
AddStep(@"progress #2", sendProgress2);
AddStep(@"barrage", () => sendBarrage());
}
private void sendBarrage(int remaining = 100)
@@ -88,34 +84,34 @@ namespace osu.Desktop.VisualTests.Tests
if (n.Progress < 1)
n.Progress += (float)(Time.Elapsed / 2000) * RNG.NextSingle();
else
n.Complete();
n.State = ProgressNotificationState.Completed;
}
}
private void sendProgress2()
{
var n = new ProgressNotification(@"Downloading Haitai...");
var n = new ProgressNotification { Text = @"Downloading Haitai..." };
manager.Post(n);
progressingNotifications.Add(n);
}
List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
private readonly List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
private void sendProgress1()
{
var n = new ProgressNotification(@"Uploading to BSS...");
var n = new ProgressNotification { Text = @"Uploading to BSS..." };
manager.Post(n);
progressingNotifications.Add(n);
}
private void sendNotification2()
{
manager.Post(new SimpleNotification(@"You are amazing"));
manager.Post(new SimpleNotification { Text = @"You are amazing" });
}
private void sendNotification1()
{
manager.Post(new SimpleNotification(@"Welcome to osu!. Enjoy your stay!"));
manager.Post(new SimpleNotification { Text = @"Welcome to osu!. Enjoy your stay!" });
}
}
}
@@ -1,19 +1,13 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics;
using osu.Game.Graphics.UserInterface;
using OpenTK.Input;
using osu.Framework.Testing;
using osu.Game.Overlays;
using osu.Framework.Graphics.Containers;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseOptions : TestCase
internal class TestCaseOptions : TestCase
{
public override string Name => @"Options";
public override string Description => @"Tests the options overlay";
private OptionsOverlay options;
@@ -1,47 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using OpenTK.Graphics;
using osu.Framework.Logging;
using osu.Framework.Graphics;
using osu.Game.Overlays.Pause;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Colour;
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics.UserInterface;
namespace osu.Desktop.VisualTests.Tests
{
class TestCasePauseOverlay : TestCase
{
public override string Name => @"PauseOverlay";
public override string Description => @"Tests the pause overlay";
private PauseOverlay pauseOverlay;
private int retryCount;
public override void Reset()
{
base.Reset();
Add(pauseOverlay = new PauseOverlay
{
Depth = -1,
OnResume = () => Logger.Log(@"Resume"),
OnRetry = () => Logger.Log(@"Retry"),
OnQuit = () => Logger.Log(@"Quit")
});
AddButton("Pause", pauseOverlay.Show);
AddButton("Add Retry", delegate
{
retryCount++;
pauseOverlay.Retries = retryCount;
});
retryCount = 0;
}
}
}
@@ -3,30 +3,30 @@
using System.Collections.Generic;
using osu.Desktop.VisualTests.Platform;
using osu.Framework.GameModes.Testing;
using osu.Framework.Testing;
using osu.Framework.MathUtils;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Filter;
namespace osu.Desktop.VisualTests.Tests
{
class TestCasePlaySongSelect : TestCase
internal class TestCasePlaySongSelect : TestCase
{
private BeatmapDatabase db, oldDb;
private BeatmapDatabase db;
private TestStorage storage;
private PlaySongSelect songSelect;
public override string Name => @"Song Select";
public override string Description => @"with fake data";
public override void Reset()
{
base.Reset();
oldDb = Dependencies.Get<BeatmapDatabase>();
if (db == null)
{
storage = new TestStorage(@"TestCasePlaySongSelect");
db = new BeatmapDatabase(storage);
Dependencies.Cache(db, true);
var sets = new List<BeatmapSetInfo>();
@@ -35,20 +35,23 @@ namespace osu.Desktop.VisualTests.Tests
db.Import(sets);
}
Add(new PlaySongSelect());
}
protected override void Dispose(bool isDisposing)
{
if (oldDb != null)
{
Dependencies.Cache(oldDb, true);
db = null;
}
base.Dispose(isDisposing);
Add(songSelect = new PlaySongSelect());
AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
AddStep(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
}
//protected override void Dispose(bool isDisposing)
//{
// if (oldDb != null)
// db = null;
// base.Dispose(isDisposing);
//}
private BeatmapSetInfo createTestBeatmapSet(int i)
{
return new BeatmapSetInfo
@@ -59,9 +62,10 @@ namespace osu.Desktop.VisualTests.Tests
Metadata = new BeatmapMetadata
{
OnlineBeatmapSetID = 1234 + i,
Artist = "MONACA",
Title = "Black Song",
Author = "Some Guy",
// Create random metadata, then we can check if sorting works based on these
Artist = "MONACA " + RNG.Next(0, 9),
Title = "Black Song " + RNG.Next(0, 9),
Author = "Some Guy " + RNG.Next(0, 9),
},
Beatmaps = new List<BeatmapInfo>(new[]
{
@@ -71,7 +75,7 @@ namespace osu.Desktop.VisualTests.Tests
Mode = PlayMode.Osu,
Path = "normal.osu",
Version = "Normal",
BaseDifficulty = new BaseDifficulty
Difficulty = new BeatmapDifficulty
{
OverallDifficulty = 3.5f,
}
@@ -82,7 +86,7 @@ namespace osu.Desktop.VisualTests.Tests
Mode = PlayMode.Osu,
Path = "hard.osu",
Version = "Hard",
BaseDifficulty = new BaseDifficulty
Difficulty = new BeatmapDifficulty
{
OverallDifficulty = 5,
}
@@ -93,7 +97,7 @@ namespace osu.Desktop.VisualTests.Tests
Mode = PlayMode.Osu,
Path = "insane.osu",
Version = "Insane",
BaseDifficulty = new BaseDifficulty
Difficulty = new BeatmapDifficulty
{
OverallDifficulty = 7,
}
+34 -21
View File
@@ -2,12 +2,10 @@
// 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.GameModes.Testing;
using osu.Framework.MathUtils;
using osu.Framework.Timing;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using OpenTK;
using osu.Framework.Graphics.Sprites;
using osu.Game.Database;
@@ -16,28 +14,33 @@ using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Screens.Play;
using OpenTK.Graphics;
using osu.Desktop.VisualTests.Beatmaps;
namespace osu.Desktop.VisualTests.Tests
{
class TestCasePlayer : TestCase
internal class TestCasePlayer : TestCase
{
private WorkingBeatmap beatmap;
public override string Name => @"Player";
protected Player Player;
private BeatmapDatabase db;
public override string Description => @"Showing everything to play the game.";
[BackgroundDependencyLoader]
private void load(BeatmapDatabase db)
{
var beatmapInfo = db.Query<BeatmapInfo>().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault();
if (beatmapInfo != null)
beatmap = db.GetWorkingBeatmap(beatmapInfo);
this.db = db;
}
public override void Reset()
{
base.Reset();
WorkingBeatmap beatmap = null;
var beatmapInfo = db.Query<BeatmapInfo>().FirstOrDefault(b => b.Mode == PlayMode.Osu);
if (beatmapInfo != null)
beatmap = db.GetWorkingBeatmap(beatmapInfo);
if (beatmap?.Track == null)
{
var objects = new List<HitObject>();
@@ -45,7 +48,7 @@ namespace osu.Desktop.VisualTests.Tests
int time = 1500;
for (int i = 0; i < 50; i++)
{
objects.Add(new HitCircle()
objects.Add(new HitCircle
{
StartTime = time,
Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512,
@@ -56,29 +59,39 @@ namespace osu.Desktop.VisualTests.Tests
time += 500;
}
var decoder = new ConstructableBeatmapDecoder();
Beatmap b = new Beatmap
{
HitObjects = objects
HitObjects = objects,
BeatmapInfo = new BeatmapInfo
{
Difficulty = new BeatmapDifficulty(),
Metadata = new BeatmapMetadata
{
Artist = @"Unknown",
Title = @"Sample Beatmap",
Author = @"peppy",
}
}
};
decoder.Process(b);
beatmap = new WorkingBeatmap(b);
beatmap = new TestWorkingBeatmap(b);
}
Add(new Box
{
RelativeSizeAxes = Framework.Graphics.Axes.Both,
Colour = Color4.Gray,
Colour = Color4.Black,
});
Add(new Player
Add(Player = CreatePlayer(beatmap));
}
protected virtual Player CreatePlayer(WorkingBeatmap beatmap)
{
return new Player
{
PreferredPlayMode = PlayMode.Osu,
Beatmap = beatmap
});
};
}
}
}
@@ -0,0 +1,22 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Osu.Mods;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseReplay : TestCasePlayer
{
public override string Description => @"Testing replay playback.";
protected override Player CreatePlayer(WorkingBeatmap beatmap)
{
beatmap.Mods.Value = new Mod[] { new OsuModAutoplay() };
return base.CreatePlayer(beatmap);
}
}
}
@@ -1,33 +1,19 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.GameModes.Testing;
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Mania;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.Taiko;
using osu.Game.Modes.Taiko.UI;
using osu.Game.Modes.UI;
using osu.Game.Screens.Play;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics.Primitives;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseScoreCounter : TestCase
internal class TestCaseScoreCounter : TestCase
{
public override string Name => @"ScoreCounter";
public override string Description => @"Tests multiple counters";
public override void Reset()
@@ -36,65 +22,31 @@ namespace osu.Desktop.VisualTests.Tests
int numerator = 0, denominator = 0;
bool maniaHold = false;
ScoreCounter score = new ScoreCounter(7)
{
Origin = Anchor.TopRight,
Anchor = Anchor.TopRight,
TextSize = 40,
Count = 0,
Margin = new MarginPadding(20),
};
Add(score);
ComboCounter standardCombo = new OsuComboCounter
ComboCounter comboCounter = new StandardComboCounter
{
Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft,
Margin = new MarginPadding(10),
Count = 0,
TextSize = 40,
};
Add(standardCombo);
Add(comboCounter);
CatchComboCounter catchCombo = new CatchComboCounter
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Count = 0,
TextSize = 40,
};
Add(catchCombo);
ComboCounter taikoCombo = new TaikoComboCounter
{
Origin = Anchor.BottomCentre,
Anchor = Anchor.Centre,
Position = new Vector2(0, -160),
Count = 0,
TextSize = 40,
};
Add(taikoCombo);
ManiaComboCounter maniaCombo = new ManiaComboCounter
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Position = new Vector2(0, -80),
Count = 0,
TextSize = 40,
};
Add(maniaCombo);
PercentageCounter accuracyCombo = new PercentageCounter
PercentageCounter accuracyCounter = new PercentageCounter
{
Origin = Anchor.TopRight,
Anchor = Anchor.TopRight,
Position = new Vector2(-20, 60),
};
Add(accuracyCombo);
Add(accuracyCounter);
StarCounter stars = new StarCounter
{
@@ -114,68 +66,42 @@ namespace osu.Desktop.VisualTests.Tests
};
Add(starsLabel);
AddButton(@"Reset all", delegate
AddStep(@"Reset all", delegate
{
score.Count = 0;
standardCombo.Count = 0;
taikoCombo.Count = 0;
maniaCombo.Count = 0;
catchCombo.Count = 0;
score.Current.Value = 0;
comboCounter.Current.Value = 0;
numerator = denominator = 0;
accuracyCombo.SetFraction(0, 0);
accuracyCounter.SetFraction(0, 0);
stars.Count = 0;
starsLabel.Text = stars.Count.ToString("0.00");
});
AddButton(@"Hit! :D", delegate
AddStep(@"Hit! :D", delegate
{
score.Count += 300 + (ulong)(300.0 * (standardCombo.Count > 0 ? standardCombo.Count - 1 : 0) / 25.0);
standardCombo.Count++;
taikoCombo.Count++;
maniaCombo.Count++;
catchCombo.CatchFruit(new Color4(
Math.Max(0.5f, RNG.NextSingle()),
Math.Max(0.5f, RNG.NextSingle()),
Math.Max(0.5f, RNG.NextSingle()),
1)
);
score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
comboCounter.Increment();
numerator++; denominator++;
accuracyCombo.SetFraction(numerator, denominator);
accuracyCounter.SetFraction(numerator, denominator);
});
AddButton(@"miss...", delegate
AddStep(@"miss...", delegate
{
standardCombo.Roll();
taikoCombo.Roll();
maniaCombo.Roll();
catchCombo.Roll();
comboCounter.Current.Value = 0;
denominator++;
accuracyCombo.SetFraction(numerator, denominator);
accuracyCounter.SetFraction(numerator, denominator);
});
AddButton(@"mania hold", delegate
AddStep(@"Alter stars", delegate
{
if (!maniaHold)
maniaCombo.HoldStart();
else
maniaCombo.HoldEnd();
maniaHold = !maniaHold;
});
AddButton(@"Alter stars", delegate
{
stars.Count = RNG.NextSingle() * (stars.MaxStars + 1);
stars.Count = RNG.NextSingle() * (stars.StarCount + 1);
starsLabel.Text = stars.Count.ToString("0.00");
});
AddButton(@"Stop counters", delegate
AddStep(@"Stop counters", delegate
{
score.StopRolling();
standardCombo.StopRolling();
catchCombo.StopRolling();
taikoCombo.StopRolling();
maniaCombo.StopRolling();
accuracyCombo.StopRolling();
comboCounter.StopRolling();
accuracyCounter.StopRolling();
stars.StopAnimation();
});
}
@@ -0,0 +1,45 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Testing;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Select.Filter;
namespace osu.Desktop.VisualTests.Tests
{
public class TestCaseTabControl : TestCase
{
public override string Description => @"Filter for song select";
public override void Reset()
{
base.Reset();
OsuSpriteText text;
OsuTabControl<GroupMode> filter;
Add(filter = new OsuTabControl<GroupMode>
{
Margin = new MarginPadding(4),
Size = new Vector2(229, 24),
AutoSort = true
});
Add(text = new OsuSpriteText
{
Text = "None",
Margin = new MarginPadding(4),
Position = new Vector2(275, 5)
});
filter.PinItem(GroupMode.All);
filter.PinItem(GroupMode.RecentlyPlayed);
filter.Current.ValueChanged += newFilter =>
{
text.Text = "Currently Selected: " + newFilter.ToString();
};
}
}
}
@@ -0,0 +1,121 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Linq;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Modes.Taiko.Objects.Drawables.Pieces;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseTaikoHitObjects : TestCase
{
public override string Description => "Taiko hit objects";
private bool kiai;
public override void Reset()
{
base.Reset();
AddToggleStep("Kiai", b =>
{
kiai = !kiai;
updateKiaiState();
});
Add(new CirclePiece
{
Position = new Vector2(100, 100),
AccentColour = Color4.DarkRed,
KiaiMode = kiai,
Children = new[]
{
new CentreHitSymbolPiece()
}
});
Add(new CirclePiece(true)
{
Position = new Vector2(350, 100),
AccentColour = Color4.DarkRed,
KiaiMode = kiai,
Children = new[]
{
new CentreHitSymbolPiece()
}
});
Add(new CirclePiece
{
Position = new Vector2(100, 300),
AccentColour = Color4.DarkBlue,
KiaiMode = kiai,
Children = new[]
{
new RimHitSymbolPiece()
}
});
Add(new CirclePiece(true)
{
Position = new Vector2(350, 300),
AccentColour = Color4.DarkBlue,
KiaiMode = kiai,
Children = new[]
{
new RimHitSymbolPiece()
}
});
Add(new CirclePiece
{
Position = new Vector2(100, 500),
AccentColour = Color4.Orange,
KiaiMode = kiai,
Children = new[]
{
new SwellSymbolPiece()
}
});
Add(new ElongatedCirclePiece
{
Position = new Vector2(575, 100),
AccentColour = Color4.Orange,
KiaiMode = kiai,
Length = 0.10f,
PlayfieldLengthReference = () => DrawSize.X
});
Add(new ElongatedCirclePiece(true)
{
Position = new Vector2(575, 300),
AccentColour = Color4.Orange,
KiaiMode = kiai,
Length = 0.10f,
PlayfieldLengthReference = () => DrawSize.X
});
}
private void updateKiaiState()
{
foreach (var c in Children.OfType<CirclePiece>())
c.KiaiMode = kiai;
}
private abstract class BaseCircle : Container
{
protected readonly CirclePiece Piece;
protected BaseCircle(CirclePiece piece)
{
Piece = piece;
Add(Piece);
}
}
}
}
@@ -0,0 +1,220 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.MathUtils;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Taiko.Judgements;
using osu.Game.Modes.Taiko.Objects;
using osu.Game.Modes.Taiko.Objects.Drawables;
using osu.Game.Modes.Taiko.UI;
using System;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseTaikoPlayfield : TestCase
{
private const double default_duration = 300;
private const float scroll_time = 1000;
public override string Description => "Taiko playfield";
protected override double TimePerAction => default_duration * 2;
private readonly Random rng = new Random(1337);
private TaikoPlayfield playfield;
private Container playfieldContainer;
public override void Reset()
{
base.Reset();
AddStep("Hit!", addHitJudgement);
AddStep("Miss :(", addMissJudgement);
AddStep("DrumRoll", () => addDrumRoll(false));
AddStep("Strong DrumRoll", () => addDrumRoll(true));
AddStep("Swell", () => addSwell());
AddStep("Centre", () => addCentreHit(false));
AddStep("Strong Centre", () => addCentreHit(true));
AddStep("Rim", () => addRimHit(false));
AddStep("Strong Rim", () => addRimHit(true));
AddStep("Add bar line", () => addBarLine(false));
AddStep("Add major bar line", () => addBarLine(true));
AddStep("Height test 1", () => changePlayfieldSize(1));
AddStep("Height test 2", () => changePlayfieldSize(2));
AddStep("Height test 3", () => changePlayfieldSize(3));
AddStep("Height test 4", () => changePlayfieldSize(4));
AddStep("Height test 5", () => changePlayfieldSize(5));
AddStep("Reset height", () => changePlayfieldSize(6));
var rateAdjustClock = new StopwatchClock(true) { Rate = 1 };
Add(playfieldContainer = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT,
Clock = new FramedClock(rateAdjustClock),
Children = new[]
{
playfield = new TaikoPlayfield()
}
});
}
private void changePlayfieldSize(int step)
{
// Add new hits
switch (step)
{
case 1:
addCentreHit(false);
break;
case 2:
addCentreHit(true);
break;
case 3:
addDrumRoll(false);
break;
case 4:
addDrumRoll(true);
break;
case 5:
addSwell(1000);
playfieldContainer.Delay(scroll_time - 100);
break;
}
// Tween playfield height
switch (step)
{
default:
playfieldContainer.ResizeTo(new Vector2(1, rng.Next(25, 400)), 500);
break;
case 6:
playfieldContainer.ResizeTo(new Vector2(1, TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT), 500);
break;
}
}
private void addHitJudgement()
{
TaikoHitResult hitResult = RNG.Next(2) == 0 ? TaikoHitResult.Good : TaikoHitResult.Great;
var h = new DrawableTestHit(new Hit())
{
X = RNG.NextSingle(hitResult == TaikoHitResult.Good ? -0.1f : -0.05f, hitResult == TaikoHitResult.Good ? 0.1f : 0.05f),
Judgement = new TaikoJudgement
{
Result = HitResult.Hit,
TaikoResult = hitResult,
TimeOffset = 0
}
};
playfield.OnJudgement(h);
if (RNG.Next(10) == 0)
{
h.Judgement.SecondHit = true;
playfield.OnJudgement(h);
}
}
private void addMissJudgement()
{
playfield.OnJudgement(new DrawableTestHit(new Hit())
{
Judgement = new TaikoJudgement
{
Result = HitResult.Miss,
TimeOffset = 0
}
});
}
private void addBarLine(bool major, double delay = scroll_time)
{
BarLine bl = new BarLine
{
StartTime = playfield.Time.Current + delay,
ScrollTime = scroll_time
};
playfield.AddBarLine(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl));
}
private void addSwell(double duration = default_duration)
{
playfield.Add(new DrawableSwell(new Swell
{
StartTime = playfield.Time.Current + scroll_time,
Duration = duration,
ScrollTime = scroll_time
}));
}
private void addDrumRoll(bool strong, double duration = default_duration)
{
addBarLine(true);
addBarLine(true, scroll_time + duration);
var d = new DrumRoll
{
StartTime = playfield.Time.Current + scroll_time,
IsStrong = strong,
Duration = duration,
ScrollTime = scroll_time,
};
playfield.Add(new DrawableDrumRoll(d));
}
private void addCentreHit(bool strong)
{
Hit h = new Hit
{
StartTime = playfield.Time.Current + scroll_time,
ScrollTime = scroll_time
};
if (strong)
playfield.Add(new DrawableCentreHitStrong(h));
else
playfield.Add(new DrawableCentreHit(h));
}
private void addRimHit(bool strong)
{
Hit h = new Hit
{
StartTime = playfield.Time.Current + scroll_time,
ScrollTime = scroll_time
};
if (strong)
playfield.Add(new DrawableRimHitStrong(h));
else
playfield.Add(new DrawableRimHit(h));
}
private class DrawableTestHit : DrawableHitObject<TaikoHitObject, TaikoJudgement>
{
public DrawableTestHit(TaikoHitObject hitObject)
: base(hitObject)
{
}
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
protected override void UpdateState(ArmedState state)
{
}
}
}
}
@@ -2,7 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.GameModes.Testing;
using osu.Framework.Testing;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.MathUtils;
@@ -12,19 +12,17 @@ using OpenTK.Graphics;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseTextAwesome : TestCase
internal class TestCaseTextAwesome : TestCase
{
public override string Name => @"TextAwesome";
public override string Description => @"Tests display of icons";
public override void Reset()
{
base.Reset();
FlowContainer flow;
FillFlowContainer flow;
Add(flow = new FlowContainer()
Add(flow = new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.5f),
@@ -1,19 +1,14 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Menu;
using osu.Game.Screens.Play;
using OpenTK.Graphics;
namespace osu.Desktop.VisualTests.Tests
{
class TestCaseTwoLayerButton : TestCase
internal class TestCaseTwoLayerButton : TestCase
{
public override string Name => @"TwoLayerButton";
public override string Description => @"Back and skip and what not";
public override void Reset()
+17 -10
View File
@@ -1,28 +1,35 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework;
using osu.Framework.GameModes.Testing;
using osu.Framework.Graphics.Cursor;
using osu.Game.Database;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game;
using osu.Framework.Desktop.Platform;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Game.Screens.Backgrounds;
namespace osu.Desktop.VisualTests
{
class VisualTestGame : OsuGameBase
internal class VisualTestGame : OsuGameBase
{
protected override void LoadComplete()
{
base.LoadComplete();
LoadComponentAsync(new BackgroundScreenDefault { Depth = 10 }, AddInternal);
// Have to construct this here, rather than in the constructor, because
// we depend on some dependencies to be loaded within OsuGameBase.load().
Add(new TestBrowser());
}
public override void SetHost(GameHost host)
{
base.SetHost(host);
host.UpdateThread.InactiveHz = host.UpdateThread.ActiveHz;
host.DrawThread.InactiveHz = host.DrawThread.ActiveHz;
host.InputThread.InactiveHz = host.InputThread.ActiveHz;
host.Window.CursorState = CursorState.Hidden;
}
}
}
-16
View File
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -23,6 +23,7 @@
<SignAssembly>false</SignAssembly>
<TargetZone>LocalIntranet</TargetZone>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@@ -59,6 +60,7 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -73,6 +75,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<Win32Resource>
@@ -80,14 +83,20 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
</Reference>
<Reference Include="SharpCompress, Version=0.15.2.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\SharpCompress.0.15.2\lib\net45\SharpCompress.dll</HintPath>
</Reference>
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="Newtonsoft.Json">
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="SQLiteNetExtensions">
<HintPath>$(SolutionDir)\packages\SQLiteNetExtensions.1.3.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\SQLiteNetExtensions.dll</HintPath>
</Reference>
@@ -97,15 +106,13 @@
<Reference Include="SQLite.Net.Platform.Generic">
<HintPath>$(SolutionDir)\packages\SQLite.Net-PCL.3.1.1\lib\net40\SQLite.Net.Platform.Generic.dll</HintPath>
</Reference>
<Reference Include="OpenTK">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="OpenTK.dll.config" />
</ItemGroup>
@@ -141,6 +148,10 @@
<Project>{65dc628f-a640-4111-ab35-3a5652bc1e17}</Project>
<Name>osu.Framework.Desktop</Name>
</ProjectReference>
<ProjectReference Include="..\osu-framework\osu.Framework.Testing\osu.Framework.Testing.csproj">
<Project>{007b2356-ab6f-4bd9-96d5-116fc2dce69a}</Project>
<Name>osu.Framework.Testing</Name>
</ProjectReference>
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
<Project>{c76bf5b3-985e-4d39-95fe-97c9c879b83a}</Project>
<Name>osu.Framework</Name>
@@ -171,27 +182,41 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Benchmark.cs" />
<Compile Include="AutomatedVisualTestGame.cs" />
<Compile Include="Program.cs" />
<Compile Include="Tests\TestCaseChatDisplay.cs" />
<Compile Include="Tests\TestCaseBeatmapDetails.cs" />
<Compile Include="Tests\TestCaseDrawings.cs" />
<Compile Include="Tests\TestCaseGamefield.cs" />
<Compile Include="Tests\TestCaseGraph.cs" />
<Compile Include="Tests\TestCaseMenuOverlays.cs" />
<Compile Include="Tests\TestCaseMusicController.cs" />
<Compile Include="Tests\TestCaseNotificationManager.cs" />
<Compile Include="Tests\TestCasePlayer.cs" />
<Compile Include="Tests\TestCaseHitObjects.cs" />
<Compile Include="Tests\TestCaseKeyCounter.cs" />
<Compile Include="Tests\TestCaseMenuButtonSystem.cs" />
<Compile Include="Tests\TestCaseReplay.cs" />
<Compile Include="Tests\TestCaseScoreCounter.cs" />
<Compile Include="Tests\TestCaseTabControl.cs" />
<Compile Include="Tests\TestCaseTaikoHitObjects.cs" />
<Compile Include="Tests\TestCaseTaikoPlayfield.cs" />
<Compile Include="Tests\TestCaseTextAwesome.cs" />
<Compile Include="Tests\TestCasePlaySongSelect.cs" />
<Compile Include="Tests\TestCaseTwoLayerButton.cs" />
<Compile Include="VisualTestGame.cs" />
<Compile Include="Platform\TestStorage.cs" />
<Compile Include="Tests\TestCaseOptions.cs" />
<Compile Include="Tests\TestCasePauseOverlay.cs" />
<Compile Include="Tests\TestCaseModSelectOverlay.cs" />
<Compile Include="Tests\TestCaseDialogOverlay.cs" />
<Compile Include="Tests\TestCaseBeatmapOptionsOverlay.cs" />
<Compile Include="Tests\TestCaseLeaderboard.cs" />
<Compile Include="Beatmaps\TestWorkingBeatmap.cs" />
<Compile Include="Tests\TestCaseBeatmapDetailArea.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup />
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
+4 -3
View File
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1339" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
<package id="SharpCompress" version="0.15.2" targetFramework="net45" />
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
@@ -1,14 +1,9 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.IO;
using osu.Game.Beatmaps;
using osu.Game.Database;
namespace osu.Desktop.Beatmaps.IO
{
@@ -19,26 +14,18 @@ namespace osu.Desktop.Beatmaps.IO
{
public static void Register() => AddReader<LegacyFilesystemReader>((storage, path) => Directory.Exists(path));
private string basePath { get; set; }
private string[] beatmaps { get; set; }
private Beatmap firstMap { get; set; }
private string basePath { get; }
public LegacyFilesystemReader(string path)
{
basePath = path;
beatmaps = Directory.GetFiles(basePath, @"*.osu").Select(f => Path.GetFileName(f)).ToArray();
if (beatmaps.Length == 0)
throw new FileNotFoundException(@"This directory contains no beatmaps");
using (var stream = new StreamReader(GetStream(beatmaps[0])))
{
var decoder = BeatmapDecoder.GetDecoder(stream);
firstMap = decoder.Decode(stream);
}
}
public override string[] ReadBeatmaps()
{
return beatmaps;
BeatmapFilenames = Directory.GetFiles(basePath, @"*.osu").Select(Path.GetFileName).ToArray();
if (BeatmapFilenames.Length == 0)
throw new FileNotFoundException(@"This directory contains no beatmaps");
StoryboardFilename = Directory.GetFiles(basePath, @"*.osb").Select(Path.GetFileName).FirstOrDefault();
}
public override Stream GetStream(string name)
@@ -46,11 +33,6 @@ namespace osu.Desktop.Beatmaps.IO
return File.OpenRead(Path.Combine(basePath, name));
}
public override BeatmapMetadata ReadMetadata()
{
return firstMap.BeatmapInfo.Metadata;
}
public override void Dispose()
{
// no-op
+29
View File
@@ -0,0 +1,29 @@
<!--
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
<!-- XQuartz compatibility (X11 on Mac) -->
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
</configuration>
+42 -15
View File
@@ -2,32 +2,52 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using osu.Framework.Platform;
using osu.Framework.Desktop.Platform;
using osu.Game.Database;
using osu.Desktop.Overlays;
using System.Reflection;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;
using osu.Game.Screens.Menu;
namespace osu.Desktop
{
class OsuGameDesktop : OsuGame
internal class OsuGameDesktop : OsuGame
{
private readonly VersionManager versionManager;
public OsuGameDesktop(string[] args = null)
: base(args)
{
versionManager = new VersionManager { Depth = int.MinValue };
}
public override void SetHost(BasicGameHost host)
protected override void LoadComplete()
{
base.LoadComplete();
LoadComponentAsync(versionManager);
ScreenChanged += s =>
{
if (!versionManager.IsAlive && s is Intro)
Add(versionManager);
};
}
public override void SetHost(GameHost host)
{
base.SetHost(host);
var desktopWindow = host.Window as DesktopGameWindow;
if (desktopWindow != null)
{
desktopWindow.CursorState = CursorState.Hidden;
desktopWindow.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
desktopWindow.Title = Name;
desktopWindow.DragEnter += dragEnter;
desktopWindow.DragDrop += dragDrop;
}
@@ -36,22 +56,29 @@ namespace osu.Desktop
private void dragDrop(DragEventArgs e)
{
// this method will only be executed if e.Effect in dragEnter gets set to something other that None.
var dropData = e.Data.GetData(DataFormats.FileDrop) as object[];
var dropData = (object[])e.Data.GetData(DataFormats.FileDrop);
var filePaths = dropData.Select(f => f.ToString()).ToArray();
ImportBeatmaps(filePaths);
if (filePaths.All(f => Path.GetExtension(f) == @".osz"))
Task.Run(() => BeatmapDatabase.Import(filePaths));
else if (filePaths.All(f => Path.GetExtension(f) == @".osr"))
Task.Run(() =>
{
var score = ScoreDatabase.ReadReplayFile(filePaths.First());
Schedule(() => LoadScore(score));
});
}
private static readonly string[] allowed_extensions = { @".osz", @".osr" };
private void dragEnter(DragEventArgs e)
{
// dragDrop will only be executed if e.Effect gets set to something other that None in this method.
bool isFile = e.Data.GetDataPresent(DataFormats.FileDrop);
if (isFile)
{
var paths = (e.Data.GetData(DataFormats.FileDrop) as object[]).Select(f => f.ToString()).ToArray();
if (paths.Any(p => !p.EndsWith(".osz")))
e.Effect = DragDropEffects.None;
else
e.Effect = DragDropEffects.Copy;
var paths = ((object[])e.Data.GetData(DataFormats.FileDrop)).Select(f => f.ToString()).ToArray();
e.Effect = allowed_extensions.Any(ext => paths.All(p => p.EndsWith(ext))) ? DragDropEffects.Copy : DragDropEffects.None;
}
}
}
+229
View File
@@ -0,0 +1,229 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using Squirrel;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Graphics;
using OpenTK;
using OpenTK.Graphics;
using System.Net.Http;
using osu.Framework.Logging;
using osu.Game;
namespace osu.Desktop.Overlays
{
public class VersionManager : OverlayContainer
{
private UpdateManager updateManager;
private NotificationManager notificationManager;
protected override bool HideOnEscape => false;
public override bool HandleInput => false;
[BackgroundDependencyLoader]
private void load(NotificationManager notification, OsuColour colours, TextureStore textures, OsuGameBase game)
{
notificationManager = notification;
AutoSizeAxes = Axes.Both;
Anchor = Anchor.BottomCentre;
Origin = Anchor.BottomCentre;
Alpha = 0;
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(5),
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Children = new Drawable[]
{
new OsuSpriteText
{
Font = @"Exo2.0-Bold",
Text = game.Name
},
new OsuSpriteText
{
Colour = game.IsDebug ? colours.Red : Color4.White,
Text = game.Version
},
}
},
new OsuSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
TextSize = 12,
Colour = colours.Yellow,
Font = @"Venera",
Text = @"Development Build"
},
new Sprite
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Texture = textures.Get(@"Menu/dev-build-footer"),
},
}
}
};
if (game.IsDeployedBuild)
checkForUpdateAsync();
}
protected override void LoadComplete()
{
base.LoadComplete();
State = Visibility.Visible;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
updateManager?.Dispose();
}
private async void checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification notification = null)
{
//should we schedule a retry on completion of this check?
bool scheduleRetry = true;
try
{
if (updateManager == null) updateManager = await UpdateManager.GitHubUpdateManager(@"https://github.com/ppy/osu", @"osulazer", null, null, true);
var info = await updateManager.CheckForUpdate(!useDeltaPatching);
if (info.ReleasesToApply.Count == 0)
//no updates available. bail and retry later.
return;
if (notification == null)
{
notification = new UpdateProgressNotification { State = ProgressNotificationState.Active };
Schedule(() => notificationManager.Post(notification));
}
Schedule(() =>
{
notification.Progress = 0;
notification.Text = @"Downloading update...";
});
try
{
await updateManager.DownloadReleases(info.ReleasesToApply, p => Schedule(() => notification.Progress = p / 100f));
Schedule(() =>
{
notification.Progress = 0;
notification.Text = @"Installing update...";
});
await updateManager.ApplyReleases(info, p => Schedule(() => notification.Progress = p / 100f));
Schedule(() => notification.State = ProgressNotificationState.Completed);
}
catch (Exception e)
{
if (useDeltaPatching)
{
Logger.Error(e, @"delta patching failed!");
//could fail if deltas are unavailable for full update path (https://github.com/Squirrel/Squirrel.Windows/issues/959)
//try again without deltas.
checkForUpdateAsync(false, notification);
scheduleRetry = false;
}
else
{
Logger.Error(e, @"update failed!");
}
}
}
catch (HttpRequestException)
{
//likely have no internet connection.
//we'll ignore this and retry later.
}
finally
{
if (scheduleRetry)
{
//check again in 30 minutes.
Scheduler.AddDelayed(() => checkForUpdateAsync(), 60000 * 30);
if (notification != null)
notification.State = ProgressNotificationState.Cancelled;
}
}
}
protected override void PopIn()
{
FadeIn(1000);
}
protected override void PopOut()
{
}
private class UpdateProgressNotification : ProgressNotification
{
private OsuGame game;
protected override Notification CreateCompletionNotification() => new ProgressCompletionNotification()
{
Text = @"Update ready to install. Click to restart!",
Activated = () =>
{
UpdateManager.RestartAppWhenExited();
game.GracefullyExit();
return true;
}
};
[BackgroundDependencyLoader]
private void load(OsuColour colours, OsuGame game)
{
this.game = game;
IconContent.Add(new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
ColourInfo = ColourInfo.GradientVertical(colours.YellowDark, colours.Yellow)
},
new TextAwesome
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Icon = FontAwesome.fa_upload,
Colour = Color4.White,
TextSize = 20
}
});
}
}
}
}
+3 -10
View File
@@ -3,14 +3,9 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using osu.Desktop.Beatmaps.IO;
using osu.Framework;
using osu.Framework.Desktop;
using osu.Framework.Desktop.Platform;
using osu.Framework.Platform;
using osu.Game;
using osu.Game.IPC;
using osu.Game.Modes;
using osu.Game.Modes.Catch;
@@ -34,13 +29,13 @@ namespace osu.Desktop
{
if (!host.IsPrimaryInstance)
{
var importer = new BeatmapImporter(host);
var importer = new BeatmapIPCChannel(host);
// Restore the cwd so relative paths given at the command line work correctly
Directory.SetCurrentDirectory(cwd);
foreach (var file in args)
{
Console.WriteLine(@"Importing {0}", file);
if (!importer.Import(Path.GetFullPath(file)).Wait(3000))
if (!importer.ImportAsync(Path.GetFullPath(file)).Wait(3000))
throw new TimeoutException(@"IPC took too long to send");
}
}
@@ -51,9 +46,7 @@ namespace osu.Desktop
Ruleset.Register(new ManiaRuleset());
Ruleset.Register(new CatchRuleset());
BaseGame osu = new OsuGameDesktop(args);
host.Add(osu);
host.Run();
host.Run(new OsuGameDesktop(args));
}
return 0;
}
+28
View File
@@ -0,0 +1,28 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu!lazer")]
[assembly: AssemblyDescription("click the circles. to the beat.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ppy Pty Ltd")]
[assembly: AssemblyProduct("osu!lazer")]
[assembly: AssemblyCopyright("ppy Pty Ltd 2007-2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("55e28cb2-7b6c-4595-8dcc-9871d8aad7e9")]
[assembly: AssemblyVersion("0.0.0")]
[assembly: AssemblyFileVersion("0.0.0")]
+72 -4
View File
@@ -23,6 +23,7 @@
<SignAssembly>false</SignAssembly>
<TargetZone>LocalIntranet</TargetZone>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@@ -59,6 +60,7 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<Commandlineparameters>
</Commandlineparameters>
</PropertyGroup>
@@ -75,21 +77,84 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<Win32Resource>osu!.res</Win32Resource>
<Win32Resource>
</Win32Resource>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>lazer.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="DeltaCompressionDotNet, Version=1.1.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="DeltaCompressionDotNet.MsDelta, Version=1.1.0.0, Culture=neutral, PublicKeyToken=46b2138a390abf55, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.MsDelta.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="DeltaCompressionDotNet.PatchApi, Version=1.1.0.0, Culture=neutral, PublicKeyToken=3e8888ee913ed789, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4" />
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
</Reference>
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Squirrel, Version=1.5.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\Squirrel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="OpenTK.dll.config" />
<None Include="osu!.res" />
<None Include="packages.config" />
<None Include="Properties\app.manifest" />
</ItemGroup>
<ItemGroup>
@@ -155,11 +220,14 @@
</ItemGroup>
<ItemGroup>
<Compile Include="OsuGameDesktop.cs" />
<Compile Include="Overlays\VersionManager.cs" />
<Compile Include="Program.cs" />
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="lazer.ico" />
</ItemGroup>
<ItemGroup />
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>osulazer</id>
<version>0.0.0</version>
<title>osulazer</title>
<authors>ppy Pty Ltd</authors>
<owners>Dean Herbert</owners>
<projectUrl>https://osu.ppy.sh/</projectUrl>
<iconUrl>https://puu.sh/tYyXZ/9a01a5d1b0.ico</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>click the circles. to the beat.</description>
<summary>click the circles.</summary>
<releaseNotes>testing</releaseNotes>
<copyright>Copyright ppy Pty Ltd 2007-2017</copyright>
<language>en-AU</language>
</metadata>
<files>
<file src="*.exe" target="lib\net45\" exclude="**vshost**"/>
<file src="*.dll" target="lib\net45\"/>
<file src="*.config" target="lib\net45\"/>
<file src="x86\*.dll" target="lib\net45\x86\"/>
<file src="x64\*.dll" target="lib\net45\x64\"/>
</files>
</package>
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
<package id="Splat" version="2.0.0" targetFramework="net45" />
<package id="squirrel.windows" version="1.5.2" targetFramework="net45" />
</packages>
@@ -0,0 +1,20 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Catch.Objects;
using System.Collections.Generic;
namespace osu.Game.Modes.Catch.Beatmaps
{
internal class CatchBeatmapConverter : IBeatmapConverter<CatchBaseHit>
{
public Beatmap<CatchBaseHit> Convert(Beatmap original)
{
return new Beatmap<CatchBaseHit>(original)
{
HitObjects = new List<CatchBaseHit>() // Todo: Convert HitObjects
};
}
}
}
@@ -0,0 +1,19 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Catch.Objects;
namespace osu.Game.Modes.Catch.Beatmaps
{
internal class CatchBeatmapProcessor : IBeatmapProcessor<CatchBaseHit>
{
public void SetDefaults(CatchBaseHit hitObject, Beatmap<CatchBaseHit> beatmap)
{
}
public void PostProcess(Beatmap<CatchBaseHit> beatmap)
{
}
}
}
@@ -0,0 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Catch.Beatmaps;
using osu.Game.Modes.Catch.Objects;
using System.Collections.Generic;
namespace osu.Game.Modes.Catch
{
public class CatchDifficultyCalculator : DifficultyCalculator<CatchBaseHit>
{
public CatchDifficultyCalculator(Beatmap beatmap) : base(beatmap)
{
}
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
{
return 0;
}
protected override IBeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter();
}
}
+78 -11
View File
@@ -1,29 +1,96 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Graphics;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
using OpenTK.Input;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Modes.Catch.Mods;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Mods;
using osu.Game.Modes.UI;
using osu.Game.Screens.Play;
using System.Collections.Generic;
using osu.Game.Modes.Catch.Scoring;
using osu.Game.Modes.Scoring;
namespace osu.Game.Modes.Catch
{
public class CatchRuleset : Ruleset
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap) => new CatchHitRenderer(beatmap);
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new CatchHitRenderer { Beatmap = beatmap };
public override IEnumerable<Mod> GetModsFor(ModType type)
{
switch (type)
{
case ModType.DifficultyReduction:
return new Mod[]
{
new CatchModEasy(),
new CatchModNoFail(),
new CatchModHalfTime(),
};
case ModType.DifficultyIncrease:
return new Mod[]
{
new CatchModHardRock(),
new MultiMod
{
Mods = new Mod[]
{
new CatchModSuddenDeath(),
new CatchModPerfect(),
},
},
new MultiMod
{
Mods = new Mod[]
{
new CatchModDoubleTime(),
new CatchModNightcore(),
},
},
new CatchModHidden(),
new CatchModFlashlight(),
};
case ModType.Special:
return new Mod[]
{
new CatchModRelax(),
null,
null,
new MultiMod
{
Mods = new Mod[]
{
new ModAutoplay(),
new ModCinema(),
},
},
};
default:
return new Mod[] { };
}
}
protected override PlayMode PlayMode => PlayMode.Catch;
public override string Description => "osu!catch";
public override FontAwesome Icon => FontAwesome.fa_osu_fruits_o;
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null;
public override IEnumerable<KeyCounter> CreateGameplayKeys() => new KeyCounter[]
{
new KeyCounterKeyboard(Key.ShiftLeft),
new KeyCounterMouse(MouseButton.Left),
new KeyCounterMouse(MouseButton.Right)
};
public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap);
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor();
}
}
@@ -0,0 +1,14 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Judgements;
namespace osu.Game.Modes.Catch.Judgements
{
public class CatchJudgement : Judgement
{
public override string ResultString => string.Empty;
public override string MaxResultString => string.Empty;
}
}
+64
View File
@@ -0,0 +1,64 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Mods;
namespace osu.Game.Modes.Catch.Mods
{
public class CatchModNoFail : ModNoFail
{
}
public class CatchModEasy : ModEasy
{
}
public class CatchModHidden : ModHidden
{
public override string Description => @"Play with no approach circles and fading notes for a slight score advantage.";
public override double ScoreMultiplier => 1.06;
}
public class CatchModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.12;
public override bool Ranked => true;
}
public class CatchModSuddenDeath : ModSuddenDeath
{
}
public class CatchModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.06;
}
public class CatchModRelax : ModRelax
{
public override string Description => @"Use the mouse to control the catcher.";
}
public class CatchModHalfTime : ModHalfTime
{
public override double ScoreMultiplier => 0.5;
}
public class CatchModNightcore : ModNightcore
{
public override double ScoreMultiplier => 1.06;
}
public class CatchModFlashlight : ModFlashlight
{
public override double ScoreMultiplier => 1.12;
}
public class CatchModPerfect : ModPerfect
{
}
}
+1 -1
View File
@@ -7,6 +7,6 @@ namespace osu.Game.Modes.Catch.Objects
{
public abstract class CatchBaseHit : HitObject
{
public float Position;
public float Position { get; set; }
}
}
@@ -1,40 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Beatmaps;
namespace osu.Game.Modes.Catch.Objects
{
class CatchConverter : HitObjectConverter<CatchBaseHit>
{
public override List<CatchBaseHit> Convert(Beatmap beatmap)
{
List<CatchBaseHit> output = new List<CatchBaseHit>();
foreach (HitObject i in beatmap.HitObjects)
{
CatchBaseHit h = i as CatchBaseHit;
if (h == null)
{
OsuHitObject o = i as OsuHitObject;
if (o == null) throw new HitObjectConvertException(@"Catch", i);
h = new Fruit
{
StartTime = o.StartTime,
Position = o.Position.X,
};
}
output.Add(h);
}
return output;
}
}
}
@@ -5,14 +5,14 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.Transformations;
using osu.Framework.Graphics.Transforms;
using OpenTK;
namespace osu.Game.Modes.Catch.Objects.Drawable
{
class DrawableFruit : Sprite
internal class DrawableFruit : Sprite
{
private CatchBaseHit h;
private readonly CatchBaseHit h;
public DrawableFruit(CatchBaseHit h)
{
@@ -29,8 +29,10 @@ namespace osu.Game.Modes.Catch.Objects.Drawable
{
Texture = textures.Get(@"Menu/logo");
const double duration = 0;
Transforms.Add(new TransformPosition { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position, -0.1f), EndValue = new Vector2(h.Position, 0.9f) });
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 });
Expire(true);
}
}
+1 -2
View File
@@ -1,8 +1,7 @@
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
@@ -2,10 +2,9 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu.Game.Modes.Catch")]
@@ -17,8 +16,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -28,11 +27,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
@@ -0,0 +1,26 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Catch.Judgements;
using osu.Game.Modes.Catch.Objects;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Catch.Scoring
{
internal class CatchScoreProcessor : ScoreProcessor<CatchBaseHit, CatchJudgement>
{
public CatchScoreProcessor()
{
}
public CatchScoreProcessor(HitRenderer<CatchBaseHit, CatchJudgement> hitRenderer)
: base(hitRenderer)
{
}
protected override void OnNewJudgement(CatchJudgement judgement)
{
}
}
}
@@ -1,65 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Osu.UI;
using OpenTK.Graphics;
namespace osu.Game.Modes.Catch.UI
{
/// <summary>
/// Similar to Standard, but without the 'x' and has tinted pop-ups. Used in osu!catch.
/// </summary>
public class CatchComboCounter : OsuComboCounter
{
protected override bool CanPopOutWhileRolling => true;
protected virtual double FadeOutDelay => 1000;
protected override double FadeOutDuration => 300;
protected override string FormatCount(ulong count)
{
return $@"{count:#,0}";
}
private void animateFade()
{
Show();
Delay(FadeOutDelay);
FadeOut(FadeOutDuration);
DelayReset();
}
protected override void OnCountChange(ulong currentValue, ulong newValue)
{
if (newValue != 0)
animateFade();
base.OnCountChange(currentValue, newValue);
}
protected override void OnCountRolling(ulong currentValue, ulong newValue)
{
if (!IsRolling)
{
PopOutCount.Colour = DisplayedCountSpriteText.Colour;
FadeOut(FadeOutDuration);
}
base.OnCountRolling(currentValue, newValue);
}
protected override void OnCountIncrement(ulong currentValue, ulong newValue)
{
animateFade();
base.OnCountIncrement(currentValue, newValue);
}
/// <summary>
/// Increaces counter and tints pop-out before animation.
/// </summary>
/// <param name="colour">Last grabbed fruit colour.</param>
public void CatchFruit(Color4 colour)
{
PopOutCount.Colour = colour;
Count++;
}
}
}
+18 -5
View File
@@ -1,19 +1,32 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Catch.Beatmaps;
using osu.Game.Modes.Catch.Judgements;
using osu.Game.Modes.Catch.Objects;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Catch.Scoring;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Catch.UI
{
public class CatchHitRenderer : HitRenderer<CatchBaseHit>
public class CatchHitRenderer : HitRenderer<CatchBaseHit, CatchJudgement>
{
protected override HitObjectConverter<CatchBaseHit> Converter => new CatchConverter();
public CatchHitRenderer(WorkingBeatmap beatmap)
: base(beatmap)
{
}
protected override Playfield CreatePlayfield() => new CatchPlayfield();
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this);
protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) => null;// new DrawableFruit(h);
protected override IBeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter();
protected override IBeatmapProcessor<CatchBaseHit> CreateBeatmapProcessor() => new CatchBeatmapProcessor();
protected override Playfield<CatchBaseHit, CatchJudgement> CreatePlayfield() => new CatchPlayfield();
protected override DrawableHitObject<CatchBaseHit, CatchJudgement> GetVisualRepresentation(CatchBaseHit h) => null;
}
}
+4 -3
View File
@@ -3,17 +3,18 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Modes.Catch.Objects;
using osu.Game.Modes.UI;
using OpenTK;
using osu.Game.Modes.Catch.Judgements;
namespace osu.Game.Modes.Catch.UI
{
public class CatchPlayfield : Playfield
public class CatchPlayfield : Playfield<CatchBaseHit, CatchJudgement>
{
public CatchPlayfield()
{
RelativeSizeAxes = Axes.Y;
Size = new Vector2(512, 0.9f);
Size = new Vector2(1, 0.9f);
Anchor = Anchor.BottomCentre;
Origin = Anchor.BottomCentre;
@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,11 +29,11 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>..\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private>
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -45,16 +46,20 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Beatmaps\CatchBeatmapConverter.cs" />
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
<Compile Include="CatchDifficultyCalculator.cs" />
<Compile Include="Scoring\CatchScoreProcessor.cs" />
<Compile Include="Judgements\CatchJudgement.cs" />
<Compile Include="Objects\CatchBaseHit.cs" />
<Compile Include="Objects\CatchConverter.cs" />
<Compile Include="Objects\Drawable\DrawableFruit.cs" />
<Compile Include="Objects\Droplet.cs" />
<Compile Include="Objects\Fruit.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UI\CatchComboCounter.cs" />
<Compile Include="UI\CatchHitRenderer.cs" />
<Compile Include="UI\CatchPlayfield.cs" />
<Compile Include="CatchRuleset.cs" />
<Compile Include="Mods\CatchMod.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\osu.licenseheader">
@@ -78,7 +83,7 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
+3 -3
View File
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="ppy.OpenTK" version="2.0.50727.1339" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
</packages>
@@ -0,0 +1,20 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Objects;
using System.Collections.Generic;
namespace osu.Game.Modes.Mania.Beatmaps
{
internal class ManiaBeatmapConverter : IBeatmapConverter<ManiaBaseHit>
{
public Beatmap<ManiaBaseHit> Convert(Beatmap original)
{
return new Beatmap<ManiaBaseHit>(original)
{
HitObjects = new List<ManiaBaseHit>() // Todo: Implement
};
}
}
}
@@ -0,0 +1,19 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Objects;
namespace osu.Game.Modes.Mania.Beatmaps
{
internal class ManiaBeatmapProcessor : IBeatmapProcessor<ManiaBaseHit>
{
public void SetDefaults(ManiaBaseHit hitObject, Beatmap<ManiaBaseHit> beatmap)
{
}
public void PostProcess(Beatmap<ManiaBaseHit> beatmap)
{
}
}
}
@@ -0,0 +1,14 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Judgements;
namespace osu.Game.Modes.Mania.Judgements
{
public class ManiaJudgement : Judgement
{
public override string ResultString => string.Empty;
public override string MaxResultString => string.Empty;
}
}
@@ -0,0 +1,25 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Beatmaps;
using osu.Game.Modes.Mania.Objects;
using System.Collections.Generic;
namespace osu.Game.Modes.Mania
{
public class ManiaDifficultyCalculator : DifficultyCalculator<ManiaBaseHit>
{
public ManiaDifficultyCalculator(Beatmap beatmap)
: base(beatmap)
{
}
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
{
return 0;
}
protected override IBeatmapConverter<ManiaBaseHit> CreateBeatmapConverter() => new ManiaBeatmapConverter();
}
}
+93 -12
View File
@@ -1,30 +1,111 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Graphics;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Modes.Mania.Mods;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Mods;
using osu.Game.Modes.UI;
using osu.Game.Screens.Play;
using System.Collections.Generic;
using osu.Game.Modes.Mania.Scoring;
using osu.Game.Modes.Scoring;
namespace osu.Game.Modes.Mania
{
public class ManiaRuleset : Ruleset
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap) => new ManiaHitRenderer(beatmap);
public override HitRenderer CreateHitRendererWith(Beatmap beatmap) => new ManiaHitRenderer { Beatmap = beatmap };
public override IEnumerable<Mod> GetModsFor(ModType type)
{
switch (type)
{
case ModType.DifficultyReduction:
return new Mod[]
{
new ManiaModEasy(),
new ManiaModNoFail(),
new ManiaModHalfTime(),
};
case ModType.DifficultyIncrease:
return new Mod[]
{
new ManiaModHardRock(),
new MultiMod
{
Mods = new Mod[]
{
new ManiaModSuddenDeath(),
new ManiaModPerfect(),
},
},
new MultiMod
{
Mods = new Mod[]
{
new ManiaModDoubleTime(),
new ManiaModNightcore(),
},
},
new MultiMod
{
Mods = new Mod[]
{
new ManiaModFadeIn(),
new ManiaModHidden(),
}
},
new ManiaModFlashlight(),
};
case ModType.Special:
return new Mod[]
{
new MultiMod
{
Mods = new Mod[]
{
new ManiaModKey4(),
new ManiaModKey5(),
new ManiaModKey6(),
new ManiaModKey7(),
new ManiaModKey8(),
new ManiaModKey9(),
new ManiaModKey1(),
new ManiaModKey2(),
new ManiaModKey3(),
},
},
new ManiaModRandom(),
new ManiaModKeyCoop(),
new MultiMod
{
Mods = new Mod[]
{
new ModAutoplay(),
new ModCinema(),
},
},
};
default:
return new Mod[] { };
}
}
protected override PlayMode PlayMode => PlayMode.Mania;
public override string Description => "osu!mania";
public override FontAwesome Icon => FontAwesome.fa_osu_mania_o;
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null;
public override IEnumerable<KeyCounter> CreateGameplayKeys() => new KeyCounter[] { /* Todo: Should be keymod specific */ };
public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap);
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor();
}
}
+147
View File
@@ -0,0 +1,147 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Graphics;
using osu.Game.Modes.Mods;
using System;
namespace osu.Game.Modes.Mania.Mods
{
public class ManiaModNoFail : ModNoFail
{
}
public class ManiaModEasy : ModEasy
{
}
public class ManiaModHidden : ModHidden
{
public override string Description => @"The notes fade out before you hit them!";
public override double ScoreMultiplier => 1.0;
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
}
public class ManiaModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.0;
}
public class ManiaModSuddenDeath : ModSuddenDeath
{
}
public class ManiaModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.0;
}
public class ManiaModHalfTime : ModHalfTime
{
public override double ScoreMultiplier => 0.3;
}
public class ManiaModNightcore : ModNightcore
{
public override double ScoreMultiplier => 1.0;
}
public class ManiaModFlashlight : ModFlashlight
{
public override double ScoreMultiplier => 1.0;
public override Type[] IncompatibleMods => new[] { typeof(ModHidden) };
}
public class ManiaModPerfect : ModPerfect
{
}
public class ManiaModFadeIn : Mod
{
public override string Name => "FadeIn";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
public override double ScoreMultiplier => 1;
public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
}
public class ManiaModRandom : Mod
{
public override string Name => "Random";
public override string Description => @"Shuffle around the notes!";
public override double ScoreMultiplier => 1;
}
public abstract class ManiaKeyMod : Mod
{
public abstract int KeyCount { get; }
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier
public override bool Ranked => true;
}
public class ManiaModKey1 : ManiaKeyMod
{
public override int KeyCount => 1;
public override string Name => "1K";
}
public class ManiaModKey2 : ManiaKeyMod
{
public override int KeyCount => 2;
public override string Name => "2K";
}
public class ManiaModKey3 : ManiaKeyMod
{
public override int KeyCount => 3;
public override string Name => "3K";
}
public class ManiaModKey4 : ManiaKeyMod
{
public override int KeyCount => 4;
public override string Name => "4K";
}
public class ManiaModKey5 : ManiaKeyMod
{
public override int KeyCount => 5;
public override string Name => "5K";
}
public class ManiaModKey6 : ManiaKeyMod
{
public override int KeyCount => 6;
public override string Name => "6K";
}
public class ManiaModKey7 : ManiaKeyMod
{
public override int KeyCount => 7;
public override string Name => "7K";
}
public class ManiaModKey8 : ManiaKeyMod
{
public override int KeyCount => 8;
public override string Name => "8K";
}
public class ManiaModKey9 : ManiaKeyMod
{
public override int KeyCount => 9;
public override string Name => "9K";
}
public class ManiaModKeyCoop : Mod
{
public override string Name => "KeyCoop";
public override string Description => @"Double the key amount, double the fun!";
public override double ScoreMultiplier => 1;
public override bool Ranked => true;
}
}
@@ -4,7 +4,7 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.Transformations;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Graphics;
using OpenTK;
@@ -26,8 +26,10 @@ namespace osu.Game.Modes.Mania.Objects.Drawable
{
Texture = textures.Get(@"Menu/logo");
Transforms.Add(new TransformPositionY() { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f });
Transforms.Add(new TransformAlpha() { StartTime = note.StartTime + note.Duration + 200, EndTime = note.StartTime + note.Duration + 400, StartValue = 1, EndValue = 0 });
const double duration = 0;
Transforms.Add(new TransformPositionY { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f });
Transforms.Add(new TransformAlpha { StartTime = note.StartTime + duration + 200, EndTime = note.StartTime + duration + 400, StartValue = 1, EndValue = 0 });
Expire(true);
}
}
@@ -1,48 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Beatmaps;
namespace osu.Game.Modes.Mania.Objects
{
class ManiaConverter : HitObjectConverter<ManiaBaseHit>
{
private readonly int columns;
public ManiaConverter(int columns)
{
this.columns = columns;
}
public override List<ManiaBaseHit> Convert(Beatmap beatmap)
{
List<ManiaBaseHit> output = new List<ManiaBaseHit>();
foreach (HitObject i in beatmap.HitObjects)
{
ManiaBaseHit h = i as ManiaBaseHit;
if (h == null)
{
OsuHitObject o = i as OsuHitObject;
if (o == null) throw new HitObjectConvertException(@"Mania", i);
h = new Note
{
StartTime = o.StartTime,
Column = (int)Math.Round(o.Position.X / 512 * columns)
};
}
output.Add(h);
}
return output;
}
}
}
+1 -2
View File
@@ -1,8 +1,7 @@
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
@@ -2,10 +2,9 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu.Game.Modes.Mania")]
@@ -17,8 +16,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -28,11 +27,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
@@ -0,0 +1,26 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Mania.Judgements;
using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Mania.Scoring
{
internal class ManiaScoreProcessor : ScoreProcessor<ManiaBaseHit, ManiaJudgement>
{
public ManiaScoreProcessor()
{
}
public ManiaScoreProcessor(HitRenderer<ManiaBaseHit, ManiaJudgement> hitRenderer)
: base(hitRenderer)
{
}
protected override void OnNewJudgement(ManiaJudgement judgement)
{
}
}
}
@@ -1,78 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Graphics.Transformations;
using osu.Game.Modes.Taiko.UI;
using OpenTK.Graphics;
namespace osu.Game.Modes.Mania.UI
{
/// <summary>
/// Similar to osu!taiko, with a pop-out animation when failing (rolling). Used in osu!mania.
/// </summary>
public class ManiaComboCounter : TaikoComboCounter
{
protected ushort KeysHeld = 0;
protected Color4 OriginalColour;
protected Color4 TintColour => Color4.Orange;
protected EasingTypes TintEasing => EasingTypes.None;
protected int TintDuration => 500;
protected Color4 PopOutColor => Color4.Red;
protected override float PopOutInitialAlpha => 1.0f;
protected override double PopOutDuration => 300;
protected override void LoadComplete()
{
base.LoadComplete();
PopOutCount.Anchor = Anchor.BottomCentre;
PopOutCount.Origin = Anchor.Centre;
PopOutCount.FadeColour(PopOutColor, 0);
OriginalColour = DisplayedCountSpriteText.Colour;
}
protected override void OnCountRolling(ulong currentValue, ulong newValue)
{
if (!IsRolling && newValue < currentValue)
{
PopOutCount.Text = FormatCount(currentValue);
PopOutCount.FadeTo(PopOutInitialAlpha);
PopOutCount.ScaleTo(1.0f);
PopOutCount.FadeOut(PopOutDuration, PopOutEasing);
PopOutCount.ScaleTo(PopOutScale, PopOutDuration, PopOutEasing);
}
base.OnCountRolling(currentValue, newValue);
}
/// <summary>
/// Tints text while holding a key.
/// </summary>
/// <remarks>
/// Does not alter combo. This has to be done depending of the scoring system.
/// (i.e. v1 = each period of time; v2 = when starting and ending a key hold)
/// </remarks>
public void HoldStart()
{
if (KeysHeld == 0)
DisplayedCountSpriteText.FadeColour(TintColour, TintDuration, TintEasing);
KeysHeld++;
}
/// <summary>
/// Ends tinting.
/// </summary>
public void HoldEnd()
{
KeysHeld--;
if (KeysHeld == 0)
DisplayedCountSpriteText.FadeColour(OriginalColour, TintDuration, TintEasing);
}
}
}
+15 -14
View File
@@ -1,34 +1,35 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Beatmaps;
using osu.Game.Modes.Mania.Judgements;
using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Mania.Scoring;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Scoring;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Mania.UI
{
public class ManiaHitRenderer : HitRenderer<ManiaBaseHit>
public class ManiaHitRenderer : HitRenderer<ManiaBaseHit, ManiaJudgement>
{
private readonly int columns;
public ManiaHitRenderer(int columns = 5)
public ManiaHitRenderer(WorkingBeatmap beatmap, int columns = 5)
: base(beatmap)
{
this.columns = columns;
}
protected override HitObjectConverter<ManiaBaseHit> Converter => new ManiaConverter(columns);
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this);
protected override Playfield CreatePlayfield() => new ManiaPlayfield(columns);
protected override IBeatmapConverter<ManiaBaseHit> CreateBeatmapConverter() => new ManiaBeatmapConverter();
protected override DrawableHitObject GetVisualRepresentation(ManiaBaseHit h)
{
return null;
//return new DrawableNote(h)
//{
// Position = new Vector2((float)(h.Column + 0.5) / columns, -0.1f),
// RelativePositionAxes = Axes.Both
//};
}
protected override IBeatmapProcessor<ManiaBaseHit> CreateBeatmapProcessor() => new ManiaBeatmapProcessor();
protected override Playfield<ManiaBaseHit, ManiaJudgement> CreatePlayfield() => new ManiaPlayfield(columns);
protected override DrawableHitObject<ManiaBaseHit, ManiaJudgement> GetVisualRepresentation(ManiaBaseHit h) => null;
}
}
+5 -7
View File
@@ -3,28 +3,26 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.UI;
using OpenTK;
using OpenTK.Graphics;
using osu.Game.Modes.Mania.Judgements;
namespace osu.Game.Modes.Mania.UI
{
public class ManiaPlayfield : Playfield
public class ManiaPlayfield : Playfield<ManiaBaseHit, ManiaJudgement>
{
private readonly int columns;
public ManiaPlayfield(int columns)
{
this.columns = columns;
RelativeSizeAxes = Axes.Both;
Size = new Vector2(columns / 20f, 1f);
Size = new Vector2(0.8f, 1f);
Anchor = Anchor.BottomCentre;
Origin = Anchor.BottomCentre;
Add(new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.5f });
for (int i = 0; i < columns; i++)
Add(new Box()
Add(new Box
{
RelativeSizeAxes = Axes.Y,
Size = new Vector2(2, 1),
-16
View File
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,11 +29,11 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>..\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private>
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -45,16 +46,20 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Beatmaps\ManiaBeatmapConverter.cs" />
<Compile Include="Beatmaps\ManiaBeatmapProcessor.cs" />
<Compile Include="Judgements\ManiaJudgement.cs" />
<Compile Include="ManiaDifficultyCalculator.cs" />
<Compile Include="Scoring\ManiaScoreProcessor.cs" />
<Compile Include="Objects\Drawable\DrawableNote.cs" />
<Compile Include="Objects\HoldNote.cs" />
<Compile Include="Objects\ManiaBaseHit.cs" />
<Compile Include="Objects\ManiaConverter.cs" />
<Compile Include="Objects\Note.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UI\ManiaComboCounter.cs" />
<Compile Include="UI\ManiaHitRenderer.cs" />
<Compile Include="UI\ManiaPlayfield.cs" />
<Compile Include="ManiaRuleset.cs" />
<Compile Include="Mods\ManiaMod.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
@@ -78,12 +83,12 @@
<None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="app.config" />
<None Include="OpenTK.dll.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
+3 -3
View File
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-->
<packages>
<package id="ppy.OpenTK" version="2.0.50727.1339" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
</packages>
@@ -1,34 +1,81 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Modes.Objects;
using osu.Game.Beatmaps;
using osu.Game.Modes.Osu.Objects.Drawables;
using OpenTK;
using osu.Game.Beatmaps;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.Objects.Drawables;
using System.Collections.Generic;
using osu.Game.Modes.Objects.Types;
using System.Linq;
namespace osu.Game.Modes.Osu.Objects
namespace osu.Game.Modes.Osu.Beatmaps
{
public class OsuHitObjectConverter : HitObjectConverter<OsuHitObject>
internal class OsuBeatmapConverter : IBeatmapConverter<OsuHitObject>
{
public override List<OsuHitObject> Convert(Beatmap beatmap)
public Beatmap<OsuHitObject> Convert(Beatmap original)
{
List<OsuHitObject> output = new List<OsuHitObject>();
foreach (HitObject h in beatmap.HitObjects)
output.Add(h as OsuHitObject);
UpdateStacking(output, beatmap.BeatmapInfo?.StackLeniency ?? 0.7f);
return output;
return new Beatmap<OsuHitObject>(original)
{
HitObjects = convertHitObjects(original.HitObjects, original.BeatmapInfo?.StackLeniency ?? 0.7f)
};
}
public static void UpdateStacking(List<OsuHitObject> hitObjects, float stackLeniency, int startIndex = 0, int endIndex = -1)
private List<OsuHitObject> convertHitObjects(List<HitObject> hitObjects, float stackLeniency)
{
List<OsuHitObject> converted = hitObjects.Select(convertHitObject).ToList();
updateStacking(converted, stackLeniency);
return converted;
}
private OsuHitObject convertHitObject(HitObject original)
{
IHasCurve curveData = original as IHasCurve;
IHasEndTime endTimeData = original as IHasEndTime;
IHasPosition positionData = original as IHasPosition;
IHasCombo comboData = original as IHasCombo;
if (curveData != null)
{
return new Slider
{
StartTime = original.StartTime,
Samples = original.Samples,
CurveObject = curveData,
Position = positionData?.Position ?? Vector2.Zero,
NewCombo = comboData?.NewCombo ?? false
};
}
if (endTimeData != null)
{
return new Spinner
{
StartTime = original.StartTime,
Samples = original.Samples,
Position = new Vector2(512, 384) / 2,
EndTime = endTimeData.EndTime
};
}
return new HitCircle
{
StartTime = original.StartTime,
Samples = original.Samples,
Position = positionData?.Position ?? Vector2.Zero,
NewCombo = comboData?.NewCombo ?? false
};
}
private void updateStacking(List<OsuHitObject> hitObjects, float stackLeniency, int startIndex = 0, int endIndex = -1)
{
if (endIndex == -1)
endIndex = hitObjects.Count - 1;
int stackDistance = 3;
const int stack_distance = 3;
float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * stackLeniency;
// Reset stacking inside the update range
@@ -46,14 +93,17 @@ namespace osu.Game.Modes.Osu.Objects
if (stackBaseObject is Spinner) break;
OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) continue;
if (objectN is Spinner)
continue;
if (objectN.StartTime - stackBaseObject.EndTime > stackThreshold)
double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime;
if (objectN.StartTime - endTime > stackThreshold)
//We are no longer within stacking range of the next object.
break;
if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stackDistance ||
(stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stackDistance))
if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stack_distance ||
stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
{
stackBaseIndex = n;
@@ -100,7 +150,9 @@ namespace osu.Game.Modes.Osu.Objects
OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) continue;
if (objectI.StartTime - objectN.EndTime > stackThreshold)
double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime;
if (objectI.StartTime - endTime > stackThreshold)
//We are no longer within stacking range of the previous object.
break;
@@ -116,14 +168,14 @@ namespace osu.Game.Modes.Osu.Objects
* o <- hitCircle has stack of -1
* o <- hitCircle has stack of -2
*/
if (objectN is Slider && Vector2.Distance(objectN.EndPosition, objectI.Position) < stackDistance)
if (objectN is Slider && Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
{
int offset = objectI.StackHeight - objectN.StackHeight + 1;
for (int j = n + 1; j <= i; j++)
{
//For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
OsuHitObject objectJ = hitObjects[j];
if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stackDistance)
if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stack_distance)
objectJ.StackHeight -= offset;
}
@@ -132,7 +184,7 @@ namespace osu.Game.Modes.Osu.Objects
break;
}
if (Vector2.Distance(objectN.Position, objectI.Position) < stackDistance)
if (Vector2.Distance(objectN.Position, objectI.Position) < stack_distance)
{
//Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out.
//NOTE: Sliders with start positions stacking are a special case that is also handled here.
@@ -156,7 +208,7 @@ namespace osu.Game.Modes.Osu.Objects
//We are no longer within stacking range of the previous object.
break;
if (Vector2.Distance(objectN.EndPosition, objectI.Position) < stackDistance)
if (Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
{
objectN.StackHeight = objectI.StackHeight + 1;
objectI = objectN;
@@ -165,6 +217,5 @@ namespace osu.Game.Modes.Osu.Objects
}
}
}
}
}

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