mirror of
https://github.com/osukey/osukey.git
synced 2025-05-21 21:47:31 +09:00
Merge branch 'master' into numpad-enter
This commit is contained in:
commit
ae79ba48be
@ -1 +1 @@
|
|||||||
Subproject commit 3ad1dd52ae511b816fb928f70ef811ec605c5c18
|
Subproject commit c80d5f53e740ffe63d9deca41749c5ba0573e744
|
@ -31,6 +31,10 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
|||||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-0.17.1.0" newVersion="0.17.1.0" />
|
||||||
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
</configuration>
|
</configuration>
|
@ -49,10 +49,6 @@
|
|||||||
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\DeltaCompressionDotNet.1.1.0\lib\net20\DeltaCompressionDotNet.PatchApi.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, processorArchitecture=MSIL">
|
|
||||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\ICSharpCode.SharpZipLib.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
@ -73,15 +69,19 @@
|
|||||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<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.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SharpCompress, Version=0.17.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||||
|
<HintPath>$(SolutionDir)\packages\SharpCompress.0.17.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.5.2.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Squirrel, Version=1.7.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\Squirrel.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\Squirrel.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -7,7 +7,8 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
|||||||
<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.2" targetFramework="net452" />
|
||||||
<package id="NuGet.CommandLine" version="3.5.0" targetFramework="net452" developmentDependency="true" />
|
<package id="NuGet.CommandLine" version="4.1.0" targetFramework="net452" developmentDependency="true" />
|
||||||
|
<package id="SharpCompress" version="0.17.1" targetFramework="net452" />
|
||||||
<package id="Splat" version="2.0.0" targetFramework="net452" />
|
<package id="Splat" version="2.0.0" targetFramework="net452" />
|
||||||
<package id="squirrel.windows" version="1.5.2" targetFramework="net452" />
|
<package id="squirrel.windows" version="1.7.5" targetFramework="net452" />
|
||||||
</packages>
|
</packages>
|
11
osu.Desktop.Tests/app.config
Normal file
11
osu.Desktop.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>
|
@ -37,8 +37,9 @@
|
|||||||
<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.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="nunit.framework, Version=3.6.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
|
||||||
|
<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">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
@ -100,6 +101,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" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -5,7 +5,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
|||||||
-->
|
-->
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
||||||
<package id="NUnit" version="3.6.1" targetFramework="net45" />
|
<package id="NUnit" version="3.7.1" targetFramework="net45" />
|
||||||
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
||||||
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
||||||
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
|
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
|
||||||
|
125
osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs
Normal file
125
osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
// 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 osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Transforms;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Desktop.VisualTests.Tests
|
||||||
|
{
|
||||||
|
internal class TestCaseContextMenu : TestCase
|
||||||
|
{
|
||||||
|
public override string Description => @"Menu visible on right click";
|
||||||
|
|
||||||
|
private const int start_time = 0;
|
||||||
|
private const int duration = 1000;
|
||||||
|
|
||||||
|
private MyContextMenuContainer container;
|
||||||
|
|
||||||
|
public override void Reset()
|
||||||
|
{
|
||||||
|
base.Reset();
|
||||||
|
|
||||||
|
Add(container = new MyContextMenuContainer
|
||||||
|
{
|
||||||
|
Size = new Vector2(200),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Green,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new AnotherContextMenuContainer
|
||||||
|
{
|
||||||
|
Size = new Vector2(200),
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Red,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
container.Transforms.Add(new TransformPosition
|
||||||
|
{
|
||||||
|
StartValue = Vector2.Zero,
|
||||||
|
EndValue = new Vector2(0, 100),
|
||||||
|
StartTime = start_time,
|
||||||
|
EndTime = start_time + duration,
|
||||||
|
LoopCount = -1,
|
||||||
|
LoopDelay = duration * 3
|
||||||
|
});
|
||||||
|
container.Transforms.Add(new TransformPosition
|
||||||
|
{
|
||||||
|
StartValue = new Vector2(0, 100),
|
||||||
|
EndValue = new Vector2(100, 100),
|
||||||
|
StartTime = start_time + duration,
|
||||||
|
EndTime = start_time + duration * 2,
|
||||||
|
LoopCount = -1,
|
||||||
|
LoopDelay = duration * 3
|
||||||
|
});
|
||||||
|
container.Transforms.Add(new TransformPosition
|
||||||
|
{
|
||||||
|
StartValue = new Vector2(100, 100),
|
||||||
|
EndValue = new Vector2(100, 0),
|
||||||
|
StartTime = start_time + duration * 2,
|
||||||
|
EndTime = start_time + duration * 3,
|
||||||
|
LoopCount = -1,
|
||||||
|
LoopDelay = duration * 3
|
||||||
|
});
|
||||||
|
container.Transforms.Add(new TransformPosition
|
||||||
|
{
|
||||||
|
StartValue = new Vector2(100, 0),
|
||||||
|
EndValue = Vector2.Zero,
|
||||||
|
StartTime = start_time + duration * 3,
|
||||||
|
EndTime = start_time + duration * 4,
|
||||||
|
LoopCount = -1,
|
||||||
|
LoopDelay = duration * 3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MyContextMenuContainer : Container, IHasContextMenu
|
||||||
|
{
|
||||||
|
public ContextMenuItem[] ContextMenuItems => new ContextMenuItem[]
|
||||||
|
{
|
||||||
|
new OsuContextMenuItem(@"Some option"),
|
||||||
|
new OsuContextMenuItem(@"Highlighted option", MenuItemType.Highlighted),
|
||||||
|
new OsuContextMenuItem(@"Another option"),
|
||||||
|
new OsuContextMenuItem(@"Choose me please"),
|
||||||
|
new OsuContextMenuItem(@"And me too"),
|
||||||
|
new OsuContextMenuItem(@"Trying to fill"),
|
||||||
|
new OsuContextMenuItem(@"Destructive option", MenuItemType.Destructive),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AnotherContextMenuContainer : Container, IHasContextMenu
|
||||||
|
{
|
||||||
|
public ContextMenuItem[] ContextMenuItems => new ContextMenuItem[]
|
||||||
|
{
|
||||||
|
new OsuContextMenuItem(@"Simple option"),
|
||||||
|
new OsuContextMenuItem(@"Simple very very long option"),
|
||||||
|
new OsuContextMenuItem(@"Change width", MenuItemType.Highlighted) { Action = () => ResizeWidthTo(Width * 2, 100, EasingTypes.OutQuint) },
|
||||||
|
new OsuContextMenuItem(@"Change height", MenuItemType.Highlighted) { Action = () => ResizeHeightTo(Height * 2, 100, EasingTypes.OutQuint) },
|
||||||
|
new OsuContextMenuItem(@"Change width back", MenuItemType.Destructive) { Action = () => ResizeWidthTo(Width / 2, 100, EasingTypes.OutQuint) },
|
||||||
|
new OsuContextMenuItem(@"Change height back", MenuItemType.Destructive) { Action = () => ResizeHeightTo(Height / 2, 100, EasingTypes.OutQuint) },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -79,7 +79,8 @@ namespace osu.Desktop.VisualTests.Tests
|
|||||||
{
|
{
|
||||||
score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
|
score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0);
|
||||||
comboCounter.Increment();
|
comboCounter.Increment();
|
||||||
numerator++; denominator++;
|
numerator++;
|
||||||
|
denominator++;
|
||||||
accuracyCounter.SetFraction(numerator, denominator);
|
accuracyCounter.SetFraction(numerator, denominator);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -87,11 +87,13 @@
|
|||||||
<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.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OpenTK, Version=2.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.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SharpCompress, Version=0.15.2.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
<Reference Include="SharpCompress, Version=0.17.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\SharpCompress.0.15.2\lib\net45\SharpCompress.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll</HintPath>
|
||||||
|
<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">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
@ -187,6 +189,7 @@
|
|||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Tests\TestCaseChatDisplay.cs" />
|
<Compile Include="Tests\TestCaseChatDisplay.cs" />
|
||||||
<Compile Include="Tests\TestCaseBeatmapDetails.cs" />
|
<Compile Include="Tests\TestCaseBeatmapDetails.cs" />
|
||||||
|
<Compile Include="Tests\TestCaseContextMenu.cs" />
|
||||||
<Compile Include="Tests\TestCaseDrawings.cs" />
|
<Compile Include="Tests\TestCaseDrawings.cs" />
|
||||||
<Compile Include="Tests\TestCaseGamefield.cs" />
|
<Compile Include="Tests\TestCaseGamefield.cs" />
|
||||||
<Compile Include="Tests\TestCaseGraph.cs" />
|
<Compile Include="Tests\TestCaseGraph.cs" />
|
||||||
|
@ -5,8 +5,8 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
|
|||||||
-->
|
-->
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
|
||||||
<package id="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
|
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||||
<package id="SharpCompress" version="0.15.2" targetFramework="net45" />
|
<package id="SharpCompress" version="0.17.1" targetFramework="net45" />
|
||||||
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
||||||
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
||||||
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
|
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net45" />
|
||||||
|
@ -121,18 +121,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.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OpenTK, Version=2.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.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SharpCompress, Version=0.17.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">
|
||||||
|
<HintPath>$(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll</HintPath>
|
||||||
|
<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.5.2.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Squirrel, Version=1.7.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.5.2\lib\Net45\Squirrel.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\Squirrel.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -7,7 +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="2.0.50727.1341" targetFramework="net45" />
|
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||||
|
<package id="SharpCompress" version="0.17.1" targetFramework="net45" />
|
||||||
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
<package id="Splat" version="2.0.0" targetFramework="net45" />
|
||||||
<package id="squirrel.windows" version="1.5.2" targetFramework="net45" />
|
<package id="squirrel.windows" version="1.7.5" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -33,8 +33,9 @@
|
|||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=2.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.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
@ -5,5 +5,5 @@ 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="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
|
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -448,7 +448,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
return curveData.RepeatSamples[index];
|
return curveData.RepeatSamples[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs and adds a note to a pattern.
|
/// Constructs and adds a note to a pattern.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -480,7 +479,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
Tail = { Samples = sampleInfoListAt(endTime) }
|
Tail = { Samples = sampleInfoListAt(endTime) }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
newObject = holdNote;
|
newObject = holdNote;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,5 @@ namespace osu.Game.Rulesets.Mania.MathUtils
|
|||||||
bitIndex++;
|
bitIndex++;
|
||||||
return ((bitBuffer >>= 1) & 1) == 1;
|
return ((bitBuffer >>= 1) & 1) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
{
|
{
|
||||||
base.AccentColour = value;
|
base.AccentColour = value;
|
||||||
|
|
||||||
glowContainer.EdgeEffect = new EdgeEffect
|
glowContainer.EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Radius = 2f,
|
Radius = 2f,
|
||||||
|
@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Mania.Timing
|
|||||||
public override void InvalidateFromChild(Invalidation invalidation)
|
public override void InvalidateFromChild(Invalidation invalidation)
|
||||||
{
|
{
|
||||||
// We only want to re-compute our size when a child's size or position has changed
|
// We only want to re-compute our size when a child's size or position has changed
|
||||||
if ((invalidation & Invalidation.Geometry) == 0)
|
if ((invalidation & Invalidation.RequiredParentSizeToFit) == 0)
|
||||||
{
|
{
|
||||||
base.InvalidateFromChild(invalidation);
|
base.InvalidateFromChild(invalidation);
|
||||||
return;
|
return;
|
||||||
|
@ -171,14 +171,14 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
background.Colour = accentColour;
|
background.Colour = accentColour;
|
||||||
|
|
||||||
hitTargetBar.EdgeEffect = new EdgeEffect
|
hitTargetBar.EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Radius = 5,
|
Radius = 5,
|
||||||
Colour = accentColour.Opacity(0.5f),
|
Colour = accentColour.Opacity(0.5f),
|
||||||
};
|
};
|
||||||
|
|
||||||
keyIcon.EdgeEffect = new EdgeEffect
|
keyIcon.EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Radius = 5,
|
Radius = 5,
|
||||||
|
@ -33,8 +33,9 @@
|
|||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=2.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.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
@ -5,5 +5,5 @@ 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="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
|
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
Masking = true;
|
Masking = true;
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
CornerRadius = width / 2;
|
CornerRadius = width / 2;
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Colour = Color4.White.Opacity(0.2f),
|
Colour = Color4.White.Opacity(0.2f),
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
{
|
{
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Radius = 60,
|
Radius = 60,
|
||||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
{
|
{
|
||||||
Disc.Colour = value;
|
Disc.Colour = value;
|
||||||
|
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Hollow = true,
|
Hollow = true,
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
{
|
{
|
||||||
Colour = Color4.Black,
|
Colour = Color4.Black,
|
||||||
Alpha = 0.4f,
|
Alpha = 0.4f,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Radius = 10,
|
Radius = 10,
|
||||||
|
@ -1,201 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using OpenTK;
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects
|
|
||||||
{
|
|
||||||
internal class OsuHitObjectDifficulty
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Factor by how much speed / aim strain decays per second.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// These values are results of tweaking a lot and taking into account general feedback.
|
|
||||||
/// Opinionated observation: Speed is easier to maintain than accurate jumps.
|
|
||||||
/// </remarks>
|
|
||||||
internal static readonly double[] DECAY_BASE = { 0.3, 0.15 };
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pseudo threshold values to distinguish between "singles" and "streams"
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Of course the border can not be defined clearly, therefore the algorithm has a smooth transition between those values.
|
|
||||||
/// They also are based on tweaking and general feedback.
|
|
||||||
/// </remarks>
|
|
||||||
private const double stream_spacing_threshold = 110,
|
|
||||||
single_spacing_threshold = 125;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Scaling values for weightings to keep aim and speed difficulty in balance.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Found from testing a very large map pool (containing all ranked maps) and keeping the average values the same.
|
|
||||||
/// </remarks>
|
|
||||||
private static readonly double[] spacing_weight_scaling = { 1400, 26.25 };
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Almost the normed diameter of a circle (104 osu pixel). That is -after- position transforming.
|
|
||||||
/// </summary>
|
|
||||||
private const double almost_diameter = 90;
|
|
||||||
|
|
||||||
internal OsuHitObject BaseHitObject;
|
|
||||||
internal double[] Strains = { 1, 1 };
|
|
||||||
|
|
||||||
internal int MaxCombo = 1;
|
|
||||||
|
|
||||||
private readonly float scalingFactor;
|
|
||||||
private float lazySliderLength;
|
|
||||||
|
|
||||||
private readonly Vector2 startPosition;
|
|
||||||
private readonly Vector2 endPosition;
|
|
||||||
|
|
||||||
internal OsuHitObjectDifficulty(OsuHitObject baseHitObject)
|
|
||||||
{
|
|
||||||
BaseHitObject = baseHitObject;
|
|
||||||
float circleRadius = baseHitObject.Scale * 64;
|
|
||||||
|
|
||||||
Slider slider = BaseHitObject as Slider;
|
|
||||||
if (slider != null)
|
|
||||||
MaxCombo += slider.Ticks.Count();
|
|
||||||
|
|
||||||
// We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
|
|
||||||
scalingFactor = 52.0f / circleRadius;
|
|
||||||
if (circleRadius < 30)
|
|
||||||
{
|
|
||||||
float smallCircleBonus = Math.Min(30.0f - circleRadius, 5.0f) / 50.0f;
|
|
||||||
scalingFactor *= 1.0f + smallCircleBonus;
|
|
||||||
}
|
|
||||||
|
|
||||||
lazySliderLength = 0;
|
|
||||||
startPosition = baseHitObject.StackedPosition;
|
|
||||||
|
|
||||||
// Calculate approximation of lazy movement on the slider
|
|
||||||
if (slider != null)
|
|
||||||
{
|
|
||||||
float sliderFollowCircleRadius = circleRadius * 3; // Not sure if this is correct, but here we do not need 100% exact values. This comes pretty darn close in my tests.
|
|
||||||
|
|
||||||
// For simplifying this step we use actual osu! coordinates and simply scale the length, that we obtain by the ScalingFactor later
|
|
||||||
Vector2 cursorPos = startPosition;
|
|
||||||
|
|
||||||
Action<Vector2> addSliderVertex = delegate (Vector2 pos)
|
|
||||||
{
|
|
||||||
Vector2 difference = pos - cursorPos;
|
|
||||||
float distance = difference.Length;
|
|
||||||
|
|
||||||
// Did we move away too far?
|
|
||||||
if (distance > sliderFollowCircleRadius)
|
|
||||||
{
|
|
||||||
// Yep, we need to move the cursor
|
|
||||||
difference.Normalize(); // Obtain the direction of difference. We do no longer need the actual difference
|
|
||||||
distance -= sliderFollowCircleRadius;
|
|
||||||
cursorPos += difference * distance; // We move the cursor just as far as needed to stay in the follow circle
|
|
||||||
lazySliderLength += distance;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Actual computation of the first lazy curve
|
|
||||||
foreach (var tick in slider.Ticks)
|
|
||||||
addSliderVertex(tick.StackedPosition);
|
|
||||||
|
|
||||||
addSliderVertex(baseHitObject.StackedEndPosition);
|
|
||||||
|
|
||||||
lazySliderLength *= scalingFactor;
|
|
||||||
endPosition = cursorPos;
|
|
||||||
}
|
|
||||||
// We have a normal HitCircle or a spinner
|
|
||||||
else
|
|
||||||
endPosition = startPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void CalculateStrains(OsuHitObjectDifficulty previousHitObject, double timeRate)
|
|
||||||
{
|
|
||||||
calculateSpecificStrain(previousHitObject, OsuDifficultyCalculator.DifficultyType.Speed, timeRate);
|
|
||||||
calculateSpecificStrain(previousHitObject, OsuDifficultyCalculator.DifficultyType.Aim, timeRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Caution: The subjective values are strong with this one
|
|
||||||
private static double spacingWeight(double distance, OsuDifficultyCalculator.DifficultyType type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case OsuDifficultyCalculator.DifficultyType.Speed:
|
|
||||||
if (distance > single_spacing_threshold)
|
|
||||||
return 2.5;
|
|
||||||
else if (distance > stream_spacing_threshold)
|
|
||||||
return 1.6 + 0.9 * (distance - stream_spacing_threshold) / (single_spacing_threshold - stream_spacing_threshold);
|
|
||||||
else if (distance > almost_diameter)
|
|
||||||
return 1.2 + 0.4 * (distance - almost_diameter) / (stream_spacing_threshold - almost_diameter);
|
|
||||||
else if (distance > almost_diameter / 2)
|
|
||||||
return 0.95 + 0.25 * (distance - almost_diameter / 2) / (almost_diameter / 2);
|
|
||||||
else
|
|
||||||
return 0.95;
|
|
||||||
|
|
||||||
case OsuDifficultyCalculator.DifficultyType.Aim:
|
|
||||||
return Math.Pow(distance, 0.99);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.Assert(false, "Invalid osu difficulty hit object type.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateSpecificStrain(OsuHitObjectDifficulty previousHitObject, OsuDifficultyCalculator.DifficultyType type, double timeRate)
|
|
||||||
{
|
|
||||||
double addition = 0;
|
|
||||||
double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate;
|
|
||||||
double decay = Math.Pow(DECAY_BASE[(int)type], timeElapsed / 1000);
|
|
||||||
|
|
||||||
if (BaseHitObject is Spinner)
|
|
||||||
{
|
|
||||||
// Do nothing for spinners
|
|
||||||
}
|
|
||||||
else if (BaseHitObject is Slider)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case OsuDifficultyCalculator.DifficultyType.Speed:
|
|
||||||
|
|
||||||
// For speed strain we treat the whole slider as a single spacing entity, since "Speed" is about how hard it is to click buttons fast.
|
|
||||||
// The spacing weight exists to differentiate between being able to easily alternate or having to single.
|
|
||||||
addition =
|
|
||||||
spacingWeight(previousHitObject.lazySliderLength +
|
|
||||||
DistanceTo(previousHitObject), type) *
|
|
||||||
spacing_weight_scaling[(int)type];
|
|
||||||
|
|
||||||
break;
|
|
||||||
case OsuDifficultyCalculator.DifficultyType.Aim:
|
|
||||||
|
|
||||||
// For Aim strain we treat each slider segment and the jump after the end of the slider as separate jumps, since movement-wise there is no difference
|
|
||||||
// to multiple jumps.
|
|
||||||
addition =
|
|
||||||
(
|
|
||||||
spacingWeight(previousHitObject.lazySliderLength, type) +
|
|
||||||
spacingWeight(DistanceTo(previousHitObject), type)
|
|
||||||
) *
|
|
||||||
spacing_weight_scaling[(int)type];
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (BaseHitObject is HitCircle)
|
|
||||||
{
|
|
||||||
addition = spacingWeight(DistanceTo(previousHitObject), type) * spacing_weight_scaling[(int)type];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scale addition by the time, that elapsed. Filter out HitObjects that are too close to be played anyway to avoid crazy values by division through close to zero.
|
|
||||||
// You will never find maps that require this amongst ranked maps.
|
|
||||||
addition /= Math.Max(timeElapsed, 50);
|
|
||||||
|
|
||||||
Strains[(int)type] = previousHitObject.Strains[(int)type] * decay + addition;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal double DistanceTo(OsuHitObjectDifficulty other)
|
|
||||||
{
|
|
||||||
// Scale the distance by circle size.
|
|
||||||
return (startPosition - other.endPosition).Length * scalingFactor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,73 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing;
|
||||||
|
using osu.Game.Rulesets.Osu.OsuDifficulty.Skills;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.OsuDifficulty
|
||||||
|
{
|
||||||
|
public class OsuDifficultyCalculator : DifficultyCalculator<OsuHitObject>
|
||||||
|
{
|
||||||
|
private const int section_length = 400;
|
||||||
|
private const double difficulty_multiplier = 0.0675;
|
||||||
|
|
||||||
|
public OsuDifficultyCalculator(Beatmap beatmap) : base(beatmap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PreprocessHitObjects()
|
||||||
|
{
|
||||||
|
foreach (OsuHitObject h in Objects)
|
||||||
|
(h as Slider)?.Curve?.Calculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
|
||||||
|
{
|
||||||
|
OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap(Objects);
|
||||||
|
Skill[] skills =
|
||||||
|
{
|
||||||
|
new Aim(),
|
||||||
|
new Speed()
|
||||||
|
};
|
||||||
|
|
||||||
|
double sectionEnd = section_length / TimeRate;
|
||||||
|
foreach (OsuDifficultyHitObject h in beatmap)
|
||||||
|
{
|
||||||
|
while (h.BaseObject.StartTime > sectionEnd)
|
||||||
|
{
|
||||||
|
foreach (Skill s in skills)
|
||||||
|
{
|
||||||
|
s.SaveCurrentPeak();
|
||||||
|
s.StartNewSectionFrom(sectionEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sectionEnd += section_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Skill s in skills)
|
||||||
|
s.Process(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier;
|
||||||
|
double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
|
||||||
|
|
||||||
|
double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2;
|
||||||
|
|
||||||
|
if (categoryDifficulty != null)
|
||||||
|
{
|
||||||
|
categoryDifficulty.Add("Aim", aimRating.ToString("0.00"));
|
||||||
|
categoryDifficulty.Add("Speed", speedRating.ToString("0.00"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return starRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
// 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An enumerable container wrapping <see cref="OsuHitObject"/> input as <see cref="OsuDifficultyHitObject"/>
|
||||||
|
/// which contains extra data required for difficulty calculation.
|
||||||
|
/// </summary>
|
||||||
|
public class OsuDifficultyBeatmap : IEnumerable<OsuDifficultyHitObject>
|
||||||
|
{
|
||||||
|
private readonly IEnumerator<OsuDifficultyHitObject> difficultyObjects;
|
||||||
|
private readonly Queue<OsuDifficultyHitObject> onScreen = new Queue<OsuDifficultyHitObject>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an enumerator, which preprocesses a list of <see cref="OsuHitObject"/>s recieved as input, wrapping them as
|
||||||
|
/// <see cref="OsuDifficultyHitObject"/> which contains extra data required for difficulty calculation.
|
||||||
|
/// </summary>
|
||||||
|
public OsuDifficultyBeatmap(List<OsuHitObject> objects)
|
||||||
|
{
|
||||||
|
// Sort OsuHitObjects by StartTime - they are not correctly ordered in some cases.
|
||||||
|
// This should probably happen before the objects reach the difficulty calculator.
|
||||||
|
objects.Sort((a, b) => a.StartTime.CompareTo(b.StartTime));
|
||||||
|
difficultyObjects = createDifficultyObjectEnumerator(objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an enumerator that enumerates all <see cref="OsuDifficultyHitObject"/>s in the <see cref="OsuDifficultyBeatmap"/>.
|
||||||
|
/// The inner loop adds objects that appear on screen into a queue until we need to hit the next object.
|
||||||
|
/// The outer loop returns objects from this queue one at a time, only after they had to be hit, and should no longer be on screen.
|
||||||
|
/// This means that we can loop through every object that is on screen at the time when a new one appears,
|
||||||
|
/// allowing us to determine a reading strain for the object that just appeared.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerator<OsuDifficultyHitObject> GetEnumerator()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Add upcoming objects to the queue until we have at least one object that had been hit and can be dequeued.
|
||||||
|
// This means there is always at least one object in the queue unless we reached the end of the map.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!difficultyObjects.MoveNext())
|
||||||
|
break; // New objects can't be added anymore, but we still need to dequeue and return the ones already on screen.
|
||||||
|
|
||||||
|
OsuDifficultyHitObject latest = difficultyObjects.Current;
|
||||||
|
// Calculate flow values here
|
||||||
|
|
||||||
|
foreach (OsuDifficultyHitObject h in onScreen)
|
||||||
|
{
|
||||||
|
h.TimeUntilHit -= latest.DeltaTime;
|
||||||
|
// Calculate reading strain here
|
||||||
|
}
|
||||||
|
|
||||||
|
onScreen.Enqueue(latest);
|
||||||
|
}
|
||||||
|
while (onScreen.Peek().TimeUntilHit > 0); // Keep adding new objects on screen while there is still time before we have to hit the next one.
|
||||||
|
|
||||||
|
if (onScreen.Count == 0) break; // We have reached the end of the map and enumerated all the objects.
|
||||||
|
yield return onScreen.Dequeue(); // Remove and return objects one by one that had to be hit before the latest one appeared.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
|
private IEnumerator<OsuDifficultyHitObject> createDifficultyObjectEnumerator(List<OsuHitObject> objects)
|
||||||
|
{
|
||||||
|
// We will process OsuHitObjects in groups of three to form a triangle, so we can calculate an angle for each object.
|
||||||
|
OsuHitObject[] triangle = new OsuHitObject[3];
|
||||||
|
|
||||||
|
// OsuDifficultyHitObject construction requires three components, an extra copy of the first OsuHitObject is used at the beginning.
|
||||||
|
if (objects.Count > 1)
|
||||||
|
{
|
||||||
|
triangle[1] = objects[0]; // This copy will get shifted to the last spot in the triangle.
|
||||||
|
triangle[0] = objects[0]; // This component corresponds to the real first OsuHitOject.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The final component of the first triangle will be the second OsuHitOject of the map, which forms the first jump.
|
||||||
|
// If the map has less than two OsuHitObjects, the enumerator will not return anything.
|
||||||
|
for (int i = 1; i < objects.Count; ++i)
|
||||||
|
{
|
||||||
|
triangle[2] = triangle[1];
|
||||||
|
triangle[1] = triangle[0];
|
||||||
|
triangle[0] = objects[i];
|
||||||
|
|
||||||
|
yield return new OsuDifficultyHitObject(triangle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A wrapper around <see cref="OsuHitObject"/> extending it with additional data required for difficulty calculation.
|
||||||
|
/// </summary>
|
||||||
|
public class OsuDifficultyHitObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="OsuHitObject"/> this <see cref="OsuDifficultyHitObject"/> refers to.
|
||||||
|
/// </summary>
|
||||||
|
public OsuHitObject BaseObject { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalized distance from the <see cref="OsuHitObject.StackedPosition"/> of the previous <see cref="OsuDifficultyHitObject"/>.
|
||||||
|
/// </summary>
|
||||||
|
public double Distance { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Milliseconds elapsed since the StartTime of the previous <see cref="OsuDifficultyHitObject"/>.
|
||||||
|
/// </summary>
|
||||||
|
public double DeltaTime { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of milliseconds until the <see cref="OsuDifficultyHitObject"/> has to be hit.
|
||||||
|
/// </summary>
|
||||||
|
public double TimeUntilHit { get; set; }
|
||||||
|
|
||||||
|
private const int normalized_radius = 52;
|
||||||
|
|
||||||
|
private readonly OsuHitObject[] t;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the object calculating extra data required for difficulty calculation.
|
||||||
|
/// </summary>
|
||||||
|
public OsuDifficultyHitObject(OsuHitObject[] triangle)
|
||||||
|
{
|
||||||
|
t = triangle;
|
||||||
|
BaseObject = t[0];
|
||||||
|
setDistances();
|
||||||
|
setTimingValues();
|
||||||
|
// Calculate angle here
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDistances()
|
||||||
|
{
|
||||||
|
// We will scale distances by this factor, so we can assume a uniform CircleSize among beatmaps.
|
||||||
|
double scalingFactor = normalized_radius / BaseObject.Radius;
|
||||||
|
if (BaseObject.Radius < 30)
|
||||||
|
{
|
||||||
|
double smallCircleBonus = Math.Min(30 - BaseObject.Radius, 5) / 50;
|
||||||
|
scalingFactor *= 1 + smallCircleBonus;
|
||||||
|
}
|
||||||
|
|
||||||
|
Distance = (t[0].StackedPosition - t[1].StackedPosition).Length * scalingFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTimingValues()
|
||||||
|
{
|
||||||
|
// Every timing inverval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure.
|
||||||
|
DeltaTime = Math.Max(40, t[0].StartTime - t[1].StartTime);
|
||||||
|
TimeUntilHit = 450; // BaseObject.PreEmpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs
Normal file
19
osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.OsuDifficulty.Skills
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances.
|
||||||
|
/// </summary>
|
||||||
|
public class Aim : Skill
|
||||||
|
{
|
||||||
|
protected override double SkillMultiplier => 26.25;
|
||||||
|
protected override double StrainDecayBase => 0.15;
|
||||||
|
|
||||||
|
protected override double StrainValueOf(OsuDifficultyHitObject current) => Math.Pow(current.Distance, 0.99) / current.DeltaTime;
|
||||||
|
}
|
||||||
|
}
|
100
osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs
Normal file
100
osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing;
|
||||||
|
using osu.Game.Rulesets.Osu.OsuDifficulty.Utils;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.OsuDifficulty.Skills
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Used to processes strain values of <see cref="OsuDifficultyHitObject"/>s, keep track of strain levels caused by the processed objects
|
||||||
|
/// and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Skill
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract double SkillMultiplier { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines how quickly strain decays for the given skill.
|
||||||
|
/// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract double StrainDecayBase { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="OsuDifficultyHitObject"/>s that were processed previously. They can affect the strain values of the following objects.
|
||||||
|
/// </summary>
|
||||||
|
protected readonly History<OsuDifficultyHitObject> Previous = new History<OsuDifficultyHitObject>(2); // Contained objects not used yet
|
||||||
|
|
||||||
|
private double currentStrain = 1; // We keep track of the strain level at all times throughout the beatmap.
|
||||||
|
private double currentSectionPeak = 1; // We also keep track of the peak strain level in the current section.
|
||||||
|
private readonly List<double> strainPeaks = new List<double>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process an <see cref="OsuDifficultyHitObject"/> and update current strain values accordingly.
|
||||||
|
/// </summary>
|
||||||
|
public void Process(OsuDifficultyHitObject current)
|
||||||
|
{
|
||||||
|
currentStrain *= strainDecay(current.DeltaTime);
|
||||||
|
if (!(current.BaseObject is Spinner))
|
||||||
|
currentStrain += StrainValueOf(current) * SkillMultiplier;
|
||||||
|
|
||||||
|
currentSectionPeak = Math.Max(currentStrain, currentSectionPeak);
|
||||||
|
|
||||||
|
Previous.Push(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the current peak strain level to the list of strain peaks, which will be used to calculate an overall difficulty.
|
||||||
|
/// </summary>
|
||||||
|
public void SaveCurrentPeak()
|
||||||
|
{
|
||||||
|
if (Previous.Count > 0)
|
||||||
|
strainPeaks.Add(currentSectionPeak);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the initial strain level for a new section.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">The beginning of the new section in milliseconds</param>
|
||||||
|
public void StartNewSectionFrom(double offset)
|
||||||
|
{
|
||||||
|
// The maximum strain of the new section is not zero by default, strain decays as usual regardless of section boundaries.
|
||||||
|
// This means we need to capture the strain level at the beginning of the new section, and use that as the initial peak level.
|
||||||
|
if (Previous.Count > 0)
|
||||||
|
currentSectionPeak = currentStrain * strainDecay(offset - Previous[0].BaseObject.StartTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the calculated difficulty value representing all processed <see cref="OsuDifficultyHitObject"/>s.
|
||||||
|
/// </summary>
|
||||||
|
public double DifficultyValue()
|
||||||
|
{
|
||||||
|
strainPeaks.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain.
|
||||||
|
|
||||||
|
double difficulty = 0;
|
||||||
|
double weight = 1;
|
||||||
|
|
||||||
|
// Difficulty is the weighted sum of the highest strains from every section.
|
||||||
|
foreach (double strain in strainPeaks)
|
||||||
|
{
|
||||||
|
difficulty += strain * weight;
|
||||||
|
weight *= 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
return difficulty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the strain value of an <see cref="OsuDifficultyHitObject"/>. This value is affected by previously processed objects.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract double StrainValueOf(OsuDifficultyHitObject current);
|
||||||
|
|
||||||
|
private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000);
|
||||||
|
}
|
||||||
|
}
|
39
osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs
Normal file
39
osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.OsuDifficulty.Skills
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the skill required to press keys with regards to keeping up with the speed at which objects need to be hit.
|
||||||
|
/// </summary>
|
||||||
|
public class Speed : Skill
|
||||||
|
{
|
||||||
|
protected override double SkillMultiplier => 1400;
|
||||||
|
protected override double StrainDecayBase => 0.3;
|
||||||
|
|
||||||
|
private const double single_spacing_threshold = 125;
|
||||||
|
private const double stream_spacing_threshold = 110;
|
||||||
|
private const double almost_diameter = 90;
|
||||||
|
|
||||||
|
protected override double StrainValueOf(OsuDifficultyHitObject current)
|
||||||
|
{
|
||||||
|
double distance = current.Distance;
|
||||||
|
|
||||||
|
double speedValue;
|
||||||
|
if (distance > single_spacing_threshold)
|
||||||
|
speedValue = 2.5;
|
||||||
|
else if (distance > stream_spacing_threshold)
|
||||||
|
speedValue = 1.6 + 0.9 * (distance - stream_spacing_threshold) / (single_spacing_threshold - stream_spacing_threshold);
|
||||||
|
else if (distance > almost_diameter)
|
||||||
|
speedValue = 1.2 + 0.4 * (distance - almost_diameter) / (stream_spacing_threshold - almost_diameter);
|
||||||
|
else if (distance > almost_diameter / 2)
|
||||||
|
speedValue = 0.95 + 0.25 * (distance - almost_diameter / 2) / (almost_diameter / 2);
|
||||||
|
else
|
||||||
|
speedValue = 0.95;
|
||||||
|
|
||||||
|
return speedValue / current.DeltaTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs
Normal file
86
osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.OsuDifficulty.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An indexed stack with Push() only, which disposes items at the bottom after the capacity is full.
|
||||||
|
/// Indexing starts at the top of the stack.
|
||||||
|
/// </summary>
|
||||||
|
public class History<T> : IEnumerable<T>
|
||||||
|
{
|
||||||
|
public int Count { get; private set; }
|
||||||
|
|
||||||
|
private readonly T[] array;
|
||||||
|
private readonly int capacity;
|
||||||
|
private int marker; // Marks the position of the most recently added item.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the History class that is empty and has the specified capacity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="capacity">The number of items the History can hold.</param>
|
||||||
|
public History(int capacity)
|
||||||
|
{
|
||||||
|
if (capacity < 0)
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
|
||||||
|
this.capacity = capacity;
|
||||||
|
array = new T[capacity];
|
||||||
|
marker = capacity; // Set marker to the end of the array, outside of the indexed range by one.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The most recently added item is returned at index 0.
|
||||||
|
/// </summary>
|
||||||
|
public T this[int i]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (i < 0 || i > Count - 1)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
i += marker;
|
||||||
|
if (i > capacity - 1)
|
||||||
|
i -= capacity;
|
||||||
|
|
||||||
|
return array[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the item as the most recent one in the history.
|
||||||
|
/// The oldest item is disposed if the history is full.
|
||||||
|
/// </summary>
|
||||||
|
public void Push(T item) // Overwrite the oldest item instead of shifting every item by one with every addition.
|
||||||
|
{
|
||||||
|
if (marker == 0)
|
||||||
|
marker = capacity - 1;
|
||||||
|
else
|
||||||
|
--marker;
|
||||||
|
|
||||||
|
array[marker] = item;
|
||||||
|
|
||||||
|
if (Count < capacity)
|
||||||
|
++Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an enumerator which enumerates items in the history starting from the most recently added one.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerator<T> GetEnumerator()
|
||||||
|
{
|
||||||
|
for (int i = marker; i < capacity; ++i)
|
||||||
|
yield return array[i];
|
||||||
|
|
||||||
|
if (Count == capacity)
|
||||||
|
for (int i = 0; i < marker; ++i)
|
||||||
|
yield return array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
@ -1,192 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu
|
|
||||||
{
|
|
||||||
public class OsuDifficultyCalculator : DifficultyCalculator<OsuHitObject>
|
|
||||||
{
|
|
||||||
private const double star_scaling_factor = 0.0675;
|
|
||||||
private const double extreme_scaling_factor = 0.5;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// HitObjects are stored as a member variable.
|
|
||||||
/// </summary>
|
|
||||||
internal List<OsuHitObjectDifficulty> DifficultyHitObjects = new List<OsuHitObjectDifficulty>();
|
|
||||||
|
|
||||||
public OsuDifficultyCalculator(Beatmap beatmap) : base(beatmap)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void PreprocessHitObjects()
|
|
||||||
{
|
|
||||||
foreach (var h in Objects)
|
|
||||||
(h as Slider)?.Curve?.Calculate();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
|
|
||||||
{
|
|
||||||
// Fill our custom DifficultyHitObject class, that carries additional information
|
|
||||||
DifficultyHitObjects.Clear();
|
|
||||||
|
|
||||||
foreach (var hitObject in Objects)
|
|
||||||
DifficultyHitObjects.Add(new OsuHitObjectDifficulty(hitObject));
|
|
||||||
|
|
||||||
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
|
|
||||||
DifficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
|
|
||||||
|
|
||||||
if (!CalculateStrainValues()) return 0;
|
|
||||||
|
|
||||||
double speedDifficulty = CalculateDifficulty(DifficultyType.Speed);
|
|
||||||
double aimDifficulty = CalculateDifficulty(DifficultyType.Aim);
|
|
||||||
|
|
||||||
// OverallDifficulty is not considered in this algorithm and neither is HpDrainRate. That means, that in this form the algorithm determines how hard it physically is
|
|
||||||
// to play the map, assuming, that too much of an error will not lead to a death.
|
|
||||||
// It might be desirable to include OverallDifficulty into map difficulty, but in my personal opinion it belongs more to the weighting of the actual peformance
|
|
||||||
// and is superfluous in the beatmap difficulty rating.
|
|
||||||
// If it were to be considered, then I would look at the hit window of normal HitCircles only, since Sliders and Spinners are (almost) "free" 300s and take map length
|
|
||||||
// into account as well.
|
|
||||||
|
|
||||||
// The difficulty can be scaled by any desired metric.
|
|
||||||
// In osu!tp it gets squared to account for the rapid increase in difficulty as the limit of a human is approached. (Of course it also gets scaled afterwards.)
|
|
||||||
// It would not be suitable for a star rating, therefore:
|
|
||||||
|
|
||||||
// The following is a proposal to forge a star rating from 0 to 5. It consists of taking the square root of the difficulty, since by simply scaling the easier
|
|
||||||
// 5-star maps would end up with one star.
|
|
||||||
double speedStars = Math.Sqrt(speedDifficulty) * star_scaling_factor;
|
|
||||||
double aimStars = Math.Sqrt(aimDifficulty) * star_scaling_factor;
|
|
||||||
|
|
||||||
if (categoryDifficulty != null)
|
|
||||||
{
|
|
||||||
categoryDifficulty.Add("Aim", aimStars.ToString("0.00"));
|
|
||||||
categoryDifficulty.Add("Speed", speedStars.ToString("0.00"));
|
|
||||||
|
|
||||||
double hitWindow300 = 30/*HitObjectManager.HitWindow300*/ / TimeRate;
|
|
||||||
double preEmpt = 450/*HitObjectManager.PreEmpt*/ / TimeRate;
|
|
||||||
|
|
||||||
categoryDifficulty.Add("OD", (-(hitWindow300 - 80.0) / 6.0).ToString("0.00"));
|
|
||||||
categoryDifficulty.Add("AR", (preEmpt > 1200.0 ? -(preEmpt - 1800.0) / 120.0 : -(preEmpt - 1200.0) / 150.0 + 5.0).ToString("0.00"));
|
|
||||||
|
|
||||||
int maxCombo = 0;
|
|
||||||
foreach (OsuHitObjectDifficulty hitObject in DifficultyHitObjects)
|
|
||||||
maxCombo += hitObject.MaxCombo;
|
|
||||||
|
|
||||||
categoryDifficulty.Add("Max combo", maxCombo.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Again, from own observations and from the general opinion of the community a map with high speed and low aim (or vice versa) difficulty is harder,
|
|
||||||
// than a map with mediocre difficulty in both. Therefore we can not just add both difficulties together, but will introduce a scaling that favors extremes.
|
|
||||||
double starRating = speedStars + aimStars + Math.Abs(speedStars - aimStars) * extreme_scaling_factor;
|
|
||||||
// Another approach to this would be taking Speed and Aim separately to a chosen power, which again would be equivalent. This would be more convenient if
|
|
||||||
// the hit window size is to be considered as well.
|
|
||||||
|
|
||||||
// Note: The star rating is tuned extremely tight! Airman (/b/104229) and Freedom Dive (/b/126645), two of the hardest ranked maps, both score ~4.66 stars.
|
|
||||||
// Expect the easier kind of maps that officially get 5 stars to obtain around 2 by this metric. The tutorial still scores about half a star.
|
|
||||||
// Tune by yourself as you please. ;)
|
|
||||||
|
|
||||||
return starRating;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool CalculateStrainValues()
|
|
||||||
{
|
|
||||||
// Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment.
|
|
||||||
using (List<OsuHitObjectDifficulty>.Enumerator hitObjectsEnumerator = DifficultyHitObjects.GetEnumerator())
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!hitObjectsEnumerator.MoveNext()) return false;
|
|
||||||
|
|
||||||
OsuHitObjectDifficulty current = hitObjectsEnumerator.Current;
|
|
||||||
|
|
||||||
// First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject.
|
|
||||||
while (hitObjectsEnumerator.MoveNext())
|
|
||||||
{
|
|
||||||
var next = hitObjectsEnumerator.Current;
|
|
||||||
next?.CalculateStrains(current, TimeRate);
|
|
||||||
current = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size STRAIN_STEP.
|
|
||||||
/// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain.
|
|
||||||
/// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage.
|
|
||||||
/// </summary>
|
|
||||||
protected const double STRAIN_STEP = 400;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The weighting of each strain value decays to this number * it's previous value
|
|
||||||
/// </summary>
|
|
||||||
protected const double DECAY_WEIGHT = 0.9;
|
|
||||||
|
|
||||||
protected double CalculateDifficulty(DifficultyType type)
|
|
||||||
{
|
|
||||||
double actualStrainStep = STRAIN_STEP * TimeRate;
|
|
||||||
|
|
||||||
// Find the highest strain value within each strain step
|
|
||||||
List<double> highestStrains = new List<double>();
|
|
||||||
double intervalEndTime = actualStrainStep;
|
|
||||||
double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval
|
|
||||||
|
|
||||||
OsuHitObjectDifficulty previousHitObject = null;
|
|
||||||
foreach (OsuHitObjectDifficulty hitObject in DifficultyHitObjects)
|
|
||||||
{
|
|
||||||
// While we are beyond the current interval push the currently available maximum to our strain list
|
|
||||||
while (hitObject.BaseHitObject.StartTime > intervalEndTime)
|
|
||||||
{
|
|
||||||
highestStrains.Add(maximumStrain);
|
|
||||||
|
|
||||||
// The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay
|
|
||||||
// until the beginning of the next interval.
|
|
||||||
if (previousHitObject == null)
|
|
||||||
{
|
|
||||||
maximumStrain = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double decay = Math.Pow(OsuHitObjectDifficulty.DECAY_BASE[(int)type], (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000);
|
|
||||||
maximumStrain = previousHitObject.Strains[(int)type] * decay;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go to the next time interval
|
|
||||||
intervalEndTime += actualStrainStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtain maximum strain
|
|
||||||
maximumStrain = Math.Max(hitObject.Strains[(int)type], maximumStrain);
|
|
||||||
|
|
||||||
previousHitObject = hitObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the weighted sum over the highest strains for each interval
|
|
||||||
double difficulty = 0;
|
|
||||||
double weight = 1;
|
|
||||||
highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain.
|
|
||||||
|
|
||||||
foreach (double strain in highestStrains)
|
|
||||||
{
|
|
||||||
difficulty += weight * strain;
|
|
||||||
weight *= DECAY_WEIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return difficulty;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter();
|
|
||||||
|
|
||||||
// Those values are used as array indices. Be careful when changing them!
|
|
||||||
public enum DifficultyType
|
|
||||||
{
|
|
||||||
Speed = 0,
|
|
||||||
Aim,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,6 +7,7 @@ using osu.Game.Graphics;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.OsuDifficulty;
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
@ -34,8 +34,9 @@
|
|||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=2.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.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
@ -68,9 +69,14 @@
|
|||||||
<Compile Include="Objects\Drawables\Pieces\TrianglesPiece.cs" />
|
<Compile Include="Objects\Drawables\Pieces\TrianglesPiece.cs" />
|
||||||
<Compile Include="Objects\Drawables\Pieces\SliderBall.cs" />
|
<Compile Include="Objects\Drawables\Pieces\SliderBall.cs" />
|
||||||
<Compile Include="Objects\Drawables\Pieces\SliderBody.cs" />
|
<Compile Include="Objects\Drawables\Pieces\SliderBody.cs" />
|
||||||
<Compile Include="Objects\OsuHitObjectDifficulty.cs" />
|
|
||||||
<Compile Include="Objects\SliderTick.cs" />
|
<Compile Include="Objects\SliderTick.cs" />
|
||||||
<Compile Include="OsuDifficultyCalculator.cs" />
|
<Compile Include="OsuDifficulty\OsuDifficultyCalculator.cs" />
|
||||||
|
<Compile Include="OsuDifficulty\Preprocessing\OsuDifficultyBeatmap.cs" />
|
||||||
|
<Compile Include="OsuDifficulty\Preprocessing\OsuDifficultyHitObject.cs" />
|
||||||
|
<Compile Include="OsuDifficulty\Skills\Aim.cs" />
|
||||||
|
<Compile Include="OsuDifficulty\Skills\Skill.cs" />
|
||||||
|
<Compile Include="OsuDifficulty\Skills\Speed.cs" />
|
||||||
|
<Compile Include="OsuDifficulty\Utils\History.cs" />
|
||||||
<Compile Include="OsuKeyConversionInputManager.cs" />
|
<Compile Include="OsuKeyConversionInputManager.cs" />
|
||||||
<Compile Include="Scoring\OsuScoreProcessor.cs" />
|
<Compile Include="Scoring\OsuScoreProcessor.cs" />
|
||||||
<Compile Include="UI\OsuHitRenderer.cs" />
|
<Compile Include="UI\OsuHitRenderer.cs" />
|
||||||
|
@ -5,5 +5,5 @@ 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="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
|
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
private void resetEdgeEffects()
|
private void resetEdgeEffects()
|
||||||
{
|
{
|
||||||
background.EdgeEffect = new EdgeEffect
|
background.EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Colour = AccentColour.Opacity(KiaiMode ? edge_alpha_kiai : 1f),
|
Colour = AccentColour.Opacity(KiaiMode ? edge_alpha_kiai : 1f),
|
||||||
|
@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Colour = isRim ? colours.BlueDarker : colours.PinkDarker,
|
Colour = isRim ? colours.BlueDarker : colours.PinkDarker,
|
||||||
|
@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
BorderThickness = 2,
|
BorderThickness = 2,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
Colour = Color4.Black.Opacity(0.2f),
|
||||||
@ -229,7 +229,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
if (judgedObject.HitObject.Kiai)
|
if (judgedObject.HitObject.Kiai)
|
||||||
kiaiExplosionContainer.Add(new KiaiHitExplosion(judgedObject.Judgement, isRim));
|
kiaiExplosionContainer.Add(new KiaiHitExplosion(judgedObject.Judgement, isRim));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hitExplosionContainer.Children.FirstOrDefault(e => e.Judgement == judgedObject.Judgement)?.VisualiseSecondHit();
|
hitExplosionContainer.Children.FirstOrDefault(e => e.Judgement == judgedObject.Judgement)?.VisualiseSecondHit();
|
||||||
|
@ -33,8 +33,9 @@
|
|||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=2.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.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
@ -4,5 +4,5 @@ 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="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
|
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -166,4 +166,3 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,4 +86,3 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +30,13 @@
|
|||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="nunit.framework, Version=3.6.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
<Reference Include="nunit.framework, Version=3.7.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OpenTK, Version=2.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.2.0.50727.1341\lib\net45\OpenTK.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="SQLite.Net">
|
<Reference Include="SQLite.Net">
|
||||||
|
@ -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.6.1" targetFramework="net45" />
|
<package id="NUnit" version="3.7.1" targetFramework="net45" />
|
||||||
<package id="ppy.OpenTK" version="2.0.50727.1341" targetFramework="net45" />
|
<package id="ppy.OpenTK" version="3.0" targetFramework="net45" />
|
||||||
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
<package id="SQLite.Net.Core-PCL" version="3.1.1" targetFramework="net45" />
|
||||||
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
<package id="SQLite.Net-PCL" version="3.1.1" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -10,7 +10,6 @@ using OpenTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Beatmaps.Drawables
|
namespace osu.Game.Beatmaps.Drawables
|
||||||
{
|
{
|
||||||
|
|
||||||
public class DifficultyIcon : DifficultyColouredContainer
|
public class DifficultyIcon : DifficultyColouredContainer
|
||||||
{
|
{
|
||||||
private readonly BeatmapInfo beatmap;
|
private readonly BeatmapInfo beatmap;
|
||||||
|
@ -88,7 +88,7 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
protected virtual void Selected()
|
protected virtual void Selected()
|
||||||
{
|
{
|
||||||
nestedContainer.BorderThickness = 2.5f;
|
nestedContainer.BorderThickness = 2.5f;
|
||||||
nestedContainer.EdgeEffect = new EdgeEffect
|
nestedContainer.EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Colour = new Color4(130, 204, 255, 150),
|
Colour = new Color4(130, 204, 255, 150),
|
||||||
@ -100,7 +100,7 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
protected virtual void Deselected()
|
protected virtual void Deselected()
|
||||||
{
|
{
|
||||||
nestedContainer.BorderThickness = 0;
|
nestedContainer.BorderThickness = 0;
|
||||||
nestedContainer.EdgeEffect = new EdgeEffect
|
nestedContainer.EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Offset = new Vector2(1),
|
Offset = new Vector2(1),
|
||||||
|
@ -13,7 +13,6 @@ namespace osu.Game.Configuration
|
|||||||
protected override void InitialiseDefaults()
|
protected override void InitialiseDefaults()
|
||||||
{
|
{
|
||||||
// UI/selection defaults
|
// UI/selection defaults
|
||||||
|
|
||||||
Set(OsuSetting.Ruleset, 0, 0, int.MaxValue);
|
Set(OsuSetting.Ruleset, 0, 0, int.MaxValue);
|
||||||
Set(OsuSetting.BeatmapDetailTab, BeatmapDetailTab.Details);
|
Set(OsuSetting.BeatmapDetailTab, BeatmapDetailTab.Details);
|
||||||
|
|
||||||
@ -25,7 +24,6 @@ namespace osu.Game.Configuration
|
|||||||
Set(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2, 1);
|
Set(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2, 1);
|
||||||
|
|
||||||
// Online settings
|
// Online settings
|
||||||
|
|
||||||
Set(OsuSetting.Username, string.Empty);
|
Set(OsuSetting.Username, string.Empty);
|
||||||
Set(OsuSetting.Token, string.Empty);
|
Set(OsuSetting.Token, string.Empty);
|
||||||
|
|
||||||
@ -40,14 +38,12 @@ namespace osu.Game.Configuration
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
|
|
||||||
Set(OsuSetting.MenuVoice, true);
|
Set(OsuSetting.MenuVoice, true);
|
||||||
Set(OsuSetting.MenuMusic, true);
|
Set(OsuSetting.MenuMusic, true);
|
||||||
|
|
||||||
Set(OsuSetting.AudioOffset, 0, -500.0, 500.0);
|
Set(OsuSetting.AudioOffset, 0, -500.0, 500.0);
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
|
|
||||||
Set(OsuSetting.MenuCursorSize, 1.0, 0.5f, 2);
|
Set(OsuSetting.MenuCursorSize, 1.0, 0.5f, 2);
|
||||||
Set(OsuSetting.GameplayCursorSize, 1.0, 0.5f, 2);
|
Set(OsuSetting.GameplayCursorSize, 1.0, 0.5f, 2);
|
||||||
Set(OsuSetting.AutoCursorSize, false);
|
Set(OsuSetting.AutoCursorSize, false);
|
||||||
@ -56,7 +52,6 @@ namespace osu.Game.Configuration
|
|||||||
Set(OsuSetting.MouseDisableWheel, false);
|
Set(OsuSetting.MouseDisableWheel, false);
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
|
|
||||||
Set(OsuSetting.ShowFpsDisplay, false);
|
Set(OsuSetting.ShowFpsDisplay, false);
|
||||||
|
|
||||||
Set(OsuSetting.MenuParallax, true);
|
Set(OsuSetting.MenuParallax, true);
|
||||||
@ -65,7 +60,6 @@ namespace osu.Game.Configuration
|
|||||||
Set(OsuSetting.SnakingOutSliders, true);
|
Set(OsuSetting.SnakingOutSliders, true);
|
||||||
|
|
||||||
// Gameplay
|
// Gameplay
|
||||||
|
|
||||||
Set(OsuSetting.DimLevel, 0.3, 0, 1);
|
Set(OsuSetting.DimLevel, 0.3, 0, 1);
|
||||||
|
|
||||||
Set(OsuSetting.ShowInterface, true);
|
Set(OsuSetting.ShowInterface, true);
|
||||||
@ -75,7 +69,6 @@ namespace osu.Game.Configuration
|
|||||||
Set(OsuSetting.PlaybackSpeed, 1.0, 0.5f, 2);
|
Set(OsuSetting.PlaybackSpeed, 1.0, 0.5f, 2);
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
|
|
||||||
Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer);
|
Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,4 +39,3 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,4 +36,3 @@ namespace osu.Game.Database
|
|||||||
public string StoryboardFile { get; set; }
|
public string StoryboardFile { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ using osu.Framework.MathUtils;
|
|||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Graphics.OpenGL;
|
|
||||||
using osu.Framework.Graphics.Shaders;
|
using osu.Framework.Graphics.Shaders;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using OpenTK.Graphics.ES30;
|
using OpenTK.Graphics.ES30;
|
||||||
@ -16,6 +15,7 @@ using osu.Framework.Graphics.Primitives;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics.Batches;
|
using osu.Framework.Graphics.Batches;
|
||||||
|
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||||
using osu.Framework.Lists;
|
using osu.Framework.Lists;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Backgrounds
|
namespace osu.Game.Graphics.Backgrounds
|
||||||
|
@ -8,13 +8,13 @@ using osu.Framework.Graphics.Textures;
|
|||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Graphics.OpenGL;
|
|
||||||
using osu.Framework.Graphics.OpenGL.Buffers;
|
using osu.Framework.Graphics.OpenGL.Buffers;
|
||||||
using OpenTK.Graphics.ES30;
|
using OpenTK.Graphics.ES30;
|
||||||
using osu.Framework.Graphics.Primitives;
|
using osu.Framework.Graphics.Primitives;
|
||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Cursor
|
namespace osu.Game.Graphics.Cursor
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ namespace osu.Game.Graphics.Cursor
|
|||||||
Masking = true,
|
Masking = true,
|
||||||
BorderThickness = Size.X / 6,
|
BorderThickness = Size.X / 6,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Pink.Opacity(0.5f),
|
Colour = Color4.Pink.Opacity(0.5f),
|
||||||
|
18
osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs
Normal file
18
osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Cursor
|
||||||
|
{
|
||||||
|
public class OsuContextMenuContainer : ContextMenuContainer
|
||||||
|
{
|
||||||
|
protected override ContextMenu<ContextMenuItem> CreateContextMenu() => new OsuContextMenu<ContextMenuItem>();
|
||||||
|
|
||||||
|
public OsuContextMenuContainer(CursorContainer cursor) : base(cursor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,129 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using OpenTK;
|
|
||||||
using OpenTK.Graphics;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Configuration;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Cursor;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Graphics.Transforms;
|
|
||||||
using osu.Framework.Input;
|
|
||||||
using osu.Game.Configuration;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Cursor
|
|
||||||
{
|
|
||||||
public class OsuCursorContainer : CursorContainer
|
|
||||||
{
|
|
||||||
protected override Drawable CreateCursor() => new OsuCursor();
|
|
||||||
|
|
||||||
public OsuCursorContainer()
|
|
||||||
{
|
|
||||||
Add(new CursorTrail { Depth = 1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
|
||||||
{
|
|
||||||
ActiveCursor.Scale = new Vector2(1);
|
|
||||||
ActiveCursor.ScaleTo(1.2f, 100, EasingTypes.OutQuad);
|
|
||||||
return base.OnMouseDown(state, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
|
||||||
{
|
|
||||||
if (!state.Mouse.HasMainButtonPressed)
|
|
||||||
ActiveCursor.ScaleTo(1, 200, EasingTypes.OutQuad);
|
|
||||||
return base.OnMouseUp(state, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OsuCursor : Container
|
|
||||||
{
|
|
||||||
private Container cursorContainer;
|
|
||||||
private Bindable<double> cursorScale;
|
|
||||||
|
|
||||||
public OsuCursor()
|
|
||||||
{
|
|
||||||
Origin = Anchor.Centre;
|
|
||||||
Size = new Vector2(42);
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuConfigManager config)
|
|
||||||
{
|
|
||||||
cursorScale = config.GetBindable<double>(OsuConfig.CursorSize);
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
cursorContainer = new CircularContainer
|
|
||||||
{
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Scale = new Vector2((float)cursorScale),
|
|
||||||
Masking = true,
|
|
||||||
BorderThickness = Size.X / 6,
|
|
||||||
BorderColour = Color4.White,
|
|
||||||
EdgeEffect = new EdgeEffect {
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Colour = Color4.Pink.Opacity(0.5f),
|
|
||||||
Radius = 5,
|
|
||||||
},
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true,
|
|
||||||
},
|
|
||||||
new CircularContainer
|
|
||||||
{
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
BorderThickness = Size.X / 3,
|
|
||||||
BorderColour = Color4.White.Opacity(0.5f),
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
new CircularContainer
|
|
||||||
{
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Scale = new Vector2(0.1f),
|
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.White,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
cursorScale.ValueChanged += scaleChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scaleChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
cursorContainer.Scale = new Vector2((float)cursorScale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -52,7 +52,7 @@ namespace osu.Game.Graphics.Cursor
|
|||||||
|
|
||||||
CornerRadius = 5;
|
CornerRadius = 5;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(40),
|
Colour = Color4.Black.Opacity(40),
|
||||||
|
@ -87,5 +87,7 @@ namespace osu.Game.Graphics
|
|||||||
public readonly Color4 RedDarker = FromHex(@"870000");
|
public readonly Color4 RedDarker = FromHex(@"870000");
|
||||||
|
|
||||||
public readonly Color4 ChatBlue = FromHex(@"17292e");
|
public readonly Color4 ChatBlue = FromHex(@"17292e");
|
||||||
|
|
||||||
|
public readonly Color4 ContextMenuGray = FromHex(@"223034");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
Width = 0.8f,
|
Width = 0.8f,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
MaskingSmoothness = 2,
|
MaskingSmoothness = 2,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
Colour = Color4.Black.Opacity(0.2f),
|
||||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
CornerRadius = 5,
|
CornerRadius = 5,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Colour = Color4.Black.Opacity(0.04f),
|
Colour = Color4.Black.Opacity(0.04f),
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
|
@ -1,15 +1,48 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
public class LoadingAnimation : SpriteText
|
public class LoadingAnimation : VisibilityContainer
|
||||||
{
|
{
|
||||||
|
private readonly TextAwesome spinner;
|
||||||
|
|
||||||
public LoadingAnimation()
|
public LoadingAnimation()
|
||||||
{
|
{
|
||||||
Text = "Loading";
|
Size = new Vector2(20);
|
||||||
}
|
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
spinner = new TextAwesome
|
||||||
|
{
|
||||||
|
TextSize = 20,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Icon = FontAwesome.fa_spinner
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
spinner.RotateTo(360, 2000);
|
||||||
|
using (spinner.BeginDelayedSequence(2000))
|
||||||
|
spinner.Loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float transition_duration = 500;
|
||||||
|
|
||||||
|
protected override void PopIn() => FadeIn(transition_duration * 5, EasingTypes.OutQuint);
|
||||||
|
|
||||||
|
protected override void PopOut() => FadeOut(transition_duration, EasingTypes.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
12
osu.Game/Graphics/UserInterface/MenuItemType.cs
Normal file
12
osu.Game/Graphics/UserInterface/MenuItemType.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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.Graphics.UserInterface
|
||||||
|
{
|
||||||
|
public enum MenuItemType
|
||||||
|
{
|
||||||
|
Standard,
|
||||||
|
Highlighted,
|
||||||
|
Destructive,
|
||||||
|
}
|
||||||
|
}
|
@ -56,7 +56,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
GlowingAccentColour = colours.PinkLighter;
|
GlowingAccentColour = colours.PinkLighter;
|
||||||
GlowColour = colours.PinkDarker;
|
GlowColour = colours.PinkDarker;
|
||||||
|
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Colour = GlowColour,
|
Colour = GlowColour,
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
|
52
osu.Game/Graphics/UserInterface/OsuContextMenu.cs
Normal file
52
osu.Game/Graphics/UserInterface/OsuContextMenu.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// 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.Allocation;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.UserInterface
|
||||||
|
{
|
||||||
|
public class OsuContextMenu<TItem> : ContextMenu<TItem>
|
||||||
|
where TItem : ContextMenuItem
|
||||||
|
{
|
||||||
|
protected override Menu<TItem> CreateMenu() => new CustomMenu();
|
||||||
|
|
||||||
|
public class CustomMenu : Menu<TItem>
|
||||||
|
{
|
||||||
|
private const int fade_duration = 250;
|
||||||
|
|
||||||
|
public CustomMenu()
|
||||||
|
{
|
||||||
|
CornerRadius = 5;
|
||||||
|
ItemsContainer.Padding = new MarginPadding { Vertical = OsuContextMenuItem.MARGIN_VERTICAL };
|
||||||
|
Masking = true;
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Shadow,
|
||||||
|
Colour = Color4.Black.Opacity(0.1f),
|
||||||
|
Radius = 4,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
Background.Colour = colours.ContextMenuGray;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AnimateOpen() => FadeIn(fade_duration, EasingTypes.OutQuint);
|
||||||
|
protected override void AnimateClose() => FadeOut(fade_duration, EasingTypes.OutQuint);
|
||||||
|
|
||||||
|
protected override void UpdateContentHeight()
|
||||||
|
{
|
||||||
|
var actualHeight = (RelativeSizeAxes & Axes.Y) > 0 ? 1 : ContentHeight;
|
||||||
|
ResizeTo(new Vector2(1, State == MenuState.Opened ? actualHeight : 0), 300, EasingTypes.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
114
osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs
Normal file
114
osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// 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.Audio;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.UserInterface
|
||||||
|
{
|
||||||
|
public class OsuContextMenuItem : ContextMenuItem
|
||||||
|
{
|
||||||
|
private const int transition_length = 80;
|
||||||
|
private const int margin_horizontal = 17;
|
||||||
|
public const int MARGIN_VERTICAL = 4;
|
||||||
|
private const int text_size = 17;
|
||||||
|
|
||||||
|
private OsuSpriteText text;
|
||||||
|
private OsuSpriteText textBold;
|
||||||
|
|
||||||
|
private SampleChannel sampleClick;
|
||||||
|
private SampleChannel sampleHover;
|
||||||
|
|
||||||
|
private readonly MenuItemType type;
|
||||||
|
|
||||||
|
protected override Container CreateTextContainer(string title) => new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
text = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
TextSize = text_size,
|
||||||
|
Text = title,
|
||||||
|
Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL },
|
||||||
|
},
|
||||||
|
textBold = new OsuSpriteText
|
||||||
|
{
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Alpha = 0,
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
TextSize = text_size,
|
||||||
|
Text = title,
|
||||||
|
Font = @"Exo2.0-Bold",
|
||||||
|
Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public OsuContextMenuItem(string title, MenuItemType type = MenuItemType.Standard) : base(title)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(AudioManager audio)
|
||||||
|
{
|
||||||
|
sampleHover = audio.Sample.Get(@"Menu/menuclick");
|
||||||
|
sampleClick = audio.Sample.Get(@"Menu/menuback");
|
||||||
|
|
||||||
|
BackgroundColour = Color4.Transparent;
|
||||||
|
BackgroundColourHover = OsuColour.FromHex(@"172023");
|
||||||
|
|
||||||
|
updateTextColour();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTextColour()
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MenuItemType.Standard:
|
||||||
|
textBold.Colour = text.Colour = Color4.White;
|
||||||
|
break;
|
||||||
|
case MenuItemType.Destructive:
|
||||||
|
textBold.Colour = text.Colour = Color4.Red;
|
||||||
|
break;
|
||||||
|
case MenuItemType.Highlighted:
|
||||||
|
textBold.Colour = text.Colour = OsuColour.FromHex(@"ffcc22");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(InputState state)
|
||||||
|
{
|
||||||
|
sampleHover.Play();
|
||||||
|
textBold.FadeIn(transition_length, EasingTypes.OutQuint);
|
||||||
|
text.FadeOut(transition_length, EasingTypes.OutQuint);
|
||||||
|
return base.OnHover(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(InputState state)
|
||||||
|
{
|
||||||
|
textBold.FadeOut(transition_length, EasingTypes.OutQuint);
|
||||||
|
text.FadeIn(transition_length, EasingTypes.OutQuint);
|
||||||
|
base.OnHoverLost(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnClick(InputState state)
|
||||||
|
{
|
||||||
|
sampleClick.Play();
|
||||||
|
return base.OnClick(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -74,21 +74,6 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Active
|
|
||||||
{
|
|
||||||
get { return base.Active; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Active == value) return;
|
|
||||||
|
|
||||||
if (value)
|
|
||||||
fadeActive();
|
|
||||||
else
|
|
||||||
fadeInactive();
|
|
||||||
base.Active = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const float transition_length = 500;
|
private const float transition_length = 500;
|
||||||
|
|
||||||
private void fadeActive()
|
private void fadeActive()
|
||||||
@ -150,6 +135,10 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnActivated() => fadeActive();
|
||||||
|
|
||||||
|
protected override void OnDeactivated() => fadeInactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OsuTabDropdown : OsuDropdown<T>
|
private class OsuTabDropdown : OsuDropdown<T>
|
||||||
|
@ -29,21 +29,6 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
private readonly Box box;
|
private readonly Box box;
|
||||||
|
|
||||||
public override bool Active
|
|
||||||
{
|
|
||||||
get { return base.Active; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Active == value) return;
|
|
||||||
|
|
||||||
if (value)
|
|
||||||
slideActive();
|
|
||||||
else
|
|
||||||
slideInactive();
|
|
||||||
base.Active = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PageTabItem(T value) : base(value)
|
public PageTabItem(T value) : base(value)
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.X;
|
AutoSizeAxes = Axes.X;
|
||||||
@ -100,6 +85,10 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
{
|
{
|
||||||
box.ScaleTo(new Vector2(1f, 0f), transition_duration);
|
box.ScaleTo(new Vector2(1f, 0f), transition_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnActivated() => slideActive();
|
||||||
|
|
||||||
|
protected override void OnDeactivated() => slideInactive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,18 +79,21 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
Width = 0.4f,
|
Width = 0.4f,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container {
|
new Container
|
||||||
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Shear = new Vector2(shear, 0),
|
Shear = new Vector2(shear, 0),
|
||||||
Masking = true,
|
Masking = true,
|
||||||
MaskingSmoothness = 2,
|
MaskingSmoothness = 2,
|
||||||
EdgeEffect = new EdgeEffect {
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
Colour = Color4.Black.Opacity(0.2f),
|
||||||
Offset = new Vector2(2, 0),
|
Offset = new Vector2(2, 0),
|
||||||
Radius = 2,
|
Radius = 2,
|
||||||
},
|
},
|
||||||
Children = new [] {
|
Children = new[]
|
||||||
|
{
|
||||||
IconLayer = new Box
|
IconLayer = new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
@ -113,18 +116,21 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
Width = 0.6f,
|
Width = 0.6f,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container {
|
new Container
|
||||||
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Shear = new Vector2(shear, 0),
|
Shear = new Vector2(shear, 0),
|
||||||
Masking = true,
|
Masking = true,
|
||||||
MaskingSmoothness = 2,
|
MaskingSmoothness = 2,
|
||||||
EdgeEffect = new EdgeEffect {
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
Colour = Color4.Black.Opacity(0.2f),
|
||||||
Offset = new Vector2(2, 0),
|
Offset = new Vector2(2, 0),
|
||||||
Radius = 2,
|
Radius = 2,
|
||||||
},
|
},
|
||||||
Children = new [] {
|
Children = new[]
|
||||||
|
{
|
||||||
TextLayer = new Box
|
TextLayer = new Box
|
||||||
{
|
{
|
||||||
Origin = Anchor.TopLeft,
|
Origin = Anchor.TopLeft,
|
||||||
|
@ -59,7 +59,6 @@ namespace osu.Game.Online.API
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,8 +77,10 @@ namespace osu.Game
|
|||||||
public void ToggleDirect() => direct.ToggleVisibility();
|
public void ToggleDirect() => direct.ToggleVisibility();
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(FrameworkConfigManager frameworkConfig)
|
||||||
{
|
{
|
||||||
|
this.frameworkConfig = frameworkConfig;
|
||||||
|
|
||||||
if (!Host.IsPrimaryInstance)
|
if (!Host.IsPrimaryInstance)
|
||||||
{
|
{
|
||||||
Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error);
|
Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error);
|
||||||
@ -259,6 +261,19 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
switch (args.Key)
|
switch (args.Key)
|
||||||
{
|
{
|
||||||
|
case Key.R:
|
||||||
|
if (state.Keyboard.AltPressed)
|
||||||
|
{
|
||||||
|
var sensitivity = frameworkConfig.GetBindable<double>(FrameworkSetting.CursorSensitivity);
|
||||||
|
|
||||||
|
sensitivity.Disabled = false;
|
||||||
|
sensitivity.Value = 1;
|
||||||
|
sensitivity.Disabled = true;
|
||||||
|
|
||||||
|
frameworkConfig.Set(FrameworkSetting.ActiveInputHandlers, string.Empty);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Key.T:
|
case Key.T:
|
||||||
Toolbar.ToggleVisibility();
|
Toolbar.ToggleVisibility();
|
||||||
return true;
|
return true;
|
||||||
@ -284,6 +299,7 @@ namespace osu.Game
|
|||||||
private Container overlayContent;
|
private Container overlayContent;
|
||||||
|
|
||||||
private OsuScreen currentScreen;
|
private OsuScreen currentScreen;
|
||||||
|
private FrameworkConfigManager frameworkConfig;
|
||||||
|
|
||||||
private void screenChanged(Screen newScreen)
|
private void screenChanged(Screen newScreen)
|
||||||
{
|
{
|
||||||
|
@ -158,6 +158,7 @@ namespace osu.Game
|
|||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
Cursor = new MenuCursor(),
|
Cursor = new MenuCursor(),
|
||||||
|
new OsuContextMenuContainer(Cursor) { Depth = -2 },
|
||||||
new OsuTooltipContainer(Cursor) { Depth = -1 },
|
new OsuTooltipContainer(Cursor) { Depth = -1 },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -26,6 +26,8 @@ namespace osu.Game.Overlays.Chat
|
|||||||
|
|
||||||
public readonly Bindable<bool> ChannelSelectorActive = new Bindable<bool>();
|
public readonly Bindable<bool> ChannelSelectorActive = new Bindable<bool>();
|
||||||
|
|
||||||
|
private readonly ChannelTabItem.ChannelSelectorTabItem selectorTab;
|
||||||
|
|
||||||
public ChatTabControl()
|
public ChatTabControl()
|
||||||
{
|
{
|
||||||
TabContainer.Margin = new MarginPadding { Left = 50 };
|
TabContainer.Margin = new MarginPadding { Left = 50 };
|
||||||
@ -41,7 +43,22 @@ namespace osu.Game.Overlays.Chat
|
|||||||
Padding = new MarginPadding(10),
|
Padding = new MarginPadding(10),
|
||||||
});
|
});
|
||||||
|
|
||||||
AddTabItem(new ChannelTabItem.ChannelSelectorTabItem(new Channel { Name = "+" }, ChannelSelectorActive));
|
AddTabItem(selectorTab = new ChannelTabItem.ChannelSelectorTabItem(new Channel { Name = "+" }));
|
||||||
|
|
||||||
|
ChannelSelectorActive.BindTo(selectorTab.Active);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SelectTab(TabItem<Channel> tab)
|
||||||
|
{
|
||||||
|
if (tab is ChannelTabItem.ChannelSelectorTabItem)
|
||||||
|
{
|
||||||
|
tab.Active.Toggle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectorTab.Active.Value = false;
|
||||||
|
|
||||||
|
base.SelectTab(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ChannelTabItem : TabItem<Channel>
|
private class ChannelTabItem : TabItem<Channel>
|
||||||
@ -56,18 +73,6 @@ namespace osu.Game.Overlays.Chat
|
|||||||
private readonly Box highlightBox;
|
private readonly Box highlightBox;
|
||||||
private readonly TextAwesome icon;
|
private readonly TextAwesome icon;
|
||||||
|
|
||||||
public override bool Active
|
|
||||||
{
|
|
||||||
get { return base.Active; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Active == value) return;
|
|
||||||
|
|
||||||
base.Active = value;
|
|
||||||
updateState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateState()
|
private void updateState()
|
||||||
{
|
{
|
||||||
if (Active)
|
if (Active)
|
||||||
@ -141,7 +146,7 @@ namespace osu.Game.Overlays.Chat
|
|||||||
Shear = new Vector2(shear_width / ChatOverlay.TAB_AREA_HEIGHT, 0);
|
Shear = new Vector2(shear_width / ChatOverlay.TAB_AREA_HEIGHT, 0);
|
||||||
|
|
||||||
Masking = true;
|
Masking = true;
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Radius = 10,
|
Radius = 10,
|
||||||
@ -205,28 +210,8 @@ namespace osu.Game.Overlays.Chat
|
|||||||
|
|
||||||
public class ChannelSelectorTabItem : ChannelTabItem
|
public class ChannelSelectorTabItem : ChannelTabItem
|
||||||
{
|
{
|
||||||
public override bool Active
|
public ChannelSelectorTabItem(Channel value) : base(value)
|
||||||
{
|
{
|
||||||
get { return false; }
|
|
||||||
// ReSharper disable once ValueParameterNotUsed
|
|
||||||
set
|
|
||||||
{
|
|
||||||
// we basically never want this tab to become active.
|
|
||||||
// this allows us to become a "toggle" tab.
|
|
||||||
// is a bit hacky, to say the least.
|
|
||||||
activeBindable.Value = !activeBindable.Value;
|
|
||||||
base.Active = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly Bindable<bool> activeBindable;
|
|
||||||
|
|
||||||
public ChannelSelectorTabItem(Channel value, Bindable<bool> active) : base(value)
|
|
||||||
{
|
|
||||||
activeBindable = active;
|
|
||||||
activeBindable.ValueChanged += v => selectorUpdateState();
|
|
||||||
|
|
||||||
|
|
||||||
Depth = float.MaxValue;
|
Depth = float.MaxValue;
|
||||||
Width = 45;
|
Width = 45;
|
||||||
|
|
||||||
@ -242,27 +227,11 @@ namespace osu.Game.Overlays.Chat
|
|||||||
backgroundInactive = colour.Gray2;
|
backgroundInactive = colour.Gray2;
|
||||||
backgroundActive = colour.Gray3;
|
backgroundActive = colour.Gray3;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
selectorUpdateState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(InputState state)
|
protected override void OnActivated() => updateState();
|
||||||
{
|
|
||||||
selectorUpdateState();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void selectorUpdateState()
|
protected override void OnDeactivated() => updateState();
|
||||||
{
|
|
||||||
if (activeBindable.Value)
|
|
||||||
fadeActive();
|
|
||||||
else
|
|
||||||
fadeInactive();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,6 @@ namespace osu.Game.Overlays.Chat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scrollToEnd() => Scheduler.AddDelayed(() => scroll.ScrollToEnd(), 50);
|
private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Online.Chat;
|
using osu.Game.Online.Chat;
|
||||||
@ -33,7 +32,9 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
private ScheduledDelegate messageRequest;
|
private ScheduledDelegate messageRequest;
|
||||||
|
|
||||||
private readonly Container currentChannelContainer;
|
private readonly Container<DrawableChannel> currentChannelContainer;
|
||||||
|
|
||||||
|
private readonly LoadingAnimation loading;
|
||||||
|
|
||||||
private readonly FocusedTextBox inputTextBox;
|
private readonly FocusedTextBox inputTextBox;
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
currentChannelContainer = new Container
|
currentChannelContainer = new Container<DrawableChannel>
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding
|
Padding = new MarginPadding
|
||||||
@ -138,7 +139,8 @@ namespace osu.Game.Overlays
|
|||||||
HoldFocus = true,
|
HoldFocus = true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
loading = new LoadingAnimation(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
@ -274,14 +276,7 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
private void initializeChannels()
|
private void initializeChannels()
|
||||||
{
|
{
|
||||||
SpriteText loading;
|
loading.Show();
|
||||||
Add(loading = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = @"initialising chat...",
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
TextSize = 40,
|
|
||||||
});
|
|
||||||
|
|
||||||
messageRequest?.Cancel();
|
messageRequest?.Cancel();
|
||||||
|
|
||||||
@ -290,9 +285,6 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
Scheduler.Add(delegate
|
Scheduler.Add(delegate
|
||||||
{
|
{
|
||||||
loading.FadeOut(100);
|
|
||||||
loading.Expire();
|
|
||||||
|
|
||||||
addChannel(channels.Find(c => c.Name == @"#lazer"));
|
addChannel(channels.Find(c => c.Name == @"#lazer"));
|
||||||
addChannel(channels.Find(c => c.Name == @"#osu"));
|
addChannel(channels.Find(c => c.Name == @"#osu"));
|
||||||
addChannel(channels.Find(c => c.Name == @"#lobby"));
|
addChannel(channels.Find(c => c.Name == @"#lobby"));
|
||||||
@ -336,13 +328,17 @@ namespace osu.Game.Overlays
|
|||||||
if (loaded == null)
|
if (loaded == null)
|
||||||
{
|
{
|
||||||
currentChannelContainer.FadeOut(500, EasingTypes.OutQuint);
|
currentChannelContainer.FadeOut(500, EasingTypes.OutQuint);
|
||||||
|
loading.Show();
|
||||||
|
|
||||||
loaded = new DrawableChannel(currentChannel);
|
loaded = new DrawableChannel(currentChannel);
|
||||||
loadedChannels.Add(loaded);
|
loadedChannels.Add(loaded);
|
||||||
LoadComponentAsync(loaded, l =>
|
LoadComponentAsync(loaded, l =>
|
||||||
{
|
{
|
||||||
|
if (currentChannel.Messages.Any())
|
||||||
|
loading.Hide();
|
||||||
|
|
||||||
currentChannelContainer.Clear(false);
|
currentChannelContainer.Clear(false);
|
||||||
currentChannelContainer.Add(l);
|
currentChannelContainer.Add(loaded);
|
||||||
currentChannelContainer.FadeIn(500, EasingTypes.OutQuint);
|
currentChannelContainer.FadeIn(500, EasingTypes.OutQuint);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -367,7 +363,6 @@ namespace osu.Game.Overlays
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
careChannels.Add(channel);
|
careChannels.Add(channel);
|
||||||
channelTabs.AddItem(channel);
|
channelTabs.AddItem(channel);
|
||||||
}
|
}
|
||||||
@ -387,6 +382,7 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
req.Success += delegate (List<Message> messages)
|
req.Success += delegate (List<Message> messages)
|
||||||
{
|
{
|
||||||
|
loading.Hide();
|
||||||
channel.AddNewMessages(messages.ToArray());
|
channel.AddNewMessages(messages.ToArray());
|
||||||
Debug.Write("success!");
|
Debug.Write("success!");
|
||||||
};
|
};
|
||||||
|
@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Dialog
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.5f),
|
Colour = Color4.Black.Opacity(0.5f),
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Overlays
|
|||||||
State = Visibility.Visible;
|
State = Visibility.Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDialogOnStateChanged(OverlayContainer dialog, Visibility v)
|
private void onDialogOnStateChanged(VisibilityContainer dialog, Visibility v)
|
||||||
{
|
{
|
||||||
if (v != Visibility.Hidden) return;
|
if (v != Visibility.Hidden) return;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
CornerRadius = 4;
|
CornerRadius = 4;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
|
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Offset = new Vector2(0f, 1f),
|
Offset = new Vector2(0f, 1f),
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
Height = height;
|
Height = height;
|
||||||
CornerRadius = 5;
|
CornerRadius = 5;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Offset = new Vector2(0f, 1f),
|
Offset = new Vector2(0f, 1f),
|
||||||
|
@ -20,7 +20,6 @@ using osu.Framework.Graphics.Cursor;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Mods
|
namespace osu.Game.Overlays.Mods
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a clickable button which can cycle through one of more mods.
|
/// Represents a clickable button which can cycle through one of more mods.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -80,7 +79,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
backgroundIcon.RotateTo(-rotate_angle * direction, mod_switch_duration, mod_switch_easing);
|
backgroundIcon.RotateTo(-rotate_angle * direction, mod_switch_duration, mod_switch_easing);
|
||||||
|
|
||||||
backgroundIcon.Icon = modAfter.Icon;
|
backgroundIcon.Icon = modAfter.Icon;
|
||||||
using (iconsContainer.BeginDelayedSequence(mod_switch_duration, true))
|
using (BeginDelayedSequence(mod_switch_duration, true))
|
||||||
{
|
{
|
||||||
foregroundIcon.RotateTo(-rotate_angle * direction);
|
foregroundIcon.RotateTo(-rotate_angle * direction);
|
||||||
foregroundIcon.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
foregroundIcon.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
||||||
@ -88,7 +87,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
backgroundIcon.RotateTo(rotate_angle * direction);
|
backgroundIcon.RotateTo(rotate_angle * direction);
|
||||||
backgroundIcon.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
backgroundIcon.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
||||||
|
|
||||||
iconsContainer.Schedule(() => displayMod(modAfter));
|
Schedule(() => displayMod(modAfter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
Icon.TextSize = 14;
|
Icon.TextSize = 14;
|
||||||
Icon.Margin = new MarginPadding(0);
|
Icon.Margin = new MarginPadding(0);
|
||||||
Foreground.Padding = new MarginPadding { Top = 4, Bottom = 4, Left = 10, Right = 10 };
|
Foreground.Padding = new MarginPadding { Top = 4, Bottom = 4, Left = 10, Right = 10 };
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.3f),
|
Colour = Color4.Black.Opacity(0.3f),
|
||||||
@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
public CollectionsMenu()
|
public CollectionsMenu()
|
||||||
{
|
{
|
||||||
CornerRadius = 5;
|
CornerRadius = 5;
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.3f),
|
Colour = Color4.Black.Opacity(0.3f),
|
||||||
|
@ -137,6 +137,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
|
|
||||||
public bool MatchingFilter
|
public bool MatchingFilter
|
||||||
{
|
{
|
||||||
|
get { return matching; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (matching == value) return;
|
if (matching == value) return;
|
||||||
@ -145,10 +146,6 @@ namespace osu.Game.Overlays.Music
|
|||||||
|
|
||||||
FadeTo(matching ? 1 : 0, 200);
|
FadeTo(matching ? 1 : 0, 200);
|
||||||
}
|
}
|
||||||
get
|
|
||||||
{
|
|
||||||
return matching;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
CornerRadius = 5,
|
CornerRadius = 5,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(40),
|
Colour = Color4.Black.Opacity(40),
|
||||||
|
@ -106,7 +106,7 @@ namespace osu.Game.Overlays
|
|||||||
Height = player_height,
|
Height = player_height,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
CornerRadius = 5,
|
CornerRadius = 5,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(40),
|
Colour = Color4.Black.Opacity(40),
|
||||||
|
@ -238,7 +238,7 @@ namespace osu.Game.Overlays.Notifications
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
base.Colour = value;
|
base.Colour = value;
|
||||||
pulsateLayer.EdgeEffect = new EdgeEffect
|
pulsateLayer.EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Colour = ((Color4)value).Opacity(0.5f), //todo: avoid cast
|
Colour = ((Color4)value).Opacity(0.5f), //todo: avoid cast
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
|
@ -125,6 +125,14 @@ namespace osu.Game.Overlays
|
|||||||
trackSetting(frameworkConfig.GetBindable<int>(FrameworkSetting.Width), v => displayResolution());
|
trackSetting(frameworkConfig.GetBindable<int>(FrameworkSetting.Width), v => displayResolution());
|
||||||
trackSetting(frameworkConfig.GetBindable<int>(FrameworkSetting.Height), v => displayResolution());
|
trackSetting(frameworkConfig.GetBindable<int>(FrameworkSetting.Height), v => displayResolution());
|
||||||
|
|
||||||
|
trackSetting(frameworkConfig.GetBindable<double>(FrameworkSetting.CursorSensitivity), v => display(v, "Cursor Sensitivity", v.ToString(@"0.##x"), "Ctrl+Alt+R to reset"));
|
||||||
|
trackSetting(frameworkConfig.GetBindable<string>(FrameworkSetting.ActiveInputHandlers),
|
||||||
|
delegate (string v)
|
||||||
|
{
|
||||||
|
bool raw = v.Contains("Raw");
|
||||||
|
display(raw, "Raw Input", raw ? "enabled" : "disabled", "Ctrl+Alt+R to reset");
|
||||||
|
});
|
||||||
|
|
||||||
trackSetting(frameworkConfig.GetBindable<WindowMode>(FrameworkSetting.WindowMode), v => display(v, "Screen Mode", v.ToString(), "Alt+Enter"));
|
trackSetting(frameworkConfig.GetBindable<WindowMode>(FrameworkSetting.WindowMode), v => display(v, "Screen Mode", v.ToString(), "Alt+Enter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +253,7 @@ namespace osu.Game.Overlays
|
|||||||
Masking = true;
|
Masking = true;
|
||||||
CornerRadius = 3;
|
CornerRadius = 3;
|
||||||
|
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Colour = colours.BlueDark.Opacity(glow_strength),
|
Colour = colours.BlueDark.Opacity(glow_strength),
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
|
@ -41,4 +41,3 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
bounding = value;
|
bounding = value;
|
||||||
Invalidate(Invalidation.Geometry);
|
Invalidate(Invalidation.MiscGeometry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +290,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
Margin = new MarginPadding { Bottom = 5 };
|
Margin = new MarginPadding { Bottom = 5 };
|
||||||
Masking = true;
|
Masking = true;
|
||||||
CornerRadius = 5;
|
CornerRadius = 5;
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.25f),
|
Colour = Color4.Black.Opacity(0.25f),
|
||||||
@ -326,7 +326,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
CornerRadius = 5;
|
CornerRadius = 5;
|
||||||
ItemsContainer.Padding = new MarginPadding(0);
|
ItemsContainer.Padding = new MarginPadding(0);
|
||||||
Masking = true;
|
Masking = true;
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(0.25f),
|
Colour = Color4.Black.Opacity(0.25f),
|
||||||
|
@ -33,4 +33,3 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,4 +22,3 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,4 +24,3 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,6 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuConfigManager osuConfig, FrameworkConfigManager config)
|
private void load(OsuConfigManager osuConfig, FrameworkConfigManager config)
|
||||||
{
|
{
|
||||||
activeInputHandlers = config.GetBindable<string>(FrameworkSetting.ActiveInputHandlers);
|
|
||||||
rawInputToggle.Value = activeInputHandlers.Value.Contains("Raw");
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
@ -62,11 +59,17 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
activeInputHandlers.Value = enabled ?
|
activeInputHandlers.Value = enabled ?
|
||||||
activeInputHandlers.Value.Replace(standard_mouse_handler, raw_mouse_handler) :
|
activeInputHandlers.Value.Replace(standard_mouse_handler, raw_mouse_handler) :
|
||||||
activeInputHandlers.Value.Replace(raw_mouse_handler, standard_mouse_handler);
|
activeInputHandlers.Value.Replace(raw_mouse_handler, standard_mouse_handler);
|
||||||
|
|
||||||
sensitivity.Bindable.Disabled = !enabled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rawInputToggle.TriggerChange();
|
activeInputHandlers = config.GetBindable<string>(FrameworkSetting.ActiveInputHandlers);
|
||||||
|
activeInputHandlers.ValueChanged += handlers =>
|
||||||
|
{
|
||||||
|
bool raw = handlers.Contains("Raw");
|
||||||
|
rawInputToggle.Value = raw;
|
||||||
|
sensitivity.Bindable.Disabled = !raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
activeInputHandlers.TriggerChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SensitivitySetting : SettingsSlider<double, SensitivitySlider>
|
private class SensitivitySetting : SettingsSlider<double, SensitivitySlider>
|
||||||
|
@ -22,4 +22,3 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,4 +52,3 @@ namespace osu.Game.Overlays.Settings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ using OpenTK.Graphics;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Overlays.SearchableList;
|
using osu.Game.Overlays.SearchableList;
|
||||||
@ -29,6 +30,8 @@ namespace osu.Game.Overlays
|
|||||||
protected override SearchableListFilterControl<SocialSortCriteria, SortDirection> CreateFilterControl() => new FilterControl();
|
protected override SearchableListFilterControl<SocialSortCriteria, SortDirection> CreateFilterControl() => new FilterControl();
|
||||||
|
|
||||||
private IEnumerable<User> users;
|
private IEnumerable<User> users;
|
||||||
|
private readonly LoadingAnimation loading;
|
||||||
|
|
||||||
public IEnumerable<User> Users
|
public IEnumerable<User> Users
|
||||||
{
|
{
|
||||||
get { return users; }
|
get { return users; }
|
||||||
@ -68,6 +71,8 @@ namespace osu.Game.Overlays
|
|||||||
Spacing = new Vector2(10f),
|
Spacing = new Vector2(10f),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Add(loading = new LoadingAnimation());
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -83,8 +88,14 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
// no this is not the correct data source, but it's something.
|
// no this is not the correct data source, but it's something.
|
||||||
var request = new GetUsersRequest();
|
var request = new GetUsersRequest();
|
||||||
request.Success += res => Users = res.Select(e => e.User);
|
request.Success += res =>
|
||||||
|
{
|
||||||
|
Users = res.Select(e => e.User);
|
||||||
|
loading.Hide();
|
||||||
|
};
|
||||||
|
|
||||||
api.Queue(request);
|
api.Queue(request);
|
||||||
|
loading.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void APIStateChanged(APIAccess api, APIState state)
|
public void APIStateChanged(APIAccess api, APIState state)
|
||||||
|
@ -172,7 +172,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
MaskingSmoothness = 0;
|
MaskingSmoothness = 0;
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Colour = Color4.Black.Opacity(40),
|
Colour = Color4.Black.Opacity(40),
|
||||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
{
|
{
|
||||||
DrawableIcon.Colour = Color4.White;
|
DrawableIcon.Colour = Color4.White;
|
||||||
DrawableIcon.Masking = true;
|
DrawableIcon.Masking = true;
|
||||||
DrawableIcon.EdgeEffect = new EdgeEffect
|
DrawableIcon.EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Colour = new Color4(255, 194, 224, 100),
|
Colour = new Color4(255, 194, 224, 100),
|
||||||
|
@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.TopLeft,
|
Origin = Anchor.TopLeft,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Colour = new Color4(255, 194, 224, 100),
|
Colour = new Color4(255, 194, 224, 100),
|
||||||
|
@ -45,7 +45,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
stateContainer.StateChanged -= stateChanged;
|
stateContainer.StateChanged -= stateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stateChanged(OverlayContainer c, Visibility state)
|
private void stateChanged(VisibilityContainer c, Visibility state)
|
||||||
{
|
{
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
CornerRadius = 4,
|
CornerRadius = 4,
|
||||||
EdgeEffect = new EdgeEffect
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Type = EdgeEffectType.Shadow,
|
||||||
Radius = 4,
|
Radius = 4,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user