1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 20:07:29 +08:00

Merge remote-tracking branch 'upstream/master' into lead-in-fixes

This commit is contained in:
Dean Herbert 2019-11-21 14:22:17 +09:00
commit c0b9bb5a12
89 changed files with 419 additions and 212 deletions

View File

@ -18,10 +18,14 @@
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="2.9.7" PrivateAssets="All" /> <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="2.9.7" PrivateAssets="All" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" /> <AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
</ItemGroup> </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>

View File

@ -10,7 +10,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>
@ -53,6 +53,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<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.Android" Version="2019.1112.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2019.1121.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -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" />

View File

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

View File

@ -8,7 +8,6 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osuTK;
using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Catch.MathUtils;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -78,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
catchObject.XOffset = 0; catchObject.XOffset = 0;
if (catchObject is TinyDroplet) if (catchObject is TinyDroplet)
catchObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); catchObject.XOffset = Math.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X);
else if (catchObject is Droplet) else if (catchObject is Droplet)
rng.Next(); // osu!stable retrieved a random droplet rotation rng.Next(); // osu!stable retrieved a random droplet rotation
} }
@ -230,7 +229,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
else else
{ {
currentObject.DistanceToHyperDash = distanceToHyper; currentObject.DistanceToHyperDash = distanceToHyper;
lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth); lastExcess = Math.Clamp(distanceToHyper, 0, halfCatcherWidth);
} }
lastDirection = thisDirection; lastDirection = thisDirection;

View File

@ -10,7 +10,6 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Scoring.Legacy; using osu.Game.Scoring.Legacy;
using osuTK;
namespace osu.Game.Rulesets.Catch.Difficulty namespace osu.Game.Rulesets.Catch.Difficulty
{ {
@ -96,7 +95,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
return value; return value;
} }
private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f);
private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed;
private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit;
private int totalComboHits() => misses + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit;

View File

@ -6,7 +6,6 @@ using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Difficulty.Skills;
using osuTK;
namespace osu.Game.Rulesets.Catch.Difficulty.Skills namespace osu.Game.Rulesets.Catch.Difficulty.Skills
{ {
@ -31,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
if (lastPlayerPosition == null) if (lastPlayerPosition == null)
lastPlayerPosition = catchCurrent.LastNormalizedPosition; lastPlayerPosition = catchCurrent.LastNormalizedPosition;
float playerPosition = MathHelper.Clamp( float playerPosition = Math.Clamp(
lastPlayerPosition.Value, lastPlayerPosition.Value,
catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error),
catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error)

View File

@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {
base.Update(); base.Update();
border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); border.Alpha = (float)Math.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1);
} }
private Color4 colourForRepresentation(FruitVisualRepresentation representation) private Color4 colourForRepresentation(FruitVisualRepresentation representation)

View File

@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI
fruit.Y -= RNG.NextSingle() * diff; fruit.Y -= RNG.NextSingle() * diff;
} }
fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2);
caughtFruit.Add(fruit); caughtFruit.Add(fruit);
} }
@ -378,7 +378,7 @@ namespace osu.Game.Rulesets.Catch.UI
double speed = BASE_SPEED * dashModifier * hyperDashModifier; double speed = BASE_SPEED * dashModifier * hyperDashModifier;
Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y);
X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); X = (float)Math.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1);
// Correct overshooting. // Correct overshooting.
if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) ||

View File

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

View File

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

View File

@ -7,7 +7,6 @@ using JetBrains.Annotations;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.MathUtils;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osuTK;
namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
{ {
@ -54,11 +53,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
if (allowSpecial && TotalColumns == 8) if (allowSpecial && TotalColumns == 8)
{ {
const float local_x_divisor = 512f / 7; const float local_x_divisor = 512f / 7;
return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1;
} }
float localXDivisor = 512f / TotalColumns; float localXDivisor = 512f / TotalColumns;
return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1);
} }
/// <summary> /// <summary>
@ -113,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
drainTime = 10000; drainTime = 10000;
BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty;
conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15;
conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); conversionDifficulty = Math.Min(conversionDifficulty.Value, 12);
return conversionDifficulty.Value; return conversionDifficulty.Value;
@ -139,7 +138,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 +183,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>

View File

@ -1,6 +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 System;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Timing; using osu.Framework.Timing;
@ -9,7 +10,6 @@ using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
namespace osu.Game.Rulesets.Mania.Edit namespace osu.Game.Rulesets.Mania.Edit
{ {
@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Mania.Edit
maxColumn = obj.Column; maxColumn = obj.Column;
} }
columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); columnDelta = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn);
foreach (var obj in SelectedHitObjects.OfType<ManiaHitObject>()) foreach (var obj in SelectedHitObjects.OfType<ManiaHitObject>())
obj.Column += columnDelta; obj.Column += columnDelta;

View File

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

View File

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

View File

@ -1,6 +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 System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -13,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring; using osu.Game.Scoring;
using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Rulesets.Osu.Mods namespace osu.Game.Rulesets.Osu.Mods
@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Mods
}; };
} }
private float calculateGap(float value) => MathHelper.Clamp(value, 0, target_clamp) * targetBreakMultiplier; private float calculateGap(float value) => Math.Clamp(value, 0, target_clamp) * targetBreakMultiplier;
// lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve // lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve
private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value; private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value;

View File

@ -1,6 +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 System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Bindables; using osu.Framework.Bindables;
@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Mods
var destination = e.MousePosition; var destination = e.MousePosition;
FlashlightPosition = Interpolation.ValueAt( FlashlightPosition = Interpolation.ValueAt(
MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); Math.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out);
return base.OnMouseMove(e); return base.OnMouseMove(e);
} }

View File

@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
else else
{ {
// If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly). // If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly).
Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint);
} }
} }
} }

View File

@ -1,6 +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 System;
using osuTK; using osuTK;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -165,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Tracking.Value = Ball.Tracking; Tracking.Value = Ball.Tracking;
double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
Ball.UpdateProgress(completionProgress); Ball.UpdateProgress(completionProgress);
Body.UpdateProgress(completionProgress); Body.UpdateProgress(completionProgress);

View File

@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
base.Update(); base.Update();
double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
if (!IsHit) if (!IsHit)

View File

@ -1,6 +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 System;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
positionBindable.BindTo(HitObject.PositionBindable); positionBindable.BindTo(HitObject.PositionBindable);
} }
public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); public float Progress => Math.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1);
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
{ {

View File

@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
var spanProgress = slider.ProgressAt(completionProgress); var spanProgress = slider.ProgressAt(completionProgress);
double start = 0; double start = 0;
double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1;
if (span >= slider.SpanCount() - 1) if (span >= slider.SpanCount() - 1)
{ {

View File

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

View File

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

View File

@ -1,12 +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 System;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
else else
rollingHits--; rollingHits--;
rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour);
Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1);
MainPiece.FadeAccent(newColour, 100); MainPiece.FadeAccent(newColour, 100);

View File

@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
@ -179,7 +178,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
var completion = (float)numHits / HitObject.RequiredHits; var completion = (float)numHits / HitObject.RequiredHits;
expandingRing expandingRing
.FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50)
.Then() .Then()
.FadeTo(completion / 8, 2000, Easing.OutQuint); .FadeTo(completion / 8, 2000, Easing.OutQuint);

View File

@ -1,6 +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 System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osuTK; using osuTK;
@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
base.Update(); base.Update();
float aspectAdjust = MathHelper.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; float aspectAdjust = Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect;
Size = new Vector2(1, default_relative_height * aspectAdjust); Size = new Vector2(1, default_relative_height * aspectAdjust);
} }
} }

View File

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

View File

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

View File

@ -3,6 +3,7 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Audio; using osu.Game.Audio;
@ -13,7 +14,9 @@ namespace osu.Game.Tests.Visual.Components
{ {
public class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner public class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner
{ {
private readonly PreviewTrackManager trackManager = new TestPreviewTrackManager(); private readonly TestPreviewTrackManager trackManager = new TestPreviewTrackManager();
private AudioManager audio;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{ {
@ -24,8 +27,10 @@ namespace osu.Game.Tests.Visual.Components
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load(AudioManager audio)
{ {
this.audio = audio;
Add(trackManager); Add(trackManager);
} }
@ -108,6 +113,60 @@ namespace osu.Game.Tests.Visual.Components
AddAssert("track stopped", () => !track.IsRunning); AddAssert("track stopped", () => !track.IsRunning);
} }
/// <summary>
/// Ensures that <see cref="PreviewTrackManager.CurrentTrack"/> changes correctly.
/// </summary>
[Test]
public void TestCurrentTrackChanges()
{
PreviewTrack track = null;
TestTrackOwner owner = null;
AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack())));
AddUntilStep("wait loaded", () => track.IsLoaded);
AddStep("start track", () => track.Start());
AddAssert("current is track", () => trackManager.CurrentTrack == track);
AddStep("pause manager updates", () => trackManager.AllowUpdate = false);
AddStep("stop any playing", () => trackManager.StopAnyPlaying(owner));
AddAssert("current not changed", () => trackManager.CurrentTrack == track);
AddStep("resume manager updates", () => trackManager.AllowUpdate = true);
AddAssert("current is null", () => trackManager.CurrentTrack == null);
}
/// <summary>
/// Ensures that <see cref="PreviewTrackManager"/> mutes game-wide audio tracks correctly.
/// </summary>
[TestCase(false)]
[TestCase(true)]
public void TestEnsureMutingCorrectly(bool stopAnyPlaying)
{
PreviewTrack track = null;
TestTrackOwner owner = null;
AddStep("ensure volume not zero", () =>
{
if (audio.Volume.Value == 0)
audio.Volume.Value = 1;
if (audio.VolumeTrack.Value == 0)
audio.VolumeTrack.Value = 1;
});
AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0);
AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack())));
AddUntilStep("wait loaded", () => track.IsLoaded);
AddStep("start track", () => track.Start());
AddAssert("game is muted", () => audio.Tracks.AggregateVolume.Value == 0);
if (stopAnyPlaying)
AddStep("stop any playing", () => trackManager.StopAnyPlaying(owner));
else
AddStep("stop track", () => track.Stop());
AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0);
}
private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null); private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null);
private TestPreviewTrack getOwnedTrack() private TestPreviewTrack getOwnedTrack()
@ -144,8 +203,20 @@ namespace osu.Game.Tests.Visual.Components
public class TestPreviewTrackManager : PreviewTrackManager public class TestPreviewTrackManager : PreviewTrackManager
{ {
public bool AllowUpdate = true;
public new PreviewTrack CurrentTrack => base.CurrentTrack;
protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore);
public override bool UpdateSubTree()
{
if (!AllowUpdate)
return true;
return base.UpdateSubTree();
}
public class TestPreviewTrack : TrackManagerPreviewTrack public class TestPreviewTrack : TrackManagerPreviewTrack
{ {
private readonly ITrackStore trackManager; private readonly ITrackStore trackManager;

View File

@ -57,23 +57,6 @@ namespace osu.Game.Tests.Visual.SongSelect
typeof(DrawableCarouselBeatmapSet), typeof(DrawableCarouselBeatmapSet),
}; };
private class TestSongSelect : PlaySongSelect
{
public Action StartRequested;
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
public new BeatmapCarousel Carousel => base.Carousel;
protected override bool OnStart()
{
StartRequested?.Invoke();
return base.OnStart();
}
}
private TestSongSelect songSelect; private TestSongSelect songSelect;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -101,6 +84,17 @@ namespace osu.Game.Tests.Visual.SongSelect
manager?.Delete(manager.GetAllUsableBeatmapSets()); manager?.Delete(manager.GetAllUsableBeatmapSets());
}); });
[Test]
public void TestSingleFilterOnEnter()
{
addRulesetImportStep(0);
addRulesetImportStep(0);
createSongSelect();
AddAssert("filter count is 1", () => songSelect.FilterCount == 1);
}
[Test] [Test]
public void TestAudioResuming() public void TestAudioResuming()
{ {
@ -242,6 +236,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()
{ {
@ -357,5 +367,30 @@ namespace osu.Game.Tests.Visual.SongSelect
base.Dispose(isDisposing); base.Dispose(isDisposing);
rulesets?.Dispose(); rulesets?.Dispose();
} }
private class TestSongSelect : PlaySongSelect
{
public Action StartRequested;
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
public new BeatmapCarousel Carousel => base.Carousel;
protected override bool OnStart()
{
StartRequested?.Invoke();
return base.OnStart();
}
public int FilterCount;
protected override void ApplyFilterToCarousel(FilterCriteria criteria)
{
FilterCount++;
base.ApplyFilterToCarousel(criteria);
}
}
} }
} }

View File

@ -1,6 +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 System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Ladder
protected override bool OnScroll(ScrollEvent e) protected override bool OnScroll(ScrollEvent e)
{ {
var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); var newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale);
this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint);
this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint);

View File

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

View File

@ -22,7 +22,7 @@ namespace osu.Game.Audio
private AudioManager audio; private AudioManager audio;
private PreviewTrackStore trackStore; private PreviewTrackStore trackStore;
private TrackManagerPreviewTrack current; protected TrackManagerPreviewTrack CurrentTrack;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio) private void load(AudioManager audio)
@ -48,17 +48,17 @@ namespace osu.Game.Audio
track.Started += () => Schedule(() => track.Started += () => Schedule(() =>
{ {
current?.Stop(); CurrentTrack?.Stop();
current = track; CurrentTrack = track;
audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable);
}); });
track.Stopped += () => Schedule(() => track.Stopped += () => Schedule(() =>
{ {
if (current != track) if (CurrentTrack != track)
return; return;
current = null; CurrentTrack = null;
audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable);
}); });
@ -76,11 +76,11 @@ namespace osu.Game.Audio
/// <param name="source">The <see cref="IPreviewTrackOwner"/> which may be the owner of the <see cref="PreviewTrack"/>.</param> /// <param name="source">The <see cref="IPreviewTrackOwner"/> which may be the owner of the <see cref="PreviewTrack"/>.</param>
public void StopAnyPlaying(IPreviewTrackOwner source) public void StopAnyPlaying(IPreviewTrackOwner source)
{ {
if (current == null || current.Owner != source) if (CurrentTrack == null || CurrentTrack.Owner != source)
return; return;
current.Stop(); CurrentTrack.Stop();
current = null; // CurrentTrack should not be set to null here as it will result in incorrect handling in the track.Stopped callback above.
} }
/// <summary> /// <summary>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +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 System;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input; using osu.Framework.Input;
@ -48,7 +49,7 @@ namespace osu.Game.Graphics.Containers
if (!parallaxEnabled.Value) if (!parallaxEnabled.Value)
{ {
content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint);
content.Scale = new Vector2(1 + System.Math.Abs(ParallaxAmount)); content.Scale = new Vector2(1 + Math.Abs(ParallaxAmount));
} }
}; };
} }
@ -71,10 +72,10 @@ namespace osu.Game.Graphics.Containers
const float parallax_duration = 100; const float parallax_duration = 100;
double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration);
content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint);
content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint);
} }
firstUpdate = false; firstUpdate = false;

View File

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

View File

@ -1,12 +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 System;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
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 System;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
@ -29,7 +29,7 @@ namespace osu.Game.Graphics.UserInterface
get => length; get => length;
set set
{ {
length = MathHelper.Clamp(value, 0, 1); length = Math.Clamp(value, 0, 1);
updateBarLength(); updateBarLength();
} }
} }

View File

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

View File

@ -175,9 +175,9 @@ namespace osu.Game.Graphics.UserInterface
protected override void UpdateAfterChildren() protected override void UpdateAfterChildren()
{ {
base.UpdateAfterChildren(); base.UpdateAfterChildren();
leftBox.Scale = new Vector2(MathHelper.Clamp( leftBox.Scale = new Vector2(Math.Clamp(
Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1);
rightBox.Scale = new Vector2(MathHelper.Clamp( rightBox.Scale = new Vector2(Math.Clamp(
DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1);
} }

View File

@ -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;
@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface
// dont bother calculating if the strip is invisible // dont bother calculating if the strip is invisible
if (strip.Colour.MaxAlpha > 0) if (strip.Colour.MaxAlpha > 0)
strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint);
} }
public class OsuTabItem : TabItem<T>, IHasAccentColour public class OsuTabItem : TabItem<T>, IHasAccentColour

View File

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

View File

@ -227,7 +227,7 @@ namespace osu.Game.Online.API
{ {
try try
{ {
return JObject.Parse(req.ResponseString).SelectToken("form_error", true).ToObject<RegistrationRequest.RegistrationRequestErrors>(); return JObject.Parse(req.GetResponseString()).SelectToken("form_error", true).ToObject<RegistrationRequest.RegistrationRequestErrors>();
} }
catch catch
{ {

View File

@ -113,7 +113,7 @@ namespace osu.Game.Online.API
cancelled = true; cancelled = true;
WebRequest?.Abort(); WebRequest?.Abort();
string responseString = WebRequest?.ResponseString; string responseString = WebRequest?.GetResponseString();
if (!string.IsNullOrEmpty(responseString)) if (!string.IsNullOrEmpty(responseString))
{ {

View File

@ -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>();

View File

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

View File

@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs
private void tabCloseRequested(TabItem<Channel> tab) private void tabCloseRequested(TabItem<Channel> tab)
{ {
int totalTabs = TabContainer.Count - 1; // account for selectorTab int totalTabs = TabContainer.Count - 1; // account for selectorTab
int currentIndex = MathHelper.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); int currentIndex = Math.Clamp(TabContainer.IndexOf(tab), 1, totalTabs);
if (tab == SelectedTab && totalTabs > 1) if (tab == SelectedTab && totalTabs > 1)
// Select the tab after tab-to-be-removed's index, or the tab before if current == last // Select the tab after tab-to-be-removed's index, or the tab before if current == last

View File

@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Music
break; break;
} }
dstIndex = MathHelper.Clamp(dstIndex, 0, items.Count - 1); dstIndex = Math.Clamp(dstIndex, 0, items.Count - 1);
if (srcIndex == dstIndex) if (srcIndex == dstIndex)
return; return;

View File

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

View File

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

View File

@ -1,6 +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 System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -8,7 +9,6 @@ using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osuTK;
namespace osu.Game.Overlays.Profile.Header.Components namespace osu.Game.Overlays.Profile.Header.Components
{ {
@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
{ {
set set
{ {
int count = MathHelper.Clamp(value, 0, 3); int count = Math.Clamp(value, 0, 3);
if (count == 0) if (count == 0)
{ {

View File

@ -9,7 +9,6 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osuTK;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mods
/// <param name="amount">The amount of adjustment to apply (from 0..1).</param> /// <param name="amount">The amount of adjustment to apply (from 0..1).</param>
private void applyAdjustment(double amount) private void applyAdjustment(double amount)
{ {
double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment));
switch (clock) switch (clock)
{ {

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osuTK;
namespace osu.Game.Rulesets.Objects namespace osu.Game.Rulesets.Objects
{ {
@ -18,7 +17,7 @@ namespace osu.Game.Rulesets.Objects
const double max_length = 100000; const double max_length = 100000;
var length = Math.Min(max_length, totalDistance); var length = Math.Min(max_length, totalDistance);
tickDistance = MathHelper.Clamp(tickDistance, 0, length); tickDistance = Math.Clamp(tickDistance, 0, length);
var minDistanceFromEnd = velocity * 10; var minDistanceFromEnd = velocity * 10;

View File

@ -246,7 +246,7 @@ namespace osu.Game.Rulesets.Objects
private double progressToDistance(double progress) private double progressToDistance(double progress)
{ {
return MathHelper.Clamp(progress, 0, 1) * Distance; return Math.Clamp(progress, 0, 1) * Distance;
} }
private Vector2 interpolateVertices(int i, double d) private Vector2 interpolateVertices(int i, double d)

View File

@ -7,7 +7,6 @@ using JetBrains.Annotations;
using osu.Framework.Input.StateChanges; using osu.Framework.Input.StateChanges;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays; using osu.Game.Replays;
using osuTK;
namespace osu.Game.Rulesets.Replays namespace osu.Game.Rulesets.Replays
{ {
@ -52,7 +51,7 @@ namespace osu.Game.Rulesets.Replays
private int? currentFrameIndex; private int? currentFrameIndex;
private int nextFrameIndex => currentFrameIndex.HasValue ? MathHelper.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; private int nextFrameIndex => currentFrameIndex.HasValue ? Math.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0;
protected FramedReplayInputHandler(Replay replay) protected FramedReplayInputHandler(Replay replay)
{ {

View File

@ -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);
@ -517,6 +517,12 @@ namespace osu.Game.Rulesets.UI
public BindableDouble Frequency => throw new NotImplementedException(); public BindableDouble Frequency => throw new NotImplementedException();
public IBindable<double> AggregateVolume => throw new NotImplementedException();
public IBindable<double> AggregateBalance => throw new NotImplementedException();
public IBindable<double> AggregateFrequency => throw new NotImplementedException();
public int PlaybackConcurrency public int PlaybackConcurrency
{ {
get => throw new NotImplementedException(); get => throw new NotImplementedException();

View File

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

View File

@ -1,9 +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 System;
using osu.Framework.Lists; using osu.Framework.Lists;
using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.Timing;
using osuTK;
namespace osu.Game.Rulesets.UI.Scrolling.Algorithms namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
{ {
@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
} }
} }
i = MathHelper.Clamp(i, 0, controlPoints.Count - 1); i = Math.Clamp(i, 0, controlPoints.Count - 1);
return controlPoints[i].StartTime + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength; return controlPoints[i].StartTime + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength;
} }

View File

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

View File

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

View File

@ -1,6 +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 System;
using osuTK; using osuTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -59,7 +60,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
if (Beatmap.Value == null) if (Beatmap.Value == null)
return; return;
float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth);
adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length); adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length);
}); });
} }

View File

@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
float distance = direction.Length; float distance = direction.Length;
float radius = DistanceSpacing; float radius = DistanceSpacing;
int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals);
Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 normalisedDirection = direction * new Vector2(1f / distance);
Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius;

View File

@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
get => zoomTarget; get => zoomTarget;
set set
{ {
value = MathHelper.Clamp(value, MinZoom, MaxZoom); value = Math.Clamp(value, MinZoom, MaxZoom);
if (IsLoaded) if (IsLoaded)
setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X);
@ -117,7 +117,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
private void setZoomTarget(float newZoom, float focusPoint) private void setZoomTarget(float newZoom, float focusPoint)
{ {
zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom);
transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing);
} }

View File

@ -7,7 +7,6 @@ using osu.Framework.MathUtils;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osuTK;
namespace osu.Game.Screens.Edit namespace osu.Game.Screens.Edit
{ {
@ -125,7 +124,7 @@ namespace osu.Game.Screens.Edit
seekTime = nextTimingPoint.Time; seekTime = nextTimingPoint.Time;
// Ensure the sought point is within the boundaries // Ensure the sought point is within the boundaries
seekTime = MathHelper.Clamp(seekTime, 0, TrackLength); seekTime = Math.Clamp(seekTime, 0, TrackLength);
Seek(seekTime); Seek(seekTime);
} }
} }

View File

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

View File

@ -236,7 +236,7 @@ namespace osu.Game.Screens.Menu
protected override void Update() protected override void Update()
{ {
iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); iconText.Alpha = Math.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1);
base.Update(); base.Update();
} }

View File

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

View File

@ -74,7 +74,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components
set set
{ {
matchingFilter = value; matchingFilter = value;
this.FadeTo(MatchingFilter ? 1 : 0, 200);
if (IsLoaded)
this.FadeTo(MatchingFilter ? 1 : 0, 200);
} }
} }
@ -203,7 +205,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
this.FadeInFromZero(transition_duration);
if (matchingFilter)
this.FadeInFromZero(transition_duration);
else
Alpha = 0;
} }
private class RoomName : OsuSpriteText private class RoomName : OsuSpriteText

View File

@ -4,6 +4,7 @@
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Threading;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.SearchableList;
using osuTK.Graphics; using osuTK.Graphics;
@ -37,12 +38,22 @@ namespace osu.Game.Screens.Multi.Lounge.Components
{ {
base.LoadComplete(); base.LoadComplete();
Search.Current.BindValueChanged(_ => updateFilter()); Search.Current.BindValueChanged(_ => scheduleUpdateFilter());
Tabs.Current.BindValueChanged(_ => updateFilter(), true); Tabs.Current.BindValueChanged(_ => updateFilter(), true);
} }
private ScheduledDelegate scheduledFilterUpdate;
private void scheduleUpdateFilter()
{
scheduledFilterUpdate?.Cancel();
scheduledFilterUpdate = Scheduler.AddDelayed(updateFilter, 200);
}
private void updateFilter() private void updateFilter()
{ {
scheduledFilterUpdate?.Cancel();
filter.Value = new FilterCriteria filter.Value = new FilterCriteria
{ {
SearchString = Search.Current.Value ?? string.Empty, SearchString = Search.Current.Value ?? string.Empty,

View File

@ -24,6 +24,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components
private readonly FillFlowContainer<DrawableRoom> roomFlow; private readonly FillFlowContainer<DrawableRoom> roomFlow;
public IReadOnlyList<DrawableRoom> Rooms => roomFlow; public IReadOnlyList<DrawableRoom> Rooms => roomFlow;
[Resolved(CanBeNull = true)]
private Bindable<FilterCriteria> filter { get; set; }
[Resolved] [Resolved]
private Bindable<Room> currentRoom { get; set; } private Bindable<Room> currentRoom { get; set; }
@ -57,7 +60,10 @@ namespace osu.Game.Screens.Multi.Lounge.Components
addRooms(rooms); addRooms(rooms);
} }
private FilterCriteria currentFilter; protected override void LoadComplete()
{
filter?.BindValueChanged(f => Filter(f.NewValue), true);
}
public void Filter(FilterCriteria criteria) public void Filter(FilterCriteria criteria)
{ {
@ -74,15 +80,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components
{ {
default: default:
case SecondaryFilter.Public: case SecondaryFilter.Public:
r.MatchingFilter = r.Room.Availability.Value == RoomAvailability.Public; matchingFilter &= r.Room.Availability.Value == RoomAvailability.Public;
break; break;
} }
r.MatchingFilter = matchingFilter; r.MatchingFilter = matchingFilter;
} }
}); });
currentFilter = criteria;
} }
private void addRooms(IEnumerable<Room> rooms) private void addRooms(IEnumerable<Room> rooms)
@ -90,7 +94,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components
foreach (var r in rooms) foreach (var r in rooms)
roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) }); roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) });
Filter(currentFilter); if (filter != null)
Filter(filter.Value);
} }
private void removeRooms(IEnumerable<Room> rooms) private void removeRooms(IEnumerable<Room> rooms)

View File

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

View File

@ -102,8 +102,8 @@ namespace osu.Game.Screens.Play.HUD
else else
{ {
Alpha = Interpolation.ValueAt( Alpha = Interpolation.ValueAt(
MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), Math.Clamp(Clock.ElapsedFrameTime, 0, 200),
Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); Alpha, Math.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint);
} }
} }

View File

@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play
{ {
base.Update(); base.Update();
float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1));
fill.Width = newX; fill.Width = newX;
handleBase.X = newX; handleBase.X = newX;

View File

@ -256,7 +256,7 @@ namespace osu.Game.Screens.Play
{ {
Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour; Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour;
int countFilled = (int)MathHelper.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); int countFilled = (int)Math.Clamp(filled * drawableRows.Count, 0, drawableRows.Count);
for (int i = 0; i < drawableRows.Count; i++) for (int i = 0; i < drawableRows.Count; i++)
drawableRows[i].Colour = i < countFilled ? colour : EmptyColour; drawableRows[i].Colour = i < countFilled ? colour : EmptyColour;

View File

@ -87,9 +87,9 @@ namespace osu.Game.Screens
private static Color4 getColourFor(object type) private static Color4 getColourFor(object type)
{ {
int hash = type.GetHashCode(); int hash = type.GetHashCode();
byte r = (byte)MathHelper.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); byte r = (byte)Math.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255);
byte g = (byte)MathHelper.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); byte g = (byte)Math.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255);
byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); byte b = (byte)Math.Clamp((hash & 0x0000FF) * 0.8f, 20, 255);
return new Color4(r, g, b, 255); return new Color4(r, g, b, 255);
} }

View File

@ -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>
@ -452,9 +452,6 @@ namespace osu.Game.Screens.Select
if (!itemsCache.IsValid) if (!itemsCache.IsValid)
updateItems(); updateItems();
if (!scrollPositionCache.IsValid)
updateScrollPosition();
// Remove all items that should no longer be on-screen // Remove all items that should no longer be on-screen
scrollableContent.RemoveAll(p => p.Y < visibleUpperBound - p.DrawHeight || p.Y > visibleBottomBound || !p.IsPresent); scrollableContent.RemoveAll(p => p.Y < visibleUpperBound - p.DrawHeight || p.Y > visibleBottomBound || !p.IsPresent);
@ -519,6 +516,14 @@ namespace osu.Game.Screens.Select
updateItem(p); updateItem(p);
} }
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
if (!scrollPositionCache.IsValid)
updateScrollPosition();
}
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);
@ -637,8 +642,11 @@ namespace osu.Game.Screens.Select
private void updateScrollPosition() private void updateScrollPosition()
{ {
if (scrollTarget != null) scroll.ScrollTo(scrollTarget.Value); if (scrollTarget != null)
scrollPositionCache.Validate(); {
scroll.ScrollTo(scrollTarget.Value);
scrollPositionCache.Validate();
}
} }
/// <summary> /// <summary>
@ -677,7 +685,7 @@ namespace osu.Game.Screens.Select
// We are applying a multiplicative alpha (which is internally done by nesting an // We are applying a multiplicative alpha (which is internally done by nesting an
// additional container and setting that container's alpha) such that we can // additional container and setting that container's alpha) such that we can
// layer transformations on top, with a similar reasoning to the previous comment. // layer transformations on top, with a similar reasoning to the previous comment.
p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1)); p.SetMultiplicativeAlpha(Math.Clamp(1.75f - 1.5f * dist, 0, 1));
} }
private class CarouselRoot : CarouselGroupEagerSelect private class CarouselRoot : CarouselGroupEagerSelect

View File

@ -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 osuTK; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select.Details
retryGraph.MaxValue = maxValue; retryGraph.MaxValue = maxValue;
failGraph.Values = fails.Select(f => (float)f); failGraph.Values = fails.Select(f => (float)f);
retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue)); retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + Math.Clamp(fail, 0, maxValue));
} }
} }

View File

@ -46,52 +46,54 @@ namespace osu.Game.Screens.Select
protected const float BACKGROUND_BLUR = 20; protected const float BACKGROUND_BLUR = 20;
private const float left_area_padding = 20; private const float left_area_padding = 20;
public readonly FilterControl FilterControl; public FilterControl FilterControl { get; private set; }
protected virtual bool ShowFooter => true; protected virtual bool ShowFooter => true;
/// <summary> /// <summary>
/// Can be null if <see cref="ShowFooter"/> is false. /// Can be null if <see cref="ShowFooter"/> is false.
/// </summary> /// </summary>
protected readonly BeatmapOptionsOverlay BeatmapOptions; protected BeatmapOptionsOverlay BeatmapOptions { get; private set; }
/// <summary> /// <summary>
/// Can be null if <see cref="ShowFooter"/> is false. /// Can be null if <see cref="ShowFooter"/> is false.
/// </summary> /// </summary>
protected readonly Footer Footer; protected Footer Footer { get; private set; }
/// <summary> /// <summary>
/// Contains any panel which is triggered by a footer button. /// Contains any panel which is triggered by a footer button.
/// Helps keep them located beneath the footer itself. /// Helps keep them located beneath the footer itself.
/// </summary> /// </summary>
protected readonly Container FooterPanels; protected Container FooterPanels { get; private set; }
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value);
protected readonly BeatmapCarousel Carousel; protected BeatmapCarousel Carousel { get; private set; }
private readonly BeatmapInfoWedge beatmapInfoWedge;
private BeatmapInfoWedge beatmapInfoWedge;
private DialogOverlay dialogOverlay; private DialogOverlay dialogOverlay;
private BeatmapManager beatmaps; private BeatmapManager beatmaps;
protected readonly ModSelectOverlay ModSelect; protected ModSelectOverlay ModSelect { get; private set; }
protected SampleChannel SampleConfirm { get; private set; }
protected SampleChannel SampleConfirm;
private SampleChannel sampleChangeDifficulty; private SampleChannel sampleChangeDifficulty;
private SampleChannel sampleChangeBeatmap; private SampleChannel sampleChangeBeatmap;
protected readonly BeatmapDetailArea BeatmapDetails; protected BeatmapDetailArea BeatmapDetails { get; private set; }
private readonly Bindable<RulesetInfo> decoupledRuleset = new Bindable<RulesetInfo>(); private readonly Bindable<RulesetInfo> decoupledRuleset = new Bindable<RulesetInfo>();
[Resolved(canBeNull: true)] [Resolved(canBeNull: true)]
private MusicController music { get; set; } private MusicController music { get; set; }
[Cached] [BackgroundDependencyLoader(true)]
[Cached(Type = typeof(IBindable<IReadOnlyList<Mod>>))] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores)
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()
{ {
// initial value transfer is required for FilterControl (it uses our re-cached bindables in its async load for the initial filter).
transferRulesetValue();
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
{ {
new ParallaxContainer new ParallaxContainer
@ -165,7 +167,7 @@ namespace osu.Game.Screens.Select
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = FilterControl.HEIGHT, Height = FilterControl.HEIGHT,
FilterChanged = c => Carousel.Filter(c), FilterChanged = ApplyFilterToCarousel,
Background = { Width = 2 }, Background = { Width = 2 },
}, },
} }
@ -215,14 +217,10 @@ namespace osu.Game.Screens.Select
} }
BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score));
}
[BackgroundDependencyLoader(true)]
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores)
{
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,11 +260,10 @@ namespace osu.Game.Screens.Select
} }
} }
protected override void LoadComplete() protected virtual void ApplyFilterToCarousel(FilterCriteria criteria)
{ {
base.LoadComplete(); if (this.IsCurrentScreen())
Carousel.Filter(criteria);
mods.BindTo(Mods);
} }
private DependencyContainer dependencies; private DependencyContainer dependencies;
@ -390,7 +387,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.
@ -440,6 +437,8 @@ namespace osu.Game.Screens.Select
{ {
base.OnEntering(last); base.OnEntering(last);
Carousel.Filter(FilterControl.CreateCriteria(), false);
this.FadeInFromZero(250); this.FadeInFromZero(250);
FilterControl.Activate(); FilterControl.Activate();
} }
@ -538,9 +537,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;
} }
@ -638,7 +634,7 @@ namespace osu.Game.Screens.Select
return; return;
// manual binding to parent ruleset to allow for delayed load in the incoming direction. // manual binding to parent ruleset to allow for delayed load in the incoming direction.
rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; transferRulesetValue();
Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue); Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue);
decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue;
@ -650,6 +646,11 @@ namespace osu.Game.Screens.Select
boundLocalBindables = true; boundLocalBindables = true;
} }
private void transferRulesetValue()
{
rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value;
}
private void delete(BeatmapSetInfo beatmap) private void delete(BeatmapSetInfo beatmap)
{ {
if (beatmap == null || beatmap.ID <= 0) return; if (beatmap == null || beatmap.ID <= 0) return;

View File

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

View File

@ -22,7 +22,6 @@ using osu.Game.Online.API;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Beatmaps;
using osuTK;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
@ -250,7 +249,7 @@ namespace osu.Game.Tests.Visual
public override bool Seek(double seek) public override bool Seek(double seek)
{ {
offset = MathHelper.Clamp(seek, 0, Length); offset = Math.Clamp(seek, 0, Length);
lastReferenceTime = null; lastReferenceTime = null;
return offset == seek; return offset == seek;

View File

@ -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>
@ -21,7 +21,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<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" Version="2019.1112.0" /> <PackageReference Include="ppy.osu.Framework" Version="2019.1121.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />

View File

@ -73,6 +73,19 @@
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<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.1121.0" />
</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> </ItemGroup>
</Project> </Project>