mirror of
https://github.com/ppy/osu.git
synced 2025-01-06 04:53:12 +08:00
Merge branch 'master' into online-beatmap-set-overlay
This commit is contained in:
commit
02fa9eeb3b
6
NuGet.config
Normal file
6
NuGet.config
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
<add key="opentk-develop" value="https://www.myget.org/F/opentk-develop" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
@ -1,3 +1,4 @@
|
|||||||
|
# 2017-09-14
|
||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
version: '{branch}-{build}'
|
version: '{branch}-{build}'
|
||||||
configuration: Debug
|
configuration: Debug
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 1a259925b82c31ddcebf7b330a6ef9d3a9daf089
|
Subproject commit 7347c386dcd10eb799b1ce1512536879328109f9
|
@ -33,7 +33,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
|||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral" />
|
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-0.17.1.0" newVersion="0.17.1.0" />
|
<bindingRedirect oldVersion="0.0.0.0-0.18.1.0" newVersion="0.18.1.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
@ -66,22 +66,23 @@
|
|||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
|
||||||
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SharpCompress, Version=0.17.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SharpCompress, Version=0.18.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||||
|
<HintPath>$(SolutionDir)\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Squirrel, Version=1.7.5.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Squirrel, Version=1.7.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\Squirrel.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\Squirrel.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -6,9 +6,9 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
|||||||
<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" />
|
||||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
|
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||||
<package id="NuGet.CommandLine" version="4.1.0" targetFramework="net452" developmentDependency="true" />
|
<package id="NuGet.CommandLine" version="4.3.0" targetFramework="net461" developmentDependency="true" />
|
||||||
<package id="SharpCompress" version="0.17.1" targetFramework="net452" />
|
<package id="SharpCompress" version="0.18.1" targetFramework="net461" />
|
||||||
<package id="Splat" version="2.0.0" targetFramework="net452" />
|
<package id="Splat" version="2.0.0" targetFramework="net452" />
|
||||||
<package id="squirrel.windows" version="1.7.5" targetFramework="net452" />
|
<package id="squirrel.windows" version="1.7.8" targetFramework="net461" />
|
||||||
</packages>
|
</packages>
|
25
osu.Desktop.Tests/OpenTK.dll.config
Normal file
25
osu.Desktop.Tests/OpenTK.dll.config
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<configuration>
|
||||||
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||||
|
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||||
|
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||||
|
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||||
|
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||||
|
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||||
|
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||||
|
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||||
|
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||||
|
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||||
|
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||||
|
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||||
|
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||||
|
</configuration>
|
90
osu.Desktop.Tests/Visual/TestCaseStoryboard.cs
Normal file
90
osu.Desktop.Tests/Visual/TestCaseStoryboard.cs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Storyboards.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Desktop.Tests.Visual
|
||||||
|
{
|
||||||
|
internal class TestCaseStoryboard : OsuTestCase
|
||||||
|
{
|
||||||
|
public override string Description => @"Tests storyboards.";
|
||||||
|
|
||||||
|
private readonly Bindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
private readonly Container<DrawableStoryboard> storyboardContainer;
|
||||||
|
private DrawableStoryboard storyboard;
|
||||||
|
|
||||||
|
public TestCaseStoryboard()
|
||||||
|
{
|
||||||
|
Clock = new FramedClock();
|
||||||
|
|
||||||
|
Add(new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Black,
|
||||||
|
},
|
||||||
|
storyboardContainer = new Container<DrawableStoryboard>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Add(new MusicController
|
||||||
|
{
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
State = Visibility.Visible,
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Restart", restart);
|
||||||
|
AddToggleStep("Passing", passing => { if (storyboard != null) storyboard.Passing = passing; });
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuGameBase game)
|
||||||
|
{
|
||||||
|
beatmapBacking.BindTo(game.Beatmap);
|
||||||
|
beatmapBacking.ValueChanged += beatmapChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void beatmapChanged(WorkingBeatmap working)
|
||||||
|
=> loadStoryboard(working);
|
||||||
|
|
||||||
|
private void restart()
|
||||||
|
{
|
||||||
|
var track = beatmapBacking.Value.Track;
|
||||||
|
|
||||||
|
track.Reset();
|
||||||
|
loadStoryboard(beatmapBacking.Value);
|
||||||
|
track.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadStoryboard(WorkingBeatmap working)
|
||||||
|
{
|
||||||
|
if (storyboard != null)
|
||||||
|
storyboardContainer.Remove(storyboard);
|
||||||
|
|
||||||
|
var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true };
|
||||||
|
decoupledClock.ChangeSource(working.Track);
|
||||||
|
storyboardContainer.Clock = decoupledClock;
|
||||||
|
|
||||||
|
storyboardContainer.Add(storyboard = working.Beatmap.Storyboard.CreateDrawable());
|
||||||
|
storyboard.Passing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,14 +35,15 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="mscorlib" />
|
<Reference Include="mscorlib" />
|
||||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</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">
|
||||||
@ -91,6 +92,7 @@
|
|||||||
<Compile Include="Visual\TestCaseMenuButtonSystem.cs" />
|
<Compile Include="Visual\TestCaseMenuButtonSystem.cs" />
|
||||||
<Compile Include="Visual\TestCaseMenuOverlays.cs" />
|
<Compile Include="Visual\TestCaseMenuOverlays.cs" />
|
||||||
<Compile Include="Visual\TestCaseMods.cs" />
|
<Compile Include="Visual\TestCaseMods.cs" />
|
||||||
|
<Compile Include="Visual\TestCaseStoryboard.cs" />
|
||||||
<Compile Include="Visual\TestCaseMusicController.cs" />
|
<Compile Include="Visual\TestCaseMusicController.cs" />
|
||||||
<Compile Include="Visual\TestCaseNotificationOverlay.cs" />
|
<Compile Include="Visual\TestCaseNotificationOverlay.cs" />
|
||||||
<Compile Include="Visual\TestCaseOnScreenDisplay.cs" />
|
<Compile Include="Visual\TestCaseOnScreenDisplay.cs" />
|
||||||
@ -157,6 +159,7 @@
|
|||||||
<Link>osu.licenseheader</Link>
|
<Link>osu.licenseheader</Link>
|
||||||
</None>
|
</None>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
<None Include="OpenTK.dll.config" />
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -4,9 +4,9 @@ Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|||||||
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
-->
|
-->
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||||
<package id="NUnit" version="3.7.1" targetFramework="net45" />
|
<package id="NUnit" version="3.8.1" targetFramework="net461" />
|
||||||
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||||
<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" />
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
<!--
|
|
||||||
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>
|
||||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
15
osu.Desktop/app.config
Normal file
15
osu.Desktop/app.config
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-0.18.1.0" newVersion="0.18.1.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
@ -136,23 +136,23 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="mscorlib" />
|
<Reference Include="mscorlib" />
|
||||||
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SharpCompress, Version=0.17.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
<Reference Include="SharpCompress, Version=0.18.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Squirrel, Version=1.7.5.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Squirrel, Version=1.7.8.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\Squirrel.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\Squirrel.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@ -173,6 +173,7 @@
|
|||||||
<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="osu!.res" />
|
<None Include="osu!.res" />
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
@ -7,8 +7,8 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
|||||||
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" />
|
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" />
|
||||||
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
|
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
|
||||||
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net45" />
|
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net45" />
|
||||||
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||||
<package id="SharpCompress" version="0.17.1" targetFramework="net45" />
|
<package id="SharpCompress" version="0.18.1" targetFramework="net461" />
|
||||||
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
||||||
<package id="squirrel.windows" version="1.7.5" targetFramework="net45" />
|
<package id="squirrel.windows" version="1.7.8" targetFramework="net461" />
|
||||||
</packages>
|
</packages>
|
@ -9,8 +9,6 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Catch.Scoring;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch
|
namespace osu.Game.Rulesets.Catch
|
||||||
@ -99,8 +97,6 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap);
|
||||||
|
|
||||||
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor();
|
|
||||||
|
|
||||||
public override int LegacyID => 2;
|
public override int LegacyID => 2;
|
||||||
|
|
||||||
public CatchRuleset(RulesetInfo rulesetInfo)
|
public CatchRuleset(RulesetInfo rulesetInfo)
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
<!--
|
|
||||||
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>
|
||||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
@ -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 osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
|
|
||||||
@ -18,17 +17,5 @@ namespace osu.Game.Rulesets.Catch.Scoring
|
|||||||
: base(rulesetContainer)
|
: base(rulesetContainer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Reset()
|
|
||||||
{
|
|
||||||
base.Reset();
|
|
||||||
|
|
||||||
Health.Value = 1;
|
|
||||||
Accuracy.Value = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnNewJudgement(Judgement judgement)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,14 +45,15 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public override void Add(DrawableHitObject h)
|
public override void Add(DrawableHitObject h)
|
||||||
{
|
{
|
||||||
|
h.Depth = (float)h.HitObject.StartTime;
|
||||||
|
|
||||||
base.Add(h);
|
base.Add(h);
|
||||||
|
|
||||||
var fruit = (DrawableFruit)h;
|
var fruit = (DrawableFruit)h;
|
||||||
fruit.CheckPosition = catcherArea.CheckIfWeCanCatch;
|
fruit.CheckPosition = catcherArea.CheckIfWeCanCatch;
|
||||||
fruit.OnJudgement += Fruit_OnJudgement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Fruit_OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||||
{
|
{
|
||||||
if (judgement.IsHit)
|
if (judgement.IsHit)
|
||||||
{
|
{
|
||||||
|
@ -163,7 +163,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
float distance = fruit.DrawSize.X / 2 * fruit.Scale.X;
|
float distance = fruit.DrawSize.X / 2 * fruit.Scale.X;
|
||||||
|
|
||||||
while (Children.OfType<DrawableFruit>().Any(f => Vector2.DistanceSquared(f.Position, fruit.Position) < distance * distance))
|
while (Children.OfType<DrawableFruit>().Any(f => Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance))
|
||||||
{
|
{
|
||||||
fruit.X += RNG.Next(-5, 5);
|
fruit.X += RNG.Next(-5, 5);
|
||||||
fruit.Y -= RNG.Next(0, 5);
|
fruit.Y -= RNG.Next(0, 5);
|
||||||
|
11
osu.Game.Rulesets.Catch/app.config
Normal file
11
osu.Game.Rulesets.Catch/app.config
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
@ -34,7 +34,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@ -69,6 +69,7 @@
|
|||||||
<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>
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
<?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="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||||
</packages>
|
</packages>
|
@ -23,17 +23,5 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
|||||||
return base.NumericResultFor(HasBroken ? HitResult.Good : result);
|
return base.NumericResultFor(HasBroken ? HitResult.Good : result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override int NumericResultForAccuracy(HitResult result)
|
|
||||||
{
|
|
||||||
switch (result)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return base.NumericResultForAccuracy(result);
|
|
||||||
case HitResult.Great:
|
|
||||||
case HitResult.Perfect:
|
|
||||||
return base.NumericResultForAccuracy(HasBroken ? HitResult.Good : result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,6 +10,5 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
|||||||
public override bool AffectsCombo => false;
|
public override bool AffectsCombo => false;
|
||||||
|
|
||||||
protected override int NumericResultFor(HitResult result) => 20;
|
protected override int NumericResultFor(HitResult result) => 20;
|
||||||
protected override int NumericResultForAccuracy(HitResult result) => 0; // Don't count ticks into accuracy
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,11 +8,6 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
|||||||
{
|
{
|
||||||
public class ManiaJudgement : Judgement
|
public class ManiaJudgement : Judgement
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The maximum result value for the accuracy portion of the score.
|
|
||||||
/// </summary>
|
|
||||||
public int MaxNumericAccuracyResult => NumericResultForAccuracy(HitResult.Perfect);
|
|
||||||
|
|
||||||
protected override int NumericResultFor(HitResult result)
|
protected override int NumericResultFor(HitResult result)
|
||||||
{
|
{
|
||||||
switch (result)
|
switch (result)
|
||||||
@ -30,29 +25,5 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
|||||||
return 300;
|
return 300;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int NumericAccuracyResult => NumericResultForAccuracy(Result);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The result value for the accuracy portion of the score.
|
|
||||||
/// </summary>
|
|
||||||
protected virtual int NumericResultForAccuracy(HitResult result)
|
|
||||||
{
|
|
||||||
switch (result)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
case HitResult.Meh:
|
|
||||||
return 50;
|
|
||||||
case HitResult.Ok:
|
|
||||||
return 100;
|
|
||||||
case HitResult.Good:
|
|
||||||
return 200;
|
|
||||||
case HitResult.Great:
|
|
||||||
return 300;
|
|
||||||
case HitResult.Perfect:
|
|
||||||
return 305;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,6 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Scoring;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania
|
namespace osu.Game.Rulesets.Mania
|
||||||
{
|
{
|
||||||
@ -111,8 +109,6 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap);
|
||||||
|
|
||||||
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor();
|
|
||||||
|
|
||||||
public override int LegacyID => 3;
|
public override int LegacyID => 3;
|
||||||
|
|
||||||
public ManiaRuleset(RulesetInfo rulesetInfo)
|
public ManiaRuleset(RulesetInfo rulesetInfo)
|
||||||
|
@ -78,8 +78,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ManiaJudgement CreateJudgement() => new HoldNoteTickJudgement();
|
|
||||||
|
|
||||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||||
{
|
{
|
||||||
if (!userTriggered)
|
if (!userTriggered)
|
||||||
@ -91,7 +89,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
if (HoldStartTime?.Invoke() > HitObject.StartTime)
|
if (HoldStartTime?.Invoke() > HitObject.StartTime)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateState(ArmedState state)
|
protected override void UpdateState(ArmedState state)
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
<!--
|
|
||||||
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>
|
||||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
@ -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.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -15,32 +14,6 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
{
|
{
|
||||||
internal class ManiaScoreProcessor : ScoreProcessor<ManiaHitObject>
|
internal class ManiaScoreProcessor : ScoreProcessor<ManiaHitObject>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The maximum score achievable.
|
|
||||||
/// Does _not_ include bonus score - for bonus score see <see cref="bonusScore"/>.
|
|
||||||
/// </summary>
|
|
||||||
private const int max_score = 1000000;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The amount of the score attributed to combo.
|
|
||||||
/// </summary>
|
|
||||||
private const double combo_portion_max = max_score * 0.2;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The amount of the score attributed to accuracy.
|
|
||||||
/// </summary>
|
|
||||||
private const double accuracy_portion_max = max_score * 0.8;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The factor used to determine relevance of combos.
|
|
||||||
/// </summary>
|
|
||||||
private const double combo_base = 4;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The combo value at which hit objects result in the max score possible.
|
|
||||||
/// </summary>
|
|
||||||
private const int combo_relevance_cap = 400;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The hit HP multiplier at OD = 0.
|
/// The hit HP multiplier at OD = 0.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -116,42 +89,6 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private double hpMultiplier = 1;
|
private double hpMultiplier = 1;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The cumulative combo portion of the score.
|
|
||||||
/// </summary>
|
|
||||||
private double comboScore => combo_portion_max * comboPortion / maxComboPortion;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The cumulative accuracy portion of the score.
|
|
||||||
/// </summary>
|
|
||||||
private double accuracyScore => accuracy_portion_max * Math.Pow(Accuracy, 4) * totalHits / maxTotalHits;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The cumulative bonus score.
|
|
||||||
/// This is added on top of <see cref="max_score"/>, thus the total score can exceed <see cref="max_score"/>.
|
|
||||||
/// </summary>
|
|
||||||
private double bonusScore;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="comboPortion"/> achieved by a perfect playthrough.
|
|
||||||
/// </summary>
|
|
||||||
private double maxComboPortion;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The portion of the score dedicated to combo.
|
|
||||||
/// </summary>
|
|
||||||
private double comboPortion;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="totalHits"/> achieved by a perfect playthrough.
|
|
||||||
/// </summary>
|
|
||||||
private int maxTotalHits;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The total hits.
|
|
||||||
/// </summary>
|
|
||||||
private int totalHits;
|
|
||||||
|
|
||||||
public ManiaScoreProcessor()
|
public ManiaScoreProcessor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -161,7 +98,7 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ComputeTargets(Beatmap<ManiaHitObject> beatmap)
|
protected override void SimulateAutoplay(Beatmap<ManiaHitObject> beatmap)
|
||||||
{
|
{
|
||||||
BeatmapDifficulty difficulty = beatmap.BeatmapInfo.Difficulty;
|
BeatmapDifficulty difficulty = beatmap.BeatmapInfo.Difficulty;
|
||||||
hpMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_min, hp_multiplier_mid, hp_multiplier_max);
|
hpMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_min, hp_multiplier_mid, hp_multiplier_max);
|
||||||
@ -173,11 +110,7 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
{
|
{
|
||||||
var holdNote = obj as HoldNote;
|
var holdNote = obj as HoldNote;
|
||||||
|
|
||||||
if (obj is Note)
|
if (holdNote != null)
|
||||||
{
|
|
||||||
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
|
||||||
}
|
|
||||||
else if (holdNote != null)
|
|
||||||
{
|
{
|
||||||
// Head
|
// Head
|
||||||
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
||||||
@ -186,9 +119,9 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
int tickCount = holdNote.Ticks.Count();
|
int tickCount = holdNote.Ticks.Count();
|
||||||
for (int i = 0; i < tickCount; i++)
|
for (int i = 0; i < tickCount; i++)
|
||||||
AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
|
AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
|
||||||
|
|
||||||
AddJudgement(new HoldNoteTailJudgement { Result = HitResult.Perfect });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasFailed)
|
if (!HasFailed)
|
||||||
@ -197,29 +130,23 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
hpMultiplier *= 1.01;
|
hpMultiplier *= 1.01;
|
||||||
hpMissMultiplier *= 0.98;
|
hpMissMultiplier *= 0.98;
|
||||||
|
|
||||||
Reset();
|
Reset(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
maxTotalHits = totalHits;
|
|
||||||
maxComboPortion = comboPortion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewJudgement(Judgement judgement)
|
protected override void OnNewJudgement(Judgement judgement)
|
||||||
{
|
{
|
||||||
|
base.OnNewJudgement(judgement);
|
||||||
|
|
||||||
bool isTick = judgement is HoldNoteTickJudgement;
|
bool isTick = judgement is HoldNoteTickJudgement;
|
||||||
|
|
||||||
if (isTick)
|
if (isTick)
|
||||||
{
|
{
|
||||||
if (judgement.IsHit)
|
if (judgement.IsHit)
|
||||||
{
|
|
||||||
Health.Value += hpMultiplier * hp_increase_tick;
|
Health.Value += hpMultiplier * hp_increase_tick;
|
||||||
bonusScore += judgement.NumericResult;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
totalHits++;
|
|
||||||
|
|
||||||
switch (judgement.Result)
|
switch (judgement.Result)
|
||||||
{
|
{
|
||||||
case HitResult.Miss:
|
case HitResult.Miss:
|
||||||
@ -241,40 +168,7 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
|||||||
Health.Value += hpMultiplier * hp_increase_perfect;
|
Health.Value += hpMultiplier * hp_increase_perfect;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (judgement.IsHit)
|
|
||||||
{
|
|
||||||
// A factor that is applied to make higher combos more relevant
|
|
||||||
double comboRelevance = Math.Min(Math.Max(0.5, Math.Log(Combo.Value, combo_base)), Math.Log(combo_relevance_cap, combo_base));
|
|
||||||
comboPortion += judgement.NumericResult * comboRelevance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int scoreForAccuracy = 0;
|
|
||||||
int maxScoreForAccuracy = 0;
|
|
||||||
|
|
||||||
foreach (var j in Judgements)
|
|
||||||
{
|
|
||||||
var maniaJudgement = (ManiaJudgement)j;
|
|
||||||
|
|
||||||
scoreForAccuracy += maniaJudgement.NumericAccuracyResult;
|
|
||||||
maxScoreForAccuracy += maniaJudgement.MaxNumericAccuracyResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy;
|
|
||||||
TotalScore.Value = comboScore + accuracyScore + bonusScore;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Reset()
|
|
||||||
{
|
|
||||||
base.Reset();
|
|
||||||
|
|
||||||
Health.Value = 1;
|
|
||||||
Accuracy.Value = 1;
|
|
||||||
|
|
||||||
bonusScore = 0;
|
|
||||||
comboPortion = 0;
|
|
||||||
totalHits = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,6 +203,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
/// <param name="hitObject">The DrawableHitObject to add.</param>
|
/// <param name="hitObject">The DrawableHitObject to add.</param>
|
||||||
public override void Add(DrawableHitObject hitObject)
|
public override void Add(DrawableHitObject hitObject)
|
||||||
{
|
{
|
||||||
|
hitObject.Depth = (float)hitObject.HitObject.StartTime;
|
||||||
|
|
||||||
hitObject.AccentColour = AccentColour;
|
hitObject.AccentColour = AccentColour;
|
||||||
HitObjects.Add(hitObject);
|
HitObjects.Add(hitObject);
|
||||||
}
|
}
|
||||||
|
11
osu.Game.Rulesets.Mania/app.config
Normal file
11
osu.Game.Rulesets.Mania/app.config
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
@ -34,7 +34,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@ -110,6 +110,7 @@
|
|||||||
<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>
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
<?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="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||||
</packages>
|
</packages>
|
@ -1,7 +1,7 @@
|
|||||||
// 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.Framework.Graphics;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Beatmaps;
|
using osu.Game.Rulesets.Beatmaps;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
@ -64,8 +64,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
//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) < stack_distance ||
|
if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance ||
|
||||||
stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
|
stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
|
||||||
{
|
{
|
||||||
stackBaseIndex = n;
|
stackBaseIndex = n;
|
||||||
|
|
||||||
@ -130,14 +130,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
* o <- hitCircle has stack of -1
|
* o <- hitCircle has stack of -1
|
||||||
* o <- hitCircle has stack of -2
|
* o <- hitCircle has stack of -2
|
||||||
*/
|
*/
|
||||||
if (objectN is Slider && Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
if (objectN is Slider && Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||||
{
|
{
|
||||||
int offset = objectI.StackHeight - objectN.StackHeight + 1;
|
int offset = objectI.StackHeight - objectN.StackHeight + 1;
|
||||||
for (int j = n + 1; j <= i; j++)
|
for (int j = n + 1; j <= i; j++)
|
||||||
{
|
{
|
||||||
//For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
|
//For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above).
|
||||||
OsuHitObject objectJ = beatmap.HitObjects[j];
|
OsuHitObject objectJ = beatmap.HitObjects[j];
|
||||||
if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stack_distance)
|
if (Vector2Extensions.Distance(objectN.EndPosition, objectJ.Position) < stack_distance)
|
||||||
objectJ.StackHeight -= offset;
|
objectJ.StackHeight -= offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vector2.Distance(objectN.Position, objectI.Position) < stack_distance)
|
if (Vector2Extensions.Distance(objectN.Position, objectI.Position) < stack_distance)
|
||||||
{
|
{
|
||||||
//Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out.
|
//Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out.
|
||||||
//NOTE: Sliders with start positions stacking are a special case that is also handled here.
|
//NOTE: Sliders with start positions stacking are a special case that is also handled here.
|
||||||
@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
//We are no longer within stacking range of the previous object.
|
//We are no longer within stacking range of the previous object.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
if (Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance)
|
||||||
{
|
{
|
||||||
objectN.StackHeight = objectI.StackHeight + 1;
|
objectN.StackHeight = objectI.StackHeight + 1;
|
||||||
objectI = objectN;
|
objectI = objectN;
|
||||||
|
@ -8,12 +8,10 @@ using osu.Game.Rulesets.Objects.Drawables;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Judgements
|
namespace osu.Game.Rulesets.Osu.Judgements
|
||||||
{
|
{
|
||||||
public class SliderTickJudgement : OsuJudgement
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OsuJudgement : Judgement
|
public class OsuJudgement : Judgement
|
||||||
{
|
{
|
||||||
|
public override HitResult MaxResult => HitResult.Great;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The positional hit offset.
|
/// The positional hit offset.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
Scale = s.Scale,
|
Scale = s.Scale,
|
||||||
ComboColour = s.ComboColour,
|
ComboColour = s.ComboColour,
|
||||||
Samples = s.Samples,
|
Samples = s.Samples,
|
||||||
}),
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
components.Add(body);
|
components.Add(body);
|
||||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||||
{
|
{
|
||||||
if (timeOffset >= 0)
|
if (timeOffset >= 0)
|
||||||
AddJudgement(new SliderTickJudgement { Result = Tracking ? HitResult.Perfect : HitResult.Miss });
|
AddJudgement(new OsuJudgement { Result = Tracking ? HitResult.Great : HitResult.Miss });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdatePreemptState()
|
protected override void UpdatePreemptState()
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
<!--
|
|
||||||
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>
|
||||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
@ -12,8 +12,6 @@ using osu.Game.Rulesets.UI;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Osu.Scoring;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Overlays.Settings;
|
using osu.Game.Overlays.Settings;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
|
|
||||||
@ -118,8 +116,6 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
|
|
||||||
public override string Description => "osu!";
|
public override string Description => "osu!";
|
||||||
|
|
||||||
public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor();
|
|
||||||
|
|
||||||
public override SettingsSubsection CreateSettings() => new OsuSettings();
|
public override SettingsSubsection CreateSettings() => new OsuSettings();
|
||||||
|
|
||||||
public override int LegacyID => 0;
|
public override int LegacyID => 0;
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
// 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.Framework.Configuration;
|
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -18,8 +16,6 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
|||||||
{
|
{
|
||||||
internal class OsuScoreProcessor : ScoreProcessor<OsuHitObject>
|
internal class OsuScoreProcessor : ScoreProcessor<OsuHitObject>
|
||||||
{
|
{
|
||||||
public readonly Bindable<ScoringMode> Mode = new Bindable<ScoringMode>(ScoringMode.Exponential);
|
|
||||||
|
|
||||||
public OsuScoreProcessor()
|
public OsuScoreProcessor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -31,31 +27,33 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
|||||||
|
|
||||||
private float hpDrainRate;
|
private float hpDrainRate;
|
||||||
|
|
||||||
private int totalAccurateJudgements;
|
|
||||||
|
|
||||||
private readonly Dictionary<HitResult, int> scoreResultCounts = new Dictionary<HitResult, int>();
|
private readonly Dictionary<HitResult, int> scoreResultCounts = new Dictionary<HitResult, int>();
|
||||||
private readonly Dictionary<ComboResult, int> comboResultCounts = new Dictionary<ComboResult, int>();
|
private readonly Dictionary<ComboResult, int> comboResultCounts = new Dictionary<ComboResult, int>();
|
||||||
|
|
||||||
private double comboMaxScore;
|
protected override void SimulateAutoplay(Beatmap<OsuHitObject> beatmap)
|
||||||
|
|
||||||
protected override void ComputeTargets(Beatmap<OsuHitObject> beatmap)
|
|
||||||
{
|
{
|
||||||
hpDrainRate = beatmap.BeatmapInfo.Difficulty.DrainRate;
|
hpDrainRate = beatmap.BeatmapInfo.Difficulty.DrainRate;
|
||||||
totalAccurateJudgements = beatmap.HitObjects.Count;
|
|
||||||
|
|
||||||
foreach (var unused in beatmap.HitObjects)
|
foreach (var obj in beatmap.HitObjects)
|
||||||
{
|
{
|
||||||
// TODO: add support for other object types.
|
var slider = obj as Slider;
|
||||||
|
if (slider != null)
|
||||||
|
{
|
||||||
|
// Head
|
||||||
|
AddJudgement(new OsuJudgement { Result = HitResult.Great });
|
||||||
|
|
||||||
|
// Ticks
|
||||||
|
foreach (var unused in slider.Ticks)
|
||||||
|
AddJudgement(new OsuJudgement { Result = HitResult.Great });
|
||||||
|
}
|
||||||
|
|
||||||
AddJudgement(new OsuJudgement { Result = HitResult.Great });
|
AddJudgement(new OsuJudgement { Result = HitResult.Great });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Reset()
|
protected override void Reset(bool storeResults)
|
||||||
{
|
{
|
||||||
base.Reset();
|
base.Reset(storeResults);
|
||||||
|
|
||||||
Health.Value = 1;
|
|
||||||
Accuracy.Value = 1;
|
|
||||||
|
|
||||||
scoreResultCounts.Clear();
|
scoreResultCounts.Clear();
|
||||||
comboResultCounts.Clear();
|
comboResultCounts.Clear();
|
||||||
@ -73,6 +71,8 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
|||||||
|
|
||||||
protected override void OnNewJudgement(Judgement judgement)
|
protected override void OnNewJudgement(Judgement judgement)
|
||||||
{
|
{
|
||||||
|
base.OnNewJudgement(judgement);
|
||||||
|
|
||||||
var osuJudgement = (OsuJudgement)judgement;
|
var osuJudgement = (OsuJudgement)judgement;
|
||||||
|
|
||||||
if (judgement.Result != HitResult.None)
|
if (judgement.Result != HitResult.None)
|
||||||
@ -103,52 +103,6 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
|||||||
Health.Value -= hpDrainRate * 0.04;
|
Health.Value -= hpDrainRate * 0.04;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateScore();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateScore()
|
|
||||||
{
|
|
||||||
int baseScore = 0;
|
|
||||||
double comboScore = 0;
|
|
||||||
|
|
||||||
int baseMaxScore = 0;
|
|
||||||
|
|
||||||
foreach (var j in Judgements)
|
|
||||||
{
|
|
||||||
baseScore += j.NumericResult;
|
|
||||||
baseMaxScore += j.MaxNumericResult;
|
|
||||||
|
|
||||||
comboScore += j.NumericResult * (1 + Combo.Value / 10d);
|
|
||||||
}
|
|
||||||
|
|
||||||
Accuracy.Value = (double)baseScore / baseMaxScore;
|
|
||||||
|
|
||||||
if (comboScore > comboMaxScore)
|
|
||||||
comboMaxScore = comboScore;
|
|
||||||
|
|
||||||
if (baseScore == 0)
|
|
||||||
TotalScore.Value = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// temporary to make scoring feel more like score v1 without being score v1.
|
|
||||||
float exponentialFactor = Mode.Value == ScoringMode.Exponential ? (float)Judgements.Count / 100 : 1;
|
|
||||||
|
|
||||||
TotalScore.Value =
|
|
||||||
(int)
|
|
||||||
(
|
|
||||||
exponentialFactor *
|
|
||||||
700000 * comboScore / comboMaxScore +
|
|
||||||
300000 * Math.Pow(Accuracy.Value, 10) * ((double)Judgements.Count / totalAccurateJudgements) +
|
|
||||||
0 /* bonusScore */
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ScoringMode
|
|
||||||
{
|
|
||||||
Standardised,
|
|
||||||
Exponential
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,8 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
|
|
||||||
public override void Add(DrawableHitObject h)
|
public override void Add(DrawableHitObject h)
|
||||||
{
|
{
|
||||||
|
h.Depth = (float)h.HitObject.StartTime;
|
||||||
|
|
||||||
var c = h as IDrawableHitObjectWithProxiedApproach;
|
var c = h as IDrawableHitObjectWithProxiedApproach;
|
||||||
if (c != null)
|
if (c != null)
|
||||||
approachCircles.Add(c.ProxiedLayer.CreateProxy());
|
approachCircles.Add(c.ProxiedLayer.CreateProxy());
|
||||||
|
11
osu.Game.Rulesets.Osu/app.config
Normal file
11
osu.Game.Rulesets.Osu/app.config
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
@ -35,7 +35,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@ -110,6 +110,7 @@
|
|||||||
<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>
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
<?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="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||||
</packages>
|
</packages>
|
@ -19,10 +19,5 @@ namespace osu.Game.Rulesets.Taiko.Judgements
|
|||||||
return 200;
|
return 200;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override int NumericResultForAccuracy(HitResult result)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,19 +8,10 @@ namespace osu.Game.Rulesets.Taiko.Judgements
|
|||||||
{
|
{
|
||||||
public class TaikoJudgement : Judgement
|
public class TaikoJudgement : Judgement
|
||||||
{
|
{
|
||||||
/// <summary>
|
public override HitResult MaxResult => HitResult.Great;
|
||||||
/// The result value for the accuracy portion of the score.
|
|
||||||
/// </summary>
|
|
||||||
public int ResultNumericForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(Result);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum result value for the accuracy portion of the score.
|
|
||||||
/// </summary>
|
|
||||||
public int MaxResultValueForAccuracy => NumericResultForAccuracy(HitResult.Great);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the numeric result value for the combo portion of the score.
|
/// Computes the numeric result value for the combo portion of the score.
|
||||||
/// For the accuracy portion of the score (including accuracy percentage), see <see cref="NumericResultForAccuracy(HitResult)"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="result">The result to compute the value for.</param>
|
/// <param name="result">The result to compute the value for.</param>
|
||||||
/// <returns>The numeric result value.</returns>
|
/// <returns>The numeric result value.</returns>
|
||||||
@ -36,24 +27,5 @@ namespace osu.Game.Rulesets.Taiko.Judgements
|
|||||||
return 300;
|
return 300;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Computes the numeric result value for the accuracy portion of the score.
|
|
||||||
/// For the combo portion of the score, see <see cref="NumericResultFor(HitResult)"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="result">The result to compute the value for.</param>
|
|
||||||
/// <returns>The numeric result value.</returns>
|
|
||||||
protected virtual int NumericResultForAccuracy(HitResult result)
|
|
||||||
{
|
|
||||||
switch (result)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
case HitResult.Good:
|
|
||||||
return 150;
|
|
||||||
case HitResult.Great:
|
|
||||||
return 300;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ namespace osu.Game.Rulesets.Taiko.Judgements
|
|||||||
{
|
{
|
||||||
public class TaikoStrongHitJudgement : TaikoJudgement
|
public class TaikoStrongHitJudgement : TaikoJudgement
|
||||||
{
|
{
|
||||||
|
public override bool AffectsCombo => false;
|
||||||
|
|
||||||
public TaikoStrongHitJudgement()
|
public TaikoStrongHitJudgement()
|
||||||
{
|
{
|
||||||
base.Result = HitResult.Perfect;
|
base.Result = HitResult.Perfect;
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
<!--
|
|
||||||
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>
|
||||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
@ -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 osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -9,33 +8,11 @@ using osu.Game.Rulesets.Scoring;
|
|||||||
using osu.Game.Rulesets.Taiko.Judgements;
|
using osu.Game.Rulesets.Taiko.Judgements;
|
||||||
using osu.Game.Rulesets.Taiko.Objects;
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using OpenTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Scoring
|
namespace osu.Game.Rulesets.Taiko.Scoring
|
||||||
{
|
{
|
||||||
internal class TaikoScoreProcessor : ScoreProcessor<TaikoHitObject>
|
internal class TaikoScoreProcessor : ScoreProcessor<TaikoHitObject>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The maximum score achievable.
|
|
||||||
/// Does _not_ include bonus score - for bonus score see <see cref="bonusScore"/>.
|
|
||||||
/// </summary>
|
|
||||||
private const int max_score = 1000000;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The amount of the score attributed to combo.
|
|
||||||
/// </summary>
|
|
||||||
private const double combo_portion_max = max_score * 0.2;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The amount of the score attributed to accuracy.
|
|
||||||
/// </summary>
|
|
||||||
private const double accuracy_portion_max = max_score * 0.8;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The factor used to determine relevance of combos.
|
|
||||||
/// </summary>
|
|
||||||
private const double combo_base = 4;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HP awarded by a <see cref="HitResult.Great"/> hit.
|
/// The HP awarded by a <see cref="HitResult.Great"/> hit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -76,40 +53,13 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Taiko fails at the end of the map if the player has not half-filled their HP bar.
|
/// Taiko fails at the end of the map if the player has not half-filled their HP bar.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override bool HasFailed => totalHits == maxTotalHits && Health.Value <= 0.5;
|
public override bool HasFailed => Hits == MaxHits && Health.Value <= 0.5;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The cumulative combo portion of the score.
|
|
||||||
/// </summary>
|
|
||||||
private double comboScore => combo_portion_max * comboPortion / maxComboPortion;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The cumulative accuracy portion of the score.
|
|
||||||
/// </summary>
|
|
||||||
private double accuracyScore => accuracy_portion_max * Math.Pow(Accuracy, 3.6) * totalHits / maxTotalHits;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The cumulative bonus score.
|
|
||||||
/// This is added on top of <see cref="max_score"/>, thus the total score can exceed <see cref="max_score"/>.
|
|
||||||
/// </summary>
|
|
||||||
private double bonusScore;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The multiple of the original score added to the combo portion of the score
|
|
||||||
/// for correctly hitting a strong hit object with both keys.
|
|
||||||
/// </summary>
|
|
||||||
private double strongHitScale;
|
|
||||||
|
|
||||||
private double hpIncreaseTick;
|
private double hpIncreaseTick;
|
||||||
private double hpIncreaseGreat;
|
private double hpIncreaseGreat;
|
||||||
private double hpIncreaseGood;
|
private double hpIncreaseGood;
|
||||||
private double hpIncreaseMiss;
|
private double hpIncreaseMiss;
|
||||||
|
|
||||||
private double maxComboPortion;
|
|
||||||
private double comboPortion;
|
|
||||||
private int maxTotalHits;
|
|
||||||
private int totalHits;
|
|
||||||
|
|
||||||
public TaikoScoreProcessor()
|
public TaikoScoreProcessor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -119,7 +69,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ComputeTargets(Beatmap<TaikoHitObject> beatmap)
|
protected override void SimulateAutoplay(Beatmap<TaikoHitObject> beatmap)
|
||||||
{
|
{
|
||||||
double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, 0.5, 0.75, 0.98));
|
double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, 0.5, 0.75, 0.98));
|
||||||
|
|
||||||
@ -128,13 +78,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
hpIncreaseGood = hpMultiplierNormal * hp_hit_good;
|
hpIncreaseGood = hpMultiplierNormal * hp_hit_good;
|
||||||
hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max);
|
hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max);
|
||||||
|
|
||||||
var strongHits = beatmap.HitObjects.FindAll(o => o is Hit && o.IsStrong);
|
|
||||||
|
|
||||||
// This is a linear function that awards:
|
|
||||||
// 10 times bonus points for hitting a strong hit object with both keys with 30 strong hit objects in the map
|
|
||||||
// 3 times bonus points for hitting a strong hit object with both keys with 120 strong hit objects in the map
|
|
||||||
strongHitScale = -7d / 90d * MathHelper.Clamp(strongHits.Count, 30, 120) + 111d / 9d;
|
|
||||||
|
|
||||||
foreach (var obj in beatmap.HitObjects)
|
foreach (var obj in beatmap.HitObjects)
|
||||||
{
|
{
|
||||||
if (obj is Hit)
|
if (obj is Hit)
|
||||||
@ -163,46 +106,14 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
maxTotalHits = totalHits;
|
|
||||||
maxComboPortion = comboPortion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewJudgement(Judgement judgement)
|
protected override void OnNewJudgement(Judgement judgement)
|
||||||
{
|
{
|
||||||
bool isStrong = judgement is TaikoStrongHitJudgement;
|
base.OnNewJudgement(judgement);
|
||||||
|
|
||||||
bool isTick = judgement is TaikoDrumRollTickJudgement;
|
bool isTick = judgement is TaikoDrumRollTickJudgement;
|
||||||
|
|
||||||
// Don't consider ticks and strong hits as a type of hit that counts towards map completion
|
|
||||||
if (!isTick && !isStrong)
|
|
||||||
totalHits++;
|
|
||||||
|
|
||||||
// Apply score changes
|
|
||||||
if (judgement.IsHit)
|
|
||||||
{
|
|
||||||
double baseValue = judgement.NumericResult;
|
|
||||||
|
|
||||||
if (isStrong)
|
|
||||||
{
|
|
||||||
// Add increased score for the previous judgement by hitting a strong hit object with the second key
|
|
||||||
var prevJudgement = Judgements[Judgements.Count - 1];
|
|
||||||
baseValue = prevJudgement.NumericResult * strongHitScale;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add score to portions
|
|
||||||
if (judgement is TaikoDrumRollTickJudgement)
|
|
||||||
bonusScore += baseValue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// A relevance factor that needs to be applied to make higher combos more relevant
|
|
||||||
// Value is capped at 400 combo
|
|
||||||
double comboRelevance = Math.Min(Math.Log(400, combo_base), Math.Max(0.5, Math.Log(Combo.Value, combo_base)));
|
|
||||||
|
|
||||||
comboPortion += baseValue * comboRelevance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply HP changes
|
// Apply HP changes
|
||||||
switch (judgement.Result)
|
switch (judgement.Result)
|
||||||
{
|
{
|
||||||
@ -221,32 +132,13 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
Health.Value += hpIncreaseGreat;
|
Health.Value += hpIncreaseGreat;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scoreForAccuracy = 0;
|
|
||||||
int maxScoreForAccuracy = 0;
|
|
||||||
|
|
||||||
foreach (var j in Judgements)
|
|
||||||
{
|
|
||||||
var taikoJudgement = (TaikoJudgement)j;
|
|
||||||
|
|
||||||
scoreForAccuracy += taikoJudgement.ResultNumericForAccuracy;
|
|
||||||
maxScoreForAccuracy += taikoJudgement.MaxResultValueForAccuracy;
|
|
||||||
}
|
|
||||||
|
|
||||||
Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy;
|
|
||||||
TotalScore.Value = comboScore + accuracyScore + bonusScore;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Reset()
|
protected override void Reset(bool storeResults)
|
||||||
{
|
{
|
||||||
base.Reset();
|
base.Reset(storeResults);
|
||||||
|
|
||||||
Health.Value = 0;
|
Health.Value = 0;
|
||||||
Accuracy.Value = 1;
|
|
||||||
|
|
||||||
bonusScore = 0;
|
|
||||||
comboPortion = 0;
|
|
||||||
totalHits = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@ using osu.Game.Rulesets.Taiko.UI;
|
|||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Rulesets.Taiko.Scoring;
|
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko
|
namespace osu.Game.Rulesets.Taiko
|
||||||
@ -101,8 +99,6 @@ namespace osu.Game.Rulesets.Taiko
|
|||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap);
|
||||||
|
|
||||||
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor();
|
|
||||||
|
|
||||||
public override int LegacyID => 1;
|
public override int LegacyID => 1;
|
||||||
|
|
||||||
public TaikoRuleset(RulesetInfo rulesetInfo)
|
public TaikoRuleset(RulesetInfo rulesetInfo)
|
||||||
|
@ -205,6 +205,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
public override void Add(DrawableHitObject h)
|
public override void Add(DrawableHitObject h)
|
||||||
{
|
{
|
||||||
|
h.Depth = (float)h.HitObject.StartTime;
|
||||||
|
|
||||||
base.Add(h);
|
base.Add(h);
|
||||||
|
|
||||||
var barline = h as DrawableBarLine;
|
var barline = h as DrawableBarLine;
|
||||||
|
11
osu.Game.Rulesets.Taiko/app.config
Normal file
11
osu.Game.Rulesets.Taiko/app.config
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
@ -34,7 +34,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@ -100,6 +100,7 @@
|
|||||||
<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>
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
<?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="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||||
</packages>
|
</packages>
|
@ -1,7 +1,3 @@
|
|||||||
<!--
|
|
||||||
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>
|
||||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
11
osu.Game.Tests/app.config
Normal file
11
osu.Game.Tests/app.config
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
@ -30,12 +30,12 @@
|
|||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@ -53,6 +53,7 @@
|
|||||||
<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>
|
||||||
|
@ -4,8 +4,8 @@ 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
|
||||||
-->
|
-->
|
||||||
<packages>
|
<packages>
|
||||||
<package id="NUnit" version="3.7.1" targetFramework="net45" />
|
<package id="NUnit" version="3.8.1" targetFramework="net461" />
|
||||||
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||||
<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" />
|
||||||
</packages>
|
</packages>
|
@ -8,6 +8,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.IO.Serialization;
|
using osu.Game.IO.Serialization;
|
||||||
|
using osu.Game.Storyboards;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps
|
namespace osu.Game.Beatmaps
|
||||||
{
|
{
|
||||||
@ -40,6 +41,11 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double TotalBreakTime => Breaks.Sum(b => b.Duration);
|
public double TotalBreakTime => Breaks.Sum(b => b.Duration);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Beatmap's Storyboard.
|
||||||
|
/// </summary>
|
||||||
|
public Storyboard Storyboard = new Storyboard();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new beatmap.
|
/// Constructs a new beatmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -51,6 +57,7 @@ namespace osu.Game.Beatmaps
|
|||||||
Breaks = original?.Breaks ?? Breaks;
|
Breaks = original?.Breaks ?? Breaks;
|
||||||
ComboColors = original?.ComboColors ?? ComboColors;
|
ComboColors = original?.ComboColors ?? ComboColors;
|
||||||
HitObjects = original?.HitObjects ?? HitObjects;
|
HitObjects = original?.HitObjects ?? HitObjects;
|
||||||
|
Storyboard = original?.Storyboard ?? Storyboard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ using osu.Framework.Audio.Track;
|
|||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps
|
namespace osu.Game.Beatmaps
|
||||||
@ -62,11 +61,6 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => null;
|
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => null;
|
||||||
|
|
||||||
public override ScoreProcessor CreateScoreProcessor()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Description => "dummy";
|
public override string Description => "dummy";
|
||||||
|
|
||||||
public DummyRuleset(RulesetInfo rulesetInfo)
|
public DummyRuleset(RulesetInfo rulesetInfo)
|
||||||
|
@ -10,6 +10,10 @@ using osu.Game.Beatmaps.Timing;
|
|||||||
using osu.Game.Beatmaps.Legacy;
|
using osu.Game.Beatmaps.Legacy;
|
||||||
using osu.Game.Rulesets.Objects.Legacy;
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Storyboards;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.IO.File;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Formats
|
namespace osu.Game.Beatmaps.Formats
|
||||||
{
|
{
|
||||||
@ -238,42 +242,231 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEvents(Beatmap beatmap, string line)
|
private void handleEvents(Beatmap beatmap, string line, ref StoryboardSprite storyboardSprite, ref CommandTimelineGroup timelineGroup)
|
||||||
{
|
{
|
||||||
|
var depth = 0;
|
||||||
|
while (line.StartsWith(" ") || line.StartsWith("_"))
|
||||||
|
{
|
||||||
|
++depth;
|
||||||
|
line = line.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
decodeVariables(ref line);
|
decodeVariables(ref line);
|
||||||
|
|
||||||
string[] split = line.Split(',');
|
string[] split = line.Split(',');
|
||||||
|
|
||||||
EventType type;
|
if (depth == 0)
|
||||||
if (!Enum.TryParse(split[0], out type))
|
|
||||||
throw new InvalidDataException($@"Unknown event type {split[0]}");
|
|
||||||
|
|
||||||
// Todo: Implement the rest
|
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case EventType.Video:
|
storyboardSprite = null;
|
||||||
case EventType.Background:
|
|
||||||
string filename = split[2].Trim('"');
|
|
||||||
|
|
||||||
if (type == EventType.Background)
|
EventType type;
|
||||||
beatmap.BeatmapInfo.Metadata.BackgroundFile = filename;
|
if (!Enum.TryParse(split[0], out type))
|
||||||
|
throw new InvalidDataException($@"Unknown event type {split[0]}");
|
||||||
|
|
||||||
break;
|
switch (type)
|
||||||
case EventType.Break:
|
{
|
||||||
var breakEvent = new BreakPeriod
|
case EventType.Video:
|
||||||
{
|
case EventType.Background:
|
||||||
StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo),
|
string filename = split[2].Trim('"');
|
||||||
EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!breakEvent.HasEffect)
|
if (type == EventType.Background)
|
||||||
return;
|
beatmap.BeatmapInfo.Metadata.BackgroundFile = filename;
|
||||||
|
|
||||||
beatmap.Breaks.Add(breakEvent);
|
break;
|
||||||
break;
|
case EventType.Break:
|
||||||
|
var breakEvent = new BreakPeriod
|
||||||
|
{
|
||||||
|
StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo),
|
||||||
|
EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!breakEvent.HasEffect)
|
||||||
|
return;
|
||||||
|
|
||||||
|
beatmap.Breaks.Add(breakEvent);
|
||||||
|
break;
|
||||||
|
case EventType.Sprite:
|
||||||
|
{
|
||||||
|
var layer = parseLayer(split[1]);
|
||||||
|
var origin = parseOrigin(split[2]);
|
||||||
|
var path = cleanFilename(split[3]);
|
||||||
|
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
|
||||||
|
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
|
||||||
|
storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y));
|
||||||
|
beatmap.Storyboard.GetLayer(layer).Add(storyboardSprite);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.Animation:
|
||||||
|
{
|
||||||
|
var layer = parseLayer(split[1]);
|
||||||
|
var origin = parseOrigin(split[2]);
|
||||||
|
var path = cleanFilename(split[3]);
|
||||||
|
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
|
||||||
|
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
|
||||||
|
var frameCount = int.Parse(split[6]);
|
||||||
|
var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo);
|
||||||
|
var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever;
|
||||||
|
storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType);
|
||||||
|
beatmap.Storyboard.GetLayer(layer).Add(storyboardSprite);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.Sample:
|
||||||
|
{
|
||||||
|
var time = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||||
|
var layer = parseLayer(split[2]);
|
||||||
|
var path = cleanFilename(split[3]);
|
||||||
|
var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100;
|
||||||
|
beatmap.Storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (depth < 2)
|
||||||
|
timelineGroup = storyboardSprite?.TimelineGroup;
|
||||||
|
|
||||||
|
var commandType = split[0];
|
||||||
|
switch (commandType)
|
||||||
|
{
|
||||||
|
case "T":
|
||||||
|
{
|
||||||
|
var triggerName = split[1];
|
||||||
|
var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue;
|
||||||
|
var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue;
|
||||||
|
var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0;
|
||||||
|
timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "L":
|
||||||
|
{
|
||||||
|
var startTime = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||||
|
var loopCount = int.Parse(split[2]);
|
||||||
|
timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(split[3]))
|
||||||
|
split[3] = split[2];
|
||||||
|
|
||||||
|
var easing = (Easing)int.Parse(split[1]);
|
||||||
|
var startTime = double.Parse(split[2], CultureInfo.InvariantCulture);
|
||||||
|
var endTime = double.Parse(split[3], CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
switch (commandType)
|
||||||
|
{
|
||||||
|
case "F":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "S":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "V":
|
||||||
|
{
|
||||||
|
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||||
|
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||||
|
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||||
|
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "R":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "M":
|
||||||
|
{
|
||||||
|
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||||
|
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||||
|
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||||
|
timelineGroup?.X.Add(easing, startTime, endTime, startX, endX);
|
||||||
|
timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "MX":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "MY":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "C":
|
||||||
|
{
|
||||||
|
var startRed = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var startGreen = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||||
|
var startBlue = float.Parse(split[6], CultureInfo.InvariantCulture);
|
||||||
|
var endRed = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startRed;
|
||||||
|
var endGreen = split.Length > 8 ? float.Parse(split[8], CultureInfo.InvariantCulture) : startGreen;
|
||||||
|
var endBlue = split.Length > 9 ? float.Parse(split[9], CultureInfo.InvariantCulture) : startBlue;
|
||||||
|
timelineGroup?.Colour.Add(easing, startTime, endTime,
|
||||||
|
new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1),
|
||||||
|
new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "P":
|
||||||
|
{
|
||||||
|
var type = split[4];
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case "A": timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit); break;
|
||||||
|
case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime); break;
|
||||||
|
case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidDataException($@"Unknown command type: {commandType}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string cleanFilename(string path)
|
||||||
|
=> FileSafety.PathStandardise(path.Trim('\"'));
|
||||||
|
|
||||||
|
private static Anchor parseOrigin(string value)
|
||||||
|
{
|
||||||
|
var origin = (LegacyOrigins)Enum.Parse(typeof(LegacyOrigins), value);
|
||||||
|
switch (origin)
|
||||||
|
{
|
||||||
|
case LegacyOrigins.TopLeft: return Anchor.TopLeft;
|
||||||
|
case LegacyOrigins.TopCentre: return Anchor.TopCentre;
|
||||||
|
case LegacyOrigins.TopRight: return Anchor.TopRight;
|
||||||
|
case LegacyOrigins.CentreLeft: return Anchor.CentreLeft;
|
||||||
|
case LegacyOrigins.Centre: return Anchor.Centre;
|
||||||
|
case LegacyOrigins.CentreRight: return Anchor.CentreRight;
|
||||||
|
case LegacyOrigins.BottomLeft: return Anchor.BottomLeft;
|
||||||
|
case LegacyOrigins.BottomCentre: return Anchor.BottomCentre;
|
||||||
|
case LegacyOrigins.BottomRight: return Anchor.BottomRight;
|
||||||
|
}
|
||||||
|
throw new InvalidDataException($@"Unknown origin: {value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string parseLayer(string value)
|
||||||
|
=> Enum.Parse(typeof(StoryLayer), value).ToString();
|
||||||
|
|
||||||
private void handleTimingPoints(Beatmap beatmap, string line)
|
private void handleTimingPoints(Beatmap beatmap, string line)
|
||||||
{
|
{
|
||||||
string[] split = line.Split(',');
|
string[] split = line.Split(',');
|
||||||
@ -414,6 +607,8 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
Section section = Section.None;
|
Section section = Section.None;
|
||||||
bool hasCustomColours = false;
|
bool hasCustomColours = false;
|
||||||
|
StoryboardSprite storyboardSprite = null;
|
||||||
|
CommandTimelineGroup timelineGroup = null;
|
||||||
|
|
||||||
string line;
|
string line;
|
||||||
while ((line = stream.ReadLine()) != null)
|
while ((line = stream.ReadLine()) != null)
|
||||||
@ -421,7 +616,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
if (string.IsNullOrEmpty(line))
|
if (string.IsNullOrEmpty(line))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (line.StartsWith(" ") || line.StartsWith("_") || line.StartsWith("//"))
|
if (line.StartsWith("//"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (line.StartsWith(@"osu file format v"))
|
if (line.StartsWith(@"osu file format v"))
|
||||||
@ -452,7 +647,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
handleDifficulty(beatmap, line);
|
handleDifficulty(beatmap, line);
|
||||||
break;
|
break;
|
||||||
case Section.Events:
|
case Section.Events:
|
||||||
handleEvents(beatmap, line);
|
handleEvents(beatmap, line, ref storyboardSprite, ref timelineGroup);
|
||||||
break;
|
break;
|
||||||
case Section.TimingPoints:
|
case Section.TimingPoints:
|
||||||
handleTimingPoints(beatmap, line);
|
handleTimingPoints(beatmap, line);
|
||||||
@ -509,5 +704,27 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
Sample = 5,
|
Sample = 5,
|
||||||
Animation = 6
|
Animation = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal enum LegacyOrigins
|
||||||
|
{
|
||||||
|
TopLeft,
|
||||||
|
Centre,
|
||||||
|
CentreLeft,
|
||||||
|
TopRight,
|
||||||
|
BottomCentre,
|
||||||
|
TopCentre,
|
||||||
|
Custom,
|
||||||
|
CentreRight,
|
||||||
|
BottomLeft,
|
||||||
|
BottomRight
|
||||||
|
};
|
||||||
|
|
||||||
|
internal enum StoryLayer
|
||||||
|
{
|
||||||
|
Background = 0,
|
||||||
|
Fail = 1,
|
||||||
|
Pass = 2,
|
||||||
|
Foreground = 3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,8 +100,11 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public void TransferTo(WorkingBeatmap other)
|
public void TransferTo(WorkingBeatmap other)
|
||||||
{
|
{
|
||||||
if (track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo))
|
lock (trackLock)
|
||||||
other.track = track;
|
{
|
||||||
|
if (track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo))
|
||||||
|
other.track = track;
|
||||||
|
}
|
||||||
|
|
||||||
if (background != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo))
|
if (background != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo))
|
||||||
other.background = background;
|
other.background = background;
|
||||||
|
@ -228,9 +228,9 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
var size = new Vector2(2 * offset.X, offset.Y);
|
var size = new Vector2(2 * offset.X, offset.Y);
|
||||||
|
|
||||||
var triangle = new Triangle(
|
var triangle = new Triangle(
|
||||||
particle.Position * Size * DrawInfo.Matrix,
|
Vector2Extensions.Transform(particle.Position * Size, DrawInfo.Matrix),
|
||||||
(particle.Position * Size + offset) * DrawInfo.Matrix,
|
Vector2Extensions.Transform(particle.Position * Size + offset, DrawInfo.Matrix),
|
||||||
(particle.Position * Size + new Vector2(-offset.X, offset.Y)) * DrawInfo.Matrix
|
Vector2Extensions.Transform(particle.Position * Size + new Vector2(-offset.X, offset.Y), DrawInfo.Matrix)
|
||||||
);
|
);
|
||||||
|
|
||||||
ColourInfo colourInfo = DrawInfo.Colour;
|
ColourInfo colourInfo = DrawInfo.Colour;
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Graphics.Cursor
|
|||||||
|
|
||||||
// don't start rotating until we're moved a minimum distance away from the mouse down location,
|
// don't start rotating until we're moved a minimum distance away from the mouse down location,
|
||||||
// else it can have an annoying effect.
|
// else it can have an annoying effect.
|
||||||
startRotation |= Vector2.Distance(state.Mouse.Position, state.Mouse.PositionMouseDown.Value) > 30;
|
startRotation |= Vector2Extensions.Distance(state.Mouse.Position, state.Mouse.PositionMouseDown.Value) > 30;
|
||||||
|
|
||||||
if (startRotation)
|
if (startRotation)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
@ -112,7 +113,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
return base.OnMouseUp(state, args);
|
return base.OnMouseUp(state, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] FilterTerms => new[] { Text };
|
public IEnumerable<string> FilterTerms => new[] { Text };
|
||||||
|
|
||||||
public bool MatchingFilter
|
public bool MatchingFilter
|
||||||
{
|
{
|
||||||
|
25
osu.Game/OpenTK.dll.config
Normal file
25
osu.Game/OpenTK.dll.config
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<configuration>
|
||||||
|
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||||
|
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||||
|
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||||
|
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||||
|
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||||
|
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||||
|
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||||
|
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||||
|
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||||
|
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||||
|
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||||
|
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||||
|
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||||
|
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||||
|
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||||
|
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||||
|
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||||
|
</configuration>
|
@ -2,6 +2,7 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -34,7 +35,7 @@ namespace osu.Game.Overlays.Chat
|
|||||||
private Color4 topicColour;
|
private Color4 topicColour;
|
||||||
private Color4 hoverColour;
|
private Color4 hoverColour;
|
||||||
|
|
||||||
public string[] FilterTerms => new[] { channel.Name };
|
public IEnumerable<string> FilterTerms => new[] { channel.Name };
|
||||||
public bool MatchingFilter
|
public bool MatchingFilter
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Chat
|
|||||||
public readonly FillFlowContainer<ChannelListItem> ChannelFlow;
|
public readonly FillFlowContainer<ChannelListItem> ChannelFlow;
|
||||||
|
|
||||||
public IEnumerable<IFilterable> FilterableChildren => ChannelFlow.Children;
|
public IEnumerable<IFilterable> FilterableChildren => ChannelFlow.Children;
|
||||||
public string[] FilterTerms => new[] { Header };
|
public IEnumerable<string> FilterTerms => new[] { Header };
|
||||||
public bool MatchingFilter
|
public bool MatchingFilter
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
|
@ -12,8 +12,10 @@ using osu.Framework.Configuration;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Transforms;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
@ -56,7 +58,7 @@ namespace osu.Game.Overlays
|
|||||||
private readonly Box chatBackground;
|
private readonly Box chatBackground;
|
||||||
private readonly Box tabBackground;
|
private readonly Box tabBackground;
|
||||||
|
|
||||||
private Bindable<double> chatHeight;
|
public Bindable<double> ChatHeight { get; internal set; }
|
||||||
|
|
||||||
private readonly Container channelSelectionContainer;
|
private readonly Container channelSelectionContainer;
|
||||||
private readonly ChannelSelectionOverlay channelSelection;
|
private readonly ChannelSelectionOverlay channelSelection;
|
||||||
@ -177,18 +179,11 @@ namespace osu.Game.Overlays
|
|||||||
if (state == Visibility.Visible)
|
if (state == Visibility.Visible)
|
||||||
{
|
{
|
||||||
textbox.HoldFocus = false;
|
textbox.HoldFocus = false;
|
||||||
if (1f - chatHeight.Value < channel_selection_min_height)
|
if (1f - ChatHeight.Value < channel_selection_min_height)
|
||||||
{
|
transformChatHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint);
|
||||||
chatContainer.ResizeHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint);
|
|
||||||
channelSelectionContainer.ResizeHeightTo(channel_selection_min_height, 800, Easing.OutQuint);
|
|
||||||
channelSelection.Show();
|
|
||||||
chatHeight.Value = 1f - channel_selection_min_height;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
textbox.HoldFocus = true;
|
textbox.HoldFocus = true;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +197,7 @@ namespace osu.Game.Overlays
|
|||||||
if (!isDragging)
|
if (!isDragging)
|
||||||
return base.OnDragStart(state);
|
return base.OnDragStart(state);
|
||||||
|
|
||||||
startDragChatHeight = chatHeight.Value;
|
startDragChatHeight = ChatHeight.Value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +207,13 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
Trace.Assert(state.Mouse.PositionMouseDown != null);
|
Trace.Assert(state.Mouse.PositionMouseDown != null);
|
||||||
|
|
||||||
chatHeight.Value = startDragChatHeight - (state.Mouse.Position.Y - state.Mouse.PositionMouseDown.Value.Y) / Parent.DrawSize.Y;
|
double targetChatHeight = startDragChatHeight - (state.Mouse.Position.Y - state.Mouse.PositionMouseDown.Value.Y) / Parent.DrawSize.Y;
|
||||||
|
|
||||||
|
// If the channel selection screen is shown, mind its minimum height
|
||||||
|
if (channelSelection.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height)
|
||||||
|
targetChatHeight = 1f - channel_selection_min_height;
|
||||||
|
|
||||||
|
ChatHeight.Value = targetChatHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -272,14 +273,14 @@ namespace osu.Game.Overlays
|
|||||||
this.api = api;
|
this.api = api;
|
||||||
api.Register(this);
|
api.Register(this);
|
||||||
|
|
||||||
chatHeight = config.GetBindable<double>(OsuSetting.ChatDisplayHeight);
|
ChatHeight = config.GetBindable<double>(OsuSetting.ChatDisplayHeight);
|
||||||
chatHeight.ValueChanged += h =>
|
ChatHeight.ValueChanged += h =>
|
||||||
{
|
{
|
||||||
chatContainer.Height = (float)h;
|
chatContainer.Height = (float)h;
|
||||||
channelSelectionContainer.Height = 1f - (float)h;
|
channelSelectionContainer.Height = 1f - (float)h;
|
||||||
tabBackground.FadeTo(h == 1 ? 1 : 0.8f, 200);
|
tabBackground.FadeTo(h == 1 ? 1 : 0.8f, 200);
|
||||||
};
|
};
|
||||||
chatHeight.TriggerChange();
|
ChatHeight.TriggerChange();
|
||||||
|
|
||||||
chatBackground.Colour = colours.ChatBlue;
|
chatBackground.Colour = colours.ChatBlue;
|
||||||
}
|
}
|
||||||
@ -501,5 +502,26 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
api.Queue(req);
|
api.Queue(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void transformChatHeightTo(double newChatHeight, double duration = 0, Easing easing = Easing.None)
|
||||||
|
{
|
||||||
|
this.TransformTo(this.PopulateTransform(new TransformChatHeight(), newChatHeight, duration, easing));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TransformChatHeight : Transform<double, ChatOverlay>
|
||||||
|
{
|
||||||
|
private double valueAt(double time)
|
||||||
|
{
|
||||||
|
if (time < StartTime) return StartValue;
|
||||||
|
if (time >= EndTime) return EndValue;
|
||||||
|
|
||||||
|
return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string TargetMember => "ChatHeight.Value";
|
||||||
|
|
||||||
|
protected override void Apply(ChatOverlay d, double time) => d.ChatHeight.Value = valueAt(time);
|
||||||
|
protected override void ReadIntoStartValue(ChatOverlay d) => StartValue = d.ChatHeight.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ namespace osu.Game.Overlays.KeyBinding
|
|||||||
|
|
||||||
private FillFlowContainer<KeyButton> buttons;
|
private FillFlowContainer<KeyButton> buttons;
|
||||||
|
|
||||||
public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray();
|
public IEnumerable<string> FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray();
|
||||||
|
|
||||||
public KeyBindingRow(object action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings)
|
public KeyBindingRow(object action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings)
|
||||||
{
|
{
|
||||||
@ -371,4 +371,4 @@ namespace osu.Game.Overlays.KeyBinding
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] FilterTerms { get; private set; }
|
public IEnumerable<string> FilterTerms { get; private set; }
|
||||||
|
|
||||||
private bool matching = true;
|
private bool matching = true;
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
|
|
||||||
private class ItemSearchContainer : FillFlowContainer<PlaylistItem>, IHasFilterableChildren
|
private class ItemSearchContainer : FillFlowContainer<PlaylistItem>, IHasFilterableChildren
|
||||||
{
|
{
|
||||||
public string[] FilterTerms => new string[] { };
|
public IEnumerable<string> FilterTerms => new string[] { };
|
||||||
public bool MatchingFilter
|
public bool MatchingFilter
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
|
@ -414,8 +414,8 @@ namespace osu.Game.Overlays.Profile
|
|||||||
scoreNumberText.Add(createScoreNumberText(user.Statistics.TotalHits.ToString(@"#,0")));
|
scoreNumberText.Add(createScoreNumberText(user.Statistics.TotalHits.ToString(@"#,0")));
|
||||||
scoreText.Add(createScoreText("Max Combo"));
|
scoreText.Add(createScoreText("Max Combo"));
|
||||||
scoreNumberText.Add(createScoreNumberText(user.Statistics.MaxCombo.ToString(@"#,0")));
|
scoreNumberText.Add(createScoreNumberText(user.Statistics.MaxCombo.ToString(@"#,0")));
|
||||||
scoreText.Add(createScoreText("Replay Watched by Others"));
|
scoreText.Add(createScoreText("Replays Watched by Others"));
|
||||||
scoreNumberText.Add(createScoreNumberText(user.Statistics.ReplayWatched.ToString(@"#,0")));
|
scoreNumberText.Add(createScoreNumberText(user.Statistics.ReplaysWatched.ToString(@"#,0")));
|
||||||
|
|
||||||
gradeSS.DisplayCount = user.Statistics.GradesCount.SS;
|
gradeSS.DisplayCount = user.Statistics.GradesCount.SS;
|
||||||
gradeSS.Show();
|
gradeSS.Show();
|
||||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Text = "Force garbage collection",
|
Text = "Force garbage collection",
|
||||||
Action = () => GC.Collect()
|
Action = GC.Collect
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Text = "Open osu! folder",
|
Text = "Open osu! folder",
|
||||||
Action = () => storage.OpenInNativeExplorer(),
|
Action = storage.OpenInNativeExplorer,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Text = "Key Configuration",
|
Text = "Key Configuration",
|
||||||
Action = () => keyConfig.ToggleVisibility()
|
Action = keyConfig.ToggleVisibility
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -53,7 +54,7 @@ namespace osu.Game.Overlays.Settings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] FilterTerms => new[] { LabelText };
|
public IEnumerable<string> FilterTerms => new[] { LabelText };
|
||||||
|
|
||||||
public bool MatchingFilter
|
public bool MatchingFilter
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings
|
|||||||
public abstract string Header { get; }
|
public abstract string Header { get; }
|
||||||
|
|
||||||
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
|
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
|
||||||
public string[] FilterTerms => new[] { Header };
|
public IEnumerable<string> FilterTerms => new[] { Header };
|
||||||
|
|
||||||
private const int header_size = 26;
|
private const int header_size = 26;
|
||||||
private const int header_margin = 25;
|
private const int header_margin = 25;
|
||||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Settings
|
|||||||
protected abstract string Header { get; }
|
protected abstract string Header { get; }
|
||||||
|
|
||||||
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
|
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
|
||||||
public string[] FilterTerms => new[] { Header };
|
public IEnumerable<string> FilterTerms => new[] { Header };
|
||||||
public bool MatchingFilter
|
public bool MatchingFilter
|
||||||
{
|
{
|
||||||
set
|
set
|
||||||
|
@ -25,6 +25,10 @@ namespace osu.Game.Rulesets.Judgements
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double TimeOffset { get; internal set; }
|
public double TimeOffset { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the <see cref="Result"/> should affect the combo portion of the score.
|
||||||
|
/// If false, the <see cref="Result"/> will be considered for the bonus portion of the score.
|
||||||
|
/// </summary>
|
||||||
public virtual bool AffectsCombo => true;
|
public virtual bool AffectsCombo => true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -55,8 +55,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
{
|
{
|
||||||
HitObject = hitObject;
|
HitObject = hitObject;
|
||||||
|
|
||||||
Depth = (float)hitObject.StartTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArmedState state;
|
private ArmedState state;
|
||||||
|
@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override bool RemoveWhenNotAlive => false;
|
public override bool RemoveWhenNotAlive => false;
|
||||||
|
protected override bool RequiresChildrenUpdate => true;
|
||||||
|
|
||||||
protected DrawableScrollingHitObject(TObject hitObject)
|
protected DrawableScrollingHitObject(TObject hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
|
@ -10,7 +10,6 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Overlays.Settings;
|
using osu.Game.Overlays.Settings;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets
|
namespace osu.Game.Rulesets
|
||||||
@ -50,8 +49,6 @@ namespace osu.Game.Rulesets
|
|||||||
|
|
||||||
public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap);
|
public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap);
|
||||||
|
|
||||||
public abstract ScoreProcessor CreateScoreProcessor();
|
|
||||||
|
|
||||||
public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_question_circle };
|
public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_question_circle };
|
||||||
|
|
||||||
public abstract string Description { get; }
|
public abstract string Description { get; }
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// 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.Collections.Generic;
|
using System.Diagnostics;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -15,11 +15,17 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
public abstract class ScoreProcessor
|
public abstract class ScoreProcessor
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when the ScoreProcessor is in a failed state.
|
/// Invoked when the <see cref="ScoreProcessor"/> is in a failed state.
|
||||||
|
/// This may occur regardless of whether an <see cref="AllJudged"/> event is invoked.
|
||||||
/// Return true if the fail was permitted.
|
/// Return true if the fail was permitted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Func<bool> Failed;
|
public event Func<bool> Failed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when all <see cref="HitObject"/>s have been judged.
|
||||||
|
/// </summary>
|
||||||
|
public event Action AllJudged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the <see cref="ScoreProcessor"/>.
|
/// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the <see cref="ScoreProcessor"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -33,7 +39,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current accuracy.
|
/// The current accuracy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly BindableDouble Accuracy = new BindableDouble { MinValue = 0, MaxValue = 1 };
|
public readonly BindableDouble Accuracy = new BindableDouble(1) { MinValue = 0, MaxValue = 1 };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current health.
|
/// The current health.
|
||||||
@ -50,10 +56,15 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly BindableInt HighestCombo = new BindableInt();
|
public readonly BindableInt HighestCombo = new BindableInt();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether all <see cref="Judgement"/>s have been processed.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual bool HasCompleted => false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the score is in a failed state.
|
/// Whether the score is in a failed state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool HasFailed => false;
|
public virtual bool HasFailed => Health.Value == Health.MinValue;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this ScoreProcessor has already triggered the failed state.
|
/// Whether this ScoreProcessor has already triggered the failed state.
|
||||||
@ -63,8 +74,6 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
protected ScoreProcessor()
|
protected ScoreProcessor()
|
||||||
{
|
{
|
||||||
Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); };
|
Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); };
|
||||||
|
|
||||||
Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScoreRank rankFrom(double acc)
|
private ScoreRank rankFrom(double acc)
|
||||||
@ -85,11 +94,12 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets this ScoreProcessor to a default state.
|
/// Resets this ScoreProcessor to a default state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void Reset()
|
/// <param name="storeResults">Whether to store the current state of the <see cref="ScoreProcessor"/> for future use.</param>
|
||||||
|
protected virtual void Reset(bool storeResults)
|
||||||
{
|
{
|
||||||
TotalScore.Value = 0;
|
TotalScore.Value = 0;
|
||||||
Accuracy.Value = 0;
|
Accuracy.Value = 1;
|
||||||
Health.Value = 0;
|
Health.Value = 1;
|
||||||
Combo.Value = 0;
|
Combo.Value = 0;
|
||||||
HighestCombo.Value = 0;
|
HighestCombo.Value = 0;
|
||||||
|
|
||||||
@ -118,6 +128,9 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
protected void NotifyNewJudgement(Judgement judgement)
|
protected void NotifyNewJudgement(Judgement judgement)
|
||||||
{
|
{
|
||||||
NewJudgement?.Invoke(judgement);
|
NewJudgement?.Invoke(judgement);
|
||||||
|
|
||||||
|
if (HasCompleted)
|
||||||
|
AllJudged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -135,36 +148,55 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class ScoreProcessor<TObject> : ScoreProcessor
|
public class ScoreProcessor<TObject> : ScoreProcessor
|
||||||
where TObject : HitObject
|
where TObject : HitObject
|
||||||
{
|
{
|
||||||
/// <summary>
|
private const double base_portion = 0.3;
|
||||||
/// All judgements held by this ScoreProcessor.
|
private const double combo_portion = 0.7;
|
||||||
/// </summary>
|
private const double max_score = 1000000;
|
||||||
protected readonly List<Judgement> Judgements = new List<Judgement>();
|
|
||||||
|
|
||||||
public override bool HasFailed => Health.Value == Health.MinValue;
|
public readonly Bindable<ScoringMode> Mode = new Bindable<ScoringMode>();
|
||||||
|
|
||||||
|
protected sealed override bool HasCompleted => Hits == MaxHits;
|
||||||
|
|
||||||
|
protected int MaxHits { get; private set; }
|
||||||
|
protected int Hits { get; private set; }
|
||||||
|
|
||||||
|
private double maxHighestCombo;
|
||||||
|
|
||||||
|
private double maxBaseScore;
|
||||||
|
private double rollingMaxBaseScore;
|
||||||
|
private double baseScore;
|
||||||
|
|
||||||
protected ScoreProcessor()
|
protected ScoreProcessor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ScoreProcessor(RulesetContainer<TObject> rulesetContainer)
|
public ScoreProcessor(RulesetContainer<TObject> rulesetContainer)
|
||||||
{
|
{
|
||||||
Judgements.Capacity = rulesetContainer.Beatmap.HitObjects.Count;
|
Debug.Assert(base_portion + combo_portion == 1.0);
|
||||||
|
|
||||||
rulesetContainer.OnJudgement += AddJudgement;
|
rulesetContainer.OnJudgement += AddJudgement;
|
||||||
|
|
||||||
ComputeTargets(rulesetContainer.Beatmap);
|
SimulateAutoplay(rulesetContainer.Beatmap);
|
||||||
|
Reset(true);
|
||||||
|
|
||||||
Reset();
|
if (maxBaseScore == 0 || maxHighestCombo == 0)
|
||||||
|
{
|
||||||
|
Mode.Value = ScoringMode.Exponential;
|
||||||
|
Mode.Disabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes target scoring values for this ScoreProcessor. This is equivalent to performing an auto-play of the score to find the values.
|
/// Simulates an autoplay of <see cref="HitObject"/>s that will be judged by this <see cref="ScoreProcessor{TObject}"/>
|
||||||
|
/// by adding <see cref="Judgement"/>s for each <see cref="HitObject"/> in the <see cref="Beatmap{TObject}"/>.
|
||||||
|
/// <para>
|
||||||
|
/// This is required for <see cref="ScoringMode.Standardised"/> to work, otherwise <see cref="ScoringMode.Exponential"/> will be used.
|
||||||
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="beatmap">The Beatmap containing the objects that will be judged by this ScoreProcessor.</param>
|
/// <param name="beatmap">The <see cref="Beatmap{TObject}"/> containing the <see cref="HitObject"/>s that will be judged by this <see cref="ScoreProcessor{TObject}"/>.</param>
|
||||||
protected virtual void ComputeTargets(Beatmap<TObject> beatmap) { }
|
protected virtual void SimulateAutoplay(Beatmap<TObject> beatmap) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a judgement to this ScoreProcessor.
|
/// Adds a judgement to this ScoreProcessor.
|
||||||
@ -172,45 +204,72 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// <param name="judgement">The judgement to add.</param>
|
/// <param name="judgement">The judgement to add.</param>
|
||||||
protected void AddJudgement(Judgement judgement)
|
protected void AddJudgement(Judgement judgement)
|
||||||
{
|
{
|
||||||
bool exists = Judgements.Contains(judgement);
|
OnNewJudgement(judgement);
|
||||||
|
NotifyNewJudgement(judgement);
|
||||||
if (!exists)
|
|
||||||
{
|
|
||||||
if (judgement.AffectsCombo)
|
|
||||||
{
|
|
||||||
switch (judgement.Result)
|
|
||||||
{
|
|
||||||
case HitResult.None:
|
|
||||||
break;
|
|
||||||
case HitResult.Miss:
|
|
||||||
Combo.Value = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Combo.Value++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Judgements.Add(judgement);
|
|
||||||
OnNewJudgement(judgement);
|
|
||||||
|
|
||||||
NotifyNewJudgement(judgement);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateFailed();
|
UpdateFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Reset()
|
protected virtual void OnNewJudgement(Judgement judgement)
|
||||||
{
|
{
|
||||||
base.Reset();
|
double bonusScore = 0;
|
||||||
|
|
||||||
Judgements.Clear();
|
if (judgement.AffectsCombo)
|
||||||
|
{
|
||||||
|
switch (judgement.Result)
|
||||||
|
{
|
||||||
|
case HitResult.None:
|
||||||
|
break;
|
||||||
|
case HitResult.Miss:
|
||||||
|
Combo.Value = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Combo.Value++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseScore += judgement.NumericResult;
|
||||||
|
rollingMaxBaseScore += judgement.MaxNumericResult;
|
||||||
|
|
||||||
|
Hits++;
|
||||||
|
}
|
||||||
|
else if (judgement.IsHit)
|
||||||
|
bonusScore += judgement.NumericResult;
|
||||||
|
|
||||||
|
if (rollingMaxBaseScore != 0)
|
||||||
|
Accuracy.Value = baseScore / rollingMaxBaseScore;
|
||||||
|
|
||||||
|
switch (Mode.Value)
|
||||||
|
{
|
||||||
|
case ScoringMode.Standardised:
|
||||||
|
TotalScore.Value = max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore;
|
||||||
|
break;
|
||||||
|
case ScoringMode.Exponential:
|
||||||
|
TotalScore.Value = (baseScore + bonusScore) * Math.Log(HighestCombo + 1, 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
protected override void Reset(bool storeResults)
|
||||||
/// Updates any values that need post-processing. Invoked when a new judgement has occurred.
|
{
|
||||||
/// </summary>
|
if (storeResults)
|
||||||
/// <param name="judgement">The judgement that triggered this calculation.</param>
|
{
|
||||||
protected abstract void OnNewJudgement(Judgement judgement);
|
MaxHits = Hits;
|
||||||
|
maxHighestCombo = HighestCombo;
|
||||||
|
maxBaseScore = baseScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Reset(storeResults);
|
||||||
|
|
||||||
|
Hits = 0;
|
||||||
|
baseScore = 0;
|
||||||
|
rollingMaxBaseScore = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ScoringMode
|
||||||
|
{
|
||||||
|
Standardised,
|
||||||
|
Exponential
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Timing
|
|||||||
internal Axes ScrollingAxes;
|
internal Axes ScrollingAxes;
|
||||||
|
|
||||||
public override bool RemoveWhenNotAlive => false;
|
public override bool RemoveWhenNotAlive => false;
|
||||||
|
protected override bool RequiresChildrenUpdate => true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The control point that defines the speed adjustments for this container. This is set by the <see cref="SpeedAdjustmentContainer"/>.
|
/// The control point that defines the speed adjustments for this container. This is set by the <see cref="SpeedAdjustmentContainer"/>.
|
||||||
|
@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Timing
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override bool RemoveWhenNotAlive => false;
|
public override bool RemoveWhenNotAlive => false;
|
||||||
|
protected override bool RequiresChildrenUpdate => true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="MultiplierControlPoint"/> that defines the speed adjustments.
|
/// The <see cref="MultiplierControlPoint"/> that defines the speed adjustments.
|
||||||
|
@ -29,11 +29,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class RulesetContainer : Container
|
public abstract class RulesetContainer : Container
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Invoked when all the judgeable HitObjects have been judged.
|
|
||||||
/// </summary>
|
|
||||||
public event Action OnAllJudged;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to apply adjustments to the child <see cref="Playfield"/> based on our own size.
|
/// Whether to apply adjustments to the child <see cref="Playfield"/> based on our own size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -61,11 +56,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
public abstract IEnumerable<HitObject> Objects { get; }
|
public abstract IEnumerable<HitObject> Objects { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether all the HitObjects have been judged.
|
|
||||||
/// </summary>
|
|
||||||
protected abstract bool AllObjectsJudged { get; }
|
|
||||||
|
|
||||||
protected readonly Ruleset Ruleset;
|
protected readonly Ruleset Ruleset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -77,15 +67,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
Ruleset = ruleset;
|
Ruleset = ruleset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks whether all HitObjects have been judged, and invokes OnAllJudged.
|
|
||||||
/// </summary>
|
|
||||||
protected void CheckAllJudged()
|
|
||||||
{
|
|
||||||
if (AllObjectsJudged)
|
|
||||||
OnAllJudged?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract ScoreProcessor CreateScoreProcessor();
|
public abstract ScoreProcessor CreateScoreProcessor();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -152,7 +133,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor;
|
public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor;
|
||||||
|
|
||||||
protected override bool AllObjectsJudged => drawableObjects.All(h => h.AllJudged);
|
public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor<TObject>(this);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The playfield.
|
/// The playfield.
|
||||||
@ -162,8 +143,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
private Container content;
|
private Container content;
|
||||||
|
|
||||||
private readonly List<DrawableHitObject<TObject>> drawableObjects = new List<DrawableHitObject<TObject>>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to assume the beatmap passed into this <see cref="RulesetContainer{TObject}"/> is for the current ruleset.
|
/// Whether to assume the beatmap passed into this <see cref="RulesetContainer{TObject}"/> is for the current ruleset.
|
||||||
/// Creates a hit renderer for a beatmap.
|
/// Creates a hit renderer for a beatmap.
|
||||||
@ -250,8 +229,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void loadObjects()
|
private void loadObjects()
|
||||||
{
|
{
|
||||||
drawableObjects.Capacity = Beatmap.HitObjects.Count;
|
|
||||||
|
|
||||||
foreach (TObject h in Beatmap.HitObjects)
|
foreach (TObject h in Beatmap.HitObjects)
|
||||||
{
|
{
|
||||||
var drawableObject = GetVisualRepresentation(h);
|
var drawableObject = GetVisualRepresentation(h);
|
||||||
@ -263,10 +240,8 @@ namespace osu.Game.Rulesets.UI
|
|||||||
{
|
{
|
||||||
Playfield.OnJudgement(d, j);
|
Playfield.OnJudgement(d, j);
|
||||||
OnJudgement?.Invoke(j);
|
OnJudgement?.Invoke(j);
|
||||||
CheckAllJudged();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
drawableObjects.Add(drawableObject);
|
|
||||||
Playfield.Add(drawableObject);
|
Playfield.Add(drawableObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,10 +201,10 @@ namespace osu.Game.Screens.Menu
|
|||||||
var amplitudeOffset = new Vector2(rotationCos * barSize.Y, rotationSin * barSize.Y);
|
var amplitudeOffset = new Vector2(rotationCos * barSize.Y, rotationSin * barSize.Y);
|
||||||
|
|
||||||
var rectangle = new Quad(
|
var rectangle = new Quad(
|
||||||
(barPosition - bottomOffset) * DrawInfo.Matrix,
|
Vector2Extensions.Transform(barPosition - bottomOffset, DrawInfo.Matrix),
|
||||||
(barPosition - bottomOffset + amplitudeOffset) * DrawInfo.Matrix,
|
Vector2Extensions.Transform(barPosition - bottomOffset + amplitudeOffset, DrawInfo.Matrix),
|
||||||
(barPosition + bottomOffset) * DrawInfo.Matrix,
|
Vector2Extensions.Transform(barPosition + bottomOffset, DrawInfo.Matrix),
|
||||||
(barPosition + bottomOffset + amplitudeOffset) * DrawInfo.Matrix
|
Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix)
|
||||||
);
|
);
|
||||||
|
|
||||||
Texture.DrawQuad(
|
Texture.DrawQuad(
|
||||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
OnEdit = delegate { Push(new Editor()); },
|
OnEdit = delegate { Push(new Editor()); },
|
||||||
OnSolo = delegate { Push(consumeSongSelect()); },
|
OnSolo = delegate { Push(consumeSongSelect()); },
|
||||||
OnMulti = delegate { Push(new Lobby()); },
|
OnMulti = delegate { Push(new Lobby()); },
|
||||||
OnExit = delegate { Exit(); },
|
OnExit = Exit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -206,10 +206,8 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
hudOverlay.ModDisplay.Current.BindTo(working.Mods);
|
hudOverlay.ModDisplay.Current.BindTo(working.Mods);
|
||||||
|
|
||||||
//bind RulesetContainer to ScoreProcessor and ourselves (for a pass situation)
|
// Bind ScoreProcessor to ourselves
|
||||||
RulesetContainer.OnAllJudged += onCompletion;
|
scoreProcessor.AllJudged += onCompletion;
|
||||||
|
|
||||||
//bind ScoreProcessor to ourselves (for a fail situation)
|
|
||||||
scoreProcessor.Failed += onFail;
|
scoreProcessor.Failed += onFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
|
||||||
@ -34,10 +35,12 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
foreach (var h in objects)
|
foreach (var h in objects)
|
||||||
{
|
{
|
||||||
IHasEndTime end = h as IHasEndTime;
|
var endTime = (h as IHasEndTime)?.EndTime ?? h.StartTime;
|
||||||
|
|
||||||
|
Debug.Assert(endTime >= h.StartTime);
|
||||||
|
|
||||||
int startRange = (int)((h.StartTime - firstHit) / interval);
|
int startRange = (int)((h.StartTime - firstHit) / interval);
|
||||||
int endRange = (int)(((end?.EndTime > 0 ? end.EndTime : h.StartTime) - firstHit) / interval);
|
int endRange = (int)((endTime - firstHit) / interval);
|
||||||
for (int i = startRange; i <= endRange; i++)
|
for (int i = startRange; i <= endRange; i++)
|
||||||
Values[i]++;
|
Values[i]++;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ namespace osu.Game.Screens.Select
|
|||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.CentreRight,
|
||||||
SelectionChanged = carouselSelectionChanged,
|
SelectionChanged = carouselSelectionChanged,
|
||||||
BeatmapsChanged = carouselBeatmapsLoaded,
|
BeatmapsChanged = carouselBeatmapsLoaded,
|
||||||
DeleteRequested = b => promptDelete(b),
|
DeleteRequested = promptDelete,
|
||||||
RestoreRequested = s => { foreach (var b in s.Beatmaps) manager.Restore(b); },
|
RestoreRequested = s => { foreach (var b in s.Beatmaps) manager.Restore(b); },
|
||||||
HideDifficultyRequested = b => manager.Hide(b),
|
HideDifficultyRequested = b => manager.Hide(b),
|
||||||
StartRequested = () => carouselRaisedStart(),
|
StartRequested = () => carouselRaisedStart(),
|
||||||
|
@ -237,7 +237,7 @@ namespace osu.Game.Screens.Tournament
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
|
|
||||||
Text = "Reset",
|
Text = "Reset",
|
||||||
Action = () => reset(false)
|
Action = () => reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
osu.Game/Storyboards/CommandLoop.cs
Normal file
35
osu.Game/Storyboards/CommandLoop.cs
Normal 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 System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Storyboards
|
||||||
|
{
|
||||||
|
public class CommandLoop : CommandTimelineGroup
|
||||||
|
{
|
||||||
|
public double LoopStartTime;
|
||||||
|
public int LoopCount;
|
||||||
|
|
||||||
|
public override double StartTime => LoopStartTime;
|
||||||
|
public override double EndTime => LoopStartTime + CommandsDuration * LoopCount;
|
||||||
|
|
||||||
|
public CommandLoop(double startTime, int loopCount)
|
||||||
|
{
|
||||||
|
LoopStartTime = startTime;
|
||||||
|
LoopCount = loopCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<CommandTimeline<T>.TypedCommand> GetCommands<T>(CommandTimelineSelector<T> timelineSelector, double offset = 0)
|
||||||
|
{
|
||||||
|
for (var loop = 0; loop < LoopCount; loop++)
|
||||||
|
{
|
||||||
|
var loopOffset = LoopStartTime + loop * CommandsDuration;
|
||||||
|
foreach (var command in base.GetCommands(timelineSelector, offset + loopOffset))
|
||||||
|
yield return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
=> $"{LoopStartTime} x{LoopCount}";
|
||||||
|
}
|
||||||
|
}
|
77
osu.Game/Storyboards/CommandTimeline.cs
Normal file
77
osu.Game/Storyboards/CommandTimeline.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// 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.Caching;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace osu.Game.Storyboards
|
||||||
|
{
|
||||||
|
public class CommandTimeline<T> : ICommandTimeline
|
||||||
|
{
|
||||||
|
private readonly List<TypedCommand> commands = new List<TypedCommand>();
|
||||||
|
public IEnumerable<TypedCommand> Commands => commands.OrderBy(c => c.StartTime);
|
||||||
|
public bool HasCommands => commands.Count > 0;
|
||||||
|
|
||||||
|
private Cached<double> startTimeBacking;
|
||||||
|
public double StartTime => startTimeBacking.IsValid ? startTimeBacking : (startTimeBacking.Value = HasCommands ? commands.Min(c => c.StartTime) : double.MinValue);
|
||||||
|
|
||||||
|
private Cached<double> endTimeBacking;
|
||||||
|
public double EndTime => endTimeBacking.IsValid ? endTimeBacking : (endTimeBacking.Value = HasCommands ? commands.Max(c => c.EndTime) : double.MaxValue);
|
||||||
|
|
||||||
|
public T StartValue => HasCommands ? commands.OrderBy(c => c.StartTime).First().StartValue : default(T);
|
||||||
|
public T EndValue => HasCommands ? commands.OrderByDescending(c => c.EndTime).First().EndValue : default(T);
|
||||||
|
|
||||||
|
public void Add(Easing easing, double startTime, double endTime, T startValue, T endValue)
|
||||||
|
{
|
||||||
|
if (endTime < startTime)
|
||||||
|
return;
|
||||||
|
|
||||||
|
commands.Add(new TypedCommand { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue, });
|
||||||
|
|
||||||
|
startTimeBacking.Invalidate();
|
||||||
|
endTimeBacking.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
=> $"{commands.Count} command(s)";
|
||||||
|
|
||||||
|
public class TypedCommand : ICommand
|
||||||
|
{
|
||||||
|
public Easing Easing { get; set; }
|
||||||
|
public double StartTime { get; set; }
|
||||||
|
public double EndTime { get; set; }
|
||||||
|
public double Duration => EndTime - StartTime;
|
||||||
|
|
||||||
|
public T StartValue;
|
||||||
|
public T EndValue;
|
||||||
|
|
||||||
|
public int CompareTo(ICommand other)
|
||||||
|
{
|
||||||
|
var result = StartTime.CompareTo(other.StartTime);
|
||||||
|
if (result != 0) return result;
|
||||||
|
return EndTime.CompareTo(other.EndTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
=> $"{StartTime} -> {EndTime}, {StartValue} -> {EndValue} {Easing}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICommandTimeline
|
||||||
|
{
|
||||||
|
double StartTime { get; }
|
||||||
|
double EndTime { get; }
|
||||||
|
bool HasCommands { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICommand : IComparable<ICommand>
|
||||||
|
{
|
||||||
|
Easing Easing { get; set; }
|
||||||
|
double StartTime { get; set; }
|
||||||
|
double EndTime { get; set; }
|
||||||
|
double Duration { get; }
|
||||||
|
}
|
||||||
|
}
|
68
osu.Game/Storyboards/CommandTimelineGroup.cs
Normal file
68
osu.Game/Storyboards/CommandTimelineGroup.cs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace osu.Game.Storyboards
|
||||||
|
{
|
||||||
|
public delegate CommandTimeline<T> CommandTimelineSelector<T>(CommandTimelineGroup commandTimelineGroup);
|
||||||
|
|
||||||
|
public class CommandTimelineGroup
|
||||||
|
{
|
||||||
|
public CommandTimeline<float> X = new CommandTimeline<float>();
|
||||||
|
public CommandTimeline<float> Y = new CommandTimeline<float>();
|
||||||
|
public CommandTimeline<Vector2> Scale = new CommandTimeline<Vector2>();
|
||||||
|
public CommandTimeline<float> Rotation = new CommandTimeline<float>();
|
||||||
|
public CommandTimeline<Color4> Colour = new CommandTimeline<Color4>();
|
||||||
|
public CommandTimeline<float> Alpha = new CommandTimeline<float>();
|
||||||
|
public CommandTimeline<BlendingMode> BlendingMode = new CommandTimeline<BlendingMode>();
|
||||||
|
public CommandTimeline<bool> FlipH = new CommandTimeline<bool>();
|
||||||
|
public CommandTimeline<bool> FlipV = new CommandTimeline<bool>();
|
||||||
|
|
||||||
|
public IEnumerable<ICommandTimeline> Timelines
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return X;
|
||||||
|
yield return Y;
|
||||||
|
yield return Scale;
|
||||||
|
yield return Rotation;
|
||||||
|
yield return Colour;
|
||||||
|
yield return Alpha;
|
||||||
|
yield return BlendingMode;
|
||||||
|
yield return FlipH;
|
||||||
|
yield return FlipV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double CommandsStartTime => Timelines.Where(t => t.HasCommands).Min(t => t.StartTime);
|
||||||
|
public double CommandsEndTime => Timelines.Where(t => t.HasCommands).Max(t => t.EndTime);
|
||||||
|
public double CommandsDuration => CommandsEndTime - CommandsStartTime;
|
||||||
|
|
||||||
|
public virtual double StartTime => CommandsStartTime;
|
||||||
|
public virtual double EndTime => CommandsEndTime;
|
||||||
|
public double Duration => EndTime - StartTime;
|
||||||
|
|
||||||
|
public bool HasCommands => Timelines.Any(t => t.HasCommands);
|
||||||
|
|
||||||
|
public virtual IEnumerable<CommandTimeline<T>.TypedCommand> GetCommands<T>(CommandTimelineSelector<T> timelineSelector, double offset = 0)
|
||||||
|
{
|
||||||
|
if (offset != 0)
|
||||||
|
return timelineSelector(this).Commands.Select(command =>
|
||||||
|
new CommandTimeline<T>.TypedCommand
|
||||||
|
{
|
||||||
|
Easing = command.Easing,
|
||||||
|
StartTime = offset + command.StartTime,
|
||||||
|
EndTime = offset + command.EndTime,
|
||||||
|
StartValue = command.StartValue,
|
||||||
|
EndValue = command.EndValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
return timelineSelector(this).Commands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
osu.Game/Storyboards/CommandTrigger.cs
Normal file
24
osu.Game/Storyboards/CommandTrigger.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
namespace osu.Game.Storyboards
|
||||||
|
{
|
||||||
|
public class CommandTrigger : CommandTimelineGroup
|
||||||
|
{
|
||||||
|
public string TriggerName;
|
||||||
|
public double TriggerStartTime;
|
||||||
|
public double TriggerEndTime;
|
||||||
|
public int GroupNumber;
|
||||||
|
|
||||||
|
public CommandTrigger(string triggerName, double startTime, double endTime, int groupNumber)
|
||||||
|
{
|
||||||
|
TriggerName = triggerName;
|
||||||
|
TriggerStartTime = startTime;
|
||||||
|
TriggerEndTime = endTime;
|
||||||
|
GroupNumber = groupNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
=> $"{TriggerName} {TriggerStartTime} -> {TriggerEndTime} ({GroupNumber})";
|
||||||
|
}
|
||||||
|
}
|
59
osu.Game/Storyboards/Drawables/DrawableStoryboard.cs
Normal file
59
osu.Game/Storyboards/Drawables/DrawableStoryboard.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.IO;
|
||||||
|
|
||||||
|
namespace osu.Game.Storyboards.Drawables
|
||||||
|
{
|
||||||
|
public class DrawableStoryboard : Container<DrawableStoryboardLayer>
|
||||||
|
{
|
||||||
|
public Storyboard Storyboard { get; private set; }
|
||||||
|
|
||||||
|
protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480);
|
||||||
|
public override bool HandleInput => false;
|
||||||
|
|
||||||
|
private bool passing = true;
|
||||||
|
public bool Passing
|
||||||
|
{
|
||||||
|
get { return passing; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (passing == value) return;
|
||||||
|
passing = value;
|
||||||
|
updateLayerVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DependencyContainer dependencies;
|
||||||
|
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) =>
|
||||||
|
dependencies = new DependencyContainer(base.CreateLocalDependencies(parent));
|
||||||
|
|
||||||
|
public DrawableStoryboard(Storyboard storyboard)
|
||||||
|
{
|
||||||
|
Storyboard = storyboard;
|
||||||
|
Size = new Vector2(640, 480);
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(FileStore fileStore)
|
||||||
|
{
|
||||||
|
dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, });
|
||||||
|
|
||||||
|
foreach (var layer in Storyboard.Layers)
|
||||||
|
Add(layer.CreateDrawable());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLayerVisibility()
|
||||||
|
{
|
||||||
|
foreach (var layer in Children)
|
||||||
|
layer.Enabled = passing ? layer.Layer.EnabledWhenPassing : layer.Layer.EnabledWhenFailing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Animations;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace osu.Game.Storyboards.Drawables
|
||||||
|
{
|
||||||
|
public class DrawableStoryboardAnimation : TextureAnimation, IFlippable
|
||||||
|
{
|
||||||
|
public StoryboardAnimation Animation { get; private set; }
|
||||||
|
|
||||||
|
protected override bool ShouldBeAlive => Animation.HasCommands && base.ShouldBeAlive;
|
||||||
|
public override bool RemoveWhenNotAlive => !Animation.HasCommands || base.RemoveWhenNotAlive;
|
||||||
|
|
||||||
|
public bool FlipH { get; set; }
|
||||||
|
public bool FlipV { get; set; }
|
||||||
|
|
||||||
|
protected override Vector2 DrawScale
|
||||||
|
=> new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y);
|
||||||
|
|
||||||
|
public override Anchor Origin
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var origin = base.Origin;
|
||||||
|
|
||||||
|
if (FlipH)
|
||||||
|
{
|
||||||
|
if (origin.HasFlag(Anchor.x0))
|
||||||
|
origin = Anchor.x2 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2));
|
||||||
|
else if (origin.HasFlag(Anchor.x2))
|
||||||
|
origin = Anchor.x0 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FlipV)
|
||||||
|
{
|
||||||
|
if (origin.HasFlag(Anchor.y0))
|
||||||
|
origin = Anchor.y2 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2));
|
||||||
|
else if (origin.HasFlag(Anchor.y2))
|
||||||
|
origin = Anchor.y0 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsPresent
|
||||||
|
=> !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent;
|
||||||
|
|
||||||
|
public DrawableStoryboardAnimation(StoryboardAnimation animation)
|
||||||
|
{
|
||||||
|
Animation = animation;
|
||||||
|
Origin = animation.Origin;
|
||||||
|
Position = animation.InitialPosition;
|
||||||
|
Repeat = animation.LoopType == AnimationLoopType.LoopForever;
|
||||||
|
|
||||||
|
if (animation.HasCommands)
|
||||||
|
{
|
||||||
|
LifetimeStart = animation.StartTime;
|
||||||
|
LifetimeEnd = animation.EndTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuGameBase game, TextureStore textureStore)
|
||||||
|
{
|
||||||
|
var basePath = Animation.Path.ToLowerInvariant();
|
||||||
|
for (var frame = 0; frame < Animation.FrameCount; frame++)
|
||||||
|
{
|
||||||
|
var framePath = basePath.Replace(".", frame + ".");
|
||||||
|
|
||||||
|
var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename.ToLowerInvariant() == framePath)?.FileInfo.StoragePath;
|
||||||
|
if (path == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var texture = textureStore.Get(path);
|
||||||
|
AddFrame(texture, Animation.FrameDelay);
|
||||||
|
}
|
||||||
|
Animation.ApplyTransforms(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs
Normal file
37
osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
|
||||||
|
namespace osu.Game.Storyboards.Drawables
|
||||||
|
{
|
||||||
|
public class DrawableStoryboardLayer : Container
|
||||||
|
{
|
||||||
|
public StoryboardLayer Layer { get; private set; }
|
||||||
|
public bool Enabled;
|
||||||
|
|
||||||
|
public override bool IsPresent => Enabled && base.IsPresent;
|
||||||
|
|
||||||
|
public DrawableStoryboardLayer(StoryboardLayer layer)
|
||||||
|
{
|
||||||
|
Layer = layer;
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
Enabled = layer.EnabledWhenPassing;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
foreach (var element in Layer.Elements)
|
||||||
|
{
|
||||||
|
var drawable = element.CreateDrawable();
|
||||||
|
if (drawable != null)
|
||||||
|
Add(drawable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user