mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 15:12:57 +08:00
Merge branch 'master' into sharpen
This commit is contained in:
commit
374ef6ff83
4
CodeAnalysis/BannedSymbols.txt
Normal file
4
CodeAnalysis/BannedSymbols.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable<T> or EqualityComparer<T>.Default instead.
|
||||||
|
M:System.Object.Equals(System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable<T> or EqualityComparer<T>.Default instead.
|
||||||
|
M:System.ValueType.Equals(System.Object)~System.Boolean;Don't use object.Equals(Fallbacks to ValueType). Use IEquatable<T> or EqualityComparer<T>.Default instead.
|
||||||
|
T:System.IComparable;Don't use non-generic IComparable. Use generic version instead.
|
@ -14,10 +14,18 @@
|
|||||||
<ItemGroup Label="Resources">
|
<ItemGroup Label="Resources">
|
||||||
<EmbeddedResource Include="Resources\**\*.*" />
|
<EmbeddedResource Include="Resources\**\*.*" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup Label="Code Analysis">
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="2.9.7" PrivateAssets="All" />
|
||||||
|
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Documentation">
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<!-- DeepEqual is not netstandard-compatible. This is fine since we run tests with .NET Framework anyway.
|
<!-- 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 -->
|
This is required due to https://github.com/NuGet/Home/issues/5740 -->
|
||||||
<NoWarn>NU1701</NoWarn>
|
<NoWarn>$(NoWarn);NU1701</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Nuget">
|
<PropertyGroup Label="Nuget">
|
||||||
<Authors>ppy Pty Ltd</Authors>
|
<Authors>ppy Pty Ltd</Authors>
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
# osu!
|
# osu!
|
||||||
|
|
||||||
[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) [![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) [![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy)
|
[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu)
|
||||||
|
[![GitHub release](https://img.shields.io/github/release/ppy/osu.svg)]()
|
||||||
|
[![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu)
|
||||||
|
[![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy)
|
||||||
|
|
||||||
Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Commonly known by the codename "osu!lazer". Pew pew.
|
Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Commonly known by the codename "osu!lazer". Pew pew.
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
<AndroidApplication>True</AndroidApplication>
|
<AndroidApplication>True</AndroidApplication>
|
||||||
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
||||||
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
|
||||||
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" package="sh.ppy.osulazer" android:installLocation="auto" android:versionName="0.1.0">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" package="sh.ppy.osulazer" android:installLocation="auto" android:versionName="0.1.0">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Catch.Tests.Android" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Catch.Tests.Android" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
||||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!catch Test" />
|
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!catch Test" />
|
||||||
</manifest>
|
</manifest>
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>catch the fruit. to the beat.</Description>
|
<Description>catch the fruit. to the beat.</Description>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Mania.Tests.Android" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Mania.Tests.Android" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
||||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!mania Test" />
|
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!mania Test" />
|
||||||
</manifest>
|
</manifest>
|
@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
/// <param name="nextColumn">A function to retrieve the next column. If null, a randomisation scheme will be used.</param>
|
/// <param name="nextColumn">A function to retrieve the next column. If null, a randomisation scheme will be used.</param>
|
||||||
/// <param name="validation">A function to perform additional validation checks to determine if a column is a valid candidate for a <see cref="HitObject"/>.</param>
|
/// <param name="validation">A function to perform additional validation checks to determine if a column is a valid candidate for a <see cref="HitObject"/>.</param>
|
||||||
/// <param name="lowerBound">The minimum column index. If null, <see cref="RandomStart"/> is used.</param>
|
/// <param name="lowerBound">The minimum column index. If null, <see cref="RandomStart"/> is used.</param>
|
||||||
/// <param name="upperBound">The maximum column index. If null, <see cref="PatternGenerator.TotalColumns"/> is used.</param>
|
/// <param name="upperBound">The maximum column index. If null, <see cref="Patterns.PatternGenerator.TotalColumns">TotalColumns</see> is used.</param>
|
||||||
/// <param name="patterns">A list of patterns for which the validity of a column should be checked against.
|
/// <param name="patterns">A list of patterns for which the validity of a column should be checked against.
|
||||||
/// A column is not a valid candidate if a <see cref="HitObject"/> occupies the same column in any of the patterns.</param>
|
/// A column is not a valid candidate if a <see cref="HitObject"/> occupies the same column in any of the patterns.</param>
|
||||||
/// <returns>A column which has passed the <paramref name="validation"/> check and for which there are no
|
/// <returns>A column which has passed the <paramref name="validation"/> check and for which there are no
|
||||||
@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
/// Returns a random column index in the range [<paramref name="lowerBound"/>, <paramref name="upperBound"/>).
|
/// Returns a random column index in the range [<paramref name="lowerBound"/>, <paramref name="upperBound"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lowerBound">The minimum column index. If null, <see cref="RandomStart"/> is used.</param>
|
/// <param name="lowerBound">The minimum column index. If null, <see cref="RandomStart"/> is used.</param>
|
||||||
/// <param name="upperBound">The maximum column index. If null, <see cref="PatternGenerator.TotalColumns"/> is used.</param>
|
/// <param name="upperBound">The maximum column index. If null, <see cref="Patterns.PatternGenerator.TotalColumns"/> is used.</param>
|
||||||
protected int GetRandomColumn(int? lowerBound = null, int? upperBound = null) => Random.Next(lowerBound ?? RandomStart, upperBound ?? TotalColumns);
|
protected int GetRandomColumn(int? lowerBound = null, int? upperBound = null) => Random.Next(lowerBound ?? RandomStart, upperBound ?? TotalColumns);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>smash the keys. to the beat.</Description>
|
<Description>smash the keys. to the beat.</Description>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Osu.Tests.Android" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Osu.Tests.Android" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
||||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!standard Test" />
|
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!standard Test" />
|
||||||
</manifest>
|
</manifest>
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>click the circles. to the beat.</Description>
|
<Description>click the circles. to the beat.</Description>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Taiko.Tests.Android" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Taiko.Tests.Android" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
||||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!taiko Test" />
|
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!taiko Test" />
|
||||||
</manifest>
|
</manifest>
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>bash the drum. to the beat.</Description>
|
<Description>bash the drum. to the beat.</Description>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Tests.Android" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Tests.Android" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
||||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!visual Test" />
|
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!visual Test" />
|
||||||
</manifest>
|
</manifest>
|
@ -411,6 +411,48 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestImportWithDuplicateHashes()
|
||||||
|
{
|
||||||
|
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportNestedStructure)))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var osu = loadOsu(host);
|
||||||
|
|
||||||
|
var temp = TestResources.GetTestBeatmapForImport();
|
||||||
|
|
||||||
|
string extractedFolder = $"{temp}_extracted";
|
||||||
|
Directory.CreateDirectory(extractedFolder);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var zip = ZipArchive.Open(temp))
|
||||||
|
zip.WriteToDirectory(extractedFolder);
|
||||||
|
|
||||||
|
using (var zip = ZipArchive.Create())
|
||||||
|
{
|
||||||
|
zip.AddAllFromDirectory(extractedFolder);
|
||||||
|
zip.AddEntry("duplicate.osu", Directory.GetFiles(extractedFolder, "*.osu").First());
|
||||||
|
zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate));
|
||||||
|
}
|
||||||
|
|
||||||
|
await osu.Dependencies.Get<BeatmapManager>().Import(temp);
|
||||||
|
|
||||||
|
ensureLoaded(osu);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Directory.Delete(extractedFolder, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
host.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestImportNestedStructure()
|
public async Task TestImportNestedStructure()
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -51,11 +52,6 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
private void load(RulesetStore rulesets)
|
private void load(RulesetStore rulesets)
|
||||||
{
|
{
|
||||||
this.rulesets = rulesets;
|
this.rulesets = rulesets;
|
||||||
|
|
||||||
Add(carousel = new TestBeatmapCarousel
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -338,10 +334,19 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestHiding()
|
public void TestHiding()
|
||||||
{
|
{
|
||||||
BeatmapSetInfo hidingSet = createTestBeatmapSet(1);
|
BeatmapSetInfo hidingSet = null;
|
||||||
hidingSet.Beatmaps[1].Hidden = true;
|
List<BeatmapSetInfo> hiddenList = new List<BeatmapSetInfo>();
|
||||||
|
|
||||||
loadBeatmaps(new List<BeatmapSetInfo> { hidingSet });
|
AddStep("create hidden set", () =>
|
||||||
|
{
|
||||||
|
hidingSet = createTestBeatmapSet(1);
|
||||||
|
hidingSet.Beatmaps[1].Hidden = true;
|
||||||
|
|
||||||
|
hiddenList.Clear();
|
||||||
|
hiddenList.Add(hidingSet);
|
||||||
|
});
|
||||||
|
|
||||||
|
loadBeatmaps(hiddenList);
|
||||||
|
|
||||||
setSelected(1, 1);
|
setSelected(1, 1);
|
||||||
|
|
||||||
@ -375,9 +380,14 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestSelectingFilteredRuleset()
|
public void TestSelectingFilteredRuleset()
|
||||||
{
|
{
|
||||||
var testMixed = createTestBeatmapSet(set_count + 1);
|
BeatmapSetInfo testMixed = null;
|
||||||
|
|
||||||
|
createCarousel();
|
||||||
|
|
||||||
AddStep("add mixed ruleset beatmapset", () =>
|
AddStep("add mixed ruleset beatmapset", () =>
|
||||||
{
|
{
|
||||||
|
testMixed = createTestBeatmapSet(set_count + 1);
|
||||||
|
|
||||||
for (int i = 0; i <= 2; i++)
|
for (int i = 0; i <= 2; i++)
|
||||||
{
|
{
|
||||||
testMixed.Beatmaps[i].Ruleset = rulesets.AvailableRulesets.ElementAt(i);
|
testMixed.Beatmaps[i].Ruleset = rulesets.AvailableRulesets.ElementAt(i);
|
||||||
@ -429,6 +439,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
private void loadBeatmaps(List<BeatmapSetInfo> beatmapSets = null)
|
private void loadBeatmaps(List<BeatmapSetInfo> beatmapSets = null)
|
||||||
{
|
{
|
||||||
|
createCarousel();
|
||||||
|
|
||||||
if (beatmapSets == null)
|
if (beatmapSets == null)
|
||||||
{
|
{
|
||||||
beatmapSets = new List<BeatmapSetInfo>();
|
beatmapSets = new List<BeatmapSetInfo>();
|
||||||
@ -448,6 +460,20 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
AddUntilStep("Wait for load", () => changed);
|
AddUntilStep("Wait for load", () => changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createCarousel(Container target = null)
|
||||||
|
{
|
||||||
|
AddStep("Create carousel", () =>
|
||||||
|
{
|
||||||
|
selectedSets.Clear();
|
||||||
|
eagerSelectedIDs.Clear();
|
||||||
|
|
||||||
|
(target ?? this).Child = carousel = new TestBeatmapCarousel
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void ensureRandomFetchSuccess() =>
|
private void ensureRandomFetchSuccess() =>
|
||||||
AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet);
|
AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet);
|
||||||
|
|
||||||
|
@ -242,6 +242,22 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
void onRulesetChange(ValueChangedEvent<RulesetInfo> e) => rulesetChangeIndex = actionIndex++;
|
void onRulesetChange(ValueChangedEvent<RulesetInfo> e) => rulesetChangeIndex = actionIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestModsRetainedBetweenSongSelect()
|
||||||
|
{
|
||||||
|
AddAssert("empty mods", () => !Mods.Value.Any());
|
||||||
|
|
||||||
|
createSongSelect();
|
||||||
|
|
||||||
|
addRulesetImportStep(0);
|
||||||
|
|
||||||
|
changeMods(new OsuModHardRock());
|
||||||
|
|
||||||
|
createSongSelect();
|
||||||
|
|
||||||
|
AddAssert("mods retained", () => Mods.Value.Any());
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestStartAfterUnMatchingFilterDoesNotStart()
|
public void TestStartAfterUnMatchingFilterDoesNotStart()
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>tools for tournaments.</Description>
|
<Description>tools for tournaments.</Description>
|
||||||
|
@ -56,10 +56,22 @@ namespace osu.Game.Beatmaps
|
|||||||
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.
|
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="difficulty">The difficulty value to be mapped.</param>
|
/// <param name="difficulty">The difficulty value to be mapped.</param>
|
||||||
/// <param name="range">The values that define the two linear ranges.</param>
|
/// <param name="range">The values that define the two linear ranges.
|
||||||
/// <param name="range.od0">Minimum of the resulting range which will be achieved by a difficulty value of 0.</param>
|
/// <list type="table">
|
||||||
/// <param name="range.od5">Midpoint of the resulting range which will be achieved by a difficulty value of 5.</param>
|
/// <item>
|
||||||
/// <param name="range.od10">Maximum of the resulting range which will be achieved by a difficulty value of 10.</param>
|
/// <term>od0</term>
|
||||||
|
/// <description>Minimum of the resulting range which will be achieved by a difficulty value of 0.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>od5</term>
|
||||||
|
/// <description>Midpoint of the resulting range which will be achieved by a difficulty value of 5.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <term>od10</term>
|
||||||
|
/// <description>Maximum of the resulting range which will be achieved by a difficulty value of 10.</description>
|
||||||
|
/// </item>
|
||||||
|
/// </list>
|
||||||
|
/// </param>
|
||||||
/// <returns>Value to which the difficulty value maps in the specified range.</returns>
|
/// <returns>Value to which the difficulty value maps in the specified range.</returns>
|
||||||
public static double DifficultyRange(double difficulty, (double od0, double od5, double od10) range)
|
public static double DifficultyRange(double difficulty, (double od0, double od5, double od10) range)
|
||||||
=> DifficultyRange(difficulty, range.od0, range.od5, range.od10);
|
=> DifficultyRange(difficulty, range.od0, range.od5, range.od10);
|
||||||
|
@ -129,9 +129,12 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
var beatmapIds = beatmapSet.Beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList();
|
var beatmapIds = beatmapSet.Beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList();
|
||||||
|
|
||||||
|
LogForModel(beatmapSet, "Validating online IDs...");
|
||||||
|
|
||||||
// ensure all IDs are unique
|
// ensure all IDs are unique
|
||||||
if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1))
|
if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1))
|
||||||
{
|
{
|
||||||
|
LogForModel(beatmapSet, "Found non-unique IDs, resetting...");
|
||||||
resetIds();
|
resetIds();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -144,8 +147,12 @@ namespace osu.Game.Beatmaps
|
|||||||
// reset the import ids (to force a re-fetch) *unless* they match the candidate CheckForExisting set.
|
// reset the import ids (to force a re-fetch) *unless* they match the candidate CheckForExisting set.
|
||||||
// we can ignore the case where the new ids are contained by the CheckForExisting set as it will either be used (import skipped) or deleted.
|
// we can ignore the case where the new ids are contained by the CheckForExisting set as it will either be used (import skipped) or deleted.
|
||||||
var existing = CheckForExisting(beatmapSet);
|
var existing = CheckForExisting(beatmapSet);
|
||||||
|
|
||||||
if (existing == null || existingBeatmaps.Any(b => !existing.Beatmaps.Contains(b)))
|
if (existing == null || existingBeatmaps.Any(b => !existing.Beatmaps.Contains(b)))
|
||||||
|
{
|
||||||
|
LogForModel(beatmapSet, "Found existing import with IDs already, resetting...");
|
||||||
resetIds();
|
resetIds();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetIds() => beatmapSet.Beatmaps.ForEach(b => b.OnlineBeatmapID = null);
|
void resetIds() => beatmapSet.Beatmaps.ForEach(b => b.OnlineBeatmapID = null);
|
||||||
@ -296,8 +303,13 @@ namespace osu.Game.Beatmaps
|
|||||||
var decoder = Decoder.GetDecoder<Beatmap>(sr);
|
var decoder = Decoder.GetDecoder<Beatmap>(sr);
|
||||||
IBeatmap beatmap = decoder.Decode(sr);
|
IBeatmap beatmap = decoder.Decode(sr);
|
||||||
|
|
||||||
|
string hash = ms.ComputeSHA2Hash();
|
||||||
|
|
||||||
|
if (beatmapInfos.Any(b => b.Hash == hash))
|
||||||
|
continue;
|
||||||
|
|
||||||
beatmap.BeatmapInfo.Path = file.Filename;
|
beatmap.BeatmapInfo.Path = file.Filename;
|
||||||
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
beatmap.BeatmapInfo.Hash = hash;
|
||||||
beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();
|
beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();
|
||||||
|
|
||||||
var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);
|
var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);
|
||||||
@ -380,25 +392,30 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
var req = new GetBeatmapRequest(beatmap);
|
var req = new GetBeatmapRequest(beatmap);
|
||||||
|
|
||||||
req.Success += res =>
|
req.Failure += fail;
|
||||||
{
|
|
||||||
LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.");
|
|
||||||
|
|
||||||
beatmap.Status = res.Status;
|
|
||||||
beatmap.BeatmapSet.Status = res.BeatmapSet.Status;
|
|
||||||
beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID;
|
|
||||||
beatmap.OnlineBeatmapID = res.OnlineBeatmapID;
|
|
||||||
};
|
|
||||||
|
|
||||||
req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); };
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// intentionally blocking to limit web request concurrency
|
// intentionally blocking to limit web request concurrency
|
||||||
req.Perform(api);
|
req.Perform(api);
|
||||||
|
|
||||||
|
var res = req.Result;
|
||||||
|
|
||||||
|
beatmap.Status = res.Status;
|
||||||
|
beatmap.BeatmapSet.Status = res.BeatmapSet.Status;
|
||||||
|
beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID;
|
||||||
|
beatmap.OnlineBeatmapID = res.OnlineBeatmapID;
|
||||||
|
|
||||||
|
LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fail(Exception e)
|
||||||
|
{
|
||||||
|
beatmap.OnlineBeatmapID = null;
|
||||||
LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})");
|
LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether <see cref="newPoint"/> should be added.
|
/// Check whether <paramref name="newPoint"/> should be added.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The time to find the timing control point at.</param>
|
/// <param name="time">The time to find the timing control point at.</param>
|
||||||
/// <param name="newPoint">A point to be added.</param>
|
/// <param name="newPoint">A point to be added.</param>
|
||||||
|
@ -93,7 +93,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers a fallback decoder instantiation function.
|
/// Registers a fallback decoder instantiation function.
|
||||||
/// The fallback will be returned if the first non-empty line of the decoded stream does not match any known magic.
|
/// The fallback will be returned if the first non-empty line of the decoded stream does not match any known magic.
|
||||||
/// Calling this method will overwrite any existing global fallback registration for type <see cref="T"/> - use with caution.
|
/// Calling this method will overwrite any existing global fallback registration for type <typeparamref name="T"/> - use with caution.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">Type of object being decoded.</typeparam>
|
/// <typeparam name="T">Type of object being decoded.</typeparam>
|
||||||
/// <param name="constructor">A function that constructs the fallback<see cref="Decoder"/>.</param>
|
/// <param name="constructor">A function that constructs the fallback<see cref="Decoder"/>.</param>
|
||||||
|
@ -54,13 +54,13 @@ namespace osu.Game.Database
|
|||||||
public Action<Notification> PostNotification { protected get; set; }
|
public Action<Notification> PostNotification { protected get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a new <see cref="TModel"/> becomes available in the database.
|
/// Fired when a new <typeparamref name="TModel"/> becomes available in the database.
|
||||||
/// This is not guaranteed to run on the update thread.
|
/// This is not guaranteed to run on the update thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TModel> ItemAdded;
|
public event Action<TModel> ItemAdded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a <see cref="TModel"/> is removed from the database.
|
/// Fired when a <typeparamref name="TModel"/> is removed from the database.
|
||||||
/// This is not guaranteed to run on the update thread.
|
/// This is not guaranteed to run on the update thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TModel> ItemRemoved;
|
public event Action<TModel> ItemRemoved;
|
||||||
@ -95,7 +95,7 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Import one or more <see cref="TModel"/> items from filesystem <paramref name="paths"/>.
|
/// Import one or more <typeparamref name="TModel"/> items from filesystem <paramref name="paths"/>.
|
||||||
/// This will post notifications tracking progress.
|
/// This will post notifications tracking progress.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="paths">One or more archive locations on disk.</param>
|
/// <param name="paths">One or more archive locations on disk.</param>
|
||||||
@ -173,7 +173,7 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Import one <see cref="TModel"/> from the filesystem and delete the file on success.
|
/// Import one <typeparamref name="TModel"/> from the filesystem and delete the file on success.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The archive location on disk.</param>
|
/// <param name="path">The archive location on disk.</param>
|
||||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||||
@ -275,7 +275,7 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Import an item from a <see cref="TModel"/>.
|
/// Import an item from a <typeparamref name="TModel"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The model to be imported.</param>
|
/// <param name="item">The model to be imported.</param>
|
||||||
/// <param name="archive">An optional archive to use for model population.</param>
|
/// <param name="archive">An optional archive to use for model population.</param>
|
||||||
@ -589,7 +589,7 @@ namespace osu.Game.Database
|
|||||||
protected TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash);
|
protected TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// After an existing <see cref="TModel"/> is found during an import process, the default behaviour is to restore the existing
|
/// After an existing <typeparamref name="TModel"/> is found during an import process, the default behaviour is to restore the existing
|
||||||
/// item and skip the import. This method allows changing that behaviour.
|
/// item and skip the import. This method allows changing that behaviour.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="existing">The existing model.</param>
|
/// <param name="existing">The existing model.</param>
|
||||||
|
@ -41,17 +41,17 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the download request for this <see cref="TModel"/>.
|
/// Creates the download request for this <typeparamref name="TModel"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The <see cref="TModel"/> to be downloaded.</param>
|
/// <param name="model">The <typeparamref name="TModel"/> to be downloaded.</param>
|
||||||
/// <param name="minimiseDownloadSize">Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle.</param>
|
/// <param name="minimiseDownloadSize">Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle.</param>
|
||||||
/// <returns>The request object.</returns>
|
/// <returns>The request object.</returns>
|
||||||
protected abstract ArchiveDownloadRequest<TModel> CreateDownloadRequest(TModel model, bool minimiseDownloadSize);
|
protected abstract ArchiveDownloadRequest<TModel> CreateDownloadRequest(TModel model, bool minimiseDownloadSize);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Begin a download for the requested <see cref="TModel"/>.
|
/// Begin a download for the requested <typeparamref name="TModel"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The <see cref="TModel"/> to be downloaded.</param>
|
/// <param name="model">The <typeparamref name="TModel"/> to be downloaded.</param>
|
||||||
/// <param name="minimiseDownloadSize">Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle.</param>
|
/// <param name="minimiseDownloadSize">Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle.</param>
|
||||||
/// <returns>Whether the download was started.</returns>
|
/// <returns>Whether the download was started.</returns>
|
||||||
public bool Download(TModel model, bool minimiseDownloadSize = false)
|
public bool Download(TModel model, bool minimiseDownloadSize = false)
|
||||||
@ -131,9 +131,9 @@ namespace osu.Game.Database
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs implementation specific comparisons to determine whether a given model is present in the local store.
|
/// Performs implementation specific comparisons to determine whether a given model is present in the local store.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The <see cref="TModel"/> whose existence needs to be checked.</param>
|
/// <param name="model">The <typeparamref name="TModel"/> whose existence needs to be checked.</param>
|
||||||
/// <param name="items">The usable items present in the store.</param>
|
/// <param name="items">The usable items present in the store.</param>
|
||||||
/// <returns>Whether the <see cref="TModel"/> exists.</returns>
|
/// <returns>Whether the <typeparamref name="TModel"/> exists.</returns>
|
||||||
protected abstract bool CheckLocalAvailability(TModel model, IQueryable<TModel> items);
|
protected abstract bool CheckLocalAvailability(TModel model, IQueryable<TModel> items);
|
||||||
|
|
||||||
public ArchiveDownloadRequest<TModel> GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Model.Equals(model));
|
public ArchiveDownloadRequest<TModel> GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Model.Equals(model));
|
||||||
|
@ -14,34 +14,34 @@ namespace osu.Game.Database
|
|||||||
where TModel : class
|
where TModel : class
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a <see cref="TModel"/> download begins.
|
/// Fired when a <typeparamref name="TModel"/> download begins.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<ArchiveDownloadRequest<TModel>> DownloadBegan;
|
event Action<ArchiveDownloadRequest<TModel>> DownloadBegan;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a <see cref="TModel"/> download is interrupted, either due to user cancellation or failure.
|
/// Fired when a <typeparamref name="TModel"/> download is interrupted, either due to user cancellation or failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<ArchiveDownloadRequest<TModel>> DownloadFailed;
|
event Action<ArchiveDownloadRequest<TModel>> DownloadFailed;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks whether a given <see cref="TModel"/> is already available in the local store.
|
/// Checks whether a given <typeparamref name="TModel"/> is already available in the local store.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The <see cref="TModel"/> whose existence needs to be checked.</param>
|
/// <param name="model">The <typeparamref name="TModel"/> whose existence needs to be checked.</param>
|
||||||
/// <returns>Whether the <see cref="TModel"/> exists.</returns>
|
/// <returns>Whether the <typeparamref name="TModel"/> exists.</returns>
|
||||||
bool IsAvailableLocally(TModel model);
|
bool IsAvailableLocally(TModel model);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Begin a download for the requested <see cref="TModel"/>.
|
/// Begin a download for the requested <typeparamref name="TModel"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The <see cref="TModel"/> to be downloaded.</param>
|
/// <param name="model">The <stypeparamref name="TModel"/> to be downloaded.</param>
|
||||||
/// <param name="minimiseDownloadSize">Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle..</param>
|
/// <param name="minimiseDownloadSize">Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle..</param>
|
||||||
/// <returns>Whether the download was started.</returns>
|
/// <returns>Whether the download was started.</returns>
|
||||||
bool Download(TModel model, bool minimiseDownloadSize);
|
bool Download(TModel model, bool minimiseDownloadSize);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an existing <see cref="TModel"/> download request if it exists.
|
/// Gets an existing <typeparamref name="TModel"/> download request if it exists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The <see cref="TModel"/> whose request is wanted.</param>
|
/// <param name="model">The <typeparamref name="TModel"/> whose request is wanted.</param>
|
||||||
/// <returns>The <see cref="ArchiveDownloadRequest{TModel}"/> object if it exists, otherwise null.</returns>
|
/// <returns>The <see cref="ArchiveDownloadRequest{TModel}"/> object if it exists, otherwise null.</returns>
|
||||||
ArchiveDownloadRequest<TModel> GetExistingDownload(TModel model);
|
ArchiveDownloadRequest<TModel> GetExistingDownload(TModel model);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ using System;
|
|||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a model manager that publishes events when <see cref="TModel"/>s are added or removed.
|
/// Represents a model manager that publishes events when <typeparamref name="TModel"/>s are added or removed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TModel">The model type.</typeparam>
|
/// <typeparam name="TModel">The model type.</typeparam>
|
||||||
public interface IModelManager<out TModel>
|
public interface IModelManager<out TModel>
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Database
|
|||||||
public IQueryable<T> ConsumableItems => AddIncludesForConsumption(ContextFactory.Get().Set<T>());
|
public IQueryable<T> ConsumableItems => AddIncludesForConsumption(ContextFactory.Get().Set<T>());
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a <see cref="T"/> to the database.
|
/// Add a <typeparamref name="T"/> to the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item to add.</param>
|
/// <param name="item">The item to add.</param>
|
||||||
public void Add(T item)
|
public void Add(T item)
|
||||||
@ -45,7 +45,7 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update a <see cref="T"/> in the database.
|
/// Update a <typeparamref name="T"/> in the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item to update.</param>
|
/// <param name="item">The item to update.</param>
|
||||||
public void Update(T item)
|
public void Update(T item)
|
||||||
@ -58,7 +58,7 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a <see cref="T"/> from the database.
|
/// Delete a <typeparamref name="T"/> from the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item to delete.</param>
|
/// <param name="item">The item to delete.</param>
|
||||||
public bool Delete(T item)
|
public bool Delete(T item)
|
||||||
@ -77,7 +77,7 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restore a <see cref="T"/> from a deleted state.
|
/// Restore a <typeparamref name="T"/> from a deleted state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item to undelete.</param>
|
/// <param name="item">The item to undelete.</param>
|
||||||
public bool Undelete(T item)
|
public bool Undelete(T item)
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Graphics.Sprites
|
|||||||
public static class OsuSpriteTextTransformExtensions
|
public static class OsuSpriteTextTransformExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets <see cref="OsuSpriteText.Text"/> to a new value after a duration.
|
/// Sets <see cref="SpriteText.Text">Text</see> to a new value after a duration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
|
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
|
||||||
public static TransformSequence<T> TransformTextTo<T>(this T spriteText, string newText, double duration = 0, Easing easing = Easing.None)
|
public static TransformSequence<T> TransformTextTo<T>(this T spriteText, string newText, double duration = 0, Easing easing = Easing.None)
|
||||||
@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Sprites
|
|||||||
=> spriteText.TransformTo(nameof(OsuSpriteText.Text), newText, duration, easing);
|
=> spriteText.TransformTo(nameof(OsuSpriteText.Text), newText, duration, easing);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets <see cref="OsuSpriteText.Text"/> to a new value after a duration.
|
/// Sets <see cref="SpriteText.Text">Text</see> to a new value after a duration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
|
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
|
||||||
public static TransformSequence<T> TransformTextTo<T>(this TransformSequence<T> t, string newText, double duration = 0, Easing easing = Easing.None)
|
public static TransformSequence<T> TransformTextTo<T>(this TransformSequence<T> t, string newText, double duration = 0, Easing easing = Easing.None)
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
private Color4? iconColour;
|
private Color4? iconColour;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The icon colour. This does not affect <see cref="IconButton.Colour"/>.
|
/// The icon colour. This does not affect <see cref="Drawable.Colour">Colour</see>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Color4 IconColour
|
public Color4 IconColour
|
||||||
{
|
{
|
||||||
@ -49,7 +49,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The icon scale. This does not affect <see cref="IconButton.Scale"/>.
|
/// The icon scale. This does not affect <see cref="Drawable.Scale">Scale</see>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector2 IconScale
|
public Vector2 IconScale
|
||||||
{
|
{
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
protected virtual float StripHeight() => 1;
|
protected virtual float StripHeight() => 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether entries should be automatically populated if <see cref="T"/> is an <see cref="Enum"/> type.
|
/// Whether entries should be automatically populated if <typeparamref name="T"/> is an <see cref="Enum"/> type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual bool AddEnumEntriesAutomatically => true;
|
protected virtual bool AddEnumEntriesAutomatically => true;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Input.Bindings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ruleset">A reference to identify the current <see cref="Ruleset"/>. Used to lookup mappings. Null for global mappings.</param>
|
/// <param name="ruleset">A reference to identify the current <see cref="Ruleset"/>. Used to lookup mappings. Null for global mappings.</param>
|
||||||
/// <param name="variant">An optional variant for the specified <see cref="Ruleset"/>. Used when a ruleset has more than one possible keyboard layouts.</param>
|
/// <param name="variant">An optional variant for the specified <see cref="Ruleset"/>. Used when a ruleset has more than one possible keyboard layouts.</param>
|
||||||
/// <param name="simultaneousMode">Specify how to deal with multiple matches of <see cref="KeyCombination"/>s and <see cref="T"/>s.</param>
|
/// <param name="simultaneousMode">Specify how to deal with multiple matches of <see cref="KeyCombination"/>s and <typeparamref name="T"/>s.</param>
|
||||||
public DatabasedKeyBindingContainer(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None)
|
public DatabasedKeyBindingContainer(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None)
|
||||||
: base(simultaneousMode)
|
: base(simultaneousMode)
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ using osu.Game.Online.API;
|
|||||||
namespace osu.Game.Online
|
namespace osu.Game.Online
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A component which tracks a <see cref="TModel"/> through potential download/import/deletion.
|
/// A component which tracks a <typeparamref name="TModel"/> through potential download/import/deletion.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class DownloadTrackingComposite<TModel, TModelManager> : CompositeDrawable
|
public abstract class DownloadTrackingComposite<TModel, TModelManager> : CompositeDrawable
|
||||||
where TModel : class, IEquatable<TModel>
|
where TModel : class, IEquatable<TModel>
|
||||||
@ -22,7 +22,7 @@ namespace osu.Game.Online
|
|||||||
private TModelManager manager;
|
private TModelManager manager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Holds the current download state of the <see cref="TModel"/>, whether is has already been downloaded, is in progress, or is not downloaded.
|
/// Holds the current download state of the <typeparamref name="TModel"/>, whether is has already been downloaded, is in progress, or is not downloaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly Bindable<DownloadState> State = new Bindable<DownloadState>();
|
protected readonly Bindable<DownloadState> State = new Bindable<DownloadState>();
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
get => scope;
|
get => scope;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value.Equals(scope))
|
if (EqualityComparer<TScope>.Default.Equals(value, scope))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
scope = value;
|
scope = value;
|
||||||
|
@ -925,6 +925,8 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
OverlayActivationMode.Value = newOsuScreen.InitialOverlayActivationMode;
|
OverlayActivationMode.Value = newOsuScreen.InitialOverlayActivationMode;
|
||||||
|
|
||||||
|
musicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments;
|
||||||
|
|
||||||
if (newOsuScreen.HideOverlaysOnEnter)
|
if (newOsuScreen.HideOverlaysOnEnter)
|
||||||
CloseAllOverlays();
|
CloseAllOverlays();
|
||||||
else
|
else
|
||||||
|
@ -47,7 +47,7 @@ namespace osu.Game.Overlays
|
|||||||
get => beatmapSets;
|
get => beatmapSets;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (beatmapSets?.Equals(value) ?? false) return;
|
if (ReferenceEquals(beatmapSets, value)) return;
|
||||||
|
|
||||||
beatmapSets = value?.ToList();
|
beatmapSets = value?.ToList();
|
||||||
|
|
||||||
|
@ -233,6 +233,24 @@ namespace osu.Game.Overlays
|
|||||||
queuedDirection = null;
|
queuedDirection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool allowRateAdjustments;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether mod rate adjustments are allowed to be applied.
|
||||||
|
/// </summary>
|
||||||
|
public bool AllowRateAdjustments
|
||||||
|
{
|
||||||
|
get => allowRateAdjustments;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (allowRateAdjustments == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
allowRateAdjustments = value;
|
||||||
|
ResetTrackAdjustments();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ResetTrackAdjustments()
|
public void ResetTrackAdjustments()
|
||||||
{
|
{
|
||||||
var track = current?.Track;
|
var track = current?.Track;
|
||||||
@ -241,8 +259,11 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
track.ResetSpeedAdjustments();
|
track.ResetSpeedAdjustments();
|
||||||
|
|
||||||
foreach (var mod in mods.Value.OfType<IApplicableToClock>())
|
if (allowRateAdjustments)
|
||||||
mod.ApplyToClock(track);
|
{
|
||||||
|
foreach (var mod in mods.Value.OfType<IApplicableToClock>())
|
||||||
|
mod.ApplyToClock(track);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
@ -86,7 +86,7 @@ namespace osu.Game.Overlays
|
|||||||
/// <param name="source">The object that registered the <see cref="ConfigManager{T}"/> to be tracked.</param>
|
/// <param name="source">The object that registered the <see cref="ConfigManager{T}"/> to be tracked.</param>
|
||||||
/// <param name="configManager">The <see cref="ConfigManager{T}"/> that is being tracked.</param>
|
/// <param name="configManager">The <see cref="ConfigManager{T}"/> that is being tracked.</param>
|
||||||
/// <exception cref="ArgumentNullException">If <paramref name="configManager"/> is null.</exception>
|
/// <exception cref="ArgumentNullException">If <paramref name="configManager"/> is null.</exception>
|
||||||
/// <exception cref="InvalidOperationException">If <paramref name="configManager"/> is not being tracked from the same <see cref="source"/>.</exception>
|
/// <exception cref="InvalidOperationException">If <paramref name="configManager"/> is not being tracked from the same <paramref name="source"/>.</exception>
|
||||||
public void StopTracking(object source, ITrackableConfigManager configManager)
|
public void StopTracking(object source, ITrackableConfigManager configManager)
|
||||||
{
|
{
|
||||||
if (configManager == null) throw new ArgumentNullException(nameof(configManager));
|
if (configManager == null) throw new ArgumentNullException(nameof(configManager));
|
||||||
|
@ -12,6 +12,7 @@ namespace osu.Game.Overlays.Settings
|
|||||||
{
|
{
|
||||||
Margin = new MarginPadding { Top = 5 },
|
Margin = new MarginPadding { Top = 5 },
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
|
CommitOnFocusLost = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Overlays
|
|||||||
get => users;
|
get => users;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (users?.Equals(value) ?? false)
|
if (ReferenceEquals(users, value))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
users = value?.ToList();
|
users = value?.ToList();
|
||||||
|
@ -246,9 +246,9 @@ namespace osu.Game.Rulesets.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates and adds the visual representation of a <see cref="TObject"/> to this <see cref="DrawableRuleset{TObject}"/>.
|
/// Creates and adds the visual representation of a <typeparamref name="TObject"/> to this <see cref="DrawableRuleset{TObject}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hitObject">The <see cref="TObject"/> to add the visual representation for.</param>
|
/// <param name="hitObject">The <typeparamref name="TObject"/> to add the visual representation for.</param>
|
||||||
private void addHitObject(TObject hitObject)
|
private void addHitObject(TObject hitObject)
|
||||||
{
|
{
|
||||||
var drawableObject = CreateDrawableRepresentation(hitObject);
|
var drawableObject = CreateDrawableRepresentation(hitObject);
|
||||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="time">The point in time.</param>
|
/// <param name="time">The point in time.</param>
|
||||||
/// <param name="timeRange">The amount of visible time.</param>
|
/// <param name="timeRange">The amount of visible time.</param>
|
||||||
/// <returns>The time at which <paramref name="time"/> enters <see cref="timeRange"/>.</returns>
|
/// <returns>The time at which <paramref name="time"/> enters <paramref name="timeRange"/>.</returns>
|
||||||
double GetDisplayStartTime(double time, double timeRange);
|
double GetDisplayStartTime(double time, double timeRange);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
|
|||||||
/// <param name="startTime">The start time.</param>
|
/// <param name="startTime">The start time.</param>
|
||||||
/// <param name="endTime">The end time.</param>
|
/// <param name="endTime">The end time.</param>
|
||||||
/// <param name="timeRange">The amount of visible time.</param>
|
/// <param name="timeRange">The amount of visible time.</param>
|
||||||
/// <param name="scrollLength">The absolute spatial length through <see cref="timeRange"/>.</param>
|
/// <param name="scrollLength">The absolute spatial length through <paramref name="timeRange"/>.</param>
|
||||||
/// <returns>The absolute spatial length.</returns>
|
/// <returns>The absolute spatial length.</returns>
|
||||||
float GetLength(double startTime, double endTime, double timeRange, float scrollLength);
|
float GetLength(double startTime, double endTime, double timeRange, float scrollLength);
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
|
|||||||
/// <param name="time">The time to compute the spatial position of.</param>
|
/// <param name="time">The time to compute the spatial position of.</param>
|
||||||
/// <param name="currentTime">The current time.</param>
|
/// <param name="currentTime">The current time.</param>
|
||||||
/// <param name="timeRange">The amount of visible time.</param>
|
/// <param name="timeRange">The amount of visible time.</param>
|
||||||
/// <param name="scrollLength">The absolute spatial length through <see cref="timeRange"/>.</param>
|
/// <param name="scrollLength">The absolute spatial length through <paramref name="timeRange"/>.</param>
|
||||||
/// <returns>The absolute spatial position.</returns>
|
/// <returns>The absolute spatial position.</returns>
|
||||||
float PositionAt(double time, double currentTime, double timeRange, float scrollLength);
|
float PositionAt(double time, double currentTime, double timeRange, float scrollLength);
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
|
|||||||
/// <param name="position">The absolute spatial position.</param>
|
/// <param name="position">The absolute spatial position.</param>
|
||||||
/// <param name="currentTime">The current time.</param>
|
/// <param name="currentTime">The current time.</param>
|
||||||
/// <param name="timeRange">The amount of visible time.</param>
|
/// <param name="timeRange">The amount of visible time.</param>
|
||||||
/// <param name="scrollLength">The absolute spatial length through <see cref="timeRange"/>.</param>
|
/// <param name="scrollLength">The absolute spatial length through <paramref name="timeRange"/>.</param>
|
||||||
/// <returns>The time at which <see cref="PositionAt(double,double,double,float)"/> == <paramref name="position"/>.</returns>
|
/// <returns>The time at which <see cref="PositionAt(double,double,double,float)"/> == <paramref name="position"/>.</returns>
|
||||||
double TimeAt(float position, double currentTime, double timeRange, float scrollLength);
|
double TimeAt(float position, double currentTime, double timeRange, float scrollLength);
|
||||||
|
|
||||||
|
@ -183,6 +183,10 @@ namespace osu.Game.Scoring
|
|||||||
|
|
||||||
public override string ToString() => $"{User} playing {Beatmap}";
|
public override string ToString() => $"{User} playing {Beatmap}";
|
||||||
|
|
||||||
public bool Equals(ScoreInfo other) => other?.OnlineScoreID == OnlineScoreID;
|
public bool Equals(ScoreInfo other) =>
|
||||||
|
other != null
|
||||||
|
&& other.OnlineScoreID == OnlineScoreID
|
||||||
|
&& other.BeatmapInfoID == BeatmapInfoID
|
||||||
|
&& other.Hash == Hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,6 @@ namespace osu.Game.Scoring
|
|||||||
|
|
||||||
protected override ArchiveDownloadRequest<ScoreInfo> CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score);
|
protected override ArchiveDownloadRequest<ScoreInfo> CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score);
|
||||||
|
|
||||||
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<ScoreInfo> items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID && s.Files.Any());
|
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<ScoreInfo> items) => items.Any(s => s.Equals(model) && s.Files.Any());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,5 +51,10 @@ namespace osu.Game.Screens
|
|||||||
Bindable<WorkingBeatmap> Beatmap { get; }
|
Bindable<WorkingBeatmap> Beatmap { get; }
|
||||||
|
|
||||||
Bindable<RulesetInfo> Ruleset { get; }
|
Bindable<RulesetInfo> Ruleset { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether mod rate adjustments are allowed to be applied.
|
||||||
|
/// </summary>
|
||||||
|
bool AllowRateAdjustments { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
public override bool AllowExternalScreenChange => true;
|
public override bool AllowExternalScreenChange => true;
|
||||||
|
|
||||||
|
public override bool AllowRateAdjustments => false;
|
||||||
|
|
||||||
private Screen songSelect;
|
private Screen songSelect;
|
||||||
|
|
||||||
private MenuSideFlashes sideFlashes;
|
private MenuSideFlashes sideFlashes;
|
||||||
|
@ -102,7 +102,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
private void flash(Drawable d, double beatLength, bool kiai, TrackAmplitudes amplitudes)
|
private void flash(Drawable d, double beatLength, bool kiai, TrackAmplitudes amplitudes)
|
||||||
{
|
{
|
||||||
d.FadeTo(Math.Max(0, ((d.Equals(leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time)
|
d.FadeTo(Math.Max(0, ((ReferenceEquals(d, leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time)
|
||||||
.Then()
|
.Then()
|
||||||
.FadeOut(beatLength, Easing.In);
|
.FadeOut(beatLength, Easing.In);
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,8 @@ namespace osu.Game.Screens
|
|||||||
|
|
||||||
public Bindable<RulesetInfo> Ruleset { get; private set; }
|
public Bindable<RulesetInfo> Ruleset { get; private set; }
|
||||||
|
|
||||||
|
public virtual bool AllowRateAdjustments => true;
|
||||||
|
|
||||||
public Bindable<IReadOnlyList<Mod>> Mods { get; private set; }
|
public Bindable<IReadOnlyList<Mod>> Mods { get; private set; }
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// 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;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play
|
namespace osu.Game.Screens.Play
|
||||||
{
|
{
|
||||||
public class KeyCounterAction<T> : KeyCounter
|
public class KeyCounterAction<T> : KeyCounter
|
||||||
@ -16,7 +18,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public bool OnPressed(T action, bool forwards)
|
public bool OnPressed(T action, bool forwards)
|
||||||
{
|
{
|
||||||
if (!action.Equals(Action))
|
if (!EqualityComparer<T>.Default.Equals(action, Action))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IsLit = true;
|
IsLit = true;
|
||||||
@ -27,7 +29,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public bool OnReleased(T action, bool forwards)
|
public bool OnReleased(T action, bool forwards)
|
||||||
{
|
{
|
||||||
if (!action.Equals(Action))
|
if (!EqualityComparer<T>.Default.Equals(action, Action))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IsLit = false;
|
IsLit = false;
|
||||||
|
@ -351,7 +351,7 @@ namespace osu.Game.Screens.Select
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Half the height of the visible content.
|
/// Half the height of the visible content.
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This is different from the height of <see cref="ScrollContainer{T}.displayableContent"/>, since
|
/// This is different from the height of <see cref="ScrollContainer{T}"/>.displayableContent, since
|
||||||
/// the beatmap carousel bleeds into the <see cref="FilterControl"/> and the <see cref="Footer"/>
|
/// the beatmap carousel bleeds into the <see cref="FilterControl"/> and the <see cref="Footer"/>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -66,7 +66,7 @@ namespace osu.Game.Screens.Select
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly Container FooterPanels;
|
protected readonly Container FooterPanels;
|
||||||
|
|
||||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap();
|
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value);
|
||||||
|
|
||||||
protected readonly BeatmapCarousel Carousel;
|
protected readonly BeatmapCarousel Carousel;
|
||||||
private readonly BeatmapInfoWedge beatmapInfoWedge;
|
private readonly BeatmapInfoWedge beatmapInfoWedge;
|
||||||
@ -86,10 +86,6 @@ namespace osu.Game.Screens.Select
|
|||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private MusicController music { get; set; }
|
private MusicController music { get; set; }
|
||||||
|
|
||||||
[Cached]
|
|
||||||
[Cached(Type = typeof(IBindable<IReadOnlyList<Mod>>))]
|
|
||||||
private readonly Bindable<IReadOnlyList<Mod>> mods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>()); // Bound to the game's mods, but is not reset on exiting
|
|
||||||
|
|
||||||
protected SongSelect()
|
protected SongSelect()
|
||||||
{
|
{
|
||||||
AddRangeInternal(new Drawable[]
|
AddRangeInternal(new Drawable[]
|
||||||
@ -222,7 +218,7 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
if (Footer != null)
|
if (Footer != null)
|
||||||
{
|
{
|
||||||
Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect);
|
Footer.AddButton(new FooterButtonMods { Current = Mods }, ModSelect);
|
||||||
Footer.AddButton(new FooterButtonRandom { Action = triggerRandom });
|
Footer.AddButton(new FooterButtonRandom { Action = triggerRandom });
|
||||||
Footer.AddButton(new FooterButtonOptions(), BeatmapOptions);
|
Footer.AddButton(new FooterButtonOptions(), BeatmapOptions);
|
||||||
|
|
||||||
@ -262,13 +258,6 @@ namespace osu.Game.Screens.Select
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
mods.BindTo(Mods);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DependencyContainer dependencies;
|
private DependencyContainer dependencies;
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||||
@ -390,7 +379,7 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\"");
|
Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\"");
|
||||||
|
|
||||||
mods.Value = Array.Empty<Mod>();
|
Mods.Value = Array.Empty<Mod>();
|
||||||
decoupledRuleset.Value = ruleset;
|
decoupledRuleset.Value = ruleset;
|
||||||
|
|
||||||
// force a filter before attempting to change the beatmap.
|
// force a filter before attempting to change the beatmap.
|
||||||
@ -405,7 +394,7 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
// We may be arriving here due to another component changing the bindable Beatmap.
|
// We may be arriving here due to another component changing the bindable Beatmap.
|
||||||
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
|
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
|
||||||
if (!Equals(beatmap, Beatmap.Value.BeatmapInfo))
|
if (!EqualityComparer<BeatmapInfo>.Default.Equals(beatmap, Beatmap.Value.BeatmapInfo))
|
||||||
{
|
{
|
||||||
Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\"");
|
Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\"");
|
||||||
|
|
||||||
@ -538,9 +527,6 @@ namespace osu.Game.Screens.Select
|
|||||||
if (Beatmap.Value.Track != null)
|
if (Beatmap.Value.Track != null)
|
||||||
Beatmap.Value.Track.Looping = false;
|
Beatmap.Value.Track.Looping = false;
|
||||||
|
|
||||||
mods.UnbindAll();
|
|
||||||
Mods.Value = Array.Empty<Mod>();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ namespace osu.Game.Screens
|
|||||||
|
|
||||||
public override bool CursorVisible => false;
|
public override bool CursorVisible => false;
|
||||||
|
|
||||||
|
public override bool AllowRateAdjustments => false;
|
||||||
|
|
||||||
public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled;
|
public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -76,4 +76,17 @@
|
|||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1010.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1010.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.1112.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.1112.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
||||||
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
|
<PackageReference Include="Humanizer" Version="2.7.9" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
|
<PackageReference Include="ppy.osu.Framework" Version="2019.1112.0" />
|
||||||
|
<PackageReference Include="SharpCompress" Version="0.24.0" />
|
||||||
|
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||||
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
|
<PackageReference Include="System.ComponentModel.Annotations" Version="4.6.0" />
|
||||||
|
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2019.1112.0" ExcludeAssets="all" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user