mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 14:17:26 +08:00
Merge branch 'master' into android-multiple-import-support-suppot
This commit is contained in:
commit
1d7be6a604
@ -18,7 +18,7 @@
|
|||||||
<ItemGroup Label="Code Analysis">
|
<ItemGroup Label="Code Analysis">
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.2" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.2" PrivateAssets="All" />
|
||||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.1" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.2" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Code Analysis">
|
<PropertyGroup Label="Code Analysis">
|
||||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset</CodeAnalysisRuleSet>
|
||||||
@ -28,9 +28,17 @@
|
|||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<!-- DeepEqual is not netstandard-compatible. This is fine since we run tests with .NET Framework anyway.
|
<!--
|
||||||
This is required due to https://github.com/NuGet/Home/issues/5740 -->
|
NU1701:
|
||||||
<NoWarn>$(NoWarn);NU1701</NoWarn>
|
DeepEqual is not netstandard-compatible. This is fine since we run tests with .NET Framework anyway.
|
||||||
|
This is required due to https://github.com/NuGet/Home/issues/5740
|
||||||
|
|
||||||
|
CA9998:
|
||||||
|
Microsoft.CodeAnalysis.FxCopAnalyzers has been deprecated.
|
||||||
|
The entire package will be able to be removed after migrating to .NET 5,
|
||||||
|
as analysers are shipped as part of the .NET 5 SDK anyway.
|
||||||
|
-->
|
||||||
|
<NoWarn>$(NoWarn);NU1701;CA9998</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Nuget">
|
<PropertyGroup Label="Nuget">
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
@ -40,7 +48,7 @@
|
|||||||
<RepositoryUrl>https://github.com/ppy/osu</RepositoryUrl>
|
<RepositoryUrl>https://github.com/ppy/osu</RepositoryUrl>
|
||||||
<PackageReleaseNotes>Automated release.</PackageReleaseNotes>
|
<PackageReleaseNotes>Automated release.</PackageReleaseNotes>
|
||||||
<Company>ppy Pty Ltd</Company>
|
<Company>ppy Pty Ltd</Company>
|
||||||
<Copyright>Copyright (c) 2020 ppy Pty Ltd</Copyright>
|
<Copyright>Copyright (c) 2021 ppy Pty Ltd</Copyright>
|
||||||
<PackageTags>osu game</PackageTags>
|
<PackageTags>osu game</PackageTags>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
2
LICENCE
2
LICENCE
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2020 ppy Pty Ltd <contact@ppy.sh>.
|
Copyright (c) 2021 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
10
global.json
10
global.json
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"sdk": {
|
|
||||||
"allowPrerelease": false,
|
|
||||||
"rollForward": "minor",
|
|
||||||
"version": "3.1.100"
|
|
||||||
},
|
|
||||||
"msbuild-sdks": {
|
|
||||||
"Microsoft.Build.Traversal": "3.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
@ -52,6 +52,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.1202.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.1202.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.1229.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.115.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -9,6 +9,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -31,13 +32,15 @@ namespace osu.Desktop
|
|||||||
private readonly IBindable<UserStatus> status = new Bindable<UserStatus>();
|
private readonly IBindable<UserStatus> status = new Bindable<UserStatus>();
|
||||||
private readonly IBindable<UserActivity> activity = new Bindable<UserActivity>();
|
private readonly IBindable<UserActivity> activity = new Bindable<UserActivity>();
|
||||||
|
|
||||||
|
private readonly Bindable<DiscordRichPresenceMode> privacyMode = new Bindable<DiscordRichPresenceMode>();
|
||||||
|
|
||||||
private readonly RichPresence presence = new RichPresence
|
private readonly RichPresence presence = new RichPresence
|
||||||
{
|
{
|
||||||
Assets = new Assets { LargeImageKey = "osu_logo_lazer", }
|
Assets = new Assets { LargeImageKey = "osu_logo_lazer", }
|
||||||
};
|
};
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IAPIProvider provider)
|
private void load(IAPIProvider provider, OsuConfigManager config)
|
||||||
{
|
{
|
||||||
client = new DiscordRpcClient(client_id)
|
client = new DiscordRpcClient(client_id)
|
||||||
{
|
{
|
||||||
@ -51,6 +54,8 @@ namespace osu.Desktop
|
|||||||
|
|
||||||
client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network);
|
client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network);
|
||||||
|
|
||||||
|
config.BindWith(OsuSetting.DiscordRichPresence, privacyMode);
|
||||||
|
|
||||||
(user = provider.LocalUser.GetBoundCopy()).BindValueChanged(u =>
|
(user = provider.LocalUser.GetBoundCopy()).BindValueChanged(u =>
|
||||||
{
|
{
|
||||||
status.UnbindBindings();
|
status.UnbindBindings();
|
||||||
@ -63,6 +68,7 @@ namespace osu.Desktop
|
|||||||
ruleset.BindValueChanged(_ => updateStatus());
|
ruleset.BindValueChanged(_ => updateStatus());
|
||||||
status.BindValueChanged(_ => updateStatus());
|
status.BindValueChanged(_ => updateStatus());
|
||||||
activity.BindValueChanged(_ => updateStatus());
|
activity.BindValueChanged(_ => updateStatus());
|
||||||
|
privacyMode.BindValueChanged(_ => updateStatus());
|
||||||
|
|
||||||
client.Initialize();
|
client.Initialize();
|
||||||
}
|
}
|
||||||
@ -78,7 +84,7 @@ namespace osu.Desktop
|
|||||||
if (!client.IsInitialized)
|
if (!client.IsInitialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (status.Value is UserStatusOffline)
|
if (status.Value is UserStatusOffline || privacyMode.Value == DiscordRichPresenceMode.Off)
|
||||||
{
|
{
|
||||||
client.ClearPresence();
|
client.ClearPresence();
|
||||||
return;
|
return;
|
||||||
@ -96,7 +102,10 @@ namespace osu.Desktop
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update user information
|
// update user information
|
||||||
presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.Ranks.Global > 0 ? $" (rank #{user.Value.Statistics.Ranks.Global:N0})" : string.Empty);
|
if (privacyMode.Value == DiscordRichPresenceMode.Limited)
|
||||||
|
presence.Assets.LargeImageText = string.Empty;
|
||||||
|
else
|
||||||
|
presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.Ranks.Global > 0 ? $" (rank #{user.Value.Statistics.Ranks.Global:N0})" : string.Empty);
|
||||||
|
|
||||||
// update ruleset
|
// update ruleset
|
||||||
presence.Assets.SmallImageKey = ruleset.Value.ID <= 3 ? $"mode_{ruleset.Value.ID}" : "mode_custom";
|
presence.Assets.SmallImageKey = ruleset.Value.ID <= 3 ? $"mode_{ruleset.Value.ID}" : "mode_custom";
|
||||||
@ -137,7 +146,7 @@ namespace osu.Desktop
|
|||||||
return edit.Beatmap.ToString();
|
return edit.Beatmap.ToString();
|
||||||
|
|
||||||
case UserActivity.InLobby lobby:
|
case UserActivity.InLobby lobby:
|
||||||
return lobby.Room.Name.Value;
|
return privacyMode.Value == DiscordRichPresenceMode.Limited ? string.Empty : lobby.Room.Name.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using osu.Desktop.Overlays;
|
using osu.Desktop.Overlays;
|
||||||
@ -56,16 +57,16 @@ namespace osu.Desktop
|
|||||||
|
|
||||||
string stableInstallPath;
|
string stableInstallPath;
|
||||||
|
|
||||||
try
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
|
try
|
||||||
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
|
{
|
||||||
|
stableInstallPath = getStableInstallPathFromRegistry();
|
||||||
|
|
||||||
if (checkExists(stableInstallPath))
|
if (!string.IsNullOrEmpty(stableInstallPath) && checkExists(stableInstallPath))
|
||||||
return stableInstallPath;
|
return stableInstallPath;
|
||||||
}
|
}
|
||||||
catch
|
catch { }
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!");
|
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!");
|
||||||
@ -79,6 +80,13 @@ namespace osu.Desktop
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
private string getStableInstallPathFromRegistry()
|
||||||
|
{
|
||||||
|
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
|
||||||
|
return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
|
||||||
|
}
|
||||||
|
|
||||||
protected override UpdateManager CreateUpdateManager()
|
protected override UpdateManager CreateUpdateManager()
|
||||||
{
|
{
|
||||||
switch (RuntimeInfo.OS)
|
switch (RuntimeInfo.OS)
|
||||||
|
@ -26,9 +26,11 @@ namespace osu.Desktop.Overlays
|
|||||||
|
|
||||||
Alpha = 0;
|
Alpha = 0;
|
||||||
|
|
||||||
|
FillFlowContainer mainFill;
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new FillFlowContainer
|
mainFill = new FillFlowContainer
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
@ -55,23 +57,30 @@ namespace osu.Desktop.Overlays
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Font = OsuFont.Numeric.With(size: 12),
|
|
||||||
Colour = colours.Yellow,
|
|
||||||
Text = @"Development Build"
|
|
||||||
},
|
|
||||||
new Sprite
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Texture = textures.Get(@"Menu/dev-build-footer"),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!game.IsDeployedBuild)
|
||||||
|
{
|
||||||
|
mainFill.AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Font = OsuFont.Numeric.With(size: 12),
|
||||||
|
Colour = colours.Yellow,
|
||||||
|
Text = @"Development Build"
|
||||||
|
},
|
||||||
|
new Sprite
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Texture = textures.Get(@"Menu/dev-build-footer"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<description>A free-to-win rhythm game. Rhythm is just a *click* away!</description>
|
<description>A free-to-win rhythm game. Rhythm is just a *click* away!</description>
|
||||||
<releaseNotes>testing</releaseNotes>
|
<releaseNotes>testing</releaseNotes>
|
||||||
<copyright>Copyright (c) 2020 ppy Pty Ltd</copyright>
|
<copyright>Copyright (c) 2021 ppy Pty Ltd</copyright>
|
||||||
<language>en-AU</language>
|
<language>en-AU</language>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
|
@ -59,8 +59,8 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
{
|
{
|
||||||
base.ApplySettings(difficulty);
|
base.ApplySettings(difficulty);
|
||||||
|
|
||||||
difficulty.CircleSize = CircleSize.Value;
|
ApplySetting(CircleSize, cs => difficulty.CircleSize = cs);
|
||||||
difficulty.ApproachRate = ApproachRate.Value;
|
ApplySetting(ApproachRate, ar => difficulty.ApproachRate = ar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
@ -18,8 +22,23 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
|||||||
public void TestNoAdjustment() => CreateModTest(new ModTestData
|
public void TestNoAdjustment() => CreateModTest(new ModTestData
|
||||||
{
|
{
|
||||||
Mod = new OsuModDifficultyAdjust(),
|
Mod = new OsuModDifficultyAdjust(),
|
||||||
|
Beatmap = new Beatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo = new BeatmapInfo
|
||||||
|
{
|
||||||
|
BaseDifficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
CircleSize = 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
HitObjects = new List<HitObject>
|
||||||
|
{
|
||||||
|
new HitCircle { StartTime = 1000 },
|
||||||
|
new HitCircle { StartTime = 2000 }
|
||||||
|
}
|
||||||
|
},
|
||||||
Autoplay = true,
|
Autoplay = true,
|
||||||
PassCondition = checkSomeHit
|
PassCondition = () => checkSomeHit() && checkObjectsScale(0.29f)
|
||||||
});
|
});
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
@ -34,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
public void TestLongSpinner(bool autoplay)
|
public void TestLongSpinner(bool autoplay)
|
||||||
{
|
{
|
||||||
AddStep("Very short spinner", () => SetContents(() => testSingle(5, autoplay, 2000)));
|
AddStep("Very long spinner", () => SetContents(() => testSingle(5, autoplay, 4000)));
|
||||||
AddUntilStep("Wait for completion", () => drawableSpinner.Result.HasResult);
|
AddUntilStep("Wait for completion", () => drawableSpinner.Result.HasResult);
|
||||||
AddUntilStep("Check correct progress", () => drawableSpinner.Progress == (autoplay ? 1 : 0));
|
AddUntilStep("Check correct progress", () => drawableSpinner.Progress == (autoplay ? 1 : 0));
|
||||||
}
|
}
|
||||||
@ -55,7 +57,11 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
var spinner = new Spinner
|
var spinner = new Spinner
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + delay,
|
StartTime = Time.Current + delay,
|
||||||
EndTime = Time.Current + delay + length
|
EndTime = Time.Current + delay + length,
|
||||||
|
Samples = new List<HitSampleInfo>
|
||||||
|
{
|
||||||
|
new HitSampleInfo("hitnormal")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
|
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
|
@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
if (Attributes.ApproachRate > 10.33)
|
if (Attributes.ApproachRate > 10.33)
|
||||||
approachRateFactor += 0.4 * (Attributes.ApproachRate - 10.33);
|
approachRateFactor += 0.4 * (Attributes.ApproachRate - 10.33);
|
||||||
else if (Attributes.ApproachRate < 8.0)
|
else if (Attributes.ApproachRate < 8.0)
|
||||||
approachRateFactor += 0.1 * (8.0 - Attributes.ApproachRate);
|
approachRateFactor += 0.01 * (8.0 - Attributes.ApproachRate);
|
||||||
|
|
||||||
aimValue *= 1.0 + Math.Min(approachRateFactor, approachRateFactor * (totalHits / 1000.0));
|
aimValue *= 1.0 + Math.Min(approachRateFactor, approachRateFactor * (totalHits / 1000.0));
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
{
|
{
|
||||||
base.ApplySettings(difficulty);
|
base.ApplySettings(difficulty);
|
||||||
|
|
||||||
difficulty.CircleSize = CircleSize.Value;
|
ApplySetting(CircleSize, cs => difficulty.CircleSize = cs);
|
||||||
difficulty.ApproachRate = ApproachRate.Value;
|
ApplySetting(ApproachRate, ar => difficulty.ApproachRate = ar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
[TestCase("sample-to-type-conversions")]
|
[TestCase("sample-to-type-conversions")]
|
||||||
[TestCase("slider-conversion-v6")]
|
[TestCase("slider-conversion-v6")]
|
||||||
[TestCase("slider-conversion-v14")]
|
[TestCase("slider-conversion-v14")]
|
||||||
|
[TestCase("slider-generating-drumroll-2")]
|
||||||
public void Test(string name) => base.Test(name);
|
public void Test(string name) => base.Test(name);
|
||||||
|
|
||||||
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
|
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||||
|
@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool shouldConvertSliderToHits(HitObject obj, IBeatmap beatmap, IHasDistance distanceData, out double taikoDuration, out double tickSpacing)
|
private bool shouldConvertSliderToHits(HitObject obj, IBeatmap beatmap, IHasDistance distanceData, out int taikoDuration, out double tickSpacing)
|
||||||
{
|
{
|
||||||
// DO NOT CHANGE OR REFACTOR ANYTHING IN HERE WITHOUT TESTING AGAINST _ALL_ BEATMAPS.
|
// DO NOT CHANGE OR REFACTOR ANYTHING IN HERE WITHOUT TESTING AGAINST _ALL_ BEATMAPS.
|
||||||
// Some of these calculations look redundant, but they are not - extremely small floating point errors are introduced to maintain 1:1 compatibility with stable.
|
// Some of these calculations look redundant, but they are not - extremely small floating point errors are introduced to maintain 1:1 compatibility with stable.
|
||||||
@ -185,7 +185,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
|
|
||||||
// The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll.
|
// The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll.
|
||||||
double taikoVelocity = sliderScoringPointDistance * beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate;
|
double taikoVelocity = sliderScoringPointDistance * beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate;
|
||||||
taikoDuration = distance / taikoVelocity * beatLength;
|
taikoDuration = (int)(distance / taikoVelocity * beatLength);
|
||||||
|
|
||||||
if (isForCurrentRuleset)
|
if (isForCurrentRuleset)
|
||||||
{
|
{
|
||||||
@ -200,7 +200,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
beatLength = timingPoint.BeatLength;
|
beatLength = timingPoint.BeatLength;
|
||||||
|
|
||||||
// If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat
|
// If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat
|
||||||
tickSpacing = Math.Min(beatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, taikoDuration / spans);
|
tickSpacing = Math.Min(beatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, (double)taikoDuration / spans);
|
||||||
|
|
||||||
return tickSpacing > 0
|
return tickSpacing > 0
|
||||||
&& distance / osuVelocity * 1000 < 2 * beatLength;
|
&& distance / osuVelocity * 1000 < 2 * beatLength;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"Mappings": [{
|
"Mappings": [
|
||||||
|
{
|
||||||
"StartTime": 2000,
|
"StartTime": 2000,
|
||||||
"Objects": [{
|
"Objects": [
|
||||||
|
{
|
||||||
"StartTime": 2000,
|
"StartTime": 2000,
|
||||||
"EndTime": 2000,
|
"EndTime": 2000,
|
||||||
"IsRim": false,
|
"IsRim": false,
|
||||||
@ -23,7 +25,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"StartTime": 4000,
|
"StartTime": 4000,
|
||||||
"Objects": [{
|
"Objects": [
|
||||||
|
{
|
||||||
"StartTime": 4000,
|
"StartTime": 4000,
|
||||||
"EndTime": 4000,
|
"EndTime": 4000,
|
||||||
"IsRim": false,
|
"IsRim": false,
|
||||||
@ -45,7 +48,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"StartTime": 6000,
|
"StartTime": 6000,
|
||||||
"Objects": [{
|
"Objects": [
|
||||||
|
{
|
||||||
"StartTime": 6000,
|
"StartTime": 6000,
|
||||||
"EndTime": 6000,
|
"EndTime": 6000,
|
||||||
"IsRim": true,
|
"IsRim": true,
|
||||||
@ -76,300 +80,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"StartTime": 8000,
|
"StartTime": 8000,
|
||||||
"Objects": [{
|
"Objects": [
|
||||||
|
{
|
||||||
"StartTime": 8000,
|
"StartTime": 8000,
|
||||||
"EndTime": 8000,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8026,
|
|
||||||
"EndTime": 8026,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8053,
|
|
||||||
"EndTime": 8053,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8080,
|
|
||||||
"EndTime": 8080,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8107,
|
|
||||||
"EndTime": 8107,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8133,
|
|
||||||
"EndTime": 8133,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8160,
|
|
||||||
"EndTime": 8160,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8187,
|
|
||||||
"EndTime": 8187,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8214,
|
|
||||||
"EndTime": 8214,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8241,
|
|
||||||
"EndTime": 8241,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8267,
|
|
||||||
"EndTime": 8267,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8294,
|
|
||||||
"EndTime": 8294,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8321,
|
|
||||||
"EndTime": 8321,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8348,
|
|
||||||
"EndTime": 8348,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8374,
|
|
||||||
"EndTime": 8374,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8401,
|
|
||||||
"EndTime": 8401,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8428,
|
|
||||||
"EndTime": 8428,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8455,
|
|
||||||
"EndTime": 8455,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8482,
|
|
||||||
"EndTime": 8482,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8508,
|
|
||||||
"EndTime": 8508,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8535,
|
|
||||||
"EndTime": 8535,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8562,
|
|
||||||
"EndTime": 8562,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8589,
|
|
||||||
"EndTime": 8589,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8615,
|
|
||||||
"EndTime": 8615,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8642,
|
|
||||||
"EndTime": 8642,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8669,
|
|
||||||
"EndTime": 8669,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8696,
|
|
||||||
"EndTime": 8696,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8723,
|
|
||||||
"EndTime": 8723,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8749,
|
|
||||||
"EndTime": 8749,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8776,
|
|
||||||
"EndTime": 8776,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8803,
|
|
||||||
"EndTime": 8803,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8830,
|
|
||||||
"EndTime": 8830,
|
|
||||||
"IsRim": false,
|
|
||||||
"IsCentre": true,
|
|
||||||
"IsDrumRoll": false,
|
|
||||||
"IsSwell": false,
|
|
||||||
"IsStrong": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"StartTime": 8857,
|
|
||||||
"EndTime": 8857,
|
"EndTime": 8857,
|
||||||
"IsRim": false,
|
"IsRim": false,
|
||||||
"IsCentre": true,
|
"IsCentre": false,
|
||||||
"IsDrumRoll": false,
|
"IsDrumRoll": true,
|
||||||
"IsSwell": false,
|
"IsSwell": false,
|
||||||
"IsStrong": false
|
"IsStrong": false
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"Mappings": [
|
||||||
|
{
|
||||||
|
"StartTime": 51532,
|
||||||
|
"Objects": [
|
||||||
|
{
|
||||||
|
"StartTime": 51532,
|
||||||
|
"EndTime": 52301,
|
||||||
|
"IsRim": false,
|
||||||
|
"IsCentre": false,
|
||||||
|
"IsDrumRoll": true,
|
||||||
|
"IsSwell": false,
|
||||||
|
"IsStrong": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
Mode: 0
|
||||||
|
|
||||||
|
[Difficulty]
|
||||||
|
HPDrainRate:2
|
||||||
|
CircleSize:3.2
|
||||||
|
OverallDifficulty:2
|
||||||
|
ApproachRate:3
|
||||||
|
SliderMultiplier:0.999999999999999
|
||||||
|
SliderTickRate:1
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
763,384.615384615385,4,2,0,70,1,0
|
||||||
|
49993,-90.9090909090909,4,2,0,75,0,1
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
51,245,51532,2,0,P|18:150|17:122,2,110.000003356934,0|8|0,0:0|0:0|0:0,0:0:0:0:
|
@ -95,6 +95,26 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOutOfOrderStartTimes()
|
||||||
|
{
|
||||||
|
var decoder = new LegacyStoryboardDecoder();
|
||||||
|
|
||||||
|
using (var resStream = TestResources.OpenResource("out-of-order-starttimes.osb"))
|
||||||
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
|
{
|
||||||
|
var storyboard = decoder.Decode(stream);
|
||||||
|
|
||||||
|
StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3);
|
||||||
|
Assert.AreEqual(2, background.Elements.Count);
|
||||||
|
|
||||||
|
Assert.AreEqual(1500, background.Elements[0].StartTime);
|
||||||
|
Assert.AreEqual(1000, background.Elements[1].StartTime);
|
||||||
|
|
||||||
|
Assert.AreEqual(1000, storyboard.EarliestEventTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDecodeVariableWithSuffix()
|
public void TestDecodeVariableWithSuffix()
|
||||||
{
|
{
|
||||||
|
@ -246,5 +246,32 @@ namespace osu.Game.Tests.NonVisual
|
|||||||
Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0));
|
Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0));
|
||||||
Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(0));
|
Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCreateCopyIsDeepClone()
|
||||||
|
{
|
||||||
|
var cpi = new ControlPointInfo();
|
||||||
|
|
||||||
|
cpi.Add(1000, new TimingControlPoint { BeatLength = 500 });
|
||||||
|
|
||||||
|
var cpiCopy = cpi.CreateCopy();
|
||||||
|
|
||||||
|
cpiCopy.Add(2000, new TimingControlPoint { BeatLength = 500 });
|
||||||
|
|
||||||
|
Assert.That(cpi.Groups.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(cpiCopy.Groups.Count, Is.EqualTo(2));
|
||||||
|
|
||||||
|
Assert.That(cpi.TimingPoints.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(cpiCopy.TimingPoints.Count, Is.EqualTo(2));
|
||||||
|
|
||||||
|
Assert.That(cpi.TimingPoints[0], Is.Not.SameAs(cpiCopy.TimingPoints[0]));
|
||||||
|
Assert.That(cpi.TimingPoints[0].BeatLengthBindable, Is.Not.SameAs(cpiCopy.TimingPoints[0].BeatLengthBindable));
|
||||||
|
|
||||||
|
Assert.That(cpi.TimingPoints[0].BeatLength, Is.EqualTo(cpiCopy.TimingPoints[0].BeatLength));
|
||||||
|
|
||||||
|
cpi.TimingPoints[0].BeatLength = 800;
|
||||||
|
|
||||||
|
Assert.That(cpi.TimingPoints[0].BeatLength, Is.Not.EqualTo(cpiCopy.TimingPoints[0].BeatLength));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6
osu.Game.Tests/Resources/out-of-order-starttimes.osb
Normal file
6
osu.Game.Tests/Resources/out-of-order-starttimes.osb
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[Events]
|
||||||
|
//Storyboard Layer 0 (Background)
|
||||||
|
Sprite,Background,TopCentre,"img.jpg",320,240
|
||||||
|
F,0,1500,1600,0,1
|
||||||
|
Sprite,Background,TopCentre,"img.jpg",320,240
|
||||||
|
F,0,1000,1100,0,1
|
@ -82,7 +82,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
});
|
});
|
||||||
AddUntilStep("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied());
|
AddUntilStep("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied());
|
||||||
AddStep("Stop background preview", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
|
AddStep("Stop background preview", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
|
||||||
AddUntilStep("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && playerLoader.IsBlurCorrect());
|
AddUntilStep("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && songSelect.CheckBackgroundBlur(playerLoader.ExpectedBackgroundBlur));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -106,6 +106,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
public void TestStoryboardBackgroundVisibility()
|
public void TestStoryboardBackgroundVisibility()
|
||||||
{
|
{
|
||||||
performFullSetup();
|
performFullSetup();
|
||||||
|
AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent());
|
||||||
createFakeStoryboard();
|
createFakeStoryboard();
|
||||||
AddStep("Enable Storyboard", () =>
|
AddStep("Enable Storyboard", () =>
|
||||||
{
|
{
|
||||||
@ -198,8 +199,9 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
})));
|
})));
|
||||||
|
|
||||||
AddUntilStep("Wait for results is current", () => results.IsCurrentScreen());
|
AddUntilStep("Wait for results is current", () => results.IsCurrentScreen());
|
||||||
|
|
||||||
AddUntilStep("Screen is undimmed, original background retained", () =>
|
AddUntilStep("Screen is undimmed, original background retained", () =>
|
||||||
songSelect.IsBackgroundUndimmed() && songSelect.IsBackgroundCurrent() && results.IsBlurCorrect());
|
songSelect.IsBackgroundUndimmed() && songSelect.IsBackgroundCurrent() && songSelect.CheckBackgroundBlur(results.ExpectedBackgroundBlur));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -224,7 +226,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
AddStep("Resume PlayerLoader", () => player.Restart());
|
AddStep("Resume PlayerLoader", () => player.Restart());
|
||||||
AddUntilStep("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied());
|
AddUntilStep("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied());
|
||||||
AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
|
AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
|
||||||
AddUntilStep("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && playerLoader.IsBlurCorrect());
|
AddUntilStep("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && songSelect.CheckBackgroundBlur(playerLoader.ExpectedBackgroundBlur));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createFakeStoryboard() => AddStep("Create storyboard", () =>
|
private void createFakeStoryboard() => AddStep("Create storyboard", () =>
|
||||||
@ -274,9 +276,11 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
|
|
||||||
private class DummySongSelect : PlaySongSelect
|
private class DummySongSelect : PlaySongSelect
|
||||||
{
|
{
|
||||||
|
private FadeAccessibleBackground background;
|
||||||
|
|
||||||
protected override BackgroundScreen CreateBackground()
|
protected override BackgroundScreen CreateBackground()
|
||||||
{
|
{
|
||||||
FadeAccessibleBackground background = new FadeAccessibleBackground(Beatmap.Value);
|
background = new FadeAccessibleBackground(Beatmap.Value);
|
||||||
DimEnabled.BindTo(background.EnableUserDim);
|
DimEnabled.BindTo(background.EnableUserDim);
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
@ -294,25 +298,27 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
config.BindWith(OsuSetting.BlurLevel, BlurLevel);
|
config.BindWith(OsuSetting.BlurLevel, BlurLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsBackgroundDimmed() => ((FadeAccessibleBackground)Background).CurrentColour == OsuColour.Gray(1f - ((FadeAccessibleBackground)Background).CurrentDim);
|
public bool IsBackgroundDimmed() => background.CurrentColour == OsuColour.Gray(1f - background.CurrentDim);
|
||||||
|
|
||||||
public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == Color4.White;
|
public bool IsBackgroundUndimmed() => background.CurrentColour == Color4.White;
|
||||||
|
|
||||||
public bool IsUserBlurApplied() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2((float)BlurLevel.Value * BackgroundScreenBeatmap.USER_BLUR_FACTOR);
|
public bool IsUserBlurApplied() => background.CurrentBlur == new Vector2((float)BlurLevel.Value * BackgroundScreenBeatmap.USER_BLUR_FACTOR);
|
||||||
|
|
||||||
public bool IsUserBlurDisabled() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(0);
|
public bool IsUserBlurDisabled() => background.CurrentBlur == new Vector2(0);
|
||||||
|
|
||||||
public bool IsBackgroundInvisible() => ((FadeAccessibleBackground)Background).CurrentAlpha == 0;
|
public bool IsBackgroundInvisible() => background.CurrentAlpha == 0;
|
||||||
|
|
||||||
public bool IsBackgroundVisible() => ((FadeAccessibleBackground)Background).CurrentAlpha == 1;
|
public bool IsBackgroundVisible() => background.CurrentAlpha == 1;
|
||||||
|
|
||||||
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
public bool IsBlurCorrect() => background.CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
||||||
|
|
||||||
|
public bool CheckBackgroundBlur(Vector2 expected) => background.CurrentBlur == expected;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Make sure every time a screen gets pushed, the background doesn't get replaced
|
/// Make sure every time a screen gets pushed, the background doesn't get replaced
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Whether or not the original background (The one created in DummySongSelect) is still the current background</returns>
|
/// <returns>Whether or not the original background (The one created in DummySongSelect) is still the current background</returns>
|
||||||
public bool IsBackgroundCurrent() => ((FadeAccessibleBackground)Background).IsCurrentScreen();
|
public bool IsBackgroundCurrent() => background?.IsCurrentScreen() == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FadeAccessibleResults : ResultsScreen
|
private class FadeAccessibleResults : ResultsScreen
|
||||||
@ -324,12 +330,20 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
|
|
||||||
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
||||||
|
|
||||||
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
public Vector2 ExpectedBackgroundBlur => new Vector2(BACKGROUND_BLUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LoadBlockingTestPlayer : TestPlayer
|
private class LoadBlockingTestPlayer : TestPlayer
|
||||||
{
|
{
|
||||||
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
protected override BackgroundScreen CreateBackground() =>
|
||||||
|
new FadeAccessibleBackground(Beatmap.Value);
|
||||||
|
|
||||||
|
public override void OnEntering(IScreen last)
|
||||||
|
{
|
||||||
|
base.OnEntering(last);
|
||||||
|
|
||||||
|
ApplyToBackground(b => ReplacesBackground.BindTo(b.StoryboardReplacesBackground));
|
||||||
|
}
|
||||||
|
|
||||||
public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard;
|
public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard;
|
||||||
|
|
||||||
@ -354,15 +368,16 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
|
|
||||||
StoryboardEnabled = config.GetBindable<bool>(OsuSetting.ShowStoryboard);
|
StoryboardEnabled = config.GetBindable<bool>(OsuSetting.ShowStoryboard);
|
||||||
ReplacesBackground.BindTo(Background.StoryboardReplacesBackground);
|
|
||||||
DrawableRuleset.IsPaused.BindTo(IsPaused);
|
DrawableRuleset.IsPaused.BindTo(IsPaused);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestPlayerLoader : PlayerLoader
|
private class TestPlayerLoader : PlayerLoader
|
||||||
{
|
{
|
||||||
|
private FadeAccessibleBackground background;
|
||||||
|
|
||||||
public VisualSettings VisualSettingsPos => VisualSettings;
|
public VisualSettings VisualSettingsPos => VisualSettings;
|
||||||
public BackgroundScreen ScreenPos => Background;
|
public BackgroundScreen ScreenPos => background;
|
||||||
|
|
||||||
public TestPlayerLoader(Player player)
|
public TestPlayerLoader(Player player)
|
||||||
: base(() => player)
|
: base(() => player)
|
||||||
@ -371,9 +386,9 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
|
|
||||||
public void TriggerOnHover() => OnHover(new HoverEvent(new InputState()));
|
public void TriggerOnHover() => OnHover(new HoverEvent(new InputState()));
|
||||||
|
|
||||||
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
public Vector2 ExpectedBackgroundBlur => new Vector2(BACKGROUND_BLUR);
|
||||||
|
|
||||||
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
protected override BackgroundScreen CreateBackground() => background = new FadeAccessibleBackground(Beatmap.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FadeAccessibleBackground : BackgroundScreenBeatmap
|
private class FadeAccessibleBackground : BackgroundScreenBeatmap
|
||||||
|
@ -244,7 +244,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
||||||
{
|
{
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => new[]
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => new[]
|
||||||
{
|
{
|
||||||
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
||||||
};
|
};
|
||||||
|
@ -179,7 +179,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
||||||
{
|
{
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => new[]
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => new[]
|
||||||
{
|
{
|
||||||
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -74,6 +75,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
switch (args.Action)
|
switch (args.Action)
|
||||||
{
|
{
|
||||||
case NotifyCollectionChangedAction.Add:
|
case NotifyCollectionChangedAction.Add:
|
||||||
|
Debug.Assert(args.NewItems != null);
|
||||||
|
|
||||||
foreach (int user in args.NewItems)
|
foreach (int user in args.NewItems)
|
||||||
{
|
{
|
||||||
if (user == api.LocalUser.Value.Id)
|
if (user == api.LocalUser.Value.Id)
|
||||||
@ -83,6 +86,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NotifyCollectionChangedAction.Remove:
|
case NotifyCollectionChangedAction.Remove:
|
||||||
|
Debug.Assert(args.OldItems != null);
|
||||||
|
|
||||||
foreach (int user in args.OldItems)
|
foreach (int user in args.OldItems)
|
||||||
{
|
{
|
||||||
if (user == api.LocalUser.Value.Id)
|
if (user == api.LocalUser.Value.Id)
|
||||||
@ -298,7 +303,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
||||||
{
|
{
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => new[]
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => new[]
|
||||||
{
|
{
|
||||||
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Multiplayer
|
||||||
|
{
|
||||||
|
public class TestSceneCreateMultiplayerMatchButton : MultiplayerTestScene
|
||||||
|
{
|
||||||
|
private CreateMultiplayerMatchButton button;
|
||||||
|
|
||||||
|
public override void SetUpSteps()
|
||||||
|
{
|
||||||
|
base.SetUpSteps();
|
||||||
|
AddStep("create button", () => Child = button = new CreateMultiplayerMatchButton
|
||||||
|
{
|
||||||
|
Width = 200,
|
||||||
|
Height = 100,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestButtonEnableStateChanges()
|
||||||
|
{
|
||||||
|
IDisposable joiningRoomOperation = null;
|
||||||
|
|
||||||
|
assertButtonEnableState(true);
|
||||||
|
|
||||||
|
AddStep("begin joining room", () => joiningRoomOperation = OngoingOperationTracker.BeginOperation());
|
||||||
|
assertButtonEnableState(false);
|
||||||
|
|
||||||
|
AddStep("end joining room", () => joiningRoomOperation.Dispose());
|
||||||
|
assertButtonEnableState(true);
|
||||||
|
|
||||||
|
AddStep("disconnect client", () => Client.Disconnect());
|
||||||
|
assertButtonEnableState(false);
|
||||||
|
|
||||||
|
AddStep("re-connect client", () => Client.Connect());
|
||||||
|
assertButtonEnableState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertButtonEnableState(bool enabled)
|
||||||
|
=> AddAssert($"button {(enabled ? "enabled" : "disabled")}", () => button.Enabled.Value == enabled);
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Screens.OnlinePlay;
|
||||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
@ -18,6 +20,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
private MultiplayerMatchSubScreen screen;
|
private MultiplayerMatchSubScreen screen;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private OngoingOperationTracker ongoingOperationTracker = new OngoingOperationTracker();
|
||||||
|
|
||||||
public TestSceneMultiplayerMatchSubScreen()
|
public TestSceneMultiplayerMatchSubScreen()
|
||||||
: base(false)
|
: base(false)
|
||||||
{
|
{
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -23,10 +26,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
public class TestSceneMultiplayerReadyButton : MultiplayerTestScene
|
public class TestSceneMultiplayerReadyButton : MultiplayerTestScene
|
||||||
{
|
{
|
||||||
private MultiplayerReadyButton button;
|
private MultiplayerReadyButton button;
|
||||||
|
private BeatmapSetInfo importedSet;
|
||||||
|
|
||||||
private BeatmapManager beatmaps;
|
private BeatmapManager beatmaps;
|
||||||
private RulesetStore rulesets;
|
private RulesetStore rulesets;
|
||||||
|
|
||||||
|
private IDisposable readyClickOperation;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(GameHost host, AudioManager audio)
|
private void load(GameHost host, AudioManager audio)
|
||||||
{
|
{
|
||||||
@ -38,9 +44,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
[SetUp]
|
[SetUp]
|
||||||
public new void Setup() => Schedule(() =>
|
public new void Setup() => Schedule(() =>
|
||||||
{
|
{
|
||||||
var beatmap = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First().Beatmaps.First();
|
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
|
||||||
|
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
|
||||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap);
|
|
||||||
|
|
||||||
Child = button = new MultiplayerReadyButton
|
Child = button = new MultiplayerReadyButton
|
||||||
{
|
{
|
||||||
@ -51,13 +56,43 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
Value = new PlaylistItem
|
Value = new PlaylistItem
|
||||||
{
|
{
|
||||||
Beatmap = { Value = beatmap },
|
Beatmap = { Value = Beatmap.Value.BeatmapInfo },
|
||||||
Ruleset = { Value = beatmap.Ruleset }
|
Ruleset = { Value = Beatmap.Value.BeatmapInfo.Ruleset }
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
OnReadyClick = async () =>
|
||||||
|
{
|
||||||
|
readyClickOperation = OngoingOperationTracker.BeginOperation();
|
||||||
|
|
||||||
|
if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready)
|
||||||
|
{
|
||||||
|
await Client.StartMatch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Client.ToggleReady();
|
||||||
|
readyClickOperation.Dispose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDeletedBeatmapDisableReady()
|
||||||
|
{
|
||||||
|
OsuButton readyButton = null;
|
||||||
|
|
||||||
|
AddAssert("ensure ready button enabled", () =>
|
||||||
|
{
|
||||||
|
readyButton = button.ChildrenOfType<OsuButton>().Single();
|
||||||
|
return readyButton.Enabled.Value;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
|
||||||
|
AddAssert("ready button disabled", () => !readyButton.Enabled.Value);
|
||||||
|
AddStep("undelete beatmap", () => beatmaps.Undelete(importedSet));
|
||||||
|
AddAssert("ready button enabled back", () => readyButton.Enabled.Value);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestToggleStateWhenNotHost()
|
public void TestToggleStateWhenNotHost()
|
||||||
{
|
{
|
||||||
@ -89,8 +124,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
addClickButtonStep();
|
addClickButtonStep();
|
||||||
AddAssert("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready);
|
AddAssert("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready);
|
||||||
|
|
||||||
addClickButtonStep();
|
verifyGameplayStartFlow();
|
||||||
AddAssert("match started", () => Client.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -105,8 +139,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
addClickButtonStep();
|
addClickButtonStep();
|
||||||
AddStep("make user host", () => Client.TransferHost(Client.Room?.Users[0].UserID ?? 0));
|
AddStep("make user host", () => Client.TransferHost(Client.Room?.Users[0].UserID ?? 0));
|
||||||
|
|
||||||
addClickButtonStep();
|
verifyGameplayStartFlow();
|
||||||
AddAssert("match started", () => Client.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -160,5 +193,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
InputManager.MoveMouseTo(button);
|
InputManager.MoveMouseTo(button);
|
||||||
InputManager.Click(MouseButton.Left);
|
InputManager.Click(MouseButton.Left);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
private void verifyGameplayStartFlow()
|
||||||
|
{
|
||||||
|
addClickButtonStep();
|
||||||
|
AddAssert("user waiting for load", () => Client.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad);
|
||||||
|
AddAssert("ready button disabled", () => !button.ChildrenOfType<OsuButton>().Single().Enabled.Value);
|
||||||
|
|
||||||
|
AddStep("transitioned to gameplay", () => readyClickOperation.Dispose());
|
||||||
|
AddAssert("ready button enabled", () => button.ChildrenOfType<OsuButton>().Single().Enabled.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
RoomManager =
|
RoomManager =
|
||||||
{
|
{
|
||||||
TimeBetweenListingPolls = { Value = 1 },
|
TimeBetweenListingPolls = { Value = 1 },
|
||||||
|
TimeBetweenSelectionPolls = { Value = 1 }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Screens.Select.Details;
|
using osu.Game.Screens.Select.Details;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -141,16 +142,12 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
AddStep("select changed Difficulty Adjust mod", () =>
|
AddStep("select changed Difficulty Adjust mod", () =>
|
||||||
{
|
{
|
||||||
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
var difficultyAdjustMod = ruleset.GetAllMods().OfType<ModDifficultyAdjust>().Single();
|
var difficultyAdjustMod = ruleset.GetAllMods().OfType<OsuModDifficultyAdjust>().Single();
|
||||||
var originalDifficulty = advancedStats.Beatmap.BaseDifficulty;
|
var originalDifficulty = advancedStats.Beatmap.BaseDifficulty;
|
||||||
var adjustedDifficulty = new BeatmapDifficulty
|
|
||||||
{
|
difficultyAdjustMod.ReadFromDifficulty(originalDifficulty);
|
||||||
CircleSize = originalDifficulty.CircleSize,
|
difficultyAdjustMod.DrainRate.Value = originalDifficulty.DrainRate - 0.5f;
|
||||||
DrainRate = originalDifficulty.DrainRate - 0.5f,
|
difficultyAdjustMod.ApproachRate.Value = originalDifficulty.ApproachRate + 2.2f;
|
||||||
OverallDifficulty = originalDifficulty.OverallDifficulty,
|
|
||||||
ApproachRate = originalDifficulty.ApproachRate + 2.2f,
|
|
||||||
};
|
|
||||||
difficultyAdjustMod.ReadFromDifficulty(adjustedDifficulty);
|
|
||||||
SelectedMods.Value = new[] { difficultyAdjustMod };
|
SelectedMods.Value = new[] { difficultyAdjustMod };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -14,8 +15,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
{
|
{
|
||||||
public class TestSceneLoadingLayer : OsuTestScene
|
public class TestSceneLoadingLayer : OsuTestScene
|
||||||
{
|
{
|
||||||
private Drawable dimContent;
|
private TestLoadingLayer overlay;
|
||||||
private LoadingLayer overlay;
|
|
||||||
|
|
||||||
private Container content;
|
private Container content;
|
||||||
|
|
||||||
@ -29,14 +29,14 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Size = new Vector2(300),
|
Size = new Vector2(300),
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Children = new[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
Colour = Color4.SlateGray,
|
Colour = Color4.SlateGray,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
dimContent = new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -51,7 +51,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
new TriangleButton { Text = "puush me", Width = 200, Action = () => { } },
|
new TriangleButton { Text = "puush me", Width = 200, Action = () => { } },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
overlay = new LoadingLayer(dimContent),
|
overlay = new TestLoadingLayer(true),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -64,25 +64,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
AddStep("show", () => overlay.Show());
|
AddStep("show", () => overlay.Show());
|
||||||
|
|
||||||
AddUntilStep("wait for content dim", () => dimContent.Colour != Color4.White);
|
AddUntilStep("wait for content dim", () => overlay.BackgroundDimLayer.Alpha > 0);
|
||||||
|
|
||||||
AddStep("hide", () => overlay.Hide());
|
AddStep("hide", () => overlay.Hide());
|
||||||
|
|
||||||
AddUntilStep("wait for content restore", () => dimContent.Colour == Color4.White);
|
AddUntilStep("wait for content restore", () => Precision.AlmostEquals(overlay.BackgroundDimLayer.Alpha, 0));
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestContentRestoreOnDispose()
|
|
||||||
{
|
|
||||||
AddAssert("not visible", () => !overlay.IsPresent);
|
|
||||||
|
|
||||||
AddStep("show", () => overlay.Show());
|
|
||||||
|
|
||||||
AddUntilStep("wait for content dim", () => dimContent.Colour != Color4.White);
|
|
||||||
|
|
||||||
AddStep("expire", () => overlay.Expire());
|
|
||||||
|
|
||||||
AddUntilStep("wait for content restore", () => dimContent.Colour == Color4.White);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -98,5 +84,15 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
AddStep("hide", () => overlay.Hide());
|
AddStep("hide", () => overlay.Hide());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestLoadingLayer : LoadingLayer
|
||||||
|
{
|
||||||
|
public new Box BackgroundDimLayer => base.BackgroundDimLayer;
|
||||||
|
|
||||||
|
public TestLoadingLayer(bool dimBackground = false, bool withBox = true)
|
||||||
|
: base(dimBackground, withBox)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,18 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
AddAssert("ensure mods not selected", () => modDisplay.Current.Value.Count == 0);
|
AddAssert("ensure mods not selected", () => modDisplay.Current.Value.Count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestExternallySetCustomizedMod()
|
||||||
|
{
|
||||||
|
AddStep("set customized mod externally", () => SelectedMods.Value = new[] { new OsuModDoubleTime { SpeedChange = { Value = 1.01 } } });
|
||||||
|
|
||||||
|
AddAssert("ensure button is selected and customized accordingly", () =>
|
||||||
|
{
|
||||||
|
var button = modSelect.GetModButton(SelectedMods.Value.Single());
|
||||||
|
return ((OsuModDoubleTime)button.SelectedMod).SpeedChange.Value == 1.01;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void testSingleMod(Mod mod)
|
private void testSingleMod(Mod mod)
|
||||||
{
|
{
|
||||||
selectNext(mod);
|
selectNext(mod);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Tournament.Screens;
|
using osu.Game.Tournament.Screens.Setup;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Game.Tournament.Screens;
|
using osu.Game.Tournament.Screens.Setup;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Tests.Screens
|
namespace osu.Game.Tournament.Tests.Screens
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Game.IO;
|
using osu.Game.IO;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Game.Tournament.Configuration;
|
using osu.Game.Tournament.Configuration;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.IO
|
namespace osu.Game.Tournament.IO
|
||||||
@ -13,25 +15,39 @@ namespace osu.Game.Tournament.IO
|
|||||||
{
|
{
|
||||||
private const string default_tournament = "default";
|
private const string default_tournament = "default";
|
||||||
private readonly Storage storage;
|
private readonly Storage storage;
|
||||||
|
private readonly Storage allTournaments;
|
||||||
private readonly TournamentStorageManager storageConfig;
|
private readonly TournamentStorageManager storageConfig;
|
||||||
|
public readonly Bindable<string> CurrentTournament;
|
||||||
|
|
||||||
public TournamentStorage(Storage storage)
|
public TournamentStorage(Storage storage)
|
||||||
: base(storage.GetStorageForDirectory("tournaments"), string.Empty)
|
: base(storage.GetStorageForDirectory("tournaments"), string.Empty)
|
||||||
{
|
{
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
|
allTournaments = UnderlyingStorage;
|
||||||
|
|
||||||
storageConfig = new TournamentStorageManager(storage);
|
storageConfig = new TournamentStorageManager(storage);
|
||||||
|
|
||||||
if (storage.Exists("tournament.ini"))
|
if (storage.Exists("tournament.ini"))
|
||||||
{
|
{
|
||||||
ChangeTargetStorage(UnderlyingStorage.GetStorageForDirectory(storageConfig.Get<string>(StorageConfig.CurrentTournament)));
|
ChangeTargetStorage(allTournaments.GetStorageForDirectory(storageConfig.Get<string>(StorageConfig.CurrentTournament)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Migrate(UnderlyingStorage.GetStorageForDirectory(default_tournament));
|
Migrate(allTournaments.GetStorageForDirectory(default_tournament));
|
||||||
|
|
||||||
|
CurrentTournament = storageConfig.GetBindable<string>(StorageConfig.CurrentTournament);
|
||||||
Logger.Log("Using tournament storage: " + GetFullPath(string.Empty));
|
Logger.Log("Using tournament storage: " + GetFullPath(string.Empty));
|
||||||
|
|
||||||
|
CurrentTournament.BindValueChanged(updateTournament);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateTournament(ValueChangedEvent<string> newTournament)
|
||||||
|
{
|
||||||
|
ChangeTargetStorage(allTournaments.GetStorageForDirectory(newTournament.NewValue));
|
||||||
|
Logger.Log("Changing tournament storage: " + GetFullPath(string.Empty));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> ListTournaments() => allTournaments.GetDirectories(string.Empty);
|
||||||
|
|
||||||
public override void Migrate(Storage newStorage)
|
public override void Migrate(Storage newStorage)
|
||||||
{
|
{
|
||||||
// this migration only happens once on moving to the per-tournament storage system.
|
// this migration only happens once on moving to the per-tournament storage system.
|
||||||
|
65
osu.Game.Tournament/JsonPointConverter.cs
Normal file
65
osu.Game.Tournament/JsonPointConverter.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// We made a change from using SixLabors.ImageSharp.Point to System.Drawing.Point at some stage.
|
||||||
|
/// This handles converting to a standardised format on json serialize/deserialize operations.
|
||||||
|
/// </summary>
|
||||||
|
internal class JsonPointConverter : JsonConverter<Point>
|
||||||
|
{
|
||||||
|
public override void WriteJson(JsonWriter writer, Point value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
// use the format of LaborSharp's Point since it is nicer.
|
||||||
|
serializer.Serialize(writer, new { value.X, value.Y });
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Point ReadJson(JsonReader reader, Type objectType, Point existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonToken.StartObject)
|
||||||
|
{
|
||||||
|
// if there's no object present then this is using string representation (System.Drawing.Point serializes to "x,y")
|
||||||
|
string str = (string)reader.Value;
|
||||||
|
|
||||||
|
Debug.Assert(str != null);
|
||||||
|
|
||||||
|
return new PointConverter().ConvertFromString(str) as Point? ?? new Point();
|
||||||
|
}
|
||||||
|
|
||||||
|
var point = new Point();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.EndObject) break;
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
var name = reader.Value?.ToString();
|
||||||
|
int? val = reader.ReadAsInt32();
|
||||||
|
|
||||||
|
if (val == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "X":
|
||||||
|
point.X = val.Value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Y":
|
||||||
|
point.Y = val.Value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
osu.Game.Tournament/Screens/Setup/ActionableInfo.cs
Normal file
72
osu.Game.Tournament/Screens/Setup/ActionableInfo.cs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Screens.Setup
|
||||||
|
{
|
||||||
|
internal class ActionableInfo : LabelledDrawable<Drawable>
|
||||||
|
{
|
||||||
|
protected OsuButton Button;
|
||||||
|
|
||||||
|
public ActionableInfo()
|
||||||
|
: base(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ButtonText
|
||||||
|
{
|
||||||
|
set => Button.Text = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Value
|
||||||
|
{
|
||||||
|
set => valueText.Text = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Failing
|
||||||
|
{
|
||||||
|
set => valueText.Colour = value ? Color4.Red : Color4.White;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Action;
|
||||||
|
|
||||||
|
private TournamentSpriteText valueText;
|
||||||
|
protected FillFlowContainer FlowContainer;
|
||||||
|
|
||||||
|
protected override Drawable CreateComponent() => new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
valueText = new TournamentSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
},
|
||||||
|
FlowContainer = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Spacing = new Vector2(10, 0),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
Button = new TriangleButton
|
||||||
|
{
|
||||||
|
Size = new Vector2(100, 40),
|
||||||
|
Action = () => Action?.Invoke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
53
osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs
Normal file
53
osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Screens.Setup
|
||||||
|
{
|
||||||
|
internal class ResolutionSelector : ActionableInfo
|
||||||
|
{
|
||||||
|
private const int minimum_window_height = 480;
|
||||||
|
private const int maximum_window_height = 2160;
|
||||||
|
|
||||||
|
public new Action<int> Action;
|
||||||
|
|
||||||
|
private OsuNumberBox numberBox;
|
||||||
|
|
||||||
|
protected override Drawable CreateComponent()
|
||||||
|
{
|
||||||
|
var drawable = base.CreateComponent();
|
||||||
|
FlowContainer.Insert(-1, numberBox = new OsuNumberBox
|
||||||
|
{
|
||||||
|
Text = "1080",
|
||||||
|
Width = 100
|
||||||
|
});
|
||||||
|
|
||||||
|
base.Action = () =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(numberBox.Text))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// box contains text
|
||||||
|
if (!int.TryParse(numberBox.Text, out var number))
|
||||||
|
{
|
||||||
|
// at this point, the only reason we can arrive here is if the input number was too big to parse into an int
|
||||||
|
// so clamp to max allowed value
|
||||||
|
number = maximum_window_height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
number = Math.Clamp(number, minimum_window_height, maximum_window_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// in case number got clamped, reset number in numberBox
|
||||||
|
numberBox.Text = number.ToString();
|
||||||
|
|
||||||
|
Action?.Invoke(number);
|
||||||
|
};
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -17,9 +16,8 @@ using osu.Game.Rulesets;
|
|||||||
using osu.Game.Tournament.IPC;
|
using osu.Game.Tournament.IPC;
|
||||||
using osu.Game.Tournament.Models;
|
using osu.Game.Tournament.Models;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Screens
|
namespace osu.Game.Tournament.Screens.Setup
|
||||||
{
|
{
|
||||||
public class SetupScreen : TournamentScreen, IProvideVideo
|
public class SetupScreen : TournamentScreen, IProvideVideo
|
||||||
{
|
{
|
||||||
@ -64,9 +62,6 @@ namespace osu.Game.Tournament.Screens
|
|||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private Framework.Game game { get; set; }
|
|
||||||
|
|
||||||
private void reload()
|
private void reload()
|
||||||
{
|
{
|
||||||
var fileBasedIpc = ipc as FileBasedIPC;
|
var fileBasedIpc = ipc as FileBasedIPC;
|
||||||
@ -111,6 +106,11 @@ namespace osu.Game.Tournament.Screens
|
|||||||
Items = rulesets.AvailableRulesets,
|
Items = rulesets.AvailableRulesets,
|
||||||
Current = LadderInfo.Ruleset,
|
Current = LadderInfo.Ruleset,
|
||||||
},
|
},
|
||||||
|
new TournamentSwitcher
|
||||||
|
{
|
||||||
|
Label = "Current tournament",
|
||||||
|
Description = "Changes the background videos and bracket to match the selected tournament. This requires a restart to apply changes.",
|
||||||
|
},
|
||||||
resolution = new ResolutionSelector
|
resolution = new ResolutionSelector
|
||||||
{
|
{
|
||||||
Label = "Stream area resolution",
|
Label = "Stream area resolution",
|
||||||
@ -151,108 +151,5 @@ namespace osu.Game.Tournament.Screens
|
|||||||
Width = 0.5f,
|
Width = 0.5f,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ActionableInfo : LabelledDrawable<Drawable>
|
|
||||||
{
|
|
||||||
private OsuButton button;
|
|
||||||
|
|
||||||
public ActionableInfo()
|
|
||||||
: base(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ButtonText
|
|
||||||
{
|
|
||||||
set => button.Text = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Value
|
|
||||||
{
|
|
||||||
set => valueText.Text = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Failing
|
|
||||||
{
|
|
||||||
set => valueText.Colour = value ? Color4.Red : Color4.White;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action Action;
|
|
||||||
|
|
||||||
private TournamentSpriteText valueText;
|
|
||||||
protected FillFlowContainer FlowContainer;
|
|
||||||
|
|
||||||
protected override Drawable CreateComponent() => new Container
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
valueText = new TournamentSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
},
|
|
||||||
FlowContainer = new FillFlowContainer
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Spacing = new Vector2(10, 0),
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
button = new TriangleButton
|
|
||||||
{
|
|
||||||
Size = new Vector2(100, 40),
|
|
||||||
Action = () => Action?.Invoke()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ResolutionSelector : ActionableInfo
|
|
||||||
{
|
|
||||||
private const int minimum_window_height = 480;
|
|
||||||
private const int maximum_window_height = 2160;
|
|
||||||
|
|
||||||
public new Action<int> Action;
|
|
||||||
|
|
||||||
private OsuNumberBox numberBox;
|
|
||||||
|
|
||||||
protected override Drawable CreateComponent()
|
|
||||||
{
|
|
||||||
var drawable = base.CreateComponent();
|
|
||||||
FlowContainer.Insert(-1, numberBox = new OsuNumberBox
|
|
||||||
{
|
|
||||||
Text = "1080",
|
|
||||||
Width = 100
|
|
||||||
});
|
|
||||||
|
|
||||||
base.Action = () =>
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(numberBox.Text))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// box contains text
|
|
||||||
if (!int.TryParse(numberBox.Text, out var number))
|
|
||||||
{
|
|
||||||
// at this point, the only reason we can arrive here is if the input number was too big to parse into an int
|
|
||||||
// so clamp to max allowed value
|
|
||||||
number = maximum_window_height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
number = Math.Clamp(number, minimum_window_height, maximum_window_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// in case number got clamped, reset number in numberBox
|
|
||||||
numberBox.Text = number.ToString();
|
|
||||||
|
|
||||||
Action?.Invoke(number);
|
|
||||||
};
|
|
||||||
return drawable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,11 +13,11 @@ using osu.Game.Graphics.Sprites;
|
|||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Tournament.IPC;
|
|
||||||
using osu.Game.Tournament.Components;
|
using osu.Game.Tournament.Components;
|
||||||
|
using osu.Game.Tournament.IPC;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Tournament.Screens
|
namespace osu.Game.Tournament.Screens.Setup
|
||||||
{
|
{
|
||||||
public class StablePathSelectScreen : TournamentScreen
|
public class StablePathSelectScreen : TournamentScreen
|
||||||
{
|
{
|
44
osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs
Normal file
44
osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Tournament.IO;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Screens.Setup
|
||||||
|
{
|
||||||
|
internal class TournamentSwitcher : ActionableInfo
|
||||||
|
{
|
||||||
|
private OsuDropdown<string> dropdown;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private TournamentGameBase game { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TournamentStorage storage)
|
||||||
|
{
|
||||||
|
string startupTournament = storage.CurrentTournament.Value;
|
||||||
|
|
||||||
|
dropdown.Current = storage.CurrentTournament;
|
||||||
|
dropdown.Items = storage.ListTournaments();
|
||||||
|
dropdown.Current.BindValueChanged(v => Button.Enabled.Value = v.NewValue != startupTournament, true);
|
||||||
|
|
||||||
|
Action = () => game.GracefullyExit();
|
||||||
|
|
||||||
|
ButtonText = "Close osu!";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateComponent()
|
||||||
|
{
|
||||||
|
var drawable = base.CreateComponent();
|
||||||
|
|
||||||
|
FlowContainer.Insert(-1, dropdown = new OsuDropdown<string>
|
||||||
|
{
|
||||||
|
Width = 510
|
||||||
|
});
|
||||||
|
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,12 +8,12 @@ using Newtonsoft.Json;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Platform;
|
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Tournament.IPC;
|
|
||||||
using osu.Game.Tournament.IO;
|
using osu.Game.Tournament.IO;
|
||||||
|
using osu.Game.Tournament.IPC;
|
||||||
using osu.Game.Tournament.Models;
|
using osu.Game.Tournament.Models;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
@ -40,6 +40,8 @@ namespace osu.Game.Tournament
|
|||||||
Resources.AddStore(new DllResourceStore(typeof(TournamentGameBase).Assembly));
|
Resources.AddStore(new DllResourceStore(typeof(TournamentGameBase).Assembly));
|
||||||
|
|
||||||
dependencies.CacheAs<Storage>(storage = new TournamentStorage(baseStorage));
|
dependencies.CacheAs<Storage>(storage = new TournamentStorage(baseStorage));
|
||||||
|
dependencies.CacheAs(storage);
|
||||||
|
|
||||||
dependencies.Cache(new TournamentVideoResourceStore(storage));
|
dependencies.Cache(new TournamentVideoResourceStore(storage));
|
||||||
|
|
||||||
Textures.AddStore(new TextureLoaderStore(new StorageBackedResourceStore(storage)));
|
Textures.AddStore(new TextureLoaderStore(new StorageBackedResourceStore(storage)));
|
||||||
@ -60,7 +62,7 @@ namespace osu.Game.Tournament
|
|||||||
{
|
{
|
||||||
using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open))
|
using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open))
|
||||||
using (var sr = new StreamReader(stream))
|
using (var sr = new StreamReader(stream))
|
||||||
ladder = JsonConvert.DeserializeObject<LadderInfo>(sr.ReadToEnd());
|
ladder = JsonConvert.DeserializeObject<LadderInfo>(sr.ReadToEnd(), new JsonPointConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
ladder ??= new LadderInfo();
|
ladder ??= new LadderInfo();
|
||||||
@ -251,6 +253,7 @@ namespace osu.Game.Tournament
|
|||||||
Formatting = Formatting.Indented,
|
Formatting = Formatting.Indented,
|
||||||
NullValueHandling = NullValueHandling.Ignore,
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
DefaultValueHandling = DefaultValueHandling.Ignore,
|
DefaultValueHandling = DefaultValueHandling.Ignore,
|
||||||
|
Converters = new JsonConverter[] { new JsonPointConverter() }
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ using osu.Game.Tournament.Screens.Gameplay;
|
|||||||
using osu.Game.Tournament.Screens.Ladder;
|
using osu.Game.Tournament.Screens.Ladder;
|
||||||
using osu.Game.Tournament.Screens.MapPool;
|
using osu.Game.Tournament.Screens.MapPool;
|
||||||
using osu.Game.Tournament.Screens.Schedule;
|
using osu.Game.Tournament.Screens.Schedule;
|
||||||
|
using osu.Game.Tournament.Screens.Setup;
|
||||||
using osu.Game.Tournament.Screens.Showcase;
|
using osu.Game.Tournament.Screens.Showcase;
|
||||||
using osu.Game.Tournament.Screens.TeamIntro;
|
using osu.Game.Tournament.Screens.TeamIntro;
|
||||||
using osu.Game.Tournament.Screens.TeamWin;
|
using osu.Game.Tournament.Screens.TeamWin;
|
||||||
|
@ -50,7 +50,15 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
IBeatmap IBeatmap.Clone() => Clone();
|
IBeatmap IBeatmap.Clone() => Clone();
|
||||||
|
|
||||||
public Beatmap<T> Clone() => (Beatmap<T>)MemberwiseClone();
|
public Beatmap<T> Clone()
|
||||||
|
{
|
||||||
|
var clone = (Beatmap<T>)MemberwiseClone();
|
||||||
|
|
||||||
|
clone.ControlPointInfo = ControlPointInfo.CreateCopy();
|
||||||
|
// todo: deep clone other elements as required.
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Beatmap : Beatmap<HitObject>
|
public class Beatmap : Beatmap<HitObject>
|
||||||
|
@ -260,17 +260,10 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
catch (BeatmapInvalidForRulesetException e)
|
catch (BeatmapInvalidForRulesetException e)
|
||||||
{
|
{
|
||||||
// Conversion has failed for the given ruleset, so return the difficulty in the beatmap's default ruleset.
|
|
||||||
|
|
||||||
// Ensure the beatmap's default ruleset isn't the one already being converted to.
|
|
||||||
// This shouldn't happen as it means something went seriously wrong, but if it does an endless loop should be avoided.
|
|
||||||
if (rulesetInfo.Equals(beatmapInfo.Ruleset))
|
if (rulesetInfo.Equals(beatmapInfo.Ruleset))
|
||||||
{
|
|
||||||
Logger.Error(e, $"Failed to convert {beatmapInfo.OnlineBeatmapID} to the beatmap's default ruleset ({beatmapInfo.Ruleset}).");
|
Logger.Error(e, $"Failed to convert {beatmapInfo.OnlineBeatmapID} to the beatmap's default ruleset ({beatmapInfo.Ruleset}).");
|
||||||
return new StarDifficulty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetAsync(new DifficultyCacheLookup(key.Beatmap, key.Beatmap.Ruleset, key.OrderedMods)).Result;
|
return new StarDifficulty();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -28,5 +28,21 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
/// <param name="existing">An existing control point to compare with.</param>
|
/// <param name="existing">An existing control point to compare with.</param>
|
||||||
/// <returns>Whether this <see cref="ControlPoint"/> is redundant when placed alongside <paramref name="existing"/>.</returns>
|
/// <returns>Whether this <see cref="ControlPoint"/> is redundant when placed alongside <paramref name="existing"/>.</returns>
|
||||||
public abstract bool IsRedundant(ControlPoint existing);
|
public abstract bool IsRedundant(ControlPoint existing);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create an unbound copy of this control point.
|
||||||
|
/// </summary>
|
||||||
|
public ControlPoint CreateCopy()
|
||||||
|
{
|
||||||
|
var copy = (ControlPoint)Activator.CreateInstance(GetType());
|
||||||
|
|
||||||
|
copy.CopyFrom(this);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void CopyFrom(ControlPoint other)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,5 +297,15 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ControlPointInfo CreateCopy()
|
||||||
|
{
|
||||||
|
var controlPointInfo = new ControlPointInfo();
|
||||||
|
|
||||||
|
foreach (var point in AllControlPoints)
|
||||||
|
controlPointInfo.Add(point.Time, point.CreateCopy());
|
||||||
|
|
||||||
|
return controlPointInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,5 +39,12 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
public override bool IsRedundant(ControlPoint existing)
|
public override bool IsRedundant(ControlPoint existing)
|
||||||
=> existing is DifficultyControlPoint existingDifficulty
|
=> existing is DifficultyControlPoint existingDifficulty
|
||||||
&& SpeedMultiplier == existingDifficulty.SpeedMultiplier;
|
&& SpeedMultiplier == existingDifficulty.SpeedMultiplier;
|
||||||
|
|
||||||
|
public override void CopyFrom(ControlPoint other)
|
||||||
|
{
|
||||||
|
SpeedMultiplier = ((DifficultyControlPoint)other).SpeedMultiplier;
|
||||||
|
|
||||||
|
base.CopyFrom(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,5 +50,13 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
&& existing is EffectControlPoint existingEffect
|
&& existing is EffectControlPoint existingEffect
|
||||||
&& KiaiMode == existingEffect.KiaiMode
|
&& KiaiMode == existingEffect.KiaiMode
|
||||||
&& OmitFirstBarLine == existingEffect.OmitFirstBarLine;
|
&& OmitFirstBarLine == existingEffect.OmitFirstBarLine;
|
||||||
|
|
||||||
|
public override void CopyFrom(ControlPoint other)
|
||||||
|
{
|
||||||
|
KiaiMode = ((EffectControlPoint)other).KiaiMode;
|
||||||
|
OmitFirstBarLine = ((EffectControlPoint)other).OmitFirstBarLine;
|
||||||
|
|
||||||
|
base.CopyFrom(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,5 +72,13 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
=> existing is SampleControlPoint existingSample
|
=> existing is SampleControlPoint existingSample
|
||||||
&& SampleBank == existingSample.SampleBank
|
&& SampleBank == existingSample.SampleBank
|
||||||
&& SampleVolume == existingSample.SampleVolume;
|
&& SampleVolume == existingSample.SampleVolume;
|
||||||
|
|
||||||
|
public override void CopyFrom(ControlPoint other)
|
||||||
|
{
|
||||||
|
SampleVolume = ((SampleControlPoint)other).SampleVolume;
|
||||||
|
SampleBank = ((SampleControlPoint)other).SampleBank;
|
||||||
|
|
||||||
|
base.CopyFrom(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,5 +69,13 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
|
|
||||||
// Timing points are never redundant as they can change the time signature.
|
// Timing points are never redundant as they can change the time signature.
|
||||||
public override bool IsRedundant(ControlPoint existing) => false;
|
public override bool IsRedundant(ControlPoint existing) => false;
|
||||||
|
|
||||||
|
public override void CopyFrom(ControlPoint other)
|
||||||
|
{
|
||||||
|
TimeSignature = ((TimingControlPoint)other).TimeSignature;
|
||||||
|
BeatLength = ((TimingControlPoint)other).BeatLength;
|
||||||
|
|
||||||
|
base.CopyFrom(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,13 +164,25 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
/// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it.
|
/// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it.
|
||||||
/// DO NOT USE THIS UNLESS 100% SURE.
|
/// DO NOT USE THIS UNLESS 100% SURE.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly float BpmMultiplier;
|
public double BpmMultiplier { get; private set; }
|
||||||
|
|
||||||
public LegacyDifficultyControlPoint(double beatLength)
|
public LegacyDifficultyControlPoint(double beatLength)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
// Note: In stable, the division occurs on floats, but with compiler optimisations turned on actually seems to occur on doubles via some .NET black magic (possibly inlining?).
|
||||||
|
BpmMultiplier = beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 10000) / 100.0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LegacyDifficultyControlPoint()
|
||||||
{
|
{
|
||||||
SpeedMultiplierBindable.Precision = double.Epsilon;
|
SpeedMultiplierBindable.Precision = double.Epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
BpmMultiplier = beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 10000) / 100f : 1;
|
public override void CopyFrom(ControlPoint other)
|
||||||
|
{
|
||||||
|
base.CopyFrom(other);
|
||||||
|
|
||||||
|
BpmMultiplier = ((LegacyDifficultyControlPoint)other).BpmMultiplier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,6 +204,13 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
=> base.IsRedundant(existing)
|
=> base.IsRedundant(existing)
|
||||||
&& existing is LegacySampleControlPoint existingSample
|
&& existing is LegacySampleControlPoint existingSample
|
||||||
&& CustomSampleBank == existingSample.CustomSampleBank;
|
&& CustomSampleBank == existingSample.CustomSampleBank;
|
||||||
|
|
||||||
|
public override void CopyFrom(ControlPoint other)
|
||||||
|
{
|
||||||
|
base.CopyFrom(other);
|
||||||
|
|
||||||
|
CustomSampleBank = ((LegacySampleControlPoint)other).CustomSampleBank;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
osu.Game/Configuration/DiscordRichPresenceMode.cs
Normal file
17
osu.Game/Configuration/DiscordRichPresenceMode.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace osu.Game.Configuration
|
||||||
|
{
|
||||||
|
public enum DiscordRichPresenceMode
|
||||||
|
{
|
||||||
|
Off,
|
||||||
|
|
||||||
|
[Description("Hide identifiable information")]
|
||||||
|
Limited,
|
||||||
|
|
||||||
|
Full
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
@ -138,6 +138,8 @@ namespace osu.Game.Configuration
|
|||||||
Set(OsuSetting.MenuBackgroundSource, BackgroundSource.Skin);
|
Set(OsuSetting.MenuBackgroundSource, BackgroundSource.Skin);
|
||||||
Set(OsuSetting.SeasonalBackgroundMode, SeasonalBackgroundMode.Sometimes);
|
Set(OsuSetting.SeasonalBackgroundMode, SeasonalBackgroundMode.Sometimes);
|
||||||
|
|
||||||
|
Set(OsuSetting.DiscordRichPresence, DiscordRichPresenceMode.Full);
|
||||||
|
|
||||||
Set(OsuSetting.EditorWaveformOpacity, 1f);
|
Set(OsuSetting.EditorWaveformOpacity, 1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,6 +268,7 @@ namespace osu.Game.Configuration
|
|||||||
GameplayDisableWinKey,
|
GameplayDisableWinKey,
|
||||||
SeasonalBackgroundMode,
|
SeasonalBackgroundMode,
|
||||||
EditorWaveformOpacity,
|
EditorWaveformOpacity,
|
||||||
|
DiscordRichPresence,
|
||||||
AutomaticallyDownloadWhenSpectating,
|
AutomaticallyDownloadWhenSpectating,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
|
||||||
namespace osu.Game.Configuration
|
namespace osu.Game.Configuration
|
||||||
{
|
{
|
||||||
@ -14,6 +16,7 @@ namespace osu.Game.Configuration
|
|||||||
{
|
{
|
||||||
Set(Static.LoginOverlayDisplayed, false);
|
Set(Static.LoginOverlayDisplayed, false);
|
||||||
Set(Static.MutedAudioNotificationShownOnce, false);
|
Set(Static.MutedAudioNotificationShownOnce, false);
|
||||||
|
Set(Static.LastHoverSoundPlaybackTime, (double?)null);
|
||||||
Set<APISeasonalBackgrounds>(Static.SeasonalBackgrounds, null);
|
Set<APISeasonalBackgrounds>(Static.SeasonalBackgrounds, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,5 +31,11 @@ namespace osu.Game.Configuration
|
|||||||
/// Value under this lookup can be <c>null</c> if there are no backgrounds available (or API is not reachable).
|
/// Value under this lookup can be <c>null</c> if there are no backgrounds available (or API is not reachable).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SeasonalBackgrounds,
|
SeasonalBackgrounds,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The last playback time in milliseconds of a hover sample (from <see cref="HoverSounds"/>).
|
||||||
|
/// Used to debounce hover sounds game-wide to avoid volume saturation, especially in scrolling views with many UI controls like <see cref="SettingsOverlay"/>.
|
||||||
|
/// </summary>
|
||||||
|
LastHoverSoundPlaybackTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,8 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => new { b.RulesetID, b.Variant });
|
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => new { b.RulesetID, b.Variant });
|
||||||
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => b.IntAction);
|
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => b.IntAction);
|
||||||
|
modelBuilder.Entity<DatabasedKeyBinding>().Ignore(b => b.KeyCombination);
|
||||||
|
modelBuilder.Entity<DatabasedKeyBinding>().Ignore(b => b.Action);
|
||||||
|
|
||||||
modelBuilder.Entity<DatabasedSetting>().HasIndex(b => new { b.RulesetID, b.Variant });
|
modelBuilder.Entity<DatabasedSetting>().HasIndex(b => new { b.RulesetID, b.Variant });
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
TooltipText = "Downloading...";
|
TooltipText = "Downloading...";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.Downloaded:
|
case DownloadState.Importing:
|
||||||
background.FadeColour(colours.Yellow, 500, Easing.InOutExpo);
|
background.FadeColour(colours.Yellow, 500, Easing.InOutExpo);
|
||||||
TooltipText = "Importing";
|
TooltipText = "Importing";
|
||||||
break;
|
break;
|
||||||
|
@ -5,11 +5,12 @@ using System.ComponentModel;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Threading;
|
using osu.Game.Configuration;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
@ -22,37 +23,40 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
private SampleChannel sampleHover;
|
private SampleChannel sampleHover;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Length of debounce for hover sound playback, in milliseconds. Default is 50ms.
|
/// Length of debounce for hover sound playback, in milliseconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double HoverDebounceTime { get; } = 50;
|
public double HoverDebounceTime { get; } = 20;
|
||||||
|
|
||||||
protected readonly HoverSampleSet SampleSet;
|
protected readonly HoverSampleSet SampleSet;
|
||||||
|
|
||||||
|
private Bindable<double?> lastPlaybackTime;
|
||||||
|
|
||||||
public HoverSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal)
|
public HoverSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal)
|
||||||
{
|
{
|
||||||
SampleSet = sampleSet;
|
SampleSet = sampleSet;
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduledDelegate playDelegate;
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(AudioManager audio, SessionStatics statics)
|
||||||
|
{
|
||||||
|
lastPlaybackTime = statics.GetBindable<double?>(Static.LastHoverSoundPlaybackTime);
|
||||||
|
|
||||||
|
sampleHover = audio.Samples.Get($@"UI/generic-hover{SampleSet.GetDescription()}");
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
{
|
{
|
||||||
playDelegate?.Cancel();
|
bool enoughTimePassedSinceLastPlayback = !lastPlaybackTime.Value.HasValue || Time.Current - lastPlaybackTime.Value >= HoverDebounceTime;
|
||||||
|
|
||||||
if (HoverDebounceTime <= 0)
|
if (enoughTimePassedSinceLastPlayback)
|
||||||
|
{
|
||||||
sampleHover?.Play();
|
sampleHover?.Play();
|
||||||
else
|
lastPlaybackTime.Value = Time.Current;
|
||||||
playDelegate = Scheduler.AddDelayed(() => sampleHover?.Play(), HoverDebounceTime);
|
}
|
||||||
|
|
||||||
return base.OnHover(e);
|
return base.OnHover(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(AudioManager audio)
|
|
||||||
{
|
|
||||||
sampleHover = audio.Samples.Get($@"UI/generic-hover{SampleSet.GetDescription()}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum HoverSampleSet
|
public enum HoverSampleSet
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -17,22 +18,32 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LoadingLayer : LoadingSpinner
|
public class LoadingLayer : LoadingSpinner
|
||||||
{
|
{
|
||||||
private readonly Drawable dimTarget;
|
[CanBeNull]
|
||||||
|
protected Box BackgroundDimLayer { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constuct a new loading spinner.
|
/// Construct a new loading spinner.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dimTarget">An optional target to dim when displayed.</param>
|
/// <param name="dimBackground">Whether the full background area should be dimmed while loading.</param>
|
||||||
/// <param name="withBox">Whether the spinner should have a surrounding black box for visibility.</param>
|
/// <param name="withBox">Whether the spinner should have a surrounding black box for visibility.</param>
|
||||||
public LoadingLayer(Drawable dimTarget = null, bool withBox = true)
|
public LoadingLayer(bool dimBackground = false, bool withBox = true)
|
||||||
: base(withBox)
|
: base(withBox)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
Size = new Vector2(1);
|
Size = new Vector2(1);
|
||||||
|
|
||||||
this.dimTarget = dimTarget;
|
|
||||||
|
|
||||||
MainContents.RelativeSizeAxes = Axes.None;
|
MainContents.RelativeSizeAxes = Axes.None;
|
||||||
|
|
||||||
|
if (dimBackground)
|
||||||
|
{
|
||||||
|
AddInternal(BackgroundDimLayer = new Box
|
||||||
|
{
|
||||||
|
Depth = float.MaxValue,
|
||||||
|
Colour = Color4.Black,
|
||||||
|
Alpha = 0,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool HandleNonPositionalInput => false;
|
public override bool HandleNonPositionalInput => false;
|
||||||
@ -56,31 +67,21 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
{
|
{
|
||||||
dimTarget?.FadeColour(OsuColour.Gray(0.5f), TRANSITION_DURATION, Easing.OutQuint);
|
BackgroundDimLayer?.FadeTo(0.5f, TRANSITION_DURATION * 2, Easing.OutQuint);
|
||||||
base.PopIn();
|
base.PopIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopOut()
|
protected override void PopOut()
|
||||||
{
|
{
|
||||||
dimTarget?.FadeColour(Color4.White, TRANSITION_DURATION, Easing.OutQuint);
|
BackgroundDimLayer?.FadeOut(TRANSITION_DURATION, Easing.OutQuint);
|
||||||
base.PopOut();
|
base.PopOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
MainContents.Size = new Vector2(Math.Clamp(Math.Min(DrawWidth, DrawHeight) * 0.25f, 30, 100));
|
MainContents.Size = new Vector2(Math.Clamp(Math.Min(DrawWidth, DrawHeight) * 0.25f, 30, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
|
||||||
{
|
|
||||||
base.Dispose(isDisposing);
|
|
||||||
|
|
||||||
if (State.Value == Visibility.Visible)
|
|
||||||
{
|
|
||||||
// ensure we don't leave the target in a bad state.
|
|
||||||
dimTarget?.FadeColour(Color4.White, TRANSITION_DURATION, Easing.OutQuint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Input.Bindings
|
|||||||
|
|
||||||
private KeyBindingStore store;
|
private KeyBindingStore store;
|
||||||
|
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(variant ?? 0);
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(variant ?? 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance.
|
/// Create a new instance.
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Input.Bindings
|
|||||||
handler = game;
|
handler = game;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings).Concat(AudioControlKeyBindings).Concat(EditorKeyBindings);
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings).Concat(AudioControlKeyBindings).Concat(EditorKeyBindings);
|
||||||
|
|
||||||
public IEnumerable<KeyBinding> GlobalKeyBindings => new[]
|
public IEnumerable<KeyBinding> GlobalKeyBindings => new[]
|
||||||
{
|
{
|
||||||
@ -34,7 +34,7 @@ namespace osu.Game.Input.Bindings
|
|||||||
new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings),
|
new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings),
|
||||||
new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar),
|
new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar),
|
||||||
new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings),
|
new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings),
|
||||||
new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleDirect),
|
new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleBeatmapListing),
|
||||||
new KeyBinding(new[] { InputKey.Control, InputKey.N }, GlobalAction.ToggleNotifications),
|
new KeyBinding(new[] { InputKey.Control, InputKey.N }, GlobalAction.ToggleNotifications),
|
||||||
|
|
||||||
new KeyBinding(InputKey.Escape, GlobalAction.Back),
|
new KeyBinding(InputKey.Escape, GlobalAction.Back),
|
||||||
@ -112,8 +112,8 @@ namespace osu.Game.Input.Bindings
|
|||||||
[Description("Toggle settings")]
|
[Description("Toggle settings")]
|
||||||
ToggleSettings,
|
ToggleSettings,
|
||||||
|
|
||||||
[Description("Toggle osu!direct")]
|
[Description("Toggle beatmap listing")]
|
||||||
ToggleDirect,
|
ToggleBeatmapListing,
|
||||||
|
|
||||||
[Description("Increase volume")]
|
[Description("Increase volume")]
|
||||||
IncreaseVolume,
|
IncreaseVolume,
|
||||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertDefaults(IEnumerable<KeyBinding> defaults, int? rulesetId = null, int? variant = null)
|
private void insertDefaults(IEnumerable<IKeyBinding> defaults, int? rulesetId = null, int? variant = null)
|
||||||
{
|
{
|
||||||
using (var usage = ContextFactory.GetForWrite())
|
using (var usage = ContextFactory.GetForWrite())
|
||||||
{
|
{
|
||||||
|
@ -31,7 +31,12 @@ namespace osu.Game.Online.API
|
|||||||
Acronym = mod.Acronym;
|
Acronym = mod.Acronym;
|
||||||
|
|
||||||
foreach (var (_, property) in mod.GetSettingsSourceProperties())
|
foreach (var (_, property) in mod.GetSettingsSourceProperties())
|
||||||
Settings.Add(property.Name.Underscore(), property.GetValue(mod));
|
{
|
||||||
|
var bindable = (IBindable)property.GetValue(mod);
|
||||||
|
|
||||||
|
if (!bindable.IsDefault)
|
||||||
|
Settings.Add(property.Name.Underscore(), bindable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mod ToMod(Ruleset ruleset)
|
public Mod ToMod(Ruleset ruleset)
|
||||||
@ -46,7 +51,7 @@ namespace osu.Game.Online.API
|
|||||||
if (!Settings.TryGetValue(property.Name.Underscore(), out object settingValue))
|
if (!Settings.TryGetValue(property.Name.Underscore(), out object settingValue))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
((IBindable)property.GetValue(resultMod)).Parse(settingValue);
|
resultMod.CopyAdjustedSetting((IBindable)property.GetValue(resultMod), settingValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultMod;
|
return resultMod;
|
||||||
|
@ -7,7 +7,7 @@ namespace osu.Game.Online
|
|||||||
{
|
{
|
||||||
NotDownloaded,
|
NotDownloaded,
|
||||||
Downloading,
|
Downloading,
|
||||||
Downloaded,
|
Importing,
|
||||||
LocallyAvailable
|
LocallyAvailable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ namespace osu.Game.Online
|
|||||||
{
|
{
|
||||||
if (attachedRequest.Progress == 1)
|
if (attachedRequest.Progress == 1)
|
||||||
{
|
{
|
||||||
State.Value = DownloadState.Downloaded;
|
State.Value = DownloadState.Importing;
|
||||||
Progress.Value = 1;
|
Progress.Value = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -125,7 +125,7 @@ namespace osu.Game.Online
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onRequestSuccess(string _) => Schedule(() => State.Value = DownloadState.Downloaded);
|
private void onRequestSuccess(string _) => Schedule(() => State.Value = DownloadState.Importing);
|
||||||
|
|
||||||
private void onRequestProgress(float progress) => Schedule(() => Progress.Value = progress);
|
private void onRequestProgress(float progress) => Schedule(() => Progress.Value = progress);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
|
|
||||||
namespace osu.Game.Online.Multiplayer
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
@ -47,6 +48,13 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
/// <param name="state">The new state of the user.</param>
|
/// <param name="state">The new state of the user.</param>
|
||||||
Task UserStateChanged(int userId, MultiplayerUserState state);
|
Task UserStateChanged(int userId, MultiplayerUserState state);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signals that a user in this room changed their beatmap availability state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">The ID of the user whose beatmap availability state has changed.</param>
|
||||||
|
/// <param name="beatmapAvailability">The new beatmap availability state of the user.</param>
|
||||||
|
Task UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signals that a match is to be started. This will *only* be sent to clients which are to begin loading at this point.
|
/// Signals that a match is to be started. This will *only* be sent to clients which are to begin loading at this point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
|
|
||||||
namespace osu.Game.Online.Multiplayer
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
@ -40,6 +41,12 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
/// <exception cref="NotJoinedRoomException">If the user is not in a room.</exception>
|
/// <exception cref="NotJoinedRoomException">If the user is not in a room.</exception>
|
||||||
Task ChangeState(MultiplayerUserState newState);
|
Task ChangeState(MultiplayerUserState newState);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Change the local user's availability state of the current beatmap set in joined room.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newBeatmapAvailability">The proposed new beatmap availability state.</param>
|
||||||
|
Task ChangeBeatmapAvailability(BeatmapAvailability newBeatmapAvailability);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// As the host of a room, start the match.
|
/// As the host of a room, start the match.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,6 +14,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
|
|
||||||
namespace osu.Game.Online.Multiplayer
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
@ -173,6 +174,14 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeState), newState);
|
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeState), newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Task ChangeBeatmapAvailability(BeatmapAvailability newBeatmapAvailability)
|
||||||
|
{
|
||||||
|
if (!isConnected.Value)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeBeatmapAvailability), newBeatmapAvailability);
|
||||||
|
}
|
||||||
|
|
||||||
public override Task StartMatch()
|
public override Task StartMatch()
|
||||||
{
|
{
|
||||||
if (!isConnected.Value)
|
if (!isConnected.Value)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Online.Multiplayer
|
namespace osu.Game.Online.Multiplayer
|
||||||
@ -16,6 +17,11 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
|
|
||||||
public MultiplayerUserState State { get; set; } = MultiplayerUserState.Idle;
|
public MultiplayerUserState State { get; set; } = MultiplayerUserState.Idle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The availability state of the current beatmap.
|
||||||
|
/// </summary>
|
||||||
|
public BeatmapAvailability BeatmapAvailability { get; set; } = BeatmapAvailability.LocallyAvailable();
|
||||||
|
|
||||||
public User? User { get; set; }
|
public User? User { get; set; }
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
|
@ -52,6 +52,7 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the <see cref="StatefulMultiplayerClient"/> is currently connected.
|
/// Whether the <see cref="StatefulMultiplayerClient"/> is currently connected.
|
||||||
|
/// This is NOT thread safe and usage should be scheduled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract IBindable<bool> IsConnected { get; }
|
public abstract IBindable<bool> IsConnected { get; }
|
||||||
|
|
||||||
@ -65,6 +66,23 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly BindableList<int> CurrentMatchPlayingUserIds = new BindableList<int>();
|
public readonly BindableList<int> CurrentMatchPlayingUserIds = new BindableList<int>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="MultiplayerRoomUser"/> corresponding to the local player, if available.
|
||||||
|
/// </summary>
|
||||||
|
public MultiplayerRoomUser? LocalUser => Room?.Users.SingleOrDefault(u => u.User?.Id == api.LocalUser.Value.Id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the <see cref="LocalUser"/> is the host in <see cref="Room"/>.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsHost
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var localUser = LocalUser;
|
||||||
|
return localUser != null && Room?.Host != null && localUser.Equals(Room.Host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private UserLookupCache userLookupCache { get; set; } = null!;
|
private UserLookupCache userLookupCache { get; set; } = null!;
|
||||||
|
|
||||||
@ -178,12 +196,40 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggles the <see cref="LocalUser"/>'s ready state.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="InvalidOperationException">If a toggle of ready state is not valid at this time.</exception>
|
||||||
|
public async Task ToggleReady()
|
||||||
|
{
|
||||||
|
var localUser = LocalUser;
|
||||||
|
|
||||||
|
if (localUser == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (localUser.State)
|
||||||
|
{
|
||||||
|
case MultiplayerUserState.Idle:
|
||||||
|
await ChangeState(MultiplayerUserState.Ready);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case MultiplayerUserState.Ready:
|
||||||
|
await ChangeState(MultiplayerUserState.Idle);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Cannot toggle ready when in {localUser.State}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Task TransferHost(int userId);
|
public abstract Task TransferHost(int userId);
|
||||||
|
|
||||||
public abstract Task ChangeSettings(MultiplayerRoomSettings settings);
|
public abstract Task ChangeSettings(MultiplayerRoomSettings settings);
|
||||||
|
|
||||||
public abstract Task ChangeState(MultiplayerUserState newState);
|
public abstract Task ChangeState(MultiplayerUserState newState);
|
||||||
|
|
||||||
|
public abstract Task ChangeBeatmapAvailability(BeatmapAvailability newBeatmapAvailability);
|
||||||
|
|
||||||
public abstract Task StartMatch();
|
public abstract Task StartMatch();
|
||||||
|
|
||||||
Task IMultiplayerClient.RoomStateChanged(MultiplayerRoomState state)
|
Task IMultiplayerClient.RoomStateChanged(MultiplayerRoomState state)
|
||||||
@ -311,6 +357,27 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Task IMultiplayerClient.UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability)
|
||||||
|
{
|
||||||
|
if (Room == null)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
Scheduler.Add(() =>
|
||||||
|
{
|
||||||
|
var user = Room?.Users.SingleOrDefault(u => u.UserID == userId);
|
||||||
|
|
||||||
|
// errors here are not critical - beatmap availability state is mostly for display.
|
||||||
|
if (user == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
user.BeatmapAvailability = beatmapAvailability;
|
||||||
|
|
||||||
|
RoomUpdated?.Invoke();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
Task IMultiplayerClient.LoadRequested()
|
Task IMultiplayerClient.LoadRequested()
|
||||||
{
|
{
|
||||||
if (Room == null)
|
if (Room == null)
|
||||||
|
40
osu.Game/Online/Rooms/BeatmapAvailability.cs
Normal file
40
osu.Game/Online/Rooms/BeatmapAvailability.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.Rooms
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The local availability information about a certain beatmap for the client.
|
||||||
|
/// </summary>
|
||||||
|
public class BeatmapAvailability : IEquatable<BeatmapAvailability>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The beatmap's availability state.
|
||||||
|
/// </summary>
|
||||||
|
public readonly DownloadState State;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The beatmap's downloading progress, null when not in <see cref="DownloadState.Downloading"/> state.
|
||||||
|
/// </summary>
|
||||||
|
public readonly double? DownloadProgress;
|
||||||
|
|
||||||
|
[JsonConstructor]
|
||||||
|
private BeatmapAvailability(DownloadState state, double? downloadProgress = null)
|
||||||
|
{
|
||||||
|
State = state;
|
||||||
|
DownloadProgress = downloadProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BeatmapAvailability NotDownloaded() => new BeatmapAvailability(DownloadState.NotDownloaded);
|
||||||
|
public static BeatmapAvailability Downloading(double progress) => new BeatmapAvailability(DownloadState.Downloading, progress);
|
||||||
|
public static BeatmapAvailability Importing() => new BeatmapAvailability(DownloadState.Importing);
|
||||||
|
public static BeatmapAvailability LocallyAvailable() => new BeatmapAvailability(DownloadState.LocallyAvailable);
|
||||||
|
|
||||||
|
public bool Equals(BeatmapAvailability other) => other != null && State == other.State && DownloadProgress == other.DownloadProgress;
|
||||||
|
|
||||||
|
public override string ToString() => $"{string.Join(", ", State, $"{DownloadProgress:0.00%}")}";
|
||||||
|
}
|
||||||
|
}
|
@ -151,11 +151,11 @@ namespace osu.Game
|
|||||||
updateBlockingOverlayFade();
|
updateBlockingOverlayFade();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveBlockingOverlay(OverlayContainer overlay)
|
public void RemoveBlockingOverlay(OverlayContainer overlay) => Schedule(() =>
|
||||||
{
|
{
|
||||||
visibleBlockingOverlays.Remove(overlay);
|
visibleBlockingOverlays.Remove(overlay);
|
||||||
updateBlockingOverlayFade();
|
updateBlockingOverlayFade();
|
||||||
}
|
});
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Close all game-wide overlays.
|
/// Close all game-wide overlays.
|
||||||
@ -942,18 +942,6 @@ namespace osu.Game
|
|||||||
return base.OnExiting();
|
return base.OnExiting();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use to programatically exit the game as if the user was triggering via alt-f4.
|
|
||||||
/// Will keep persisting until an exit occurs (exit may be blocked multiple times).
|
|
||||||
/// </summary>
|
|
||||||
public void GracefullyExit()
|
|
||||||
{
|
|
||||||
if (!OnExiting())
|
|
||||||
Exit();
|
|
||||||
else
|
|
||||||
Scheduler.AddDelayed(GracefullyExit, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateAfterChildren()
|
protected override void UpdateAfterChildren()
|
||||||
{
|
{
|
||||||
base.UpdateAfterChildren();
|
base.UpdateAfterChildren();
|
||||||
|
@ -380,6 +380,18 @@ namespace osu.Game
|
|||||||
: new OsuConfigManager(Storage);
|
: new OsuConfigManager(Storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use to programatically exit the game as if the user was triggering via alt-f4.
|
||||||
|
/// Will keep persisting until an exit occurs (exit may be blocked multiple times).
|
||||||
|
/// </summary>
|
||||||
|
public void GracefullyExit()
|
||||||
|
{
|
||||||
|
if (!OnExiting())
|
||||||
|
Exit();
|
||||||
|
else
|
||||||
|
Scheduler.AddDelayed(GracefullyExit, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
protected override Storage CreateStorage(GameHost host, Storage defaultStorage) => new OsuStorage(host, defaultStorage);
|
protected override Storage CreateStorage(GameHost host, Storage defaultStorage) => new OsuStorage(host, defaultStorage);
|
||||||
|
|
||||||
private readonly List<ICanAcceptFiles> fileImporters = new List<ICanAcceptFiles>();
|
private readonly List<ICanAcceptFiles> fileImporters = new List<ICanAcceptFiles>();
|
||||||
|
@ -48,11 +48,9 @@ namespace osu.Game.Overlays.AccountCreation
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
FillFlowContainer mainContent;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
mainContent = new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
@ -124,7 +122,7 @@ namespace osu.Game.Overlays.AccountCreation
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loadingLayer = new LoadingLayer(mainContent)
|
loadingLayer = new LoadingLayer(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
textboxes = new[] { usernameTextBox, emailTextBox, passwordTextBox };
|
textboxes = new[] { usernameTextBox, emailTextBox, passwordTextBox };
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
private Container content;
|
private Container content;
|
||||||
|
|
||||||
public PreviewTrack Preview => PlayButton.Preview;
|
public PreviewTrack Preview => PlayButton.Preview;
|
||||||
public Bindable<bool> PreviewPlaying => PlayButton?.Playing;
|
public IBindable<bool> PreviewPlaying => PlayButton?.Playing;
|
||||||
|
|
||||||
protected abstract PlayButton PlayButton { get; }
|
protected abstract PlayButton PlayButton { get; }
|
||||||
protected abstract Box PreviewBar { get; }
|
protected abstract Box PreviewBar { get; }
|
||||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
switch (State.Value)
|
switch (State.Value)
|
||||||
{
|
{
|
||||||
case DownloadState.Downloading:
|
case DownloadState.Downloading:
|
||||||
case DownloadState.Downloaded:
|
case DownloadState.Importing:
|
||||||
shakeContainer.Shake();
|
shakeContainer.Shake();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
progressBar.ResizeHeightTo(4, 400, Easing.OutQuint);
|
progressBar.ResizeHeightTo(4, 400, Easing.OutQuint);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.Downloaded:
|
case DownloadState.Importing:
|
||||||
progressBar.FadeIn(400, Easing.OutQuint);
|
progressBar.FadeIn(400, Easing.OutQuint);
|
||||||
progressBar.ResizeHeightTo(4, 400, Easing.OutQuint);
|
progressBar.ResizeHeightTo(4, 400, Easing.OutQuint);
|
||||||
|
|
||||||
|
@ -18,7 +18,10 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
{
|
{
|
||||||
public class PlayButton : Container
|
public class PlayButton : Container
|
||||||
{
|
{
|
||||||
public readonly BindableBool Playing = new BindableBool();
|
public IBindable<bool> Playing => playing;
|
||||||
|
|
||||||
|
private readonly BindableBool playing = new BindableBool();
|
||||||
|
|
||||||
public PreviewTrack Preview { get; private set; }
|
public PreviewTrack Preview { get; private set; }
|
||||||
|
|
||||||
private BeatmapSetInfo beatmapSet;
|
private BeatmapSetInfo beatmapSet;
|
||||||
@ -36,7 +39,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
Preview?.Expire();
|
Preview?.Expire();
|
||||||
Preview = null;
|
Preview = null;
|
||||||
|
|
||||||
Playing.Value = false;
|
playing.Value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +85,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Playing.ValueChanged += playingStateChanged;
|
playing.ValueChanged += playingStateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
@ -96,7 +99,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnClick(ClickEvent e)
|
||||||
{
|
{
|
||||||
Playing.Toggle();
|
playing.Toggle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +111,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
{
|
{
|
||||||
if (!Playing.Value)
|
if (!playing.Value)
|
||||||
icon.FadeColour(Color4.White, 120, Easing.InOutQuint);
|
icon.FadeColour(Color4.White, 120, Easing.InOutQuint);
|
||||||
base.OnHoverLost(e);
|
base.OnHoverLost(e);
|
||||||
}
|
}
|
||||||
@ -122,7 +125,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
{
|
{
|
||||||
if (BeatmapSet == null)
|
if (BeatmapSet == null)
|
||||||
{
|
{
|
||||||
Playing.Value = false;
|
playing.Value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,10 +145,12 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
|
|
||||||
AddInternal(preview);
|
AddInternal(preview);
|
||||||
loading = false;
|
loading = false;
|
||||||
preview.Stopped += () => Playing.Value = false;
|
// make sure that the update of value of Playing (and the ensuing value change callbacks)
|
||||||
|
// are marshaled back to the update thread.
|
||||||
|
preview.Stopped += () => Schedule(() => playing.Value = false);
|
||||||
|
|
||||||
// user may have changed their mind.
|
// user may have changed their mind.
|
||||||
if (Playing.Value)
|
if (playing.Value)
|
||||||
attemptStart();
|
attemptStart();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -159,13 +164,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
private void attemptStart()
|
private void attemptStart()
|
||||||
{
|
{
|
||||||
if (Preview?.Start() != true)
|
if (Preview?.Start() != true)
|
||||||
Playing.Value = false;
|
playing.Value = false;
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
|
||||||
{
|
|
||||||
base.Dispose(isDisposing);
|
|
||||||
Playing.Value = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,14 +92,14 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
foundContent = new FillFlowContainer<BeatmapPanel>(),
|
foundContent = new FillFlowContainer<BeatmapPanel>(),
|
||||||
notFoundContent = new NotFoundDrawable(),
|
notFoundContent = new NotFoundDrawable(),
|
||||||
loadingLayer = new LoadingLayer(panelTarget)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
loadingLayer = new LoadingLayer(true)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
|||||||
Size = new Vector2(18),
|
Size = new Vector2(18),
|
||||||
Shadow = false,
|
Shadow = false,
|
||||||
},
|
},
|
||||||
loading = new LoadingLayer(icon, false),
|
loading = new LoadingLayer(true, false),
|
||||||
});
|
});
|
||||||
|
|
||||||
Action = () =>
|
Action = () =>
|
||||||
|
@ -126,7 +126,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.Downloaded:
|
case DownloadState.Importing:
|
||||||
textSprites.Children = new Drawable[]
|
textSprites.Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
|
@ -18,13 +18,12 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
|||||||
{
|
{
|
||||||
public class PreviewButton : OsuClickableContainer
|
public class PreviewButton : OsuClickableContainer
|
||||||
{
|
{
|
||||||
private const float transition_duration = 500;
|
|
||||||
|
|
||||||
private readonly Box background, progress;
|
private readonly Box background, progress;
|
||||||
private readonly PlayButton playButton;
|
private readonly PlayButton playButton;
|
||||||
|
|
||||||
private PreviewTrack preview => playButton.Preview;
|
private PreviewTrack preview => playButton.Preview;
|
||||||
public Bindable<bool> Playing => playButton.Playing;
|
|
||||||
|
public IBindable<bool> Playing => playButton.Playing;
|
||||||
|
|
||||||
public BeatmapSetInfo BeatmapSet
|
public BeatmapSetInfo BeatmapSet
|
||||||
{
|
{
|
||||||
|
@ -287,7 +287,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.Downloading:
|
case DownloadState.Downloading:
|
||||||
case DownloadState.Downloaded:
|
case DownloadState.Importing:
|
||||||
// temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design.
|
// temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design.
|
||||||
downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value);
|
downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value);
|
||||||
break;
|
break;
|
||||||
|
@ -157,11 +157,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
loading = new LoadingLayer()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
loading = new LoadingLayer()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +228,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
{
|
{
|
||||||
Scores = null;
|
Scores = null;
|
||||||
notSupporterPlaceholder.Show();
|
notSupporterPlaceholder.Show();
|
||||||
|
|
||||||
loading.Hide();
|
loading.Hide();
|
||||||
|
loading.FinishTransforms();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,6 +243,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
getScoresRequest.Success += scores =>
|
getScoresRequest.Success += scores =>
|
||||||
{
|
{
|
||||||
loading.Hide();
|
loading.Hide();
|
||||||
|
loading.FinishTransforms();
|
||||||
|
|
||||||
Scores = scores;
|
Scores = scores;
|
||||||
|
|
||||||
if (!scores.Scores.Any())
|
if (!scores.Scores.Any())
|
||||||
|
@ -128,7 +128,7 @@ namespace osu.Game.Overlays.Dashboard.Friends
|
|||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Padding = new MarginPadding { Horizontal = 50 }
|
Padding = new MarginPadding { Horizontal = 50 }
|
||||||
},
|
},
|
||||||
loading = new LoadingLayer(itemsPlaceholder)
|
loading = new LoadingLayer(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ namespace osu.Game.Overlays
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
loading = new LoadingLayer(content),
|
loading = new LoadingLayer(true),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,9 +52,10 @@ namespace osu.Game.Overlays.Mods
|
|||||||
if (newIndex == selectedIndex) return false;
|
if (newIndex == selectedIndex) return false;
|
||||||
|
|
||||||
int direction = newIndex < selectedIndex ? -1 : 1;
|
int direction = newIndex < selectedIndex ? -1 : 1;
|
||||||
|
|
||||||
bool beforeSelected = Selected;
|
bool beforeSelected = Selected;
|
||||||
|
|
||||||
Mod modBefore = SelectedMod ?? Mods[0];
|
Mod previousSelection = SelectedMod ?? Mods[0];
|
||||||
|
|
||||||
if (newIndex >= Mods.Length)
|
if (newIndex >= Mods.Length)
|
||||||
newIndex = -1;
|
newIndex = -1;
|
||||||
@ -65,40 +66,45 @@ namespace osu.Game.Overlays.Mods
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
selectedIndex = newIndex;
|
selectedIndex = newIndex;
|
||||||
Mod modAfter = SelectedMod ?? Mods[0];
|
|
||||||
|
|
||||||
if (beforeSelected != Selected)
|
Mod newSelection = SelectedMod ?? Mods[0];
|
||||||
|
|
||||||
|
Schedule(() =>
|
||||||
{
|
{
|
||||||
iconsContainer.RotateTo(Selected ? 5f : 0f, 300, Easing.OutElastic);
|
if (beforeSelected != Selected)
|
||||||
iconsContainer.ScaleTo(Selected ? 1.1f : 1f, 300, Easing.OutElastic);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modBefore != modAfter)
|
|
||||||
{
|
|
||||||
const float rotate_angle = 16;
|
|
||||||
|
|
||||||
foregroundIcon.RotateTo(rotate_angle * direction, mod_switch_duration, mod_switch_easing);
|
|
||||||
backgroundIcon.RotateTo(-rotate_angle * direction, mod_switch_duration, mod_switch_easing);
|
|
||||||
|
|
||||||
backgroundIcon.Mod = modAfter;
|
|
||||||
|
|
||||||
using (BeginDelayedSequence(mod_switch_duration, true))
|
|
||||||
{
|
{
|
||||||
foregroundIcon
|
iconsContainer.RotateTo(Selected ? 5f : 0f, 300, Easing.OutElastic);
|
||||||
.RotateTo(-rotate_angle * direction)
|
iconsContainer.ScaleTo(Selected ? 1.1f : 1f, 300, Easing.OutElastic);
|
||||||
.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
|
||||||
|
|
||||||
backgroundIcon
|
|
||||||
.RotateTo(rotate_angle * direction)
|
|
||||||
.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
|
||||||
|
|
||||||
Schedule(() => displayMod(modAfter));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
foregroundIcon.Selected.Value = Selected;
|
if (previousSelection != newSelection)
|
||||||
|
{
|
||||||
|
const float rotate_angle = 16;
|
||||||
|
|
||||||
|
foregroundIcon.RotateTo(rotate_angle * direction, mod_switch_duration, mod_switch_easing);
|
||||||
|
backgroundIcon.RotateTo(-rotate_angle * direction, mod_switch_duration, mod_switch_easing);
|
||||||
|
|
||||||
|
backgroundIcon.Mod = newSelection;
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(mod_switch_duration, true))
|
||||||
|
{
|
||||||
|
foregroundIcon
|
||||||
|
.RotateTo(-rotate_angle * direction)
|
||||||
|
.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
||||||
|
|
||||||
|
backgroundIcon
|
||||||
|
.RotateTo(rotate_angle * direction)
|
||||||
|
.RotateTo(0f, mod_switch_duration, mod_switch_easing);
|
||||||
|
|
||||||
|
Schedule(() => displayMod(newSelection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foregroundIcon.Selected.Value = Selected;
|
||||||
|
});
|
||||||
|
|
||||||
SelectionChanged?.Invoke(SelectedMod);
|
SelectionChanged?.Invoke(SelectedMod);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,20 +127,30 @@ namespace osu.Game.Overlays.Mods
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Select one or more mods in this section and deselects all other ones.
|
/// Updates all buttons with the given list of selected mods.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="modTypes">The types of <see cref="Mod"/>s which should be selected.</param>
|
/// <param name="newSelectedMods">The new list of selected mods to select.</param>
|
||||||
public void SelectTypes(IEnumerable<Type> modTypes)
|
public void UpdateSelectedMods(IReadOnlyList<Mod> newSelectedMods)
|
||||||
{
|
{
|
||||||
foreach (var button in buttons)
|
foreach (var button in buttons)
|
||||||
{
|
updateButtonMods(button, newSelectedMods);
|
||||||
int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t == m.GetType()));
|
}
|
||||||
|
|
||||||
if (i >= 0)
|
private void updateButtonMods(ModButton button, IReadOnlyList<Mod> newSelectedMods)
|
||||||
button.SelectAt(i);
|
{
|
||||||
else
|
foreach (var mod in newSelectedMods)
|
||||||
button.Deselect();
|
{
|
||||||
|
var index = Array.FindIndex(button.Mods, m1 => mod.GetType() == m1.GetType());
|
||||||
|
if (index < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var buttonMod = button.Mods[index];
|
||||||
|
buttonMod.CopyFrom(mod);
|
||||||
|
button.SelectAt(index);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.Deselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ModSection()
|
protected ModSection()
|
||||||
|
@ -249,7 +249,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
{
|
{
|
||||||
Width = 180,
|
Width = 180,
|
||||||
Text = "Deselect All",
|
Text = "Deselect All",
|
||||||
Action = DeselectAll,
|
Action = deselectAll,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
},
|
},
|
||||||
@ -318,7 +318,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
sampleOff = audio.Samples.Get(@"UI/check-off");
|
sampleOff = audio.Samples.Get(@"UI/check-off");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeselectAll()
|
private void deselectAll()
|
||||||
{
|
{
|
||||||
foreach (var section in ModSectionsContainer.Children)
|
foreach (var section in ModSectionsContainer.Children)
|
||||||
section.DeselectAll();
|
section.DeselectAll();
|
||||||
@ -331,7 +331,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="modTypes">The types of <see cref="Mod"/>s which should be deselected.</param>
|
/// <param name="modTypes">The types of <see cref="Mod"/>s which should be deselected.</param>
|
||||||
/// <param name="immediate">Set to true to bypass animations and update selections immediately.</param>
|
/// <param name="immediate">Set to true to bypass animations and update selections immediately.</param>
|
||||||
public void DeselectTypes(Type[] modTypes, bool immediate = false)
|
private void deselectTypes(Type[] modTypes, bool immediate = false)
|
||||||
{
|
{
|
||||||
if (modTypes.Length == 0) return;
|
if (modTypes.Length == 0) return;
|
||||||
|
|
||||||
@ -409,7 +409,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
private void selectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
private void selectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||||
{
|
{
|
||||||
foreach (var section in ModSectionsContainer.Children)
|
foreach (var section in ModSectionsContainer.Children)
|
||||||
section.SelectTypes(mods.NewValue.Select(m => m.GetType()).ToList());
|
section.UpdateSelectedMods(mods.NewValue);
|
||||||
|
|
||||||
updateMods();
|
updateMods();
|
||||||
}
|
}
|
||||||
@ -438,7 +438,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
{
|
{
|
||||||
if (State.Value == Visibility.Visible) sampleOn?.Play();
|
if (State.Value == Visibility.Visible) sampleOn?.Play();
|
||||||
|
|
||||||
DeselectTypes(selectedMod.IncompatibleMods, true);
|
deselectTypes(selectedMod.IncompatibleMods, true);
|
||||||
|
|
||||||
if (selectedMod.RequiresConfiguration) ModSettingsContainer.Show();
|
if (selectedMod.RequiresConfiguration) ModSettingsContainer.Show();
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ namespace osu.Game.Overlays
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loading = new LoadingLayer(content),
|
loading = new LoadingLayer(true),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
AutoSizeAxes = Axes.Y;
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
InternalChild = new ReverseChildIDFillFlowContainer<Drawable>
|
InternalChild = new ReverseChildIDFillFlowContainer<Drawable>
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
@ -68,7 +69,7 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Margin = new MarginPadding { Vertical = 10 }
|
Margin = new MarginPadding { Vertical = 10 }
|
||||||
},
|
},
|
||||||
loading = new LoadingLayer(content)
|
loading = new LoadingLayer(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@ namespace osu.Game.Overlays
|
|||||||
Depth = -float.MaxValue
|
Depth = -float.MaxValue
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
loading = new LoadingLayer(true);
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
background = new Box
|
background = new Box
|
||||||
@ -74,12 +76,12 @@ namespace osu.Game.Overlays
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Margin = new MarginPadding { Bottom = 10 }
|
Margin = new MarginPadding { Bottom = 10 }
|
||||||
},
|
},
|
||||||
loading = new LoadingLayer(contentContainer),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
loading
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user