Merge https://github.com/ppy/osu into song-progress-graph

This commit is contained in:
DrabWeb 2017-03-22 08:50:17 -03:00
commit 29c54d4d8b
372 changed files with 12163 additions and 3733 deletions

23
appveyor.yml Normal file
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.1/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"

@ -1 +1 @@
Subproject commit 5dbb4a5134dacb2e98ab8f2af219039a72bd32e6 Subproject commit 405537bd351954878ddc1d2ba53e5d0563528446

@ -1 +1 @@
Subproject commit 51f2b9b37f38cd349a3dd728a78f8fffcb3a54f5 Subproject commit f85c594c182db2b01233e29ca52639b7baa00402

View File

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?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> <configuration>
<appSettings> <appSettings>
<add key="StagingFolder" value="Staging" /> <add key="StagingFolder" value="Staging" />
@ -17,16 +21,4 @@
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup> </startup>
<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>
<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>
</assemblyBinding>
</runtime>
</configuration> </configuration>

View File

@ -1,8 +1,11 @@
using Newtonsoft.Json; // 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 namespace osu.Desktop.Deploy
{ {
internal class GitHubObject public class GitHubObject
{ {
[JsonProperty(@"id")] [JsonProperty(@"id")]
public int Id; public int Id;

View File

@ -1,8 +1,11 @@
using Newtonsoft.Json; // 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 namespace osu.Desktop.Deploy
{ {
internal class GitHubRelease public class GitHubRelease
{ {
[JsonProperty(@"id")] [JsonProperty(@"id")]
public int Id; public int Id;

View File

@ -1,5 +1,5 @@
// Copyright (c) 2007-2017 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-framework/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -40,7 +40,7 @@ namespace osu.Desktop.Deploy
/// <summary> /// <summary>
/// How many previous build deltas we want to keep when publishing. /// How many previous build deltas we want to keep when publishing.
/// </summary> /// </summary>
const int keep_delta_count = 3; 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 codeSigningCmd => string.IsNullOrEmpty(codeSigningPassword) ? "" : $"-n \"/a /f {codeSigningCertPath} /p {codeSigningPassword} /t http://timestamp.comodoca.com/authenticode\"";
@ -172,10 +172,10 @@ namespace osu.Desktop.Deploy
} }
//remove excess deltas //remove excess deltas
var deltas = releaseLines.Where(l => l.Filename.Contains("-delta")); var deltas = releaseLines.Where(l => l.Filename.Contains("-delta")).ToArray();
if (deltas.Count() > keep_delta_count) if (deltas.Length > keep_delta_count)
{ {
foreach (var l in deltas.Take(deltas.Count() - keep_delta_count)) foreach (var l in deltas.Take(deltas.Length - keep_delta_count))
{ {
write($"- Removing old delta {l.Filename}", ConsoleColor.Yellow); write($"- Removing old delta {l.Filename}", ConsoleColor.Yellow);
File.Delete(Path.Combine(ReleasesFolder, l.Filename)); File.Delete(Path.Combine(ReleasesFolder, l.Filename));
@ -198,7 +198,7 @@ namespace osu.Desktop.Deploy
write($"- Creating release {version}...", ConsoleColor.Yellow); write($"- Creating release {version}...", ConsoleColor.Yellow);
var req = new JsonWebRequest<GitHubRelease>($"{GitHubApiEndpoint}") var req = new JsonWebRequest<GitHubRelease>($"{GitHubApiEndpoint}")
{ {
Method = HttpMethod.POST Method = HttpMethod.POST,
}; };
req.AddRaw(JsonConvert.SerializeObject(new GitHubRelease req.AddRaw(JsonConvert.SerializeObject(new GitHubRelease
{ {
@ -215,6 +215,7 @@ namespace osu.Desktop.Deploy
var upload = new WebRequest(assetUploadUrl, Path.GetFileName(a)) var upload = new WebRequest(assetUploadUrl, Path.GetFileName(a))
{ {
Method = HttpMethod.POST, Method = HttpMethod.POST,
Timeout = 240000,
ContentType = "application/octet-stream", ContentType = "application/octet-stream",
}; };
@ -261,7 +262,7 @@ namespace osu.Desktop.Deploy
if (!File.Exists(Path.Combine(ReleasesFolder, nupkgDistroFilename(lastRelease.Name)))) if (!File.Exists(Path.Combine(ReleasesFolder, nupkgDistroFilename(lastRelease.Name))))
{ {
write("Last verion's package not found locally.", ConsoleColor.Red); write("Last version's package not found locally.", ConsoleColor.Red);
requireDownload = true; requireDownload = true;
} }
else else
@ -282,6 +283,8 @@ namespace osu.Desktop.Deploy
foreach (var a in assets) foreach (var a in assets)
{ {
if (a.Name.EndsWith(".exe")) continue;
write($"- Downloading {a.Name}...", ConsoleColor.Yellow); write($"- Downloading {a.Name}...", ConsoleColor.Yellow);
new FileWebRequest(Path.Combine(ReleasesFolder, a.Name), $"{GitHubApiEndpoint}/assets/{a.Id}").AuthenticatedBlockingPerform(); new FileWebRequest(Path.Combine(ReleasesFolder, a.Name), $"{GitHubApiEndpoint}/assets/{a.Id}").AuthenticatedBlockingPerform();
} }
@ -337,12 +340,17 @@ namespace osu.Desktop.Deploy
WorkingDirectory = solutionPath, WorkingDirectory = solutionPath,
CreateNoWindow = true, CreateNoWindow = true,
RedirectStandardOutput = true, RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false, UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden WindowStyle = ProcessWindowStyle.Hidden
}; };
Process p = Process.Start(psi); Process p = Process.Start(psi);
if (p == null) return false;
string output = p.StandardOutput.ReadToEnd(); string output = p.StandardOutput.ReadToEnd();
output += p.StandardError.ReadToEnd();
if (p.ExitCode == 0) return true; if (p.ExitCode == 0) return true;
write(output); write(output);

View File

@ -1,4 +1,7 @@
using System.Reflection; // 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; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following

View File

@ -101,7 +101,12 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link>
</None>
<None Include="App.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?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> <packages>
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net452" /> <package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net452" />
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net452" /> <package id="Mono.Cecil" version="0.9.6.4" targetFramework="net452" />

View File

@ -1,15 +0,0 @@
<?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>
<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>

View File

@ -100,12 +100,14 @@
<None Include="..\osu.licenseheader"> <None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link> <Link>osu.licenseheader</Link>
</None> </None>
<None Include="app.config" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Properties\" /> <Folder Include="Properties\" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <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. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright (c) 2007-2017 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 Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE

View File

@ -23,7 +23,7 @@ namespace osu.Desktop.VisualTests.Platform
platform = new SQLitePlatformWin32(); platform = new SQLitePlatformWin32();
else else
platform = new SQLitePlatformGeneric(); platform = new SQLitePlatformGeneric();
return new SQLiteConnection(platform, $@":memory:"); return new SQLiteConnection(platform, @":memory:");
} }
} }
} }

View File

@ -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.Screens.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);
AddButton(@"Toggle", overlay.ToggleVisibility);
}
}
}

View File

@ -8,18 +8,17 @@ using osu.Game.Overlays;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
class TestCaseChatDisplay : TestCase internal class TestCaseChatDisplay : TestCase
{ {
private ScheduledDelegate messageRequest; private ScheduledDelegate messageRequest;
public override string Name => @"Chat";
public override string Description => @"Testing chat api and overlay"; public override string Description => @"Testing chat api and overlay";
public override void Reset() public override void Reset()
{ {
base.Reset(); base.Reset();
Add(new ChatOverlay() Add(new ChatOverlay
{ {
State = Visibility.Visible State = Visibility.Visible
}); });

View File

@ -1,7 +1,6 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Screens.Testing; using osu.Framework.Screens.Testing;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Overlays; using osu.Game.Overlays;
@ -9,12 +8,11 @@ using osu.Game.Overlays.Dialog;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
class TestCaseDialogOverlay : TestCase internal class TestCaseDialogOverlay : TestCase
{ {
public override string Name => @"Dialog Overlay";
public override string Description => @"Display dialogs"; public override string Description => @"Display dialogs";
DialogOverlay overlay; private DialogOverlay overlay;
public override void Reset() public override void Reset()
{ {

View File

@ -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.Screens.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"
},
};
}
}
}

View File

@ -1,27 +1,27 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic; using OpenTK;
using osu.Framework.Screens.Testing;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Framework.Screens.Testing;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.IO;
using osu.Game.Database;
using osu.Game.Modes.Catch.UI; using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Mania.UI; using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Objects; using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI; using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.Taiko.UI; using osu.Game.Modes.Taiko.UI;
using OpenTK; using System.Collections.Generic;
namespace osu.Desktop.VisualTests.Tests 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 string Description => @"Showing hitobjects and what not.";
public override void Reset() public override void Reset()
@ -33,7 +33,7 @@ namespace osu.Desktop.VisualTests.Tests
int time = 500; int time = 500;
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
objects.Add(new HitCircle() objects.Add(new HitCircle
{ {
StartTime = time, StartTime = time,
Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)), Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)),
@ -43,10 +43,20 @@ namespace osu.Desktop.VisualTests.Tests
time += RNG.Next(50, 500); 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[] Add(new Drawable[]
{ {
@ -57,30 +67,26 @@ namespace osu.Desktop.VisualTests.Tests
Clock = new FramedClock(), Clock = new FramedClock(),
Children = new Drawable[] Children = new Drawable[]
{ {
new OsuHitRenderer new OsuHitRenderer(beatmap)
{ {
Beatmap = beatmap,
Scale = new Vector2(0.5f), Scale = new Vector2(0.5f),
Anchor = Anchor.TopLeft, Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft Origin = Anchor.TopLeft
}, },
new TaikoHitRenderer new TaikoHitRenderer(beatmap)
{ {
Beatmap = beatmap,
Scale = new Vector2(0.5f), Scale = new Vector2(0.5f),
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight Origin = Anchor.TopRight
}, },
new CatchHitRenderer new CatchHitRenderer(beatmap)
{ {
Beatmap = beatmap,
Scale = new Vector2(0.5f), Scale = new Vector2(0.5f),
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft Origin = Anchor.BottomLeft
}, },
new ManiaHitRenderer new ManiaHitRenderer(beatmap)
{ {
Beatmap = beatmap,
Scale = new Vector2(0.5f), Scale = new Vector2(0.5f),
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight Origin = Anchor.BottomRight
@ -89,5 +95,16 @@ namespace osu.Desktop.VisualTests.Tests
} }
}); });
} }
private class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
{
Beatmap = beatmap;
}
protected override ArchiveReader GetReader() => null;
}
} }
} }

View File

@ -1,41 +1,40 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Framework.Screens.Testing;
using osu.Framework.Graphics;
using osu.Framework.Timing;
using OpenTK; using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Game.Modes.Objects.Drawables; using osu.Framework.Graphics;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.Objects.Drawables;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using OpenTK.Graphics; using osu.Framework.Screens.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 System.Collections.Generic;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
class TestCaseHitObjects : TestCase internal class TestCaseHitObjects : TestCase
{ {
public override string Name => @"Hit Objects";
private StopwatchClock rateAdjustClock;
private FramedClock framedClock; private FramedClock framedClock;
bool auto = false; private bool auto;
public TestCaseHitObjects() public TestCaseHitObjects()
{ {
rateAdjustClock = new StopwatchClock(true); var rateAdjustClock = new StopwatchClock(true);
framedClock = new FramedClock(rateAdjustClock); framedClock = new FramedClock(rateAdjustClock);
playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; }; playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; };
} }
HitObjectType mode = HitObjectType.Slider; private HitObjectType mode = HitObjectType.Slider;
BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 }; private BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 };
private Container playfieldContainer; private Container playfieldContainer;
private Container approachContainer; private Container approachContainer;
@ -63,12 +62,15 @@ namespace osu.Desktop.VisualTests.Tests
add(new DrawableSlider(new Slider add(new DrawableSlider(new Slider
{ {
StartTime = framedClock.CurrentTime + 600, StartTime = framedClock.CurrentTime + 600,
ControlPoints = new List<Vector2>() CurveObject = new CurvedHitObject
{ {
new Vector2(-200, 0), ControlPoints = new List<Vector2>
new Vector2(400, 0), {
new Vector2(-200, 0),
new Vector2(400, 0),
},
Distance = 400
}, },
Length = 400,
Position = new Vector2(-200, 0), Position = new Vector2(-200, 0),
Velocity = 1, Velocity = 1,
TickDistance = 100, TickDistance = 100,
@ -78,7 +80,7 @@ namespace osu.Desktop.VisualTests.Tests
add(new DrawableSpinner(new Spinner add(new DrawableSpinner(new Spinner
{ {
StartTime = framedClock.CurrentTime + 600, StartTime = framedClock.CurrentTime + 600,
Length = 1000, EndTime = framedClock.CurrentTime + 1600,
Position = new Vector2(0, 0), Position = new Vector2(0, 0),
})); }));
break; break;
@ -95,7 +97,7 @@ namespace osu.Desktop.VisualTests.Tests
AddButton(@"slider", () => load(HitObjectType.Slider)); AddButton(@"slider", () => load(HitObjectType.Slider));
AddButton(@"spinner", () => load(HitObjectType.Spinner)); AddButton(@"spinner", () => load(HitObjectType.Spinner));
AddToggle(@"auto", (state) => { auto = state; load(mode); }); AddToggle(@"auto", state => { auto = state; load(mode); });
ButtonsContainer.Add(new SpriteText { Text = "Playback Speed" }); ButtonsContainer.Add(new SpriteText { Text = "Playback Speed" });
ButtonsContainer.Add(new BasicSliderBar<double> ButtonsContainer.Add(new BasicSliderBar<double>
@ -124,8 +126,9 @@ namespace osu.Desktop.VisualTests.Tests
load(mode); load(mode);
} }
int depth; private int depth;
void add(DrawableHitObject h)
private void add(DrawableOsuHitObject h)
{ {
h.Anchor = Anchor.Centre; h.Anchor = Anchor.Centre;
h.Depth = depth++; h.Depth = depth++;
@ -141,5 +144,12 @@ namespace osu.Desktop.VisualTests.Tests
if (proxyable != null) if (proxyable != null)
approachContainer.Add(proxyable.ProxiedLayer.CreateProxy()); approachContainer.Add(proxyable.ProxiedLayer.CreateProxy());
} }
private enum HitObjectType
{
Circle,
Slider,
Spinner
}
} }
} }

View File

@ -15,10 +15,8 @@ using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests 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 string Description => @"Tests key counter";
public override void Reset() public override void Reset()
@ -32,10 +30,10 @@ namespace osu.Desktop.VisualTests.Tests
IsCounting = true, IsCounting = true,
Children = new KeyCounter[] Children = new KeyCounter[]
{ {
new KeyCounterKeyboard(@"Z", Key.Z), new KeyCounterKeyboard(Key.Z),
new KeyCounterKeyboard(@"X", Key.X), new KeyCounterKeyboard(Key.X),
new KeyCounterMouse(@"M1", MouseButton.Left), new KeyCounterMouse(MouseButton.Left),
new KeyCounterMouse(@"M2", MouseButton.Right), new KeyCounterMouse(MouseButton.Right),
}, },
}; };
BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 }; BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 };
@ -43,7 +41,7 @@ namespace osu.Desktop.VisualTests.Tests
AddButton("Add Random", () => AddButton("Add Random", () =>
{ {
Key key = (Key)((int)Key.A + RNG.Next(26)); 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 SpriteText { Text = "FadeTime" });
ButtonsContainer.Add(new TestSliderBar<int> ButtonsContainer.Add(new TestSliderBar<int>

View File

@ -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.Screens.Testing;
using osu.Game.Modes;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Osu.Mods;
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),
});
AddButton(@"New Scores", newScores);
newScores();
}
}
}

View File

@ -9,9 +9,8 @@ using OpenTK.Graphics;
namespace osu.Desktop.VisualTests.Tests 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 string Description => @"Main menu button system";
public override void Reset() public override void Reset()

View File

@ -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.Screens.Testing;
using osu.Game.Modes;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseModSelectOverlay : TestCase
{
public override string Description => @"Tests the mod select overlay";
private ModSelectOverlay modSelect;
public override void Reset()
{
base.Reset();
Add(modSelect = new ModSelectOverlay
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
});
AddButton("Toggle", modSelect.ToggleVisibility);
AddButton("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu);
AddButton("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko);
AddButton("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch);
AddButton("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania);
}
}
}

View File

@ -9,9 +9,8 @@ using osu.Framework.Graphics.Containers;
namespace osu.Desktop.VisualTests.Tests 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."; public override string Description => @"Tests music controller ui.";
private MusicController mc; private MusicController mc;
@ -31,7 +30,7 @@ namespace osu.Desktop.VisualTests.Tests
Anchor = Anchor.Centre Anchor = Anchor.Centre
}; };
Add(mc); Add(mc);
AddToggle(@"Show", (state) => mc.State = state ? Visibility.Visible : Visibility.Hidden); AddToggle(@"Show", state => mc.State = state ? Visibility.Visible : Visibility.Hidden);
} }
} }
} }

View File

@ -12,12 +12,11 @@ using osu.Framework.Graphics.Containers;
namespace osu.Desktop.VisualTests.Tests 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"; public override string Description => @"I handle notifications";
NotificationManager manager; private NotificationManager manager;
public override void Reset() public override void Reset()
{ {
@ -31,7 +30,7 @@ namespace osu.Desktop.VisualTests.Tests
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
}); });
AddToggle(@"show", (state) => manager.State = state ? Visibility.Visible : Visibility.Hidden); AddToggle(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden);
AddButton(@"simple #1", sendNotification1); AddButton(@"simple #1", sendNotification1);
AddButton(@"simple #2", sendNotification2); AddButton(@"simple #2", sendNotification2);
@ -96,7 +95,7 @@ namespace osu.Desktop.VisualTests.Tests
progressingNotifications.Add(n); progressingNotifications.Add(n);
} }
List<ProgressNotification> progressingNotifications = new List<ProgressNotification>(); private List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
private void sendProgress1() private void sendProgress1()
{ {

View File

@ -6,10 +6,8 @@ using osu.Game.Overlays;
namespace osu.Desktop.VisualTests.Tests 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"; public override string Description => @"Tests the options overlay";
private OptionsOverlay options; private OptionsOverlay options;

View File

@ -2,15 +2,13 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Game.Overlays.Pause;
using osu.Framework.Screens.Testing; using osu.Framework.Screens.Testing;
using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
class TestCasePauseOverlay : TestCase internal class TestCasePauseOverlay : TestCase
{ {
public override string Name => @"PauseOverlay";
public override string Description => @"Tests the pause overlay"; public override string Description => @"Tests the pause overlay";
private PauseOverlay pauseOverlay; private PauseOverlay pauseOverlay;

View File

@ -1,7 +1,6 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Desktop.VisualTests.Platform; using osu.Desktop.VisualTests.Platform;
using osu.Framework.Screens.Testing; using osu.Framework.Screens.Testing;
@ -9,16 +8,16 @@ using osu.Framework.MathUtils;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Modes; using osu.Game.Modes;
using osu.Game.Screens.Select; using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Filter;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
class TestCasePlaySongSelect : TestCase internal class TestCasePlaySongSelect : TestCase
{ {
private BeatmapDatabase db, oldDb; private BeatmapDatabase db, oldDb;
private TestStorage storage; private TestStorage storage;
private PlaySongSelect songSelect; private PlaySongSelect songSelect;
public override string Name => @"Song Select";
public override string Description => @"with fake data"; public override string Description => @"with fake data";
public override void Reset() public override void Reset()
@ -41,10 +40,10 @@ namespace osu.Desktop.VisualTests.Tests
Add(songSelect = new PlaySongSelect()); Add(songSelect = new PlaySongSelect());
AddButton(@"Sort by Artist", delegate { songSelect.Filter.Sort = FilterControl.SortMode.Artist; }); AddButton(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
AddButton(@"Sort by Title", delegate { songSelect.Filter.Sort = FilterControl.SortMode.Title; }); AddButton(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
AddButton(@"Sort by Author", delegate { songSelect.Filter.Sort = FilterControl.SortMode.Author; }); AddButton(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
AddButton(@"Sort by Difficulty", delegate { songSelect.Filter.Sort = FilterControl.SortMode.Difficulty; }); AddButton(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
@ -81,7 +80,7 @@ namespace osu.Desktop.VisualTests.Tests
Mode = PlayMode.Osu, Mode = PlayMode.Osu,
Path = "normal.osu", Path = "normal.osu",
Version = "Normal", Version = "Normal",
BaseDifficulty = new BaseDifficulty Difficulty = new BeatmapDifficulty
{ {
OverallDifficulty = 3.5f, OverallDifficulty = 3.5f,
} }
@ -92,7 +91,7 @@ namespace osu.Desktop.VisualTests.Tests
Mode = PlayMode.Osu, Mode = PlayMode.Osu,
Path = "hard.osu", Path = "hard.osu",
Version = "Hard", Version = "Hard",
BaseDifficulty = new BaseDifficulty Difficulty = new BeatmapDifficulty
{ {
OverallDifficulty = 5, OverallDifficulty = 5,
} }
@ -103,7 +102,7 @@ namespace osu.Desktop.VisualTests.Tests
Mode = PlayMode.Osu, Mode = PlayMode.Osu,
Path = "insane.osu", Path = "insane.osu",
Version = "Insane", Version = "Insane",
BaseDifficulty = new BaseDifficulty Difficulty = new BeatmapDifficulty
{ {
OverallDifficulty = 7, OverallDifficulty = 7,
} }

View File

@ -2,10 +2,10 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Screens.Testing; using osu.Framework.Screens.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using OpenTK; using OpenTK;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps.IO; using osu.Game.Beatmaps.IO;
@ -18,25 +18,30 @@ using OpenTK.Graphics;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
class TestCasePlayer : TestCase internal class TestCasePlayer : TestCase
{ {
private WorkingBeatmap beatmap; protected Player Player;
public override string Name => @"Player"; private BeatmapDatabase db;
public override string Description => @"Showing everything to play the game."; public override string Description => @"Showing everything to play the game.";
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(BeatmapDatabase db) private void load(BeatmapDatabase db)
{ {
var beatmapInfo = db.Query<BeatmapInfo>().Where(b => b.Mode == PlayMode.Osu).FirstOrDefault(); this.db = db;
if (beatmapInfo != null)
beatmap = db.GetWorkingBeatmap(beatmapInfo);
} }
public override void Reset() public override void Reset()
{ {
base.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) if (beatmap?.Track == null)
{ {
var objects = new List<HitObject>(); var objects = new List<HitObject>();
@ -44,7 +49,7 @@ namespace osu.Desktop.VisualTests.Tests
int time = 1500; int time = 1500;
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
objects.Add(new HitCircle() objects.Add(new HitCircle
{ {
StartTime = time, StartTime = time,
Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512, Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512,
@ -55,13 +60,12 @@ namespace osu.Desktop.VisualTests.Tests
time += 500; time += 500;
} }
var decoder = new ConstructableBeatmapDecoder();
Beatmap b = new Beatmap Beatmap b = new Beatmap
{ {
HitObjects = objects, HitObjects = objects,
BeatmapInfo = new BeatmapInfo BeatmapInfo = new BeatmapInfo
{ {
Difficulty = new BeatmapDifficulty(),
Metadata = new BeatmapMetadata Metadata = new BeatmapMetadata
{ {
Artist = @"Unknown", Artist = @"Unknown",
@ -71,8 +75,6 @@ namespace osu.Desktop.VisualTests.Tests
} }
}; };
decoder.Process(b);
beatmap = new TestWorkingBeatmap(b); beatmap = new TestWorkingBeatmap(b);
} }
@ -82,17 +84,21 @@ namespace osu.Desktop.VisualTests.Tests
Colour = Color4.Black, Colour = Color4.Black,
}); });
Add(new PlayerLoader(new Player Add(new PlayerLoader(Player = CreatePlayer(beatmap))
{
PreferredPlayMode = PlayMode.Osu,
Beatmap = beatmap
})
{ {
Beatmap = beatmap Beatmap = beatmap
}); });
} }
class TestWorkingBeatmap : WorkingBeatmap protected virtual Player CreatePlayer(WorkingBeatmap beatmap)
{
return new Player
{
Beatmap = beatmap
};
}
private class TestWorkingBeatmap : WorkingBeatmap
{ {
public TestWorkingBeatmap(Beatmap beatmap) public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet) : base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)

View File

@ -0,0 +1,31 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Input.Handlers;
using osu.Game.Beatmaps;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Osu.Mods;
using osu.Game.Screens.Play;
using System;
using System.IO;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseReplay : TestCasePlayer
{
private WorkingBeatmap beatmap;
private InputHandler replay;
private Func<Stream> getReplayStream;
public override string Description => @"Testing replay playback.";
protected override Player CreatePlayer(WorkingBeatmap beatmap)
{
beatmap.Mods.Value = new Mod[] { new OsuModAutoplay() };
return base.CreatePlayer(beatmap);
}
}
}

View File

@ -1,27 +1,19 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using OpenTK;
using osu.Framework.Screens.Testing;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Framework.Screens.Testing;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.Taiko.UI;
using osu.Game.Modes.UI; using osu.Game.Modes.UI;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics.Primitives;
namespace osu.Desktop.VisualTests.Tests 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 string Description => @"Tests multiple counters";
public override void Reset() public override void Reset()
@ -37,58 +29,26 @@ namespace osu.Desktop.VisualTests.Tests
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
TextSize = 40, TextSize = 40,
Count = 0,
Margin = new MarginPadding(20), Margin = new MarginPadding(20),
}; };
Add(score); Add(score);
ComboCounter standardCombo = new OsuComboCounter ComboCounter comboCounter = new StandardComboCounter
{ {
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Margin = new MarginPadding(10), Margin = new MarginPadding(10),
Count = 0,
TextSize = 40, TextSize = 40,
}; };
Add(standardCombo); Add(comboCounter);
CatchComboCounter catchCombo = new CatchComboCounter PercentageCounter accuracyCounter = new PercentageCounter
{
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
{ {
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Position = new Vector2(-20, 60), Position = new Vector2(-20, 60),
}; };
Add(accuracyCombo); Add(accuracyCounter);
StarCounter stars = new StarCounter StarCounter stars = new StarCounter
{ {
@ -110,50 +70,27 @@ namespace osu.Desktop.VisualTests.Tests
AddButton(@"Reset all", delegate AddButton(@"Reset all", delegate
{ {
score.Count = 0; score.Current.Value = 0;
standardCombo.Count = 0; comboCounter.Current.Value = 0;
taikoCombo.Count = 0;
maniaCombo.Count = 0;
catchCombo.Count = 0;
numerator = denominator = 0; numerator = denominator = 0;
accuracyCombo.SetFraction(0, 0); accuracyCounter.SetFraction(0, 0);
stars.Count = 0; stars.Count = 0;
starsLabel.Text = stars.Count.ToString("0.00"); starsLabel.Text = stars.Count.ToString("0.00");
}); });
AddButton(@"Hit! :D", delegate AddButton(@"Hit! :D", delegate
{ {
score.Count += 300 + (ulong)(300.0 * (standardCombo.Count > 0 ? standardCombo.Count - 1 : 0) / 25.0); score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
standardCombo.Count++; comboCounter.Increment();
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)
);
numerator++; denominator++; numerator++; denominator++;
accuracyCombo.SetFraction(numerator, denominator); accuracyCounter.SetFraction(numerator, denominator);
}); });
AddButton(@"miss...", delegate AddButton(@"miss...", delegate
{ {
standardCombo.Roll(); comboCounter.Current.Value = 0;
taikoCombo.Roll();
maniaCombo.Roll();
catchCombo.Roll();
denominator++; denominator++;
accuracyCombo.SetFraction(numerator, denominator); accuracyCounter.SetFraction(numerator, denominator);
});
AddButton(@"mania hold", delegate
{
if (!maniaHold)
maniaCombo.HoldStart();
else
maniaCombo.HoldEnd();
maniaHold = !maniaHold;
}); });
AddButton(@"Alter stars", delegate AddButton(@"Alter stars", delegate
@ -165,11 +102,8 @@ namespace osu.Desktop.VisualTests.Tests
AddButton(@"Stop counters", delegate AddButton(@"Stop counters", delegate
{ {
score.StopRolling(); score.StopRolling();
standardCombo.StopRolling(); comboCounter.StopRolling();
catchCombo.StopRolling(); accuracyCounter.StopRolling();
taikoCombo.StopRolling();
maniaCombo.StopRolling();
accuracyCombo.StopRolling();
stars.StopAnimation(); stars.StopAnimation();
}); });
} }

View File

@ -9,9 +9,8 @@ using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
public class TestCaseSongProgress : TestCase internal class TestCaseSongProgress : TestCase
{ {
public override string Name => @"Song Progress";
public override string Description => @"With real data"; public override string Description => @"With real data";
private SongProgress progress; private SongProgress progress;

View File

@ -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.Screens.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.ItemChanged += (sender, mode) =>
{
text.Text = "Currently Selected: " + mode.ToString();
};
}
}
}

View File

@ -12,10 +12,8 @@ using OpenTK.Graphics;
namespace osu.Desktop.VisualTests.Tests 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 string Description => @"Tests display of icons";
public override void Reset() public override void Reset()
@ -24,7 +22,7 @@ namespace osu.Desktop.VisualTests.Tests
FillFlowContainer flow; FillFlowContainer flow;
Add(flow = new FillFlowContainer() Add(flow = new FillFlowContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Size = new Vector2(0.5f), Size = new Vector2(0.5f),

View File

@ -7,9 +7,8 @@ using osu.Game.Screens.Play;
namespace osu.Desktop.VisualTests.Tests 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 string Description => @"Back and skip and what not";
public override void Reset() public override void Reset()

View File

@ -1,23 +1,30 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Platform;
using osu.Framework.Screens.Testing; using osu.Framework.Screens.Testing;
using osu.Game; using osu.Game;
using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Backgrounds;
namespace osu.Desktop.VisualTests namespace osu.Desktop.VisualTests
{ {
class VisualTestGame : OsuGameBase internal class VisualTestGame : OsuGameBase
{ {
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
(new BackgroundScreenDefault() { Depth = 10 }).LoadAsync(this, AddInternal); new BackgroundScreenDefault { Depth = 10 }.LoadAsync(this, AddInternal);
// Have to construct this here, rather than in the constructor, because // Have to construct this here, rather than in the constructor, because
// we depend on some dependencies to be loaded within OsuGameBase.load(). // we depend on some dependencies to be loaded within OsuGameBase.load().
Add(new TestBrowser()); Add(new TestBrowser());
} }
public override void SetHost(GameHost host)
{
base.SetHost(host);
host.Window.CursorState = CursorState.Hidden;
}
} }
} }

View File

@ -1,15 +0,0 @@
<?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>
<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>

View File

@ -23,6 +23,7 @@
<SignAssembly>false</SignAssembly> <SignAssembly>false</SignAssembly>
<TargetZone>LocalIntranet</TargetZone> <TargetZone>LocalIntranet</TargetZone>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PublishUrl>publish\</PublishUrl> <PublishUrl>publish\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
@ -86,6 +87,10 @@
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1340\lib\net45\OpenTK.dll</HintPath> <HintPath>$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1340\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="SharpCompress, Version=0.15.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
<HintPath>..\packages\SharpCompress.0.15.1\lib\net45\SharpCompress.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <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> <HintPath>$(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
@ -110,7 +115,6 @@
<None Include="..\osu.licenseheader"> <None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link> <Link>osu.licenseheader</Link>
</None> </None>
<None Include="app.config" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="OpenTK.dll.config" /> <None Include="OpenTK.dll.config" />
</ItemGroup> </ItemGroup>
@ -179,6 +183,7 @@
<Compile Include="Benchmark.cs" /> <Compile Include="Benchmark.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Tests\TestCaseChatDisplay.cs" /> <Compile Include="Tests\TestCaseChatDisplay.cs" />
<Compile Include="Tests\TestCaseDrawings.cs" />
<Compile Include="Tests\TestCaseGamefield.cs" /> <Compile Include="Tests\TestCaseGamefield.cs" />
<Compile Include="Tests\TestCaseMusicController.cs" /> <Compile Include="Tests\TestCaseMusicController.cs" />
<Compile Include="Tests\TestCaseNotificationManager.cs" /> <Compile Include="Tests\TestCaseNotificationManager.cs" />
@ -186,7 +191,9 @@
<Compile Include="Tests\TestCaseHitObjects.cs" /> <Compile Include="Tests\TestCaseHitObjects.cs" />
<Compile Include="Tests\TestCaseKeyCounter.cs" /> <Compile Include="Tests\TestCaseKeyCounter.cs" />
<Compile Include="Tests\TestCaseMenuButtonSystem.cs" /> <Compile Include="Tests\TestCaseMenuButtonSystem.cs" />
<Compile Include="Tests\TestCaseReplay.cs" />
<Compile Include="Tests\TestCaseScoreCounter.cs" /> <Compile Include="Tests\TestCaseScoreCounter.cs" />
<Compile Include="Tests\TestCaseTabControl.cs" />
<Compile Include="Tests\TestCaseTextAwesome.cs" /> <Compile Include="Tests\TestCaseTextAwesome.cs" />
<Compile Include="Tests\TestCasePlaySongSelect.cs" /> <Compile Include="Tests\TestCasePlaySongSelect.cs" />
<Compile Include="Tests\TestCaseTwoLayerButton.cs" /> <Compile Include="Tests\TestCaseTwoLayerButton.cs" />
@ -195,7 +202,10 @@
<Compile Include="Tests\TestCaseOptions.cs" /> <Compile Include="Tests\TestCaseOptions.cs" />
<Compile Include="Tests\TestCasePauseOverlay.cs" /> <Compile Include="Tests\TestCasePauseOverlay.cs" />
<Compile Include="Tests\TestCaseSongProgress.cs" /> <Compile Include="Tests\TestCaseSongProgress.cs" />
<Compile Include="Tests\TestCaseModSelectOverlay.cs" />
<Compile Include="Tests\TestCaseDialogOverlay.cs" /> <Compile Include="Tests\TestCaseDialogOverlay.cs" />
<Compile Include="Tests\TestCaseBeatmapOptionsOverlay.cs" />
<Compile Include="Tests\TestCaseLeaderboard.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<ItemGroup /> <ItemGroup />

View File

@ -6,6 +6,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
<packages> <packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" /> <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="ppy.OpenTK" version="2.0.50727.1340" targetFramework="net45" /> <package id="ppy.OpenTK" version="2.0.50727.1340" targetFramework="net45" />
<package id="SharpCompress" version="0.15.1" targetFramework="net45" />
<package id="SQLite.Net.Core-PCL" version="3.1.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="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" /> <package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />

View File

@ -17,16 +17,16 @@ namespace osu.Desktop.Beatmaps.IO
{ {
public static void Register() => AddReader<LegacyFilesystemReader>((storage, path) => Directory.Exists(path)); public static void Register() => AddReader<LegacyFilesystemReader>((storage, path) => Directory.Exists(path));
private string basePath { get; set; } private string basePath { get; }
private Beatmap firstMap { get; set; } private Beatmap firstMap { get; }
public LegacyFilesystemReader(string path) public LegacyFilesystemReader(string path)
{ {
basePath = path; basePath = path;
BeatmapFilenames = Directory.GetFiles(basePath, @"*.osu").Select(f => Path.GetFileName(f)).ToArray(); BeatmapFilenames = Directory.GetFiles(basePath, @"*.osu").Select(Path.GetFileName).ToArray();
if (BeatmapFilenames.Length == 0) if (BeatmapFilenames.Length == 0)
throw new FileNotFoundException(@"This directory contains no beatmaps"); throw new FileNotFoundException(@"This directory contains no beatmaps");
StoryboardFilename = Directory.GetFiles(basePath, @"*.osb").Select(f => Path.GetFileName(f)).FirstOrDefault(); StoryboardFilename = Directory.GetFiles(basePath, @"*.osb").Select(Path.GetFileName).FirstOrDefault();
using (var stream = new StreamReader(GetStream(BeatmapFilenames[0]))) using (var stream = new StreamReader(GetStream(BeatmapFilenames[0])))
{ {
var decoder = BeatmapDecoder.GetDecoder(stream); var decoder = BeatmapDecoder.GetDecoder(stream);

View File

@ -9,16 +9,16 @@ using osu.Framework.Desktop.Platform;
using osu.Desktop.Overlays; using osu.Desktop.Overlays;
using System.Reflection; using System.Reflection;
using System.Drawing; using System.Drawing;
using System.IO;
using System.Threading.Tasks;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
namespace osu.Desktop namespace osu.Desktop
{ {
class OsuGameDesktop : OsuGame internal class OsuGameDesktop : OsuGame
{ {
private VersionManager versionManager; private VersionManager versionManager;
public override bool IsDeployedBuild => versionManager.IsDeployedBuild;
public OsuGameDesktop(string[] args = null) public OsuGameDesktop(string[] args = null)
: base(args) : base(args)
{ {
@ -30,9 +30,9 @@ namespace osu.Desktop
base.LoadComplete(); base.LoadComplete();
versionManager.LoadAsync(this); versionManager.LoadAsync(this);
ModeChanged += m => ScreenChanged += s =>
{ {
if (!versionManager.IsAlive && m is Intro) if (!versionManager.IsAlive && s is Intro)
Add(versionManager); Add(versionManager);
}; };
} }
@ -43,8 +43,10 @@ namespace osu.Desktop
var desktopWindow = host.Window as DesktopGameWindow; var desktopWindow = host.Window as DesktopGameWindow;
if (desktopWindow != null) if (desktopWindow != null)
{ {
desktopWindow.CursorState = CursorState.Hidden;
desktopWindow.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); desktopWindow.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
desktopWindow.Title = @"osu!lazer"; desktopWindow.Title = Name;
desktopWindow.DragEnter += dragEnter; desktopWindow.DragEnter += dragEnter;
desktopWindow.DragDrop += dragDrop; desktopWindow.DragDrop += dragDrop;
@ -54,22 +56,29 @@ namespace osu.Desktop
private void dragDrop(DragEventArgs e) private void dragDrop(DragEventArgs e)
{ {
// this method will only be executed if e.Effect in dragEnter gets set to something other that None. // 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(); var filePaths = dropData.Select(f => f.ToString()).ToArray();
ImportBeatmapsAsync(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) private void dragEnter(DragEventArgs e)
{ {
// dragDrop will only be executed if e.Effect gets set to something other that None in this method. // 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); bool isFile = e.Data.GetDataPresent(DataFormats.FileDrop);
if (isFile) if (isFile)
{ {
var paths = (e.Data.GetData(DataFormats.FileDrop) as object[]).Select(f => f.ToString()).ToArray(); var paths = ((object[])e.Data.GetData(DataFormats.FileDrop)).Select(f => f.ToString()).ToArray();
if (paths.Any(p => !p.EndsWith(".osz"))) e.Effect = allowed_extensions.Any(ext => paths.All(p => p.EndsWith(ext))) ? DragDropEffects.Copy : DragDropEffects.None;
e.Effect = DragDropEffects.None;
else
e.Effect = DragDropEffects.Copy;
} }
} }
} }

View File

@ -2,7 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Diagnostics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Colour;
@ -11,13 +10,14 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
using Squirrel; using Squirrel;
using System.Reflection;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Graphics; using osu.Game.Graphics;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using System.Net.Http; using System.Net.Http;
using osu.Framework.Logging;
using osu.Game;
namespace osu.Desktop.Overlays namespace osu.Desktop.Overlays
{ {
@ -26,16 +26,12 @@ namespace osu.Desktop.Overlays
private UpdateManager updateManager; private UpdateManager updateManager;
private NotificationManager notificationManager; private NotificationManager notificationManager;
AssemblyName assembly = Assembly.GetEntryAssembly().GetName();
public bool IsDeployedBuild => assembly.Version.Major > 0;
protected override bool HideOnEscape => false; protected override bool HideOnEscape => false;
public override bool HandleInput => false; public override bool HandleInput => false;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(NotificationManager notification, OsuColour colours, TextureStore textures) private void load(NotificationManager notification, OsuColour colours, TextureStore textures, OsuGameBase game)
{ {
notificationManager = notification; notificationManager = notification;
@ -44,29 +40,18 @@ namespace osu.Desktop.Overlays
Origin = Anchor.BottomCentre; Origin = Anchor.BottomCentre;
Alpha = 0; Alpha = 0;
bool isDebug = false;
Debug.Assert(isDebug = true);
string version;
if (!IsDeployedBuild)
{
version = @"local " + (isDebug ? @"debug" : @"release");
}
else
version = $@"{assembly.Version.Major}.{assembly.Version.Minor}.{assembly.Version.Build}";
Children = new Drawable[] Children = new Drawable[]
{ {
new FillFlowContainer new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Down, Direction = FillDirection.Vertical,
Children = new Drawable[] Children = new Drawable[]
{ {
new FillFlowContainer new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Right, Direction = FillDirection.Horizontal,
Spacing = new Vector2(5), Spacing = new Vector2(5),
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
@ -75,12 +60,12 @@ namespace osu.Desktop.Overlays
new OsuSpriteText new OsuSpriteText
{ {
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
Text = $@"osu!lazer" Text = game.Name
}, },
new OsuSpriteText new OsuSpriteText
{ {
Colour = isDebug ? colours.Red : Color4.White, Colour = game.IsDebug ? colours.Red : Color4.White,
Text = version Text = game.Version
}, },
} }
}, },
@ -91,7 +76,7 @@ namespace osu.Desktop.Overlays
TextSize = 12, TextSize = 12,
Colour = colours.Yellow, Colour = colours.Yellow,
Font = @"Venera", Font = @"Venera",
Text = $@"Development Build" Text = @"Development Build"
}, },
new Sprite new Sprite
{ {
@ -103,7 +88,7 @@ namespace osu.Desktop.Overlays
} }
}; };
if (IsDeployedBuild) if (game.IsDeployedBuild)
checkForUpdateAsync(); checkForUpdateAsync();
} }
@ -159,15 +144,21 @@ namespace osu.Desktop.Overlays
Schedule(() => notification.State = ProgressNotificationState.Completed); Schedule(() => notification.State = ProgressNotificationState.Completed);
} }
catch (Exception) catch (Exception e)
{ {
if (useDeltaPatching) 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) //could fail if deltas are unavailable for full update path (https://github.com/Squirrel/Squirrel.Windows/issues/959)
//try again without deltas. //try again without deltas.
checkForUpdateAsync(false, notification); checkForUpdateAsync(false, notification);
scheduleRetry = false; scheduleRetry = false;
} }
else
{
Logger.Error(e, @"update failed!");
}
} }
} }
catch (HttpRequestException) catch (HttpRequestException)
@ -196,9 +187,9 @@ namespace osu.Desktop.Overlays
{ {
} }
class UpdateProgressNotification : ProgressNotification private class UpdateProgressNotification : ProgressNotification
{ {
protected override Notification CreateCompletionNotification() => new ProgressCompletionNotification(this) protected override Notification CreateCompletionNotification() => new ProgressCompletionNotification()
{ {
Text = @"Update ready to install. Click to restart!", Text = @"Update ready to install. Click to restart!",
Activated = () => Activated = () =>
@ -221,8 +212,10 @@ namespace osu.Desktop.Overlays
new TextAwesome new TextAwesome
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Icon = FontAwesome.fa_upload, Icon = FontAwesome.fa_upload,
Colour = Color4.White, Colour = Color4.White,
TextSize = 20
} }
}); });
} }

View File

@ -29,7 +29,7 @@ namespace osu.Desktop
{ {
if (!host.IsPrimaryInstance) 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 // Restore the cwd so relative paths given at the command line work correctly
Directory.SetCurrentDirectory(cwd); Directory.SetCurrentDirectory(cwd);
foreach (var file in args) foreach (var file in args)

View File

@ -1,19 +0,0 @@
<?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>
<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>
<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>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -23,6 +23,7 @@
<SignAssembly>false</SignAssembly> <SignAssembly>false</SignAssembly>
<TargetZone>LocalIntranet</TargetZone> <TargetZone>LocalIntranet</TargetZone>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PublishUrl>publish\</PublishUrl> <PublishUrl>publish\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
@ -101,10 +102,6 @@
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll</HintPath> <HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </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"> <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> <HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -153,7 +150,6 @@
<None Include="..\osu.licenseheader"> <None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link> <Link>osu.licenseheader</Link>
</None> </None>
<None Include="app.config" />
<None Include="osu!.res" /> <None Include="osu!.res" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="Properties\app.manifest" /> <None Include="Properties\app.manifest" />

View File

@ -17,7 +17,8 @@
</metadata> </metadata>
<files> <files>
<file src="*.exe" target="lib\net45\" exclude="**vshost**"/> <file src="*.exe" target="lib\net45\" exclude="**vshost**"/>
<file src="*.dll" target="lib\net45\"/> <file src="*.dll" target="lib\net45\"/>
<file src="*.config" target="lib\net45\"/>
<file src="x86\*.dll" target="lib\net45\x86\"/> <file src="x86\*.dll" target="lib\net45\x86\"/>
<file src="x64\*.dll" target="lib\net45\x64\"/> <file src="x64\*.dll" target="lib\net45\x64\"/>
</files> </files>

View File

@ -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
};
}
}
}

View File

@ -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)
{
}
}
}

View File

@ -2,26 +2,23 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Modes.Catch.Beatmaps;
using osu.Game.Modes.Catch.Objects; using osu.Game.Modes.Catch.Objects;
using osu.Game.Modes.Objects;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace osu.Game.Modes.Catch namespace osu.Game.Modes.Catch
{ {
public class CatchDifficultyCalculator : DifficultyCalculator<CatchBaseHit> public class CatchDifficultyCalculator : DifficultyCalculator<CatchBaseHit>
{ {
protected override PlayMode PlayMode => PlayMode.Catch;
public CatchDifficultyCalculator(Beatmap beatmap) : base(beatmap) public CatchDifficultyCalculator(Beatmap beatmap) : base(beatmap)
{ {
} }
protected override HitObjectConverter<CatchBaseHit> Converter => new CatchConverter(); protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
protected override double CalculateInternal(Dictionary<String, String> categoryDifficulty)
{ {
return 0; return 0;
} }
protected override IBeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter();
} }
} }

View File

@ -1,29 +1,94 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Graphics; using OpenTK.Input;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
using osu.Game.Beatmaps; 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;
namespace osu.Game.Modes.Catch namespace osu.Game.Modes.Catch
{ {
public class CatchRuleset : Ruleset 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; protected override PlayMode PlayMode => PlayMode.Catch;
public override string Description => "osu!catch";
public override FontAwesome Icon => FontAwesome.fa_osu_fruits_o; public override FontAwesome Icon => FontAwesome.fa_osu_fruits_o;
public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null; public override IEnumerable<KeyCounter> CreateGameplayKeys() => new KeyCounter[]
{
public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser(); new KeyCounterKeyboard(Key.ShiftLeft),
new KeyCounterMouse(MouseButton.Left),
new KeyCounterMouse(MouseButton.Right)
};
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap);
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor();
} }
} }

View File

@ -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.Modes.Catch.Judgements;
using osu.Game.Modes.Catch.Objects;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Catch
{
internal class CatchScoreProcessor : ScoreProcessor<CatchBaseHit, CatchJudgementInfo>
{
public CatchScoreProcessor()
{
}
public CatchScoreProcessor(HitRenderer<CatchBaseHit, CatchJudgementInfo> hitRenderer)
: base(hitRenderer)
{
}
protected override void UpdateCalculations(CatchJudgementInfo newJudgement)
{
}
}
}

View File

@ -0,0 +1,11 @@
// 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 CatchJudgementInfo : JudgementInfo
{
}
}

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
{
}
}

View File

@ -7,6 +7,6 @@ namespace osu.Game.Modes.Catch.Objects
{ {
public abstract class CatchBaseHit : HitObject public abstract class CatchBaseHit : HitObject
{ {
public float Position; public float Position { get; set; }
} }
} }

View File

@ -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;
}
}
}

View File

@ -10,7 +10,7 @@ using OpenTK;
namespace osu.Game.Modes.Catch.Objects.Drawable namespace osu.Game.Modes.Catch.Objects.Drawable
{ {
class DrawableFruit : Sprite internal class DrawableFruit : Sprite
{ {
private CatchBaseHit h; private CatchBaseHit h;
@ -29,8 +29,10 @@ namespace osu.Game.Modes.Catch.Objects.Drawable
{ {
Texture = textures.Get(@"Menu/logo"); Texture = textures.Get(@"Menu/logo");
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 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); Expire(true);
} }
} }

View File

@ -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++;
}
}
}

View File

@ -1,19 +1,30 @@
// Copyright (c) 2007-2017 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 // 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.Catch.Objects;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.UI; using osu.Game.Modes.UI;
namespace osu.Game.Modes.Catch.UI namespace osu.Game.Modes.Catch.UI
{ {
public class CatchHitRenderer : HitRenderer<CatchBaseHit> public class CatchHitRenderer : HitRenderer<CatchBaseHit, CatchJudgementInfo>
{ {
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, CatchJudgementInfo> CreatePlayfield() => new CatchPlayfield();
protected override DrawableHitObject<CatchBaseHit, CatchJudgementInfo> GetVisualRepresentation(CatchBaseHit h) => null;
} }
} }

View File

@ -3,12 +3,14 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Modes.Catch.Objects;
using osu.Game.Modes.UI; using osu.Game.Modes.UI;
using OpenTK; using OpenTK;
using osu.Game.Modes.Catch.Judgements;
namespace osu.Game.Modes.Catch.UI namespace osu.Game.Modes.Catch.UI
{ {
public class CatchPlayfield : Playfield public class CatchPlayfield : Playfield<CatchBaseHit, CatchJudgementInfo>
{ {
public CatchPlayfield() public CatchPlayfield()
{ {

View File

@ -47,17 +47,20 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Beatmaps\CatchBeatmapConverter.cs" />
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
<Compile Include="CatchDifficultyCalculator.cs" /> <Compile Include="CatchDifficultyCalculator.cs" />
<Compile Include="CatchScoreProcessor.cs" />
<Compile Include="Judgements\CatchJudgementInfo.cs" />
<Compile Include="Objects\CatchBaseHit.cs" /> <Compile Include="Objects\CatchBaseHit.cs" />
<Compile Include="Objects\CatchConverter.cs" />
<Compile Include="Objects\Drawable\DrawableFruit.cs" /> <Compile Include="Objects\Drawable\DrawableFruit.cs" />
<Compile Include="Objects\Droplet.cs" /> <Compile Include="Objects\Droplet.cs" />
<Compile Include="Objects\Fruit.cs" /> <Compile Include="Objects\Fruit.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UI\CatchComboCounter.cs" />
<Compile Include="UI\CatchHitRenderer.cs" /> <Compile Include="UI\CatchHitRenderer.cs" />
<Compile Include="UI\CatchPlayfield.cs" /> <Compile Include="UI\CatchPlayfield.cs" />
<Compile Include="CatchRuleset.cs" /> <Compile Include="CatchRuleset.cs" />
<Compile Include="Mods\CatchMod.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\osu.licenseheader"> <None Include="..\osu.licenseheader">

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright (c) 2007-2017 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 Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE

View File

@ -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
};
}
}
}

View File

@ -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)
{
}
}
}

View File

@ -0,0 +1,11 @@
// 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 ManiaJudgementInfo : JudgementInfo
{
}
}

View File

@ -2,29 +2,24 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Beatmaps;
using osu.Game.Modes.Mania.Objects; using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.Objects;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace osu.Game.Modes.Mania namespace osu.Game.Modes.Mania
{ {
public class ManiaDifficultyCalculator : DifficultyCalculator<ManiaBaseHit> public class ManiaDifficultyCalculator : DifficultyCalculator<ManiaBaseHit>
{ {
protected override PlayMode PlayMode => PlayMode.Mania; public ManiaDifficultyCalculator(Beatmap beatmap)
: base(beatmap)
private int columns;
public ManiaDifficultyCalculator(Beatmap beatmap, int columns = 5) : base(beatmap)
{ {
this.columns = columns;
} }
protected override HitObjectConverter<ManiaBaseHit> Converter => new ManiaConverter(columns); protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
protected override double CalculateInternal(Dictionary<String, String> categoryDifficulty)
{ {
return 0; return 0;
} }
protected override IBeatmapConverter<ManiaBaseHit> CreateBeatmapConverter() => new ManiaBeatmapConverter();
} }
} }

View File

@ -1,29 +1,109 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Graphics;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
using osu.Game.Beatmaps; 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;
namespace osu.Game.Modes.Mania namespace osu.Game.Modes.Mania
{ {
public class ManiaRuleset : Ruleset 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; protected override PlayMode PlayMode => PlayMode.Mania;
public override string Description => "osu!mania";
public override FontAwesome Icon => FontAwesome.fa_osu_mania_o; 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 NullHitObjectParser();
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap);
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor();
} }
} }

View File

@ -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.Modes.Mania.Judgements;
using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Mania
{
internal class ManiaScoreProcessor : ScoreProcessor<ManiaBaseHit, ManiaJudgementInfo>
{
public ManiaScoreProcessor()
{
}
public ManiaScoreProcessor(HitRenderer<ManiaBaseHit, ManiaJudgementInfo> hitRenderer)
: base(hitRenderer)
{
}
protected override void UpdateCalculations(ManiaJudgementInfo newJudgement)
{
}
}
}

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;
}
}

View File

@ -26,8 +26,10 @@ namespace osu.Game.Modes.Mania.Objects.Drawable
{ {
Texture = textures.Get(@"Menu/logo"); Texture = textures.Get(@"Menu/logo");
Transforms.Add(new TransformPositionY() { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f }); double duration = 0;
Transforms.Add(new TransformAlpha() { StartTime = note.StartTime + note.Duration + 200, EndTime = note.StartTime + note.Duration + 400, StartValue = 1, EndValue = 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); Expire(true);
} }
} }

View File

@ -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;
}
}
}

View File

@ -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.Transforms;
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);
}
}
}

View File

@ -1,34 +1,33 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Modes.Mania.Beatmaps;
using osu.Game.Modes.Mania.Judgements;
using osu.Game.Modes.Mania.Objects; using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.UI; using osu.Game.Modes.UI;
namespace osu.Game.Modes.Mania.UI namespace osu.Game.Modes.Mania.UI
{ {
public class ManiaHitRenderer : HitRenderer<ManiaBaseHit> public class ManiaHitRenderer : HitRenderer<ManiaBaseHit, ManiaJudgementInfo>
{ {
private readonly int columns; private readonly int columns;
public ManiaHitRenderer(int columns = 5) public ManiaHitRenderer(WorkingBeatmap beatmap, int columns = 5)
: base(beatmap)
{ {
this.columns = columns; 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) protected override IBeatmapProcessor<ManiaBaseHit> CreateBeatmapProcessor() => new ManiaBeatmapProcessor();
{
return null; protected override Playfield<ManiaBaseHit, ManiaJudgementInfo> CreatePlayfield() => new ManiaPlayfield(columns);
//return new DrawableNote(h)
//{ protected override DrawableHitObject<ManiaBaseHit, ManiaJudgementInfo> GetVisualRepresentation(ManiaBaseHit h) => null;
// Position = new Vector2((float)(h.Column + 0.5) / columns, -0.1f),
// RelativePositionAxes = Axes.Both
//};
}
} }
} }

View File

@ -3,19 +3,18 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Modes.Mania.Objects;
using osu.Game.Modes.UI; using osu.Game.Modes.UI;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Modes.Mania.Judgements;
namespace osu.Game.Modes.Mania.UI namespace osu.Game.Modes.Mania.UI
{ {
public class ManiaPlayfield : Playfield public class ManiaPlayfield : Playfield<ManiaBaseHit, ManiaJudgementInfo>
{ {
private readonly int columns;
public ManiaPlayfield(int columns) public ManiaPlayfield(int columns)
{ {
this.columns = columns;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Size = new Vector2(columns / 20f, 1f); Size = new Vector2(columns / 20f, 1f);
Anchor = Anchor.BottomCentre; Anchor = Anchor.BottomCentre;
@ -24,7 +23,7 @@ namespace osu.Game.Modes.Mania.UI
Add(new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.5f }); Add(new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.5f });
for (int i = 0; i < columns; i++) for (int i = 0; i < columns; i++)
Add(new Box() Add(new Box
{ {
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Size = new Vector2(2, 1), Size = new Vector2(2, 1),

View File

@ -1,15 +0,0 @@
<?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>
<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>

View File

@ -47,17 +47,20 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Beatmaps\ManiaBeatmapConverter.cs" />
<Compile Include="Beatmaps\ManiaBeatmapProcessor.cs" />
<Compile Include="Judgements\ManiaJudgementInfo.cs" />
<Compile Include="ManiaDifficultyCalculator.cs" /> <Compile Include="ManiaDifficultyCalculator.cs" />
<Compile Include="ManiaScoreProcessor.cs" />
<Compile Include="Objects\Drawable\DrawableNote.cs" /> <Compile Include="Objects\Drawable\DrawableNote.cs" />
<Compile Include="Objects\HoldNote.cs" /> <Compile Include="Objects\HoldNote.cs" />
<Compile Include="Objects\ManiaBaseHit.cs" /> <Compile Include="Objects\ManiaBaseHit.cs" />
<Compile Include="Objects\ManiaConverter.cs" />
<Compile Include="Objects\Note.cs" /> <Compile Include="Objects\Note.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UI\ManiaComboCounter.cs" />
<Compile Include="UI\ManiaHitRenderer.cs" /> <Compile Include="UI\ManiaHitRenderer.cs" />
<Compile Include="UI\ManiaPlayfield.cs" /> <Compile Include="UI\ManiaPlayfield.cs" />
<Compile Include="ManiaRuleset.cs" /> <Compile Include="ManiaRuleset.cs" />
<Compile Include="Mods\ManiaMod.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj"> <ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
@ -81,10 +84,10 @@
<None Include="..\osu.licenseheader"> <None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link> <Link>osu.licenseheader</Link>
</None> </None>
<None Include="app.config" />
<None Include="OpenTK.dll.config" /> <None Include="OpenTK.dll.config" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <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. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright (c) 2007-2017 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 Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE

View File

@ -1,35 +1,82 @@
// Copyright (c) 2007-2017 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 // 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 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>(); return new Beatmap<OsuHitObject>(original)
int combo = 0;
foreach (HitObject h in beatmap.HitObjects)
{ {
if (h.NewCombo) combo = 0; HitObjects = convertHitObjects(original.HitObjects, original.BeatmapInfo?.StackLeniency ?? 0.7f)
};
h.ComboIndex = combo++;
output.Add(h as OsuHitObject);
}
UpdateStacking(output, beatmap.BeatmapInfo?.StackLeniency ?? 0.7f);
return output;
} }
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,
Sample = original.Sample,
CurveObject = curveData,
Position = positionData?.Position ?? Vector2.Zero,
NewCombo = comboData?.NewCombo ?? false
};
}
if (endTimeData != null)
{
return new Spinner
{
StartTime = original.StartTime,
Sample = original.Sample,
Position = new Vector2(512, 384) / 2,
EndTime = endTimeData.EndTime
};
}
return new HitCircle
{
StartTime = original.StartTime,
Sample = original.Sample,
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) if (endIndex == -1)
endIndex = hitObjects.Count - 1; endIndex = hitObjects.Count - 1;
@ -52,14 +99,17 @@ namespace osu.Game.Modes.Osu.Objects
if (stackBaseObject is Spinner) break; if (stackBaseObject is Spinner) break;
OsuHitObject objectN = hitObjects[n]; 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. //We are no longer within stacking range of the next object.
break; break;
if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stackDistance || if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stackDistance ||
(stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stackDistance)) stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stackDistance)
{ {
stackBaseIndex = n; stackBaseIndex = n;
@ -106,7 +156,9 @@ namespace osu.Game.Modes.Osu.Objects
OsuHitObject objectN = hitObjects[n]; OsuHitObject objectN = hitObjects[n];
if (objectN is Spinner) continue; 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. //We are no longer within stacking range of the previous object.
break; break;
@ -171,6 +223,5 @@ namespace osu.Game.Modes.Osu.Objects
} }
} }
} }
} }
} }

View File

@ -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 osu.Game.Beatmaps;
using osu.Game.Modes.Osu.Objects;
namespace osu.Game.Modes.Osu.Beatmaps
{
internal class OsuBeatmapProcessor : IBeatmapProcessor<OsuHitObject>
{
public void PostProcess(Beatmap<OsuHitObject> beatmap)
{
if (beatmap.ComboColors.Count == 0)
return;
int comboIndex = 0;
int colourIndex = 0;
foreach (var obj in beatmap.HitObjects)
{
if (obj.NewCombo)
{
comboIndex = 0;
colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count;
}
obj.ComboIndex = comboIndex++;
obj.ComboColour = beatmap.ComboColors[colourIndex];
}
}
}
}

View File

@ -0,0 +1,50 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Modes.Judgements;
using osu.Game.Modes.Osu.Objects.Drawables;
namespace osu.Game.Modes.Osu.Judgements
{
public class OsuJudgementInfo : JudgementInfo
{
/// <summary>
/// The positional hit offset.
/// </summary>
public Vector2 PositionOffset;
/// <summary>
/// The score the user achieved.
/// </summary>
public OsuScoreResult Score;
/// <summary>
/// The score which would be achievable on a perfect hit.
/// </summary>
public OsuScoreResult MaxScore = OsuScoreResult.Hit300;
public int ScoreValue => scoreToInt(Score);
public int MaxScoreValue => scoreToInt(MaxScore);
private int scoreToInt(OsuScoreResult result)
{
switch (result)
{
default:
return 0;
case OsuScoreResult.Hit50:
return 50;
case OsuScoreResult.Hit100:
return 100;
case OsuScoreResult.Hit300:
return 300;
case OsuScoreResult.SliderTick:
return 10;
}
}
public ComboResult Combo;
}
}

View File

@ -0,0 +1,108 @@
// 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.Graphics;
using osu.Game.Modes.Mods;
using osu.Game.Modes.Osu.Objects;
using System;
using System.Linq;
namespace osu.Game.Modes.Osu.Mods
{
public class OsuModNoFail : ModNoFail
{
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
}
public class OsuModEasy : ModEasy
{
}
public class OsuModHidden : 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 OsuModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.06;
public override bool Ranked => true;
}
public class OsuModSuddenDeath : ModSuddenDeath
{
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
}
public class OsuModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.12;
}
public class OsuModRelax : ModRelax
{
public override string Description => "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things.";
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
}
public class OsuModHalfTime : ModHalfTime
{
public override double ScoreMultiplier => 0.5;
}
public class OsuModNightcore : ModNightcore
{
public override double ScoreMultiplier => 1.12;
}
public class OsuModFlashlight : ModFlashlight
{
public override double ScoreMultiplier => 1.12;
}
public class OsuModPerfect : ModPerfect
{
}
public class OsuModSpunOut : Mod
{
public override string Name => "Spun Out";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
public override string Description => @"Spinners will be automatically completed";
public override double ScoreMultiplier => 0.9;
public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) };
}
public class OsuModAutopilot : Mod
{
public override string Name => "Autopilot";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
public override double ScoreMultiplier => 0;
public override bool Ranked => false;
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) };
}
public class OsuModAutoplay : ModAutoplay<OsuHitObject>
{
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap) => new Score
{
Replay = new OsuAutoReplay(beatmap)
};
}
public class OsuModTarget : Mod
{
public override string Name => "Target";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
public override string Description => @"";
public override double ScoreMultiplier => 1;
}
}

View File

@ -3,11 +3,11 @@
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transforms; using osu.Framework.Graphics.Transforms;
using osu.Game.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables.Connections namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
{ {
@ -17,7 +17,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
public double EndTime; public double EndTime;
public Vector2 EndPosition; public Vector2 EndPosition;
const float width = 8; private const float width = 8;
public FollowPoint() public FollowPoint()
{ {

View File

@ -1,12 +1,12 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Modes.Osu.Objects.Drawables.Connections;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenTK;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Osu.Objects.Drawables namespace osu.Game.Modes.Osu.Objects.Drawables.Connections
{ {
public class FollowPointRenderer : ConnectionRenderer<OsuHitObject> public class FollowPointRenderer : ConnectionRenderer<OsuHitObject>
{ {
@ -64,7 +64,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
Vector2 startPosition = prevHitObject.EndPosition; Vector2 startPosition = prevHitObject.EndPosition;
Vector2 endPosition = currHitObject.Position; Vector2 endPosition = currHitObject.Position;
double startTime = prevHitObject.EndTime; double startTime = (prevHitObject as IHasEndTime)?.EndTime ?? prevHitObject.StartTime;
double endTime = currHitObject.StartTime; double endTime = currHitObject.StartTime;
Vector2 distanceVector = endPosition - startPosition; Vector2 distanceVector = endPosition - startPosition;
@ -74,13 +74,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance) for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance)
{ {
float fraction = ((float)d / distance); float fraction = (float)d / distance;
Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector;
Vector2 pointEndPosition = startPosition + fraction * distanceVector; Vector2 pointEndPosition = startPosition + fraction * distanceVector;
double fadeOutTime = startTime + fraction * duration; double fadeOutTime = startTime + fraction * duration;
double fadeInTime = fadeOutTime - PreEmpt; double fadeInTime = fadeOutTime - PreEmpt;
Add(new FollowPoint() Add(new FollowPoint
{ {
StartTime = fadeInTime, StartTime = fadeInTime,
EndTime = fadeOutTime, EndTime = fadeOutTime,

View File

@ -7,6 +7,7 @@ using osu.Framework.Graphics.Transforms;
using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces; using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using OpenTK; using OpenTK;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Osu.Objects.Drawables namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
@ -35,21 +36,21 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
glow = new GlowPiece glow = new GlowPiece
{ {
Colour = osuObject.Colour Colour = osuObject.ComboColour
}, },
circle = new CirclePiece circle = new CirclePiece
{ {
Colour = osuObject.Colour, Colour = osuObject.ComboColour,
Hit = () => Hit = () =>
{ {
if (Judgement.Result.HasValue) return false; if (Judgement.Result.HasValue) return false;
((PositionalJudgementInfo)Judgement).PositionOffset = Vector2.Zero; //todo: set to correct value Judgement.PositionOffset = Vector2.Zero; //todo: set to correct value
UpdateJudgement(true); UpdateJudgement(true);
return true; return true;
}, },
}, },
number = new NumberPiece() number = new NumberPiece
{ {
Text = h is Spinner ? "S" : (HitObject.ComboIndex + 1).ToString(), Text = h is Spinner ? "S" : (HitObject.ComboIndex + 1).ToString(),
}, },
@ -57,11 +58,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
flash = new FlashPiece(), flash = new FlashPiece(),
explode = new ExplodePiece explode = new ExplodePiece
{ {
Colour = osuObject.Colour, Colour = osuObject.ComboColour,
}, },
ApproachCircle = new ApproachCircle() ApproachCircle = new ApproachCircle
{ {
Colour = osuObject.Colour, Colour = osuObject.ComboColour,
} }
}; };
@ -69,33 +70,21 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
Size = circle.DrawSize; Size = circle.DrawSize;
} }
double hit50 = 150;
double hit100 = 80;
double hit300 = 30;
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
if (!userTriggered) if (!userTriggered)
{ {
if (Judgement.TimeOffset > hit50) if (Judgement.TimeOffset > HitObject.HitWindowFor(OsuScoreResult.Hit50))
Judgement.Result = HitResult.Miss; Judgement.Result = HitResult.Miss;
return; return;
} }
double hitOffset = Math.Abs(Judgement.TimeOffset); double hitOffset = Math.Abs(Judgement.TimeOffset);
OsuJudgementInfo osuJudgement = Judgement as OsuJudgementInfo; if (hitOffset < HitObject.HitWindowFor(OsuScoreResult.Hit50))
if (hitOffset < hit50)
{ {
Judgement.Result = HitResult.Hit; Judgement.Result = HitResult.Hit;
Judgement.Score = HitObject.ScoreResultForOffset(hitOffset);
if (hitOffset < hit300)
osuJudgement.Score = OsuScoreResult.Hit300;
else if (hitOffset < hit100)
osuJudgement.Score = OsuScoreResult.Hit100;
else if (hitOffset < hit50)
osuJudgement.Score = OsuScoreResult.Hit50;
} }
else else
Judgement.Result = HitResult.Miss; Judgement.Result = HitResult.Miss;
@ -122,23 +111,26 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
if (!IsLoaded) return;
base.UpdateState(state); base.UpdateState(state);
ApproachCircle.FadeOut(); ApproachCircle.FadeOut();
glow.Delay(osuObject.Duration); double endTime = (osuObject as IHasEndTime)?.EndTime ?? osuObject.StartTime;
double duration = endTime - osuObject.StartTime;
glow.Delay(duration);
glow.FadeOut(400); glow.FadeOut(400);
switch (state) switch (state)
{ {
case ArmedState.Idle: case ArmedState.Idle:
Delay(osuObject.Duration + TIME_PREEMPT); Delay(duration + TIME_PREEMPT);
FadeOut(TIME_FADEOUT); FadeOut(TIME_FADEOUT);
Expire(true);
break; break;
case ArmedState.Miss: case ArmedState.Miss:
FadeOut(TIME_FADEOUT / 5); FadeOut(TIME_FADEOUT / 5);
Expire();
break; break;
case ArmedState.Hit: case ArmedState.Hit:
const double flash_in = 40; const double flash_in = 40;
@ -158,6 +150,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
FadeOut(800); FadeOut(800);
ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad); ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad);
Expire();
break; break;
} }
} }

View File

@ -2,12 +2,12 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel; using System.ComponentModel;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Judgements;
namespace osu.Game.Modes.Osu.Objects.Drawables namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
public class DrawableOsuHitObject : DrawableHitObject public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject, OsuJudgementInfo>
{ {
public const float TIME_PREEMPT = 600; public const float TIME_PREEMPT = 600;
public const float TIME_FADEIN = 400; public const float TIME_FADEIN = 400;
@ -18,12 +18,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
} }
public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.Hit300 }; protected override OsuJudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.Hit300 };
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
if (!IsLoaded) return;
Flush(); Flush();
UpdateInitialState(); UpdateInitialState();
@ -46,42 +44,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
} }
} }
public class OsuJudgementInfo : PositionalJudgementInfo
{
/// <summary>
/// The score the user achieved.
/// </summary>
public OsuScoreResult Score;
/// <summary>
/// The score which would be achievable on a perfect hit.
/// </summary>
public OsuScoreResult MaxScore = OsuScoreResult.Hit300;
public int ScoreValue => scoreToInt(Score);
public int MaxScoreValue => scoreToInt(MaxScore);
private int scoreToInt(OsuScoreResult result)
{
switch (result)
{
default:
return 0;
case OsuScoreResult.Hit50:
return 50;
case OsuScoreResult.Hit100:
return 100;
case OsuScoreResult.Hit300:
return 300;
case OsuScoreResult.SliderTick:
return 10;
}
}
public ComboResult Combo;
}
public enum ComboResult public enum ComboResult
{ {
[Description(@"")] [Description(@"")]

View File

@ -21,13 +21,18 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
private Container<DrawableSliderTick> ticks; private Container<DrawableSliderTick> ticks;
SliderBody body; private SliderBody body;
SliderBall ball; private SliderBall ball;
SliderBouncer bouncer1, bouncer2; private SliderBouncer bouncer2;
public DrawableSlider(Slider s) : base(s) public DrawableSlider(Slider s) : base(s)
{ {
// Since the DrawableSlider itself is just a container without a size we need to
// pass all input through.
AlwaysReceiveInput = true;
SliderBouncer bouncer1;
slider = s; slider = s;
Children = new Drawable[] Children = new Drawable[]
@ -59,7 +64,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
Position = s.StackedPosition, Position = s.StackedPosition,
ComboIndex = s.ComboIndex, ComboIndex = s.ComboIndex,
Scale = s.Scale, Scale = s.Scale,
Colour = s.Colour, ComboColour = s.ComboColour,
Sample = s.Sample, Sample = s.Sample,
}), }),
}; };
@ -71,7 +76,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
AddNested(initialCircle); AddNested(initialCircle);
var repeatDuration = s.Curve.Length / s.Velocity; var repeatDuration = s.Curve.Distance / s.Velocity;
foreach (var tick in s.Ticks) foreach (var tick in s.Ticks)
{ {
var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration; var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration;
@ -90,11 +95,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
} }
} }
// Since the DrawableSlider itself is just a container without a size we need to private int currentRepeat;
// pass all input through.
public override bool Contains(Vector2 screenSpacePos) => true;
int currentRepeat;
protected override void Update() protected override void Update()
{ {
@ -102,8 +103,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
int repeat = (int)(progress * slider.RepeatCount); int repeat = slider.RepeatAt(progress);
progress = (progress * slider.RepeatCount) % 1; progress = slider.ProgressAt(progress);
if (repeat > currentRepeat) if (repeat > currentRepeat)
{ {
@ -112,9 +113,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
currentRepeat = repeat; currentRepeat = repeat;
} }
if (repeat % 2 == 1)
progress = 1 - progress;
bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0); bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0);
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
@ -127,27 +125,24 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
var j = Judgement as OsuJudgementInfo; if (!userTriggered && Time.Current >= slider.EndTime)
var sc = initialCircle.Judgement as OsuJudgementInfo;
if (!userTriggered && Time.Current >= HitObject.EndTime)
{ {
var ticksCount = ticks.Children.Count() + 1; var ticksCount = ticks.Children.Count() + 1;
var ticksHit = ticks.Children.Count(t => t.Judgement.Result == HitResult.Hit); var ticksHit = ticks.Children.Count(t => t.Judgement.Result == HitResult.Hit);
if (sc.Result == HitResult.Hit) if (initialCircle.Judgement.Result == HitResult.Hit)
ticksHit++; ticksHit++;
var hitFraction = (double)ticksHit / ticksCount; var hitFraction = (double)ticksHit / ticksCount;
if (hitFraction == 1 && sc.Score == OsuScoreResult.Hit300) if (hitFraction == 1 && initialCircle.Judgement.Score == OsuScoreResult.Hit300)
j.Score = OsuScoreResult.Hit300; Judgement.Score = OsuScoreResult.Hit300;
else if (hitFraction >= 0.5 && sc.Score >= OsuScoreResult.Hit100) else if (hitFraction >= 0.5 && initialCircle.Judgement.Score >= OsuScoreResult.Hit100)
j.Score = OsuScoreResult.Hit100; Judgement.Score = OsuScoreResult.Hit100;
else if (hitFraction > 0) else if (hitFraction > 0)
j.Score = OsuScoreResult.Hit50; Judgement.Score = OsuScoreResult.Hit50;
else else
j.Score = OsuScoreResult.Miss; Judgement.Score = OsuScoreResult.Miss;
j.Result = j.Score != OsuScoreResult.Miss ? HitResult.Hit : HitResult.Miss; Judgement.Result = Judgement.Score != OsuScoreResult.Miss ? HitResult.Hit : HitResult.Miss;
} }
} }
@ -167,12 +162,14 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
ball.FadeIn(); ball.FadeIn();
Delay(HitObject.Duration, true); Delay(slider.Duration, true);
body.FadeOut(160); body.FadeOut(160);
ball.FadeOut(160); ball.FadeOut(160);
FadeOut(800); FadeOut(800);
Expire();
} }
public Drawable ProxiedLayer => initialCircle.ApproachCircle; public Drawable ProxiedLayer => initialCircle.ApproachCircle;

View File

@ -10,6 +10,7 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transforms; using osu.Framework.Graphics.Transforms;
using osu.Game.Beatmaps.Samples; using osu.Game.Beatmaps.Samples;
using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Judgements;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -26,7 +27,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
public override bool RemoveWhenNotAlive => false; public override bool RemoveWhenNotAlive => false;
public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.SliderTick }; protected override OsuJudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.SliderTick };
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
{ {
@ -47,7 +48,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
new Box new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = sliderTick.Colour, Colour = sliderTick.ComboColour,
Alpha = 0.3f, Alpha = 0.3f,
} }
}; };
@ -71,12 +72,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
var j = Judgement as OsuJudgementInfo;
if (Judgement.TimeOffset >= 0) if (Judgement.TimeOffset >= 0)
{ {
j.Result = Tracking ? HitResult.Hit : HitResult.Miss; Judgement.Result = Tracking ? HitResult.Hit : HitResult.Miss;
j.Score = Tracking ? OsuScoreResult.SliderTick : OsuScoreResult.Miss; Judgement.Score = Tracking ? OsuScoreResult.SliderTick : OsuScoreResult.Miss;
} }
} }
@ -96,8 +95,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
if (!IsLoaded) return;
base.UpdateState(state); base.UpdateState(state);
switch (state) switch (state)

View File

@ -24,6 +24,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
public DrawableSpinner(Spinner s) : base(s) public DrawableSpinner(Spinner s) : base(s)
{ {
AlwaysReceiveInput = true;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Position = s.Position; Position = s.Position;
@ -46,7 +48,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
Alpha = 0, Alpha = 0,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
DiscColour = s.Colour DiscColour = s.ComboColour
}, },
circleContainer = new Container circleContainer = new Container
{ {
@ -69,48 +71,44 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
disc.Scale = scaleToCircle; disc.Scale = scaleToCircle;
} }
public override bool Contains(Vector2 screenSpacePos) => true;
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
if (Time.Current < HitObject.StartTime) return; if (Time.Current < HitObject.StartTime) return;
var j = Judgement as OsuJudgementInfo;
disc.ScaleTo(Interpolation.ValueAt(Math.Sqrt(Progress), scaleToCircle, Vector2.One, 0, 1), 100); disc.ScaleTo(Interpolation.ValueAt(Math.Sqrt(Progress), scaleToCircle, Vector2.One, 0, 1), 100);
if (Progress >= 1) if (Progress >= 1)
disc.Complete = true; disc.Complete = true;
if (!userTriggered && Time.Current >= HitObject.EndTime) if (!userTriggered && Time.Current >= spinner.EndTime)
{ {
if (Progress >= 1) if (Progress >= 1)
{ {
j.Score = OsuScoreResult.Hit300; Judgement.Score = OsuScoreResult.Hit300;
j.Result = HitResult.Hit; Judgement.Result = HitResult.Hit;
} }
else if (Progress > .9) else if (Progress > .9)
{ {
j.Score = OsuScoreResult.Hit100; Judgement.Score = OsuScoreResult.Hit100;
j.Result = HitResult.Hit; Judgement.Result = HitResult.Hit;
} }
else if (Progress > .75) else if (Progress > .75)
{ {
j.Score = OsuScoreResult.Hit50; Judgement.Score = OsuScoreResult.Hit50;
j.Result = HitResult.Hit; Judgement.Result = HitResult.Hit;
} }
else else
{ {
j.Score = OsuScoreResult.Miss; Judgement.Score = OsuScoreResult.Miss;
if (Time.Current >= HitObject.EndTime) if (Time.Current >= spinner.EndTime)
j.Result = HitResult.Miss; Judgement.Result = HitResult.Miss;
} }
} }
} }
private Vector2 scaleToCircle => (circle.Scale * circle.DrawWidth / DrawWidth) * 0.95f; private Vector2 scaleToCircle => circle.Scale * circle.DrawWidth / DrawWidth * 0.95f;
private float spinsPerMinuteNeeded = 100 + (5 * 15); //TODO: read per-map OD and place it on the 5 private float spinsPerMinuteNeeded = 100 + 5 * 15; //TODO: read per-map OD and place it on the 5
private float rotationsNeeded => (float)(spinsPerMinuteNeeded * (spinner.EndTime - spinner.StartTime) / 60000f); private float rotationsNeeded => (float)(spinsPerMinuteNeeded * (spinner.EndTime - spinner.StartTime) / 60000f);
@ -136,11 +134,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
if (!IsLoaded) return;
base.UpdateState(state); base.UpdateState(state);
Delay(HitObject.Duration, true); Delay(spinner.Duration, true);
FadeOut(160); FadeOut(160);
@ -148,9 +144,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
{ {
case ArmedState.Hit: case ArmedState.Hit:
ScaleTo(Scale * 1.2f, 320, EasingTypes.Out); ScaleTo(Scale * 1.2f, 320, EasingTypes.Out);
Expire();
break; break;
case ArmedState.Miss: case ArmedState.Miss:
ScaleTo(Scale * 0.8f, 320, EasingTypes.In); ScaleTo(Scale * 0.8f, 320, EasingTypes.In);
Expire();
break; break;
} }
} }

View File

@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transforms; using osu.Framework.Graphics.Transforms;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Judgements;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -25,7 +26,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Direction = FillDirection.Down; Direction = FillDirection.Vertical;
Spacing = new Vector2(0, 2); Spacing = new Vector2(0, 2);
Position = (h?.StackedEndPosition ?? Vector2.Zero) + judgement.PositionOffset; Position = (h?.StackedEndPosition ?? Vector2.Zero) + judgement.PositionOffset;

View File

@ -21,7 +21,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
public CirclePiece() public CirclePiece()
{ {
Size = new Vector2(128); Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2);
Masking = true; Masking = true;
CornerRadius = Size.X / 2; CornerRadius = Size.X / 2;

View File

@ -1,10 +1,10 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using OpenTK.Graphics; using OpenTK.Graphics;

View File

@ -15,7 +15,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
private readonly Slider slider; private readonly Slider slider;
private Box follow; private Box follow;
const float width = 128; private const float width = 128;
public SliderBall(Slider slider) public SliderBall(Slider slider)
{ {
@ -51,7 +51,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
new Box new Box
{ {
Colour = slider.Colour, Colour = slider.ComboColour,
Alpha = 0.4f, Alpha = 0.4f,
Width = width, Width = width,
Height = width, Height = width,
@ -81,7 +81,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
return base.OnMouseMove(state); return base.OnMouseMove(state);
} }
bool tracking; private bool tracking;
public bool Tracking public bool Tracking
{ {
get { return tracking; } get { return tracking; }

View File

@ -110,10 +110,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
progress -= border_portion; progress -= border_portion;
bytes[i * 4] = (byte)(slider.Colour.R * 255); bytes[i * 4] = (byte)(slider.ComboColour.R * 255);
bytes[i * 4 + 1] = (byte)(slider.Colour.G * 255); bytes[i * 4 + 1] = (byte)(slider.ComboColour.G * 255);
bytes[i * 4 + 2] = (byte)(slider.Colour.B * 255); bytes[i * 4 + 2] = (byte)(slider.ComboColour.B * 255);
bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (slider.Colour.A * 255)); bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (slider.ComboColour.A * 255));
} }
} }

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -18,8 +19,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{ {
public class SpinnerDisc : CircularContainer public class SpinnerDisc : CircularContainer
{ {
public override bool Contains(Vector2 screenSpacePos) => true;
protected Sprite Disc; protected Sprite Disc;
public SRGBColour DiscColour public SRGBColour DiscColour
@ -28,7 +27,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
set { Disc.Colour = value; } set { Disc.Colour = value; }
} }
Color4 completeColour; private Color4 completeColour;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
@ -36,7 +35,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
completeColour = colours.YellowLight.Opacity(0.8f); completeColour = colours.YellowLight.Opacity(0.8f);
} }
class SpinnerBorder : Container private class SpinnerBorder : Container
{ {
public SpinnerBorder() public SpinnerBorder()
{ {
@ -100,6 +99,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
public SpinnerDisc() public SpinnerDisc()
{ {
AlwaysReceiveInput = true;
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Children = new Drawable[] Children = new Drawable[]
@ -115,7 +116,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
}; };
} }
bool tracking; private bool tracking;
public bool Tracking public bool Tracking
{ {
get { return tracking; } get { return tracking; }
@ -129,7 +130,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
} }
} }
bool complete; private bool complete;
public bool Complete public bool Complete
{ {
get { return complete; } get { return complete; }

View File

@ -5,6 +5,5 @@ namespace osu.Game.Modes.Osu.Objects
{ {
public class HitCircle : OsuHitObject public class HitCircle : OsuHitObject
{ {
public override HitObjectType Type => HitObjectType.Circle;
} }
} }

View File

@ -1,15 +1,25 @@
// Copyright (c) 2007-2017 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 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Game.Modes.Objects; using osu.Game.Modes.Objects;
using OpenTK; using OpenTK;
using osu.Game.Beatmaps; using osu.Game.Modes.Osu.Objects.Drawables;
using osu.Game.Modes.Objects.Types;
using OpenTK.Graphics;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
namespace osu.Game.Modes.Osu.Objects namespace osu.Game.Modes.Osu.Objects
{ {
public abstract class OsuHitObject : HitObject public abstract class OsuHitObject : HitObject, IHasCombo, IHasPosition
{ {
public const double OBJECT_RADIUS = 64;
private const double hittable_range = 300;
private const double hit_window_50 = 150;
private const double hit_window_100 = 80;
private const double hit_window_300 = 30;
public Vector2 Position { get; set; } public Vector2 Position { get; set; }
public Vector2 StackedPosition => Position + StackOffset; public Vector2 StackedPosition => Position + StackOffset;
@ -22,27 +32,45 @@ namespace osu.Game.Modes.Osu.Objects
public Vector2 StackOffset => new Vector2(StackHeight * Scale * -6.4f); public Vector2 StackOffset => new Vector2(StackHeight * Scale * -6.4f);
public double Radius => OBJECT_RADIUS * Scale;
public float Scale { get; set; } = 1; public float Scale { get; set; } = 1;
public abstract HitObjectType Type { get; } public Color4 ComboColour { get; set; }
public virtual bool NewCombo { get; set; }
public int ComboIndex { get; set; }
public override void SetDefaultsFromBeatmap(Beatmap beatmap) public double HitWindowFor(OsuScoreResult result)
{ {
base.SetDefaultsFromBeatmap(beatmap); switch (result)
{
default:
return 300;
case OsuScoreResult.Hit50:
return 150;
case OsuScoreResult.Hit100:
return 80;
case OsuScoreResult.Hit300:
return 30;
}
}
Scale = (1.0f - 0.7f * (beatmap.BeatmapInfo.BaseDifficulty.CircleSize - 5) / 5) / 2; public OsuScoreResult ScoreResultForOffset(double offset)
{
if (offset < HitWindowFor(OsuScoreResult.Hit300))
return OsuScoreResult.Hit300;
if (offset < HitWindowFor(OsuScoreResult.Hit100))
return OsuScoreResult.Hit100;
if (offset < HitWindowFor(OsuScoreResult.Hit50))
return OsuScoreResult.Hit50;
return OsuScoreResult.Miss;
}
public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{
base.ApplyDefaults(timing, difficulty);
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
} }
} }
[Flags]
public enum HitObjectType
{
Circle = 1 << 0,
Slider = 1 << 1,
NewCombo = 1 << 2,
Spinner = 1 << 3,
ColourHax = 122,
Hold = 1 << 7,
SliderTick = 1 << 8,
}
} }

View File

@ -8,7 +8,7 @@ using System.Linq;
namespace osu.Game.Modes.Osu.Objects namespace osu.Game.Modes.Osu.Objects
{ {
class OsuHitObjectDifficulty internal class OsuHitObjectDifficulty
{ {
/// <summary> /// <summary>
/// Factor by how much speed / aim strain decays per second. /// Factor by how much speed / aim strain decays per second.
@ -63,7 +63,7 @@ namespace osu.Game.Modes.Osu.Objects
MaxCombo += slider.Ticks.Count(); MaxCombo += slider.Ticks.Count();
// We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
scalingFactor = (52.0f / circleRadius); scalingFactor = 52.0f / circleRadius;
if (circleRadius < 30) if (circleRadius < 30)
{ {
float smallCircleBonus = Math.Min(30.0f - circleRadius, 5.0f) / 50.0f; float smallCircleBonus = Math.Min(30.0f - circleRadius, 5.0f) / 50.0f;
@ -130,7 +130,7 @@ namespace osu.Game.Modes.Osu.Objects
else if (distance > almost_diameter) else if (distance > almost_diameter)
return 1.2 + 0.4 * (distance - almost_diameter) / (stream_spacing_threshold - almost_diameter); return 1.2 + 0.4 * (distance - almost_diameter) / (stream_spacing_threshold - almost_diameter);
else if (distance > almost_diameter / 2) else if (distance > almost_diameter / 2)
return 0.95 + 0.25 * (distance - (almost_diameter / 2)) / (almost_diameter / 2); return 0.95 + 0.25 * (distance - almost_diameter / 2) / (almost_diameter / 2);
else else
return 0.95; return 0.95;
@ -148,11 +148,11 @@ namespace osu.Game.Modes.Osu.Objects
double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate;
double decay = Math.Pow(DECAY_BASE[(int)type], timeElapsed / 1000); double decay = Math.Pow(DECAY_BASE[(int)type], timeElapsed / 1000);
if (BaseHitObject.Type == HitObjectType.Spinner) if (BaseHitObject is Spinner)
{ {
// Do nothing for spinners // Do nothing for spinners
} }
else if (BaseHitObject.Type == HitObjectType.Slider) else if (BaseHitObject is Slider)
{ {
switch (type) switch (type)
{ {
@ -180,7 +180,7 @@ namespace osu.Game.Modes.Osu.Objects
break; break;
} }
} }
else if (BaseHitObject.Type == HitObjectType.Circle) else if (BaseHitObject is HitCircle)
{ {
addition = spacingWeight(DistanceTo(previousHitObject), type) * spacing_weight_scaling[(int)type]; addition = spacingWeight(DistanceTo(previousHitObject), type) * spacing_weight_scaling[(int)type];
} }

View File

@ -1,110 +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.Globalization;
using osu.Game.Beatmaps.Samples;
using osu.Game.Modes.Objects;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects
{
public class OsuHitObjectParser : HitObjectParser
{
public override HitObject Parse(string text)
{
string[] split = text.Split(',');
var type = (HitObjectType)int.Parse(split[3]);
bool combo = type.HasFlag(HitObjectType.NewCombo);
type &= (HitObjectType)0xF;
type &= ~HitObjectType.NewCombo;
OsuHitObject result;
switch (type)
{
case HitObjectType.Circle:
result = new HitCircle
{
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1]))
};
break;
case HitObjectType.Slider:
CurveTypes curveType = CurveTypes.Catmull;
int repeatCount;
double length = 0;
List<Vector2> points = new List<Vector2>();
points.Add(new Vector2(int.Parse(split[0]), int.Parse(split[1])));
string[] pointsplit = split[5].Split('|');
for (int i = 0; i < pointsplit.Length; i++)
{
if (pointsplit[i].Length == 1)
{
switch (pointsplit[i])
{
case @"C":
curveType = CurveTypes.Catmull;
break;
case @"B":
curveType = CurveTypes.Bezier;
break;
case @"L":
curveType = CurveTypes.Linear;
break;
case @"P":
curveType = CurveTypes.PerfectCurve;
break;
}
continue;
}
string[] temp = pointsplit[i].Split(':');
Vector2 v = new Vector2(
(int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture),
(int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture)
);
points.Add(v);
}
repeatCount = Convert.ToInt32(split[6], CultureInfo.InvariantCulture);
if (repeatCount > 9000)
{
throw new ArgumentOutOfRangeException("wacky man");
}
if (split.Length > 7)
length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture);
result = new Slider
{
ControlPoints = points,
Length = length,
CurveType = curveType,
RepeatCount = repeatCount,
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1]))
};
break;
case HitObjectType.Spinner:
result = new Spinner
{
Length = Convert.ToDouble(split[5], CultureInfo.InvariantCulture) - Convert.ToDouble(split[2], CultureInfo.InvariantCulture),
Position = new Vector2(512, 384) / 2,
};
break;
default:
throw new InvalidOperationException($@"Unknown hit object type {type}");
}
result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture);
result.Sample = new HitSampleInfo
{
Type = (SampleType)int.Parse(split[4]),
Set = SampleSet.Soft,
};
result.NewCombo = combo;
// TODO: "addition" field
return result;
}
}
}

View File

@ -2,19 +2,36 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK; using OpenTK;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Samples; using osu.Game.Beatmaps.Samples;
using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Timing;
using osu.Game.Modes.Objects.Types;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Modes.Objects;
using osu.Game.Database;
namespace osu.Game.Modes.Osu.Objects namespace osu.Game.Modes.Osu.Objects
{ {
public class Slider : OsuHitObject public class Slider : OsuHitObject, IHasCurve
{ {
public override double EndTime => StartTime + RepeatCount * Curve.Length / Velocity; public IHasCurve CurveObject { get; set; }
public override Vector2 EndPosition => RepeatCount % 2 == 0 ? Position : Curve.PositionAt(1); public SliderCurve Curve => CurveObject.Curve;
public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity;
public double Duration => EndTime - StartTime;
public override Vector2 EndPosition => PositionAt(1);
public Vector2 PositionAt(double progress) => CurveObject.PositionAt(progress);
public double ProgressAt(double progress) => CurveObject.ProgressAt(progress);
public int RepeatAt(double progress) => CurveObject.RepeatAt(progress);
public List<Vector2> ControlPoints => CurveObject.ControlPoints;
public CurveType CurveType => CurveObject.CurveType;
public double Distance => CurveObject.Distance;
public int RepeatCount => CurveObject.RepeatCount;
private int stackHeight; private int stackHeight;
public override int StackHeight public override int StackHeight
@ -27,53 +44,29 @@ namespace osu.Game.Modes.Osu.Objects
} }
} }
public List<Vector2> ControlPoints
{
get { return Curve.ControlPoints; }
set { Curve.ControlPoints = value; }
}
public double Length
{
get { return Curve.Length; }
set { Curve.Length = value; }
}
public CurveTypes CurveType
{
get { return Curve.CurveType; }
set { Curve.CurveType = value; }
}
public double Velocity; public double Velocity;
public double TickDistance; public double TickDistance;
public override void SetDefaultsFromBeatmap(Beatmap beatmap) public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{ {
base.SetDefaultsFromBeatmap(beatmap); base.ApplyDefaults(timing, difficulty);
var baseDifficulty = beatmap.BeatmapInfo.BaseDifficulty;
ControlPoint overridePoint; ControlPoint overridePoint;
ControlPoint timingPoint = beatmap.TimingPointAt(StartTime, out overridePoint); ControlPoint timingPoint = timing.TimingPointAt(StartTime, out overridePoint);
var velocityAdjustment = overridePoint?.VelocityAdjustment ?? 1; var velocityAdjustment = overridePoint?.VelocityAdjustment ?? 1;
var baseVelocity = 100 * baseDifficulty.SliderMultiplier / velocityAdjustment; var baseVelocity = 100 * difficulty.SliderMultiplier / velocityAdjustment;
Velocity = baseVelocity / timingPoint.BeatLength; Velocity = baseVelocity / timingPoint.BeatLength;
TickDistance = baseVelocity / baseDifficulty.SliderTickRate; TickDistance = baseVelocity / difficulty.SliderTickRate;
} }
public int RepeatCount = 1;
internal readonly SliderCurve Curve = new SliderCurve();
public IEnumerable<SliderTick> Ticks public IEnumerable<SliderTick> Ticks
{ {
get get
{ {
if (TickDistance == 0) yield break; if (TickDistance == 0) yield break;
var length = Curve.Length; var length = Curve.Distance;
var tickDistance = Math.Min(TickDistance, length); var tickDistance = Math.Min(TickDistance, length);
var repeatDuration = length / Velocity; var repeatDuration = length / Velocity;
@ -99,7 +92,7 @@ namespace osu.Game.Modes.Osu.Objects
Position = Curve.PositionAt(distanceProgress), Position = Curve.PositionAt(distanceProgress),
StackHeight = StackHeight, StackHeight = StackHeight,
Scale = Scale, Scale = Scale,
Colour = Colour, ComboColour = ComboColour,
Sample = new HitSampleInfo Sample = new HitSampleInfo
{ {
Type = SampleType.None, Type = SampleType.None,
@ -110,15 +103,5 @@ namespace osu.Game.Modes.Osu.Objects
} }
} }
} }
public override HitObjectType Type => HitObjectType.Slider;
}
public enum CurveTypes
{
Catmull,
Bezier,
Linear,
PerfectCurve
} }
} }

View File

@ -6,7 +6,5 @@ namespace osu.Game.Modes.Osu.Objects
public class SliderTick : OsuHitObject public class SliderTick : OsuHitObject
{ {
public int RepeatIndex { get; set; } public int RepeatIndex { get; set; }
public override HitObjectType Type => HitObjectType.SliderTick;
} }
} }

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